Подготовка к новой модели цен сторонняя система-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>
65 lines
2.2 KiB
C#
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; }
|
|
}
|