using foodmarket.Domain.Common;
namespace foodmarket.Domain.Sales;
/// Тип скидки акции.
public enum PromotionType
{
/// Процент от Subtotal (или от MatchingSubtotal если ProductGroupIds/ProductIds задан).
Percent = 1,
/// Фиксированная сумма скидки в валюте чека.
FixedDiscount = 2,
}
/// Область применения акции — на весь чек или только на товары из
/// указанных групп/конкретные товары.
public enum PromotionScope
{
All = 1,
ProductGroups = 2,
Products = 3,
}
/// Промокод/акция. Применяется к розничному чеку при выбивании.
///
/// Применение: либо кассир вводит вручную, либо для
/// акций с пустым применяется автоматически если
/// чек удовлетворяет правилам (период + минимум + scope).
///
/// Период: <= sale.Date <
/// (если EndsAt = null — бессрочная). позволяет
/// быстро отключить акцию не меняя дат.
public class Promotion : TenantEntity
{
public string Name { get; set; } = null!;
public string? Description { get; set; }
/// Код для ручного ввода. null/empty = auto-apply акция (без кода).
/// Уникальный в рамках org через unique-index (`OrganizationId`, `Code`).
///
public string? Code { get; set; }
public PromotionType Type { get; set; }
/// Значение скидки. Для Percent — [0..100], для FixedDiscount — в валюте чека.
/// Хранится как decimal(18,4).
public decimal Value { get; set; }
public PromotionScope Scope { get; set; } = PromotionScope.All;
/// Минимальная сумма чека для применения (на Subtotal). 0 = без ограничения.
public decimal MinSaleAmount { get; set; }
public DateTime StartsAt { get; set; } = DateTime.UtcNow;
public DateTime? EndsAt { get; set; }
public bool IsActive { get; set; } = true;
/// Применимые ProductGroupId'ы (для Scope=ProductGroups). Сериализуется
/// как JSONB-массив; пустой массив = ни одной группы (никогда не сматчит).
public List ProductGroupIds { get; set; } = new();
/// Применимые ProductId'ы (для Scope=Products).
public List ProductIds { get; set; } = new();
}