Files
Kalana B. Thilakarathna 93f2f1bd3b Refactor sales pipeline: ShopPO, Invoice, SysConfig models
Major refactor replacing Sale/Order with ShopPO → Invoice → LoadingSheet flow. Removed legacy Sale/Order models and features; introduced ShopPO, ShopPOItem, Invoice, LoadingSheetOrder, and SysConfig models. Updated related entities, enums, repositories, and controllers. Added new migrations for schema changes and system config. Overhauled business logic and DI registrations. Updated documentation with migration plan.
2026-09-17 10:03:22 +05:30

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? 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);