Discounts and Surcharges
v6
SyrveRms has a built-in discount system. Third-party loyalty systems (plazius, SyrveCard, etc.) are not covered in this article.
The SyrveRms discount system allows for the application of discounts and surcharges under various conditions.
A discount is understood as a reduction in the cost of an order item by a certain amount, while a surcharge is an increase. Since the difference between a discount and a surcharge lies only in the sign of the number subtracted from the cost, for the sake of simplicity, we will refer to both as discounts (in the code DiscountType, DiscountItem, DiscountCard, etc.), implying that a positive value of DiscountSum in the subject area corresponds to a discount, while a negative value corresponds to a surcharge.
In general, a discount can be configured in such a way that within an order for one dish it reduces the cost, acting as a discount, while for another dish it increases the cost, acting as a surcharge; therefore, the distinction between discounts and surcharges can be considered quite conditional.
Limitations
The rules and conditions for applying discounts (DiscountItem) are determined by the type (DiscountType), which can be a fixed amount (voucher), a percentage of the cost, rounding (dropping cents), and so on, but the result of applying a discount (AppliedDiscountItem) is always an absolute value, a specific number.
The algorithms for applying discounts depend on the category of the dish, the section of the order, the order amount (FullSum), the service mode, the current time, and the service print time; discounts may or may not be combined, and can be applied either in parallel (to the total cost) or sequentially (taking into account the application of previous discounts). All these conditions are implementation details and are not published in the API.
The API only provides general settings, such as:
IsActive— whether the discount is active in the current group,IsAutomatic— whether the discount can be added to orders automatically,CanApplyManually— whether the discount can be added to an order manually by selecting from a list,CanApplyByCardNumber— whether the discount can be added to an order by discount card number (by entering the card number on the numeric keypad),CanApplyByDiscountCard— whether the discount can be added to an order by discount card (by reading the card track),DiscountByFlexibleSum— whether it is required to specify the amount when adding a discount to an order,CanApplySelectively— whether the discount can be selectively applied to several order items.
The discount amount is calculated separately for each order item, even if the discount applies to the entire order. Thus, a discount on the order is the sum of the discounts on its items. The discount amount, like any other monetary value, is a multiple of the minimum denomination of the currency. The total of all active discounts on an order item does not exceed its cost; in other words, the result of subtracting discounts from the cost can reach zero (100% discount), but cannot become negative. There is no such limitation for surcharges; any value can be added to the cost of an order item.
Lifecycle
A discount added to an order can be in one of two states — fixed or not fixed.
Transitions between these states are possible, but cannot be directly controlled; the state is tied to the lifecycle of the order.
Currently, discounts are fixed when the order is moved to the status Bill and return to an unconfirmed state when moved to the New status, but this is an implementation detail that may change at any time.
Discount Not Fixed
When a discount is added to an order, only the data on how to calculate it is remembered. Amounts are calculated on the fly upon request, and the results of calculations are not stored. Since the latest available values of the parameters of the discount application algorithm, including settings from Syrve Office and the current time, are used in each calculation, the results may vary. Accordingly, the final cost of the order may also change.
Automatically added discounts (IsAutomatic) implicitly exist in all orders with unconfirmed discounts; until fixed, they will not appear in the Discounts list of each order, and after fixing — it depends on the presence of the effect of application to the order.
Discount Fixed
When the order reaches a point where its final cost should no longer change, the on-the-fly calculated values (prices, discounts, etc.) are fixed. The result of the last calculation is saved and used in subsequent requests instead of recalculating. This allows for independence from changes in settings or other parameters of discount applications. From this point on, in addition to the algorithm and parameters for applying the discount, specific amounts for each order item are remembered. However, if at the time of fixing the discount was not actually applied (had a zero effect), it is removed from the order.
Data Structures
DiscountType— discount type, an element of the discount directory. The entire directory can be obtained by calling the methodGetDiscountTypes.DiscountItem— discount added to the order. A discount can be added to the order using the methodsAddDiscount,AddFlexibleSumDiscount,AddDiscountByCardNumber,AddFlexibleSumDiscountByCardNumber. To remove a discount, you can useDeleteDiscount. The list of discounts added to the order isDiscounts.AppliedDiscountItem— the result of applying a previously added discount to the order, which can be obtained using the methodGetOrderAppliedDiscounts. Discounts can be applied on the fly at the time of the request, or the result of a previous application may be returned if it was recorded in the order.FullSum— the total cost of the order excluding discounts (subtotal).ResultSum— the final cost of the order including discounts.
Note: the total discount for the order should not be defined as the difference between the last two values, as they differ not only in terms of discounts but also in terms of value-added tax (VAT), which is not included in the price of goods. It is better to calculate the discount amount by summing up DiscountSum.
Selective Application of Discounts
By default, discounts apply to all dishes, including those added after the discount is assigned.
However, discounts with the CanApplySelectively setting enabled can be selectively applied to one or more items in the order, and they will only apply to those items.
For example, when selling baked goods, hot items may be sold at full price, while the same items that have cooled down may be sold at a discount.
The product item is the same in both cases.
The decision is made by the user (or plugin), setting the restriction on which dishes and modifiers the discount will apply.
This restriction works as a whitelist, so a selectively applied discount will not apply to dishes added later.
All other restrictions (by category, by time, by amount, etc.) remain in effect, meaning that the discount will effectively apply only to those items in the whitelist that meet the other conditions.
A selectively applied discount only affects the specified items in the order. For example, if there is a dish with paid modifiers in the order, and the discount is selectively applied only to the dish, it will only apply to the dish. To selectively apply the discount to both dishes and modifiers, both the dish and the modifiers must be explicitly specified.
Key Functions:
ChangeSelectiveDiscount— allows you to set a whitelist of order items that the discount can apply to. Considering different types of items, this effectively creates three lists — simple dishes, components of composite dishes, and modifiers. If all three lists are set tonull, the discount will stop being applied selectively and will apply to the entire order.GetSelectiveDiscountItemSettings— the method returns the parameters of selective application (the same three lists), ornullif the discount applies to the entire order without restrictions on items.IsSelectivelyApplied— indicates whether the discount is applied selectively or to the entire order.
Examples
An example of selective discount application can be found in the SDK plugin Resto.Front.Api.SamplePlugin (EditorTester.AddSelectiveDiscount):
/// <summary>
/// Adding a discount with the ability to select dishes.
/// </summary>
private void AddSelectiveDiscount()
{
var order = PluginContext.Operations.GetOrders().Last();
var selectedDish = new List<IOrderProductItemStub> { order.Items.OfType<IOrderProductItem>().Last() };
var discountType = PluginContext.Operations.GetDiscountTypes().Last(x => !x.Deleted && x.IsActive && x.CanApplySelectively);
var editSession = PluginContext.Operations.CreateEditSession();
editSession.AddDiscount(discountType, order);
editSession.ChangeSelectiveDiscount(order, discountType, selectedDish, null, null);
PluginContext.Operations.SubmitChanges(PluginContext.Operations.GetCredentials(), editSession);
}