Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
63 lines
5.7 KiB
Markdown
63 lines
5.7 KiB
Markdown
# Доработки сервера для iOS «FM Склад» — прогресс
|
||
|
||
Автономная задача владельца (08.10.2026). Приложение (SwiftUI) на Маке владельца
|
||
использует API стенда; серверу не хватает ряда возможностей. Стенд — не трогаем прод.
|
||
|
||
## План (пункты владельца)
|
||
1. [x] `/api/inventory/stock?groupId=` — фильтр по группе с вложенными подгруппами
|
||
(через денормализованный `ProductGroup.Path`, helper `DescendantGroupIdsAsync`).
|
||
2. [x] POST `/api/catalog/products/{id}/barcodes` {code, kind} — добавление штрихкода,
|
||
уникальность в орг (`(OrganizationId,Code)`), 409 «штрихкод уже у товара X» + название,
|
||
идемпотентно при повторе тому же товару, 400 на пустой, автоопределение типа по длине.
|
||
3. [x] `/api/me` → `permissions` (эффективные флаги `RolePermissions` с учётом роли и
|
||
простого/расширенного режима; единый источник `RolePermissions.Effective`). Веб —
|
||
хук `useCan()` на том же источнике (раньше гейтил по именам ролей/advancedMode).
|
||
4. [x] Офлайн-каталог (`ProductSyncDto`): добавлен явный `isWeighed` (+ уже были `packaging`,
|
||
`unitCode`).
|
||
5. [x] Весовые этикетки: настройки организации (`WeightBarcode*`: enabled/префиксы веса/
|
||
префиксы цены/длина кода), миграция Phase35; парсер вынесен в
|
||
`food-market.shared/Barcodes/WeightedBarcode` (кассы pos.core делегирует туда);
|
||
`by-barcode` разбирает весовую этикетку → товар + количество (вес) / встроенная цена.
|
||
`GET/PUT /api/organization/settings` отдаёт/принимает настройки (round-trip-safe).
|
||
6. [x] Тесты: unit 10 (WeightedBarcode + RolePermissions.Effective) + 4 integration
|
||
(группа/штрихкод/me-права/весовая этикетка); `docs/mobile-api.md`. Деплой на стенд — см. ниже.
|
||
|
||
НЕ трогать: прод, shared-postgres, global.json, gateway nginx, sklad. — соблюдено.
|
||
|
||
## Изученная база
|
||
- `/api/inventory/stock` — `StockController.GetStock` (storeId/productId/search/includeZero/
|
||
page/sort). Группы: `ProductGroup` иерархична, есть денормализованный `Path`
|
||
(«Родитель/Дочь/Внук») → фильтр по вложенным через префикс Path.
|
||
- Штрихкоды: `ProductBarcode(Code, Type:BarcodeType, IsPrimary)`, уникальный индекс
|
||
`(OrganizationId, Code)`. Поиск — `GET /api/catalog/products/by-barcode/{value}` и `quick-search`.
|
||
- `/api/me` — minimal-endpoint в `Program.cs`: sub/name/email/roles/orgId/hasLiveOrg/
|
||
hasActiveEmployee/advancedMode. Прав (RolePermissions) НЕ отдаёт.
|
||
- Права: `RolePermissions` (флаги) на роль сотрудника; `PermissionAuthorizationHandler`
|
||
(SuperAdmin/Admin → все; иначе роль активного Employee). `RequiresAdvancedMode` гейтит
|
||
модули Demands/Transfers/Loyalty/Promotions/PriceTypes/ABC/Audit/Telegram/Presets.
|
||
Веб гейтит по именам ролей + `advancedMode` (дублирование — свести к единому источнику).
|
||
- POS-синк каталога: `ProductSyncDto` (есть `Packaging` 1/2/3 + `UnitCode`), нужен явный `IsWeighed`.
|
||
- Весовой парсер уже есть в `pos.core/Logic/BarcodeParser.cs` (префикс 20–24 вес, 25–29 цена) —
|
||
вынести в `food-market.shared`, сделать настраиваемым, использовать и на сервере, и в кассе.
|
||
- Миграции — ручные Phase-файлы (raw SQL, IF NOT EXISTS) с `[DbContext]`+`[Migration]`.
|
||
|
||
## Итог
|
||
Все 6 пунктов выполнены. Тесты зелёные: 10 unit (WeightedBarcode + RolePermissions.Effective)
|
||
+ 4 integration (группа/штрихкод/me-права/весовая этикетка) + регресс POS 9/9. Задеплоено на
|
||
стенд (`~/deploy-stage.sh`): guard isolation OK, api+web собраны/запушены, stage-api Healthy,
|
||
миграция Phase35 применена (4 колонки `WeightBarcode*` в `organizations` на stage-БД проверены),
|
||
https://test.admin.food-market.kz OK. Прод/shared-postgres/global.json/gateway/sklad — не трогали.
|
||
|
||
Для мобильного клиента см. `docs/mobile-api.md`.
|
||
|
||
## Коммиты
|
||
- `5173eaa` feat(catalog): штрихкоды товара — добавление + весовые этикетки
|
||
- `7231c83` feat(inventory): фильтр остатков по группе товаров с вложенными
|
||
- `2a4ba14` feat(auth): эффективные права пользователя в /api/me (единый источник)
|
||
- `1400106` test(mobile-api): unit + integration доработок для «FM Склад»
|
||
- `ad812ee` docs(mobile-api): описание API для мобильного клиента + прогресс
|
||
|
||
## Журнал
|
||
- 08.10 — старт; изучена база; план зафиксирован.
|
||
- 08.10 — реализованы все 6 пунктов; 14 новых тестов зелёные; деплой на стенд, миграция применена.
|