namespace Distribution.Models
{
public enum SchemeRuleType
{
BuyXGetY,
SlabDiscount,
FlatPercent,
FreeBundle
}
public class Scheme : Template
{
public string Name { get; set; }
public SchemeRuleType RuleType { get; set; }
///
/// JSON payload for percentage-based rules only (SlabDiscount tiers, FlatPercent). Free-goods
/// rules (BuyXGetY / FreeBundle) are structured fields/child rows below, not JSON, so they can
/// be managed through their own CRUD endpoints instead of a hand-edited blob.
///
public string? RuleConfig { get; set; }
// ── BuyXGetY: trigger item/qty; shares FK_FreeItemId/FreeQty below as the payout. ──────────
public Guid? FK_TriggerItemId { get; set; }
public Item? TriggerItem { get; set; }
public int? TriggerQty { get; set; }
// ── Free-goods payout, used by both BuyXGetY and FreeBundle. ─────────────────────────────
public Guid? FK_FreeItemId { get; set; }
public Item? FreeItem { get; set; }
public decimal? FreeQty { get; set; }
/// Required component items for a FreeBundle scheme — managed via its own CRUD.
public ICollection BundleComponents { get; set; } = [];
public Guid? FK_RegionId { get; set; }
public Region? Region { get; set; }
/// Store segment this scheme applies to (Gold/Silver/Key Account/...); null = all segments.
public string? EligibleSegment { get; set; }
public DateTime DateRangeFrom { get; set; }
public DateTime DateRangeTo { get; set; }
///
/// When true, this scheme's discount is exempt from the per-role discount ceiling in
/// 08_sales_agent_controls.md and stacks on top of it unconditionally.
///
public bool AgentLimitExempt { get; set; }
///
/// Manual baseline (expected sales with no scheme running) used by getSchemeROI. Per the
/// open question in docs/17_promotions_schemes.md, this is entered at scheme creation
/// rather than computed from a trailing-period average.
///
public decimal? BaselineExpectedSales { get; set; }
public ICollection Redemptions { get; set; } = [];
}
}