food-market/src/food-market.domain/Purchases/Supply.cs
nns 6acf6b7c03 feat(domain): pricing model rename and new fields (Phase3a)
Подготовка к новой модели цен сторонняя система-style:
- Product.PurchasePrice → ReferencePrice (справочная закупочная,
  не обязательная). + ReferencePriceUpdatedAt для 30-дневного таймера.
- Product.+ Cost numeric(18,4) — себестоимость по скользящему среднему.
- Product.+ LastSupplyAt — UTC последней Posted приёмки.
- ProductGroup.+ MarkupPercent (5,2) — % наценки на cost для авто-розничной.
- Organization.+ MultiplePriceTypesEnabled (default false) и
  ShowReferencePriceOnProduct (default true).
- SupplyLine.+ RetailPriceManuallyOverridden + RetailPriceOverride —
  отметка ручной правки розничной в строке приёмки.

Миграция Phase3a_PricingModel: RENAME + AddColumn'ы. Logic перерасчёта
себестоимости, автонаценки, recalc-endpoint и Hangfire job — следующими
коммитами.

DTO/контроллеры/OtherSystem-импорт/UI поля переименованы в referencePrice
(включая фильтры списка товаров). UI-логика следующего коммита будет
показывать Cost и кнопку «привести розничную к себестоимости»; пока
referencePrice работает как раньше.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:59:09 +05:00

65 lines
2.2 KiB
C#

using foodmarket.Domain.Catalog;
using foodmarket.Domain.Common;
namespace foodmarket.Domain.Purchases;
public enum SupplyStatus
{
Draft = 0,
Posted = 1,
}
public class Supply : TenantEntity
{
/// <summary>Human-readable document number, unique per organization (e.g. "П-2026-000001").</summary>
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? SupplierInvoiceNumber { get; set; }
public DateTime? SupplierInvoiceDate { get; set; }
public string? Notes { get; set; }
/// <summary>Sum of line totals. Computed on save.</summary>
public decimal Total { get; set; }
public DateTime? PostedAt { get; set; }
public Guid? PostedByUserId { get; set; }
public ICollection<SupplyLine> Lines { get; set; } = new List<SupplyLine>();
}
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; }
/// <summary>Если true — пользователь вручную задал розничную цену для
/// этой строки (через UI приёмки). При Posting автонаценка по Group.MarkupPercent
/// для этой строки пропускается.</summary>
public bool RetailPriceManuallyOverridden { get; set; }
/// <summary>Розничная цена, которую пользователь вписал в колонке «Розничная»
/// строки приёмки. Применяется к Product.Prices[default] при Posting.</summary>
public decimal? RetailPriceOverride { get; set; }
}