food-market/docs/glossary.md
nns 72d0a71307
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
docs(s24): docs cross-check + auto-gen + onboarding + test gap-fill (8/8 ✓)
1. Docs cross-check — обновил performance-baseline.md (Sprint 18/20/23
   фиксы), secrets.md (16 новых env-vars из Sprint 20+ — Authentication
   Google/Microsoft, Monitoring, Cleanup, Hangfire:Cron, Telegram,
   Maintenance, App, Storage, PUBLIC_GA_ID/YM_ID).

2. Auto-gen api-reference — ApiReferenceDocsJob (Hangfire weekly вс
   05:30 UTC) + Python-эквивалент `/tmp/gen-api-ref.py` для commit
   actual snapshot. docs/api-reference.md = 195 endpoints, 57 controllers.

3. Coverage gap-fill — Sprint18To23FeaturesTests.cs (16 Facts):
   - bulk-update + cross-tenant isolation
   - UserPresets CRUD
   - inline-edit price PATCH
   - CSV import 2 строки транзакцией
   - OrgExport create + list isolation
   - 1C-CSV import с русскими заголовками
   - audit-log export CSV streaming + BOM check
   - MoySklad sync-status stub
   - SSO providers + 503 unconfigured + 400 unknown provider
   - bug-001 NUL byte → 400
   - bug-004 tiny price → 400
   - export CSV BOM
   Покрывает все новые контроллеры Sprint 18-23 + regression-protect
   для критичных багов.

4. Contract tests — deploy/swagger-diff.sh: pull /swagger/v1/swagger.json
   с двух URL, diff endpoints+schemas через python3. Exit 0/1/2 для
   blue-green safety gate. Multi-path auto-detect.

5. docs/error-codes.md — каталог HTTP-кодов API (200-503) + humanizeError
   pattern для фронта + retry-policy таблица.

6. docs/glossary.md — 50+ доменных терминов (Tenant/Organization/Stock/
   StockMovement/RetailSale/Counterparty/Owner/Employee/Role/Permission/
   advisory lock/Serializable/…) с ссылками на code-сущности.

7. docs/ONBOARDING.md — first 3 days для нового разработчика
   (install → запуск → структура → первый PR + FAQ).

8. README.md — обновил под текущее состояние: React 19, Sprint-history
   1-24, ссылки на ключевые docs, корректный 5-min quick start.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 02:15:56 +05:00

13 KiB
Raw Permalink Blame History

Глоссарий food-market

Доменные термины, которые используются в коде, документации и общении с пользователями. Один термин — одно определение. Ссылки на код через file:line или namespace.path.

Базовые сущности

Organization (Организация, tenant)

Корневая сущность мульти-tenancy. Один процесс API обслуживает много организаций; каждая видит только свои данные через query-filter по OrganizationId. Не tenant-scoped сама по себе (отношение «один-ко-многим» с TenantEntity). Code: foodmarket.Domain.Organizations.Organization (src/food-market.domain/Organizations/Organization.cs). См. MULTI-TENANCY.md.

TenantEntity / ITenantEntity

Базовый класс/интерфейс для всех domain-сущностей с OrganizationId. AppDbContext автоматически применяет query-filter по reflection. Code: foodmarket.Domain.Common.TenantEntity + ITenantEntity.

IOptionalTenantEntity

Двухуровневые справочники: либо системная запись (OrganizationId=null, видна всем, мутирует только SuperAdmin), либо tenant'овская. Пример: UnitOfMeasure, ProductGroup — есть глобальные «штука», есть кастомные.

User

Учётная запись для логина (ASP.NET Identity). НЕ привязан к одной org — один email может работать в нескольких организациях через Employee. Code: foodmarket.Domain.Identity.User.

Employee (Сотрудник)

Запись о работнике конкретной org. Может иметь User (для логина) или быть «без аккаунта» (только в чеках/документах). Связан с EmployeeRole. Code: foodmarket.Domain.Organizations.Employee.

Owner / AccountOwnerUserId

Первый пользователь, создавший org через signup. Хранится в Organization.AccountOwnerUserId. Не удаляется (кроме как через SuperAdmin reassign).

Role / EmployeeRole / RolePermissions

  • Identity Role (ASP.NET) — системная: SuperAdmin, Admin, Cashier, Storekeeper, Manager.
  • EmployeeRole — per-org кастомная роль (например, «Старший кассир»), привязана к сотруднику. Имеет RolePermissions (флаги типа ProductsEdit, RetailSalesOperate).
  • Permission — атрибут [RequiresPermission("Name")] на endpoint'е. Проверяет RolePermissions сотрудника текущего юзера.

Store (Склад)

Физическое место хранения остатков. У org может быть несколько; первый после signup — «MAIN» store. Code: foodmarket.Domain.Organizations.Store.

RetailPoint (Касса / торговая точка)

Привязана к Store, к ней привязывается RetailSale. Может иметь фискальные поля (FiscalSerial, FiscalRegNumber). Code: foodmarket.Domain.Organizations.RetailPoint.

Каталог

Product (Товар)

Единица каталога. Имеет несколько Prices (по типам), Barcodes, Images, принадлежит ProductGroup. Поля Sprint 19: IsArchived, IsAvailableForSale. Code: foodmarket.Domain.Catalog.Product.

ProductGroup (Группа товаров)

Иерархическая (через ParentId + Path). Корень — «Все товары». Может быть системной (OrganizationId=null) или per-org. Code: foodmarket.Domain.Catalog.ProductGroup.

ProductPrice (Цена)

Один товар × один PriceType = одна цена. Тип может быть «системным» (IsSystem — основная розничная) или «обязательным» (IsRequired — без неё нельзя сохранить товар). Code: foodmarket.Domain.Catalog.ProductPrice.

PriceType (Тип цены)

Розничная / Закупочная / Базовая / Себестоимость и т.д. Per-org. Sprint 1. Code: foodmarket.Domain.Catalog.PriceType.

ProductBarcode (Штрихкод)

Уникальный (составной UNIQUE: Code + Organization). Один товар может иметь несколько штрихкодов; один из них — IsPrimary (показывается на этикетке). Code: foodmarket.Domain.Catalog.ProductBarcode.

UnitOfMeasure (Единица измерения)

шт / кг / л / м / упак. Системные (OrganizationId=null) + org-кастомные. OrgUnitOfMeasure — таблица per-org enable/disable. Code: foodmarket.Domain.Catalog.UnitOfMeasure.

Counterparty (Контрагент)

Поставщик (Supplier) / Покупатель-юрлицо (LegalEntity) / Покупатель-физлицо (Individual). Имеет БИН/ИИН, банковские реквизиты, контакты. Code: foodmarket.Domain.Catalog.Counterparty.

Остатки и движения

Stock (Остаток)

Кеш SUM(StockMovement.Quantity) для пары (Store, Product). Поддерживается транзакционно в каждом posting'е документа. Code: foodmarket.Domain.Inventory.Stock.

StockMovement (Движение остатка)

Имматериальная запись об изменении остатка. Source: документ (Supply.Post / RetailSale.Post / Enter.Post / Loss.Post / Transfer.Post / Inventory.Post / SupplierReturn.Post / CustomerReturn.Post). Инвариант: Stock.Quantity ≡ Σ StockMovement.Quantity для каждой пары (Store, Product). Проверяется property-test'ом (Sprint 15). Code: foodmarket.Domain.Inventory.StockMovement.

Документы (Documents)

Все имеют поля: Number, Date, Status (Draft/Posted), PostedAt. Имеют IVersionedEntity для xmin concurrency check.

Supply (Приёмка)

От поставщика. Увеличивает остаток + пересчитывает скользящую себестоимость (Product.Cost). Code: foodmarket.Domain.Purchases.Supply.

Enter (Оприходование)

Внутреннее. Увеличивает остаток без поставщика. Для коррекций инвентаризации. Code: foodmarket.Domain.Inventory.Enter.

Loss (Списание)

Уменьшает остаток. Причина: порча, кража, тестовое использование. Code: foodmarket.Domain.Inventory.Loss.

Transfer (Перемещение)

Между складами. Уменьшает на исходном, увеличивает на целевом. Code: foodmarket.Domain.Inventory.Transfer.

Inventory (Инвентаризация)

Списки фактических остатков. Расхождение → автоматические Enter/Loss строки при post. Code: foodmarket.Domain.Inventory.InventoryDoc (имя класса не Inventory из-за конфликта с namespace).

RetailSale (Розничный чек)

Продажа через POS / админку. После Post → уменьшает остаток, пишет ОФД снапшот (FiscalNumber etc., Sprint 11), уведомляет SignalR. Code: foodmarket.Domain.Sales.RetailSale.

Demand (Оптовая отгрузка)

Продажа юрлицу. Аналогично RetailSale, но с накладной (печатной формой). Code: foodmarket.Domain.Sales.Demand.

SupplierReturn (Возврат поставщику)

Sprint 5. Уменьшает остаток + возвращает деньги поставщику. Code: foodmarket.Domain.Purchases.SupplierReturn.

CustomerReturn / RetailSale.IsReturn=true

Возврат от покупателя. Реализован через флаг IsReturn на RetailSale + ReferenceSaleId. Восстанавливает остаток.

Деньги

Cost (Себестоимость)

Скользящее среднее (qty_old × cost_old + qty_in × price_in) / (qty_old + qty_in). Пересчитывается на каждой проведённой Supply. Decimal(18,4).

ReferencePrice (Эталонная цена закупа)

Опциональная. Заполняется автоматически unit-price'ом первой Supply; после 30 дней без новых Supply → Hangfire-job переписывает на Cost.

VAT (НДС)

  • Product.Vat (default из Country.VatRate, в РК — 12%).
  • Product.VatEnabled — управляет видимостью поля на UI.
  • На документах: VatMode (включается «в том числе» / «сверху»).

AllowFractionalPrices (Дробные цены)

Org-настройка. Если false → все цены округляются до целых при сохранении. Sprint 23 bug-004: round-then-validate чтобы избежать «0 цена прошла required-check».

Доступ и безопасность

Tenant context

ITenantContext (resolved per request) выдаёт OrganizationId из JWT claim org_id. NULL для unauthenticated / SuperAdmin-без-override.

SuperAdmin

Системная роль. Видит все organizations + может «открыть как…» через X-Org-Override header (включает Admin claim для этой org'и). Все действия SuperAdmin'a в override-режиме пишутся в super_admin_audit_log.

OrgAuditLog

Per-tenant журнал каждой mutate-операции (CREATE/UPDATE/DELETE на любую TenantEntity). Пишется автоматически через OrgAuditInterceptor на SaveChanges.

Permission

Атрибут [RequiresPermission("ProductsEdit")] на endpoint'е. Проверяет флаг RolePermissions сотрудника текущего юзера. Если у юзера нет Employee в этой org — 403.

Фоновые операции

Hangfire job

.NET background job framework. recurring-job (по cron) и background-job (одноразовый). Хранятся в схеме hangfire той же БД.

advisory lock (Sprint 18)

PostgreSQL pg_advisory_xact_lock(int, int) — кооперативная блокировка per-(org, doctype). Используется для сериализации генерации номера документа.

Serializable transaction

PostgreSQL Isolation Level. Используется в posting'ах документов (RetailSale.Post, Supply.Post, etc.) для защиты от race на остатках. На конфликте → 40001, теперь мапится в 409 (Sprint 23).

Внешние интеграции

ОФД (OFD)

Оператор Фискальных Данных. В РК: Webkassa, Kassa24, ОФД-Соло. RetailSale.Post после успеха отправляет фискальный документ → получает FiscalNumber, FiscalQrCode. Sprint 11 scaffolding.

МойСклад

Сторонняя SaaS-система учёта. Импорт товаров/контрагентов/остатков по OAuth-token (per-org в Organization.MoySkladToken).

POS (касса)

WPF-приложение под Windows 10+. Локальный SQLite-буфер, синк через /api/pos/v1/* с idempotency-ключом (см. pos_batch_acks).

Telegram bot

Один platform-bot (token в env). Owner'ы org'и привязывают свой chat-id (Organization.OwnerTelegramChatId) для получения daily-сводки.

Тестирование

Stage

https://test.admin.food-market.kz. Контейнеры на prod-vm 192.168.1.190, deploy через ~/deploy-stage.sh.

Smoke / Regression / Verify

  • Smoke — быстрый sanity-check (5 шагов signup → login → bootstrap).
  • Regression — полный e2e через Playwright (44 spec'a в Sprint 23).
  • Verify — спринт-специфичные post-feature тесты.

Сокращения

Сокр Что
AT Access Token (JWT, TTL 1h)
RT Refresh Token (для получения нового AT)
PoS Point of Sale (касса)
ОФД Оператор Фискальных Данных
БИН 12-цифровой номер юрлица в РК
ИИН 12-цифровой номер физлица в РК
RPO Recovery Point Objective (макс. потеря данных при backup-restore)
RTO Recovery Time Objective (время восстановления)
CSP Content Security Policy (HTTP-header)
SA SuperAdmin