using Distribution.Models; namespace Distribution.Features.Scheme; // ── Rule config payloads for percentage-based rules (serialized into Scheme.RuleConfig) ── public record SlabDiscountConfig(List Tiers); public record SlabTier(decimal MinOrderAmount, decimal DiscountPercent); public record FlatPercentConfig(decimal DiscountPercent); // ── Requests ──────────────────────────────────────────────────────────── public record BundleComponentRequest(Guid ItemId, int Qty); /// /// TriggerItemId/TriggerQty/FreeItemId/FreeQty/BundleComponents are optional so plain discount /// schemes (SlabDiscount/FlatPercent) can omit them entirely. When RuleType is BuyXGetY, supplying /// TriggerItemId+TriggerQty+FreeItemId+FreeQty here creates the scheme fully populated in one call /// instead of a separate PUT .../free-goods-rule. When RuleType is FreeBundle, supplying /// FreeItemId+FreeQty+BundleComponents does the same. These can still be added/edited later via /// PUT .../free-goods-rule and PUT .../bundle-components/{itemId}. /// public record CreateSchemeRequest( string Name, SchemeRuleType RuleType, string? RuleConfig, Guid? RegionId, string? EligibleSegment, DateTime DateRangeFrom, DateTime DateRangeTo, bool AgentLimitExempt, decimal? BaselineExpectedSales, Guid? TriggerItemId = null, int? TriggerQty = null, Guid? FreeItemId = null, decimal? FreeQty = null, List? BundleComponents = null); public record UpdateSchemeRequest( string Name, string? RuleConfig, Guid? RegionId, string? EligibleSegment, DateTime DateRangeFrom, DateTime DateRangeTo, bool AgentLimitExempt, decimal? BaselineExpectedSales, bool IsActive); public record ApplySchemeRequest(Guid SchemeId); /// /// Sets the free-goods payout for a scheme. For BuyXGetY, TriggerItemId/TriggerQty are required /// (what the store must buy); for FreeBundle they are ignored — the required items instead come /// from the scheme's bundle-components CRUD. FreeItemId/FreeQty is the payout in both cases. /// public record SetFreeGoodsRuleRequest(Guid? TriggerItemId, int? TriggerQty, Guid FreeItemId, decimal FreeQty); public record UpsertBundleComponentRequest(int Qty); // ── Responses ─────────────────────────────────────────────────────────── public record BundleComponentResponse(Guid ItemId, string Sku, string ItemName, int Qty); public record SchemeResponse( Guid Id, string Name, SchemeRuleType RuleType, string? RuleConfig, Guid? TriggerItemId, string? TriggerItemName, int? TriggerQty, Guid? FreeItemId, string? FreeItemName, decimal? FreeQty, List BundleComponents, Guid? RegionId, string? RegionName, string? EligibleSegment, DateTime DateRangeFrom, DateTime DateRangeTo, bool AgentLimitExempt, decimal? BaselineExpectedSales, bool IsActive, DateTime CreatedAt); public record SchemeEligibilityResponse( Guid SchemeId, string SchemeName, SchemeRuleType RuleType, bool Eligible, string? Reason, decimal? DiscountAmount, Guid? FreeItemId, decimal? FreeQty, string? FreeItemName = null); /// A cart line for scheme suggestion before the Shop PO exists. UnitPrice null = resolve from the price list. public record SuggestLine(Guid ItemId, int Quantity, decimal? UnitPrice = null, bool IsFree = false); public record SuggestSchemesRequest(Guid StoreId, List Items); public record SchemeRedemptionResponse( Guid Id, Guid SchemeId, Guid? ShopPOId, decimal? DiscountAmount, Guid? FreeItemId, string? FreeItemName, decimal? FreeQty, decimal? FreeItemCostValue, DateTime RedeemedAt); public record SchemeSpendResponse(Guid SchemeId, decimal TotalDiscountSpend, decimal TotalFreeGoodsCostSpend, decimal TotalSpend, int RedemptionCount); public record SchemeROIResponse(Guid SchemeId, decimal BaselineExpectedSales, decimal ActualSales, decimal IncrementalSales, decimal TotalSpend, decimal? ROI);