using foodmarket.Domain.Catalog;
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Purchases;
public enum SupplyStatus
{
Draft = 0,
Posted = 1,
}
public class Supply : TenantEntity, IVersionedEntity
{
/// Postgres `xmin` — optimistic concurrency token. См. IVersionedEntity.
public uint Xmin { get; set; }
/// Human-readable document number, unique per organization (e.g. "П-2026-000001").
public string Number { get; set; } = "";
public DateTime Date { get; set; } = DateTime.UtcNow;
public SupplyStatus Status { get; set; } = SupplyStatus.Draft;
public Guid SupplierId { get; set; }
public Counterparty Supplier { get; set; } = null!;
public Guid StoreId { get; set; }
public Store Store { get; set; } = null!;
public Guid CurrencyId { get; set; }
public Currency Currency { get; set; } = null!;
public string? Notes { get; set; }
/// Sum of line totals. Computed on save.
public decimal Total { get; set; }
public DateTime? PostedAt { get; set; }
public Guid? PostedByUserId { get; set; }
/// Сколько из оплачено — сумма всех
/// проведённых MoneyTransactionLink.LinkedSum, где
/// SupplyId=этой приёмки. Пересчитывается в MoneyService
/// при проведении/отмене платежа. Инвариант: 0 ≤ PayedSum ≤ Total.
/// Статус оплаты получаем сравнением: PayedSum==0 — не оплачена,
/// 0<PayedSum<Total — частично, PayedSum>=Total — оплачена.
public decimal PayedSum { get; set; }
/// Id сущности в МойСкладе — для идемпотентного переноса истории.
public string? MoySkladExternalId { get; set; }
public ICollection Lines { get; set; } = new List();
}
public class SupplyLine : TenantEntity
{
public Guid SupplyId { get; set; }
public Supply Supply { get; set; } = null!;
public Guid ProductId { get; set; }
public Product Product { get; set; } = null!;
public decimal Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal LineTotal { get; set; }
public int SortOrder { get; set; }
/// Если true — пользователь вручную задал розничную цену для
/// этой строки (через UI приёмки). При Posting автонаценка по Group.MarkupPercent
/// для этой строки пропускается.
public bool RetailPriceManuallyOverridden { get; set; }
/// Розничная цена, которую пользователь вписал в колонке «Розничная»
/// строки приёмки. Применяется к Product.Prices[default] при Posting.
public decimal? RetailPriceOverride { get; set; }
}