From d1a7e1e647f75cb771d9bcd4ea55e8003f795f5d Mon Sep 17 00:00:00 2001 From: nns <278048682+nurdotnet@users.noreply.github.com> Date: Sat, 25 Apr 2026 12:23:45 +0500 Subject: [PATCH] =?UTF-8?q?ui(products-list):=20=D1=83=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=20=C2=AB?= =?UTF-8?q?=D0=A1=D0=BE=20=D1=88=D1=82=D1=80=D0=B8=D1=85=D0=BA=D0=BE=D0=B4?= =?UTF-8?q?=D0=BE=D0=BC=C2=BB,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=C2=AB=D0=97=D0=B0=D0=BA=D1=83=D0=BF=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D0=B0=D1=8F=20=D1=86=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=82/?= =?UTF-8?q?=D0=B4=D0=BE=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Поскольку штрихкод теперь обязательный (минимум 1 у каждого товара), фильтр «Со штрихкодом» бессмыслен — убран из UI и контроллера. Вместо него — два MoneyInput «Закупочная цена от/до» в панели фильтров. Использует символ валюты по умолчанию из настроек организации и уважает AllowFractionalPrices. Backend: ProductsController.List принимает purchasePriceFrom / purchasePriceTo (decimal?), применяет ≥ / ≤ к PurchasePrice; параметр hasBarcode удалён. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Controllers/Catalog/ProductsController.cs | 7 ++-- .../src/pages/ProductsPage.tsx | 37 ++++++++++++++++--- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/food-market.api/Controllers/Catalog/ProductsController.cs b/src/food-market.api/Controllers/Catalog/ProductsController.cs index 43acfc0..1e0acca 100644 --- a/src/food-market.api/Controllers/Catalog/ProductsController.cs +++ b/src/food-market.api/Controllers/Catalog/ProductsController.cs @@ -79,7 +79,8 @@ private async Task ResolveDefaultVatAsync(CancellationToken ct) [FromQuery] Packaging? packaging, [FromQuery] bool? isMarked, [FromQuery] bool? isActive, - [FromQuery] bool? hasBarcode, + [FromQuery] decimal? purchasePriceFrom, + [FromQuery] decimal? purchasePriceTo, CancellationToken ct) { var q = QueryIncludes().AsNoTracking(); @@ -102,8 +103,8 @@ private async Task ResolveDefaultVatAsync(CancellationToken ct) if (packaging is not null) q = q.Where(p => p.Packaging == packaging); if (isMarked is not null) q = q.Where(p => p.IsMarked == isMarked); if (isActive is not null) q = q.Where(p => p.IsActive == isActive); - if (hasBarcode is not null) - q = hasBarcode == true ? q.Where(p => p.Barcodes.Any()) : q.Where(p => !p.Barcodes.Any()); + if (purchasePriceFrom is not null) q = q.Where(p => p.PurchasePrice >= purchasePriceFrom); + if (purchasePriceTo is not null) q = q.Where(p => p.PurchasePrice <= purchasePriceTo); if (!string.IsNullOrWhiteSpace(req.Search)) { diff --git a/src/food-market.web/src/pages/ProductsPage.tsx b/src/food-market.web/src/pages/ProductsPage.tsx index ed6e9ff..fbbfe48 100644 --- a/src/food-market.web/src/pages/ProductsPage.tsx +++ b/src/food-market.web/src/pages/ProductsPage.tsx @@ -8,6 +8,7 @@ import { Plus, Filter, X, FolderTree } from 'lucide-react' import { useCatalogList } from '@/lib/useCatalog' import { useOrgSettings } from '@/lib/useOrgSettings' import { ProductGroupTree } from '@/components/ProductGroupTree' +import { MoneyInput } from '@/components/Field' import { packagingLabel, type Product } from '@/lib/types' const URL = '/api/catalog/products' @@ -20,7 +21,8 @@ interface Filters { isService: TriFilter packaging: number | null // null = все, 1/2/3 = Piece/Weight/Liquid isMarked: TriFilter - hasBarcode: TriFilter + purchasePriceFrom: number | null + purchasePriceTo: number | null } const defaultFilters: Filters = { @@ -29,7 +31,8 @@ const defaultFilters: Filters = { isService: 'all', packaging: null, isMarked: 'all', - hasBarcode: 'all', + purchasePriceFrom: null, + purchasePriceTo: null, } const toExtra = (f: Filters): Record => { @@ -39,7 +42,8 @@ const toExtra = (f: Filters): Record { if (f.isService !== 'all') n++ if (f.packaging) n++ if (f.isMarked !== 'all') n++ - if (f.hasBarcode !== 'all') n++ + if (f.purchasePriceFrom != null) n++ + if (f.purchasePriceTo != null) n++ return n } @@ -217,7 +222,29 @@ export function ProductsPage() { {showMarked && ( { setFilters({ ...filters, isMarked: v }); setPage(1) }} /> )} - { setFilters({ ...filters, hasBarcode: v }); setPage(1) }} yesLabel="есть" noLabel="нет" /> +
+ Закупочная цена +
+ { setFilters({ ...filters, purchasePriceFrom: n }); setPage(1) }} + currencyCode={org.data?.defaultCurrencyCode ?? undefined} + currencySymbol={org.data?.defaultCurrencySymbol ?? undefined} + allowFractional={org.data?.allowFractionalPrices ?? false} + placeholder="от" + /> +
+
+ { setFilters({ ...filters, purchasePriceTo: n }); setPage(1) }} + currencyCode={org.data?.defaultCurrencyCode ?? undefined} + currencySymbol={org.data?.defaultCurrencySymbol ?? undefined} + allowFractional={org.data?.allowFractionalPrices ?? false} + placeholder="до" + /> +
+
{activeCount > 0 && (