We have talked about the concept of discount base amount. Now we will discuss technical details and share extensibility interface.
Please note that everything here is not final and we may change it.
First, the interface
/// <summary>
/// Interface for priority discount base amount calculator.
/// </summary>
/// <remarks>
/// If you customize this, chances are you will have to customize the grouping
/// for discountable item group, as all sales lines in the same discountable
/// item group share the same discount base amount(s).
/// </remarks>
public interface IPriorityDiscountBaseAmountCalculator
{
/// <summary>
/// Gets the discount base amount.
/// </summary>
/// <param name="salesLine">Sales line.</param>
/// <returns>Discount base amount.</returns>
/// <remarks>This is for initial discount base amount override, before discount calculation.</remarks>
decimal GetDiscountBaseAmount(SalesLine salesLine);
/// Calculates priority discount base amount.
/// </summary>
/// <param name="currentPriority">Current priority.</param>
/// <param name="salesLine">Sales line.</param>
/// <param name="itemGroupIndex">Item group index.</param>
/// <param name="existingPriorityDiscountBaseAmounts">Existing priority discount base amounts.</param>
/// <returns>Discount base amount afer the priority.</returns>
/// <remarks>
/// Supported only for concurrnecy model of compete within priority and compound across.
/// This is to override discount base amount after the current priority
/// for the remaining compoundable discounts.
/// </remarks>
decimal CalculatePriorityDiscountBaseAmount(
int currentPriority,
SalesLine salesLine,
int itemGroupIndex,
IReadOnlyCollection<PriorityDiscountBaseAmount> existingPriorityDiscountBaseAmounts);
}
The default implementation for both methods is to return the item price.
From now on, we will focus on the concurrency model of compete within priority and compound across, as we only support initial discount base amount customization for pricing zones concurrency model and it is a simple case.
Discount base amount adjustment vs. natural compounding
Conceptually speaking, natural compounding is to adjust discount base amount downward for the next compoundable discount, which Dynamics Retail discount engine handles abundantly. We decided to have customized discount base amount adjustment supersede the natural compounding.
Example: item price is $100; 3 10%-off discounts of 3 priorities. Columns 2 and 3 are natural compounding without discount base amount override; while columns 4 and 5 have one override after P99.
Priority | Discount base amount | Discount | Discount base amount (adjusted) | Discount | Notes |
99 | $100 | $10 | $100 | $10 | |
50 | $100 ($90) | $9 | $50 - override | $5 | Ignored $10 discount from P99 |
1 | $100 ($81) | $8.1 | $50 ($45) | $4.5 | Ignored $10 discount from P99 |
To summarize from extensibility perspective, do not customize for natural compounding and customize only when you need to reset discount base amount for reasons other than natural compounding.
Decreasing discount base amount
We allow multiple rounds - priorities - of adjustments. Each adjustment has to be decreasing. Overall, we do NOT allow negative net amount where total discount amount > gross amount.
Persistence
Initially, we were thinking of persisting SalesLine.DiscountBaseAmount, as we preserve discount calculation details and customers may do something with it in financial posting. We dropped the idea in the end for two reasons. First, for the initial discount base amount adjustment, customers have to persist the adjustment amount anyway, and so the initial discount base amount is easily re-calculable. Secondly, SalesLine.DiscountBaseAmount is not sufficient, given we have to allow more fine-grained per-priority discount base amount. In summary, if customers need to persist something, they can do it on their own.
Related: Dynamics Retail Discount Concepts: Discount Base Amount
Related: Dynamics Retail Discount Concepts: Discountable Item Group
Related: Retail Discount Concurrency Control – Pricing Zone
Related: Retail Discount Concurrency Control - Compete Within Priority and Compound Across