Commercial Offer Deduction Implementation
Overviewβ
This document describes the implementation of the commercial offer deduction business rule for partial product cancellations in the SAV (Service Après-Vente) workflow.
Business Ruleβ
For Full Order Cancellationβ
When a customer receives a commercial gesture (coupon/discount/commercial offer) and later requests a FULL ORDER cancellation/refund:
refund = total_order_amount - commercial_offer_amount
For Partial Product Cancellationβ
When a customer receives a commercial offer and later cancels only one product (not the full order):
refund = max(0, cancelled_product_amount - commercial_offer_amount)
Key Requirementsβ
- Refund amount must never be negative
- The commercial offer is considered globally for the order
- If multiple products are cancelled separately, apply the rule independently for each cancellation request
- If multiple products are cancelled together in one request, the commercial offer is applied once to the total
Implementationβ
1. New Helper Methodsβ
getCommercialOfferAmount($sale): floatβ
Retrieves the commercial offer amount from the order. Checks multiple possible fields:
discount_amount
Returns the sum of all commercial offers, using absolute values to handle negative entries.
calculatePartialRefundAmount(float $cancelledProductAmount, float $commercialOfferAmount): floatβ
Calculates the refund amount for partial cancellations:
$refundAmount = $cancelledProductAmount - $commercialOfferAmount;
return max(0.0, $refundAmount);
2. Updated Methodsβ
The following methods now include commercial offer deduction:
| Method | Cancellation Type | Notes |
|---|---|---|
handleSaleCancellationWithSav | Full sale | Subtracts commercial offer from refund |
handleSaleCancellationWithGiftCard | Full sale (gift card) | Subtracts commercial offer before 115% calculation |
handleProductsCancellationWithSav | Partial/Complete products | Uses calculatePartialRefundAmount for partial, direct subtraction for complete |
handleProductsCancellationWithGiftCard | Partial products (gift card) | Subtracts commercial offer before 115% calculation |
Examplesβ
Example 1: Commercial offer exceeds cancelled product priceβ
Order total = 200
Commercial offer = 100
Cancelled product price = 50
Refund = max(0, 50 - 100) = 0
Example 2: Commercial offer less than cancelled product priceβ
Order total = 300
Commercial offer = 40
Cancelled product price = 120
Refund = max(0, 120 - 40) = 80
Example 3: Multiple products cancelled in single requestβ
Order total = 500
Commercial offer = 100
Product 1 price = 80
Product 2 price = 120
Total cancelled = 200
Refund = max(0, 200 - 100) = 100
Example 4: Multiple products cancelled separately (sequential)β
Commercial offer = 100
First cancellation: Product A = 50
Refund = max(0, 50 - 100) = 0
Second cancellation: Product B = 80
Refund = max(0, 80 - 100) = 0
Note: When products are cancelled separately, the commercial offer is applied independently to each request. This may result in the commercial offer being "used" multiple times.
Validation & Edge Casesβ
Edge Cases Handledβ
- No commercial offer: Returns full refund amount
- Commercial offer equals product price: Returns 0
- Very small commercial offer: Properly handled with float precision
- Very large commercial offer: Returns 0 (never negative)
- With existing pre-refunds: Pre-refunds are subtracted first, then commercial offer is applied
- All zeros: Returns 0
- Float precision: Results rounded to 2 decimal places for currency
Example with Pre-refundsβ
Cancelled product price = 100
Existing pre-refund amount = 20
Commercial offer = 30
Calculation:
1. Subtract pre-refunds: 100 - 20 = 80
2. Apply commercial offer: max(0, 80 - 30) = 50
Refund = 50
Refund Pattern Exclusionsβ
Some refund types are excluded from the pre-refund calculation. Refunds whose pattern contains specific keywords are NOT subtracted from the new refund amount.
Excluded Patterns (case-insensitive, configured in $excludedRefundPatterns):
modification produitmodification de produit
Examples of excluded refund patterns:
- "modifiction produit" β (excluded)
- "Modification de produit" β (excluded)
- "MODIFICATION PRODUIT" β (excluded)
- "remboursement standard" β (included)
Use Case: When a customer received a refund for product modification (e.g., wrong size, wrong color) and later cancels the order, the modification refund should not reduce the cancellation refund amount.
Configuration: Add new patterns to the $excludedRefundPatterns property in the SavWorkflowService class.
Loggingβ
All refund calculations include detailed logging for debugging and audit purposes:
SavWorkflowService: Partial refund calculation [
'cancelled_product_amount' => 50.0,
'commercial_offer_amount' => 100.0,
'refund_amount' => 0.0,
'calculation' => "max(0, 50.0 - 100.0) = 0.0"
]
Assumptionsβ
- Commercial offer is stored in
order_info['discount_amount']or similar fields - The commercial offer represents a global discount on the entire order
- The commercial offer is subtracted in full from each cancellation
- Multiple separate cancellation requests each get the full commercial offer deduction
- Refund policies may change in the future (code is designed for easy modification)
- The
calculatePartialRefundAmountfunction is isolated for easy modification