Functional Specifications
- Dynamic Promotion Applicability: Computes multi-level discounts including Percentage off, Flat Amount off, Free Shipping, and Buy One Get One (BOGO) deals.
- Smart Stacking Policy Resolver: Supports resolving discounts with
EXCLUSIVErules (only best promo),ADDITIVErules (stack all matching), andBEST_DEALoptimization. - Atomic Usage Safeguards: Locks global promotion pools and tracks per-user redemption limits atomically, ensuring thread safety and automatic recovery on transaction failure.
Operational Constraints
- Thread Concurrency: Must handle thousands of checkouts per second without race conditions or negative limit overflows.
- Atomic Payment Rollbacks: In the event of a checkout checkout failures, previously claimed usage counters must be perfectly rolled back.
Production reference implementations showcasing polymorphic discount engines, stacking resolution logic, and lock releases:
// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
enum PromotionType {
PERCENTAGE, FLAT_OFF, FREE_SHIPPING, BOGO
}
enum StackingGroup {
CART_TOTAL, ITEM_LEVEL, SHIPPING
}
enum StackingPolicy {
EXCLUSIVE, // Only one exclusive promotion can be applied (usually the best one)
ADDITIVE, // All matching promotions can stack
BEST_DEAL // Automatically calculate the single highest discount combination
}
class OrderItem {
private final String itemId;
private final String category;
private final double unitPrice;
private final int quantity;
public OrderItem(String itemId, String category, double unitPrice, int quantity) {
this.itemId = itemId;
this.category = category;
this.unitPrice = unitPrice;
this.quantity = quantity;
}
public String getItemId() { return itemId; }
public String getCategory() { return category; }
public double getUnitPrice() { return unitPrice; }
public int getQuantity() { return quantity; }
public double getTotalPrice() { return unitPrice * quantity; }
}
class OrderContext {
private final String orderId;
private final String userId;
private final List<OrderItem> items;
private final double shippingCost;
public OrderContext(String orderId, String userId, List<OrderItem> items, double shippingCost) {
this.orderId = orderId;
this.userId = userId;
this.items = items;
this.shippingCost = shippingCost;
}
public String getOrderId() { return orderId; }
public String getUserId() { return userId; }
public List<OrderItem> getItems() { return items; }
public double getShippingCost() { return shippingCost; }
public double getCartSubtotal() {
return items.stream().mapToDouble(OrderItem::getTotalPrice).sum();
}
}
class Promotion {
private final String id;
private final String code;
private final PromotionType type;
private final double value; // Percentage rate (e.g. 0.1) or Flat amount
private final String targetCategory; // Optional category filter
private final double minSpendRequirement;
private final StackingGroup stackingGroup;
private final boolean isExclusive;
private final AtomicInteger globalUsageLimit;
public Promotion(String id, String code, PromotionType type, double value,
String targetCategory, double minSpend, StackingGroup group,
boolean isExclusive, int limit) {
this.id = id;
this.code = code;
this.type = type;
this.value = value;
this.targetCategory = targetCategory;
this.minSpendRequirement = minSpend;
this.stackingGroup = group;
this.isExclusive = isExclusive;
this.globalUsageLimit = new AtomicInteger(limit);
}
public String getId() { return id; }
public String getCode() { return code; }
public PromotionType getType() { return type; }
public double getValue() { return value; }
public String getTargetCategory() { return targetCategory; }
public double getMinSpendRequirement() { return minSpendRequirement; }
public StackingGroup getStackingGroup() { return stackingGroup; }
public boolean isExclusive() { return isExclusive; }
public int getRemainingLimit() { return globalUsageLimit.get(); }
public boolean tryAcquireUsage() {
while (true) {
int current = globalUsageLimit.get();
if (current <= 0) return false;
if (globalUsageLimit.compareAndSet(current, current - 1)) {
return true;
}
}
}
public void releaseUsage() {
globalUsageLimit.incrementAndGet();
}
}
class DiscountResult {
private final Promotion promotion;
private final double discountAmount;
private final String description;
public DiscountResult(Promotion promotion, double discountAmount, String description) {
this.promotion = promotion;
this.discountAmount = discountAmount;
this.description = description;
}
public Promotion getPromotion() { return promotion; }
public double getDiscountAmount() { return discountAmount; }
public String getDescription() { return description; }
}
interface DiscountStrategy {
DiscountResult calculateDiscount(OrderContext order, Promotion promo, double currentSubtotal);
}
class PercentageDiscountStrategy implements DiscountStrategy {
@Override
public DiscountResult calculateDiscount(OrderContext order, Promotion promo, double currentSubtotal) {
if (currentSubtotal < promo.getMinSpendRequirement()) {
return new DiscountResult(promo, 0.0, "Min spend requirement not met");
}
double discount = 0.0;
if (promo.getTargetCategory() != null) {
double categoryTotal = order.getItems().stream()
.filter(i -> i.getCategory().equalsIgnoreCase(promo.getTargetCategory()))
.mapToDouble(OrderItem::getTotalPrice).sum();
discount = categoryTotal * promo.getValue();
} else {
discount = currentSubtotal * promo.getValue();
}
return new DiscountResult(promo, discount, String.format("%.0f%% discount applied", promo.getValue() * 100));
}
}
class FlatDiscountStrategy implements DiscountStrategy {
@Override
public DiscountResult calculateDiscount(OrderContext order, Promotion promo, double currentSubtotal) {
if (currentSubtotal < promo.getMinSpendRequirement()) {
return new DiscountResult(promo, 0.0, "Min spend requirement not met");
}
double discount = Math.min(currentSubtotal, promo.getValue());
return new DiscountResult(promo, discount, String.format("Flat $%.2f off total", promo.getValue()));
}
}
class FreeShippingStrategy implements DiscountStrategy {
@Override
public DiscountResult calculateDiscount(OrderContext order, Promotion promo, double currentSubtotal) {
if (currentSubtotal < promo.getMinSpendRequirement()) {
return new DiscountResult(promo, 0.0, "Min spend requirement not met");
}
return new DiscountResult(promo, order.getShippingCost(), "Free Shipping Applied");
}
}
class BogoStrategy implements DiscountStrategy {
@Override
public DiscountResult calculateDiscount(OrderContext order, Promotion promo, double currentSubtotal) {
double discount = 0.0;
for (OrderItem item : order.getItems()) {
if (promo.getTargetCategory() == null || item.getCategory().equalsIgnoreCase(promo.getTargetCategory())) {
int freePairs = item.getQuantity() / 2;
discount += freePairs * item.getUnitPrice();
}
}
return new DiscountResult(promo, discount, "BOGO Category Promotion Applied");
}
}
class UsageGuard {
private final Map<String, Set<String>> userPromoRedemptions = new ConcurrentHashMap<>();
public boolean checkAndTrackUserLimit(String userId, String promoId) {
Set<String> redeemed = userPromoRedemptions.computeIfAbsent(userId, k -> ConcurrentHashMap.newKeySet());
return redeemed.add(promoId);
}
public void releaseUserRedemption(String userId, String promoId) {
Set<String> redeemed = userPromoRedemptions.get(userId);
if (redeemed != null) {
redeemed.remove(promoId);
}
}
}
class DiscountEngine {
private final Map<PromotionType, DiscountStrategy> strategies = new HashMap<>();
private final UsageGuard usageGuard = new UsageGuard();
public DiscountEngine() {
strategies.put(PromotionType.PERCENTAGE, new PercentageDiscountStrategy());
strategies.put(PromotionType.FLAT_OFF, new FlatDiscountStrategy());
strategies.put(PromotionType.FREE_SHIPPING, new FreeShippingStrategy());
strategies.put(PromotionType.BOGO, new BogoStrategy());
}
public List<DiscountResult> calculateBestDiscounts(OrderContext order, List<Promotion> activePromotions, StackingPolicy policy) {
List<DiscountResult> applicable = new ArrayList<>();
double subtotal = order.getCartSubtotal();
for (Promotion promo : activePromotions) {
if (promo.getRemainingLimit() <= 0) continue;
DiscountStrategy strategy = strategies.get(promo.getType());
if (strategy != null) {
DiscountResult res = strategy.calculateDiscount(order, promo, subtotal);
if (res.getDiscountAmount() > 0) {
applicable.add(res);
}
}
}
if (applicable.isEmpty()) return Collections.emptyList();
List<DiscountResult> finalSelection = new ArrayList<>();
if (policy == StackingPolicy.EXCLUSIVE) {
applicable.stream()
.max(Comparator.comparingDouble(DiscountResult::getDiscountAmount))
.ifPresent(finalSelection::add);
}
else if (policy == StackingPolicy.BEST_DEAL) {
// Greedily select non-overlapping/compatible strategies or pick best single exclusive vs. stacked
applicable.sort((a, b) -> Double.compare(b.getDiscountAmount(), a.getDiscountAmount()));
for (DiscountResult res : applicable) {
if (res.getPromotion().isExclusive() && finalSelection.isEmpty()) {
finalSelection.add(res);
break;
}
if (!res.getPromotion().isExclusive()) {
finalSelection.add(res);
}
}
}
else if (policy == StackingPolicy.ADDITIVE) {
// Apply all non-exclusives, or if exclusive exists, pick highest exclusive or stacked
boolean hasExclusive = applicable.stream().anyMatch(r -> r.getPromotion().isExclusive());
if (hasExclusive) {
applicable.stream().filter(r -> !r.getPromotion().isExclusive()).forEach(finalSelection::add);
} else {
finalSelection.addAll(applicable);
}
}
return finalSelection;
}
public boolean checkout(OrderContext order, List<DiscountResult> appliedDiscounts) {
List<Promotion> acquiredPromos = new ArrayList<>();
boolean success = true;
try {
for (DiscountResult res : appliedDiscounts) {
Promotion promo = res.getPromotion();
if (!usageGuard.checkAndTrackUserLimit(order.getUserId(), promo.getId())) {
success = false;
break;
}
if (!promo.tryAcquireUsage()) {
usageGuard.releaseUserRedemption(order.getUserId(), promo.getId());
success = false;
break;
}
acquiredPromos.add(promo);
}
if (!success) {
rollback(order.getUserId(), acquiredPromos);
return false;
}
boolean paymentSuccess = processPayment(order);
if (!paymentSuccess) {
throw new RuntimeException("Payment Failed");
}
return true;
} catch (Exception e) {
rollback(order.getUserId(), acquiredPromos);
return false;
}
}
private void rollback(String userId, List<Promotion> acquiredPromos) {
for (Promotion acquired : acquiredPromos) {
acquired.releaseUsage();
usageGuard.releaseUserRedemption(userId, acquired.getId());
}
}
private boolean processPayment(OrderContext order) {
return true;
}
}
public class Main {
public static void main(String[] args) {
System.out.println("=== JAVA DISCOUNT ENGINE SIMULATION ===");
DiscountEngine engine = new DiscountEngine();
List<OrderItem> items = Arrays.asList(
new OrderItem("item1", "Electronics", 200.0, 1),
new OrderItem("item2", "Apparel", 50.0, 2)
);
OrderContext order = new OrderContext("ORD123", "USER_A", items, 15.0);
List<Promotion> promos = Arrays.asList(
new Promotion("P1", "ELEC10", PromotionType.PERCENTAGE, 0.1, "Electronics", 100.0, StackingGroup.ITEM_LEVEL, false, 5),
new Promotion("P2", "FLAT20", PromotionType.FLAT_OFF, 20.0, null, 150.0, StackingGroup.CART_TOTAL, false, 10),
new Promotion("P3", "FREESHIP", PromotionType.FREE_SHIPPING, 0.0, null, 50.0, StackingGroup.SHIPPING, false, 2)
);
System.out.println("Calculating best discounts under StackingPolicy.BEST_DEAL...");
List<DiscountResult> applied = engine.calculateBestDiscounts(order, promos, StackingPolicy.BEST_DEAL);
for (DiscountResult discount : applied) {
System.out.println(" - Applied promo: " + discount.getPromotion().getCode() + " | Discount: $" + discount.getDiscountAmount() + " (" + discount.getDescription() + ")");
}
boolean checkoutSuccess = engine.checkout(order, applied);
System.out.println("Checkout status: " + (checkoutSuccess ? "SUCCESS" : "FAILED"));
System.out.println("Remaining limits: P1=" + promos.get(0).getRemainingLimit() + ", P2=" + promos.get(1).getRemainingLimit());
System.out.println("=== END OF JAVA SIMULATION ===");
}
}