113 lines
4.0 KiB
C#
113 lines
4.0 KiB
C#
using Distribution.Models;
|
|
|
|
namespace Distribution.Features.Scheme;
|
|
|
|
// ── Rule config payloads for percentage-based rules (serialized into Scheme.RuleConfig) ──
|
|
|
|
public record SlabDiscountConfig(List<SlabTier> Tiers);
|
|
|
|
public record SlabTier(decimal MinOrderAmount, decimal DiscountPercent);
|
|
|
|
public record FlatPercentConfig(decimal DiscountPercent);
|
|
|
|
// ── Requests ────────────────────────────────────────────────────────────
|
|
|
|
public record BundleComponentRequest(Guid ItemId, int Qty);
|
|
|
|
/// <summary>
|
|
/// 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}.
|
|
/// </summary>
|
|
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<BundleComponentRequest>? 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);
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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<BundleComponentResponse> 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);
|
|
|
|
public record SchemeRedemptionResponse(
|
|
Guid Id,
|
|
Guid SchemeId,
|
|
Guid? OrderId,
|
|
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);
|