- Избранное: Product.IsFavorite/FavoriteOrder (миграция Phase37), в POS-синке (ProductSyncDto) и в карточке товара (ProductInput). Касса: PosStore хранит флаг (+ALTER для старых БД) и GetFavorites(); на экране продажи — сворачиваемая сетка плиток «быстрых товаров» (товары без штрихкода: хлеб, овощи на вес), тап добавляет в чек. Unit-тест GetFavorites (порядок/фильтр). 44 POS unit зелёные. - Тёмная тема — опция: кнопка-переключатель в шапке (ToggleTheme), выбор сохраняется на устройстве (kv device.theme), применяется при старте. На тех же токенах (ThemeDictionaries Light/Dark). По умолчанию — светлая. Кадр «тёмная тема» в галерее. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
105 lines
5 KiB
C#
105 lines
5 KiB
C#
using System.ComponentModel.DataAnnotations;
|
||
using foodmarket.Domain.Catalog;
|
||
|
||
namespace foodmarket.Application.Catalog;
|
||
|
||
public record CountryDto(
|
||
Guid Id, string Code, string Name,
|
||
Guid? DefaultCurrencyId, string? DefaultCurrencyCode, string? DefaultCurrencySymbol,
|
||
decimal VatRate);
|
||
|
||
|
||
public record CurrencyDto(Guid Id, string Code, string Name, string Symbol);
|
||
|
||
public record UnitOfMeasureDto(
|
||
Guid Id, string Code, string Name, Guid? OrganizationId,
|
||
bool IsActive = true, bool IsEnabledForOrg = true);
|
||
|
||
public record PriceTypeDto(
|
||
Guid Id, string Name, bool IsRequired, bool IsSystem,
|
||
bool IsRetail, int SortOrder);
|
||
|
||
public record StoreDto(
|
||
Guid Id, string Name, string? Code, string? Address, string? Phone,
|
||
string? ManagerName, bool IsMain, bool IsActive);
|
||
|
||
public record RetailPointDto(
|
||
Guid Id, string Name, string? Code, Guid StoreId, string? StoreName,
|
||
string? Address, string? Phone, string? FiscalSerial, string? FiscalRegNumber, bool IsActive);
|
||
|
||
public record ProductGroupDto(
|
||
Guid Id, string Name, Guid? ParentId, string Path, int SortOrder,
|
||
decimal? MarkupPercent, Guid? OrganizationId);
|
||
|
||
public record CounterpartyDto(
|
||
Guid Id, string Name, string? LegalName, CounterpartyType Type,
|
||
string? Bin, string? Iin, string? TaxNumber, Guid? CountryId, string? CountryName,
|
||
string? Address, string? Phone, string? Email,
|
||
string? BankName, string? BankAccount, string? Bik, string? ContactPerson, string? Notes,
|
||
// Port sklad 06.10 §11: служебный «Поставщик не указан». UI сортирует
|
||
// в конец списка и ставит бейдж «служебный», delete запрещён на сервере.
|
||
bool IsPlaceholder = false);
|
||
|
||
public record ProductBarcodeDto(Guid Id, string Code, BarcodeType Type, bool IsPrimary);
|
||
|
||
public record ProductPriceDto(Guid Id, Guid PriceTypeId, string PriceTypeName, decimal Amount, Guid CurrencyId, string CurrencyCode);
|
||
|
||
public record ProductDto(
|
||
Guid Id, string Name, string? Article, string? Description,
|
||
Guid UnitOfMeasureId, string UnitName,
|
||
decimal Vat, bool VatEnabled,
|
||
Guid ProductGroupId, string ProductGroupName,
|
||
Guid? DefaultSupplierId, string? DefaultSupplierName,
|
||
Guid? CountryOfOriginId, string? CountryOfOriginName,
|
||
bool IsService, Packaging Packaging, bool IsMarked,
|
||
decimal? MinStock, decimal? MaxStock,
|
||
decimal? ReferencePrice, DateTime? ReferencePriceUpdatedAt,
|
||
Guid? PurchaseCurrencyId, string? PurchaseCurrencyCode,
|
||
decimal Cost, DateTime? LastSupplyAt,
|
||
string? ImageUrl,
|
||
// Sprint 19: bulk-операции «Архивировать» / «Снять с продажи».
|
||
bool IsArchived, bool IsAvailableForSale,
|
||
IReadOnlyList<ProductPriceDto> Prices,
|
||
IReadOnlyList<ProductBarcodeDto> Barcodes);
|
||
|
||
// Upsert payloads (input)
|
||
public record CountryInput(
|
||
string Code, string Name,
|
||
Guid? DefaultCurrencyId = null, decimal VatRate = 0m);
|
||
public record CurrencyInput(string Code, string Name, string Symbol);
|
||
public record UnitOfMeasureInput(string Code, string Name);
|
||
public record PriceTypeInput(
|
||
string Name, bool IsRequired = false,
|
||
bool IsRetail = false, int SortOrder = 0);
|
||
public record StoreInput(
|
||
string Name, string? Code,
|
||
string? Address = null, string? Phone = null, string? ManagerName = null,
|
||
bool IsMain = false, bool IsActive = true);
|
||
public record RetailPointInput(
|
||
string Name, string? Code, Guid StoreId,
|
||
string? Address = null, string? Phone = null,
|
||
string? FiscalSerial = null, string? FiscalRegNumber = null, bool IsActive = true);
|
||
public record ProductGroupInput(
|
||
string Name, Guid? ParentId, int SortOrder = 0,
|
||
[Range(0, 1000)] decimal? MarkupPercent = null);
|
||
public record CounterpartyInput(
|
||
string Name, string? LegalName, CounterpartyType Type,
|
||
string? Bin, string? Iin, string? TaxNumber, Guid? CountryId,
|
||
string? Address, string? Phone, string? Email,
|
||
string? BankName, string? BankAccount, string? Bik, string? ContactPerson, string? Notes);
|
||
public record ProductBarcodeInput(string Code, BarcodeType Type = BarcodeType.Ean13, bool IsPrimary = false);
|
||
public record ProductPriceInput(Guid PriceTypeId, [Range(0, 1e10)] decimal Amount, Guid CurrencyId);
|
||
public record ProductInput(
|
||
[Required, MinLength(1), StringLength(500)] string Name,
|
||
[StringLength(500)] string? Article,
|
||
string? Description,
|
||
Guid UnitOfMeasureId, [Range(0, 100)] decimal? Vat, bool VatEnabled,
|
||
Guid ProductGroupId, Guid? DefaultSupplierId, Guid? CountryOfOriginId,
|
||
bool IsService = false, Packaging Packaging = Packaging.Piece, bool IsMarked = false,
|
||
[Range(0, 1e10)] decimal? MinStock = null, [Range(0, 1e10)] decimal? MaxStock = null,
|
||
[Range(0, 1e10)] decimal? ReferencePrice = null, Guid? PurchaseCurrencyId = null,
|
||
[StringLength(1000)] string? ImageUrl = null,
|
||
IReadOnlyList<ProductPriceInput>? Prices = null,
|
||
IReadOnlyList<ProductBarcodeInput>? Barcodes = null,
|
||
bool IsFavorite = false, int FavoriteOrder = 0);
|