food-market/docs/simple-mode.md
nns 828080c321 rebrand: пользовательские доки + скриншоты кассы с новым лого
- docs/imports.md, docs/simple-mode.md: «Food Market» → «ALL MARKET».
- Перегенерированы скриншоты кассы (вход/продажа/оплата/смена/возврат) с
  логотипом ALL MARKET в шапке и на экране входа.
- Внутренние TZ/verify-доки оставлены как историческая фиксация.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 17:35:15 +05:00

155 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Simple / Advanced mode
Sprint 29, 2026-10-04.
ALL MARKET по умолчанию работает в «простом» режиме — виден только
минимальный набор функций розничного учёта, достаточный для
обычного магазина у дома. «Расширенный» режим включает дополнительные
модули (оптовые отгрузки, перемещения, лояльность и т.д.) и доступен
только после явного включения оператором платформы (SuperAdmin).
Переключатель в настройках магазина отсутствует намеренно —
администратор организации не может ни включить, ни выключить
расширенный режим себе сам.
## Простой режим — что видно
| Раздел | Что внутри |
|---|---|
| **Главная** | KPI «Выручка сегодня / неделя / месяц», средний чек, график продаж, «Последние продажи», «Низкий остаток». |
| **Товары** | Карточка товара без артикула (генерируется автоматически), описания, нескольких типов цен, страны происхождения, НДС-галок, «Услуги», «Маркируемый», максимального остатка. Остаются: Название, Штрихкоды, Группа, Единица измерения, Цена продажи (одна), Себестоимость (только чтение), Минимальный остаток, Фасовка (шт/вес/разливной), Фото. |
| **Группы товаров** | Полный доступ. |
| **Единицы измерения** | Полный доступ. |
| **Контрагенты** | Единый список. Поля: Название, Тип лица, БИН/ИИН, Адрес, Телефон, Заметки. |
| **Склад** | Приёмка, Оприходование, Списание, Инвентаризация, Возврат поставщику, Остатки. |
| **Продажи** | Продажи (POS), Возвраты покупателей. |
| **Отчёты** | Продажи, Прибыль, Остатки на дату. |
| **Настройки** | Магазин, Склады, Кассы (RetailPoints), Сотрудники, Роли, ОФД, Импорт товаров (CSV / 1С / МойСклад). |
| **Профиль** | Смена пароля, 2FA. |
Весь интерфейс по-русски (переключателя языка нет).
## Расширенный режим — что добавляется
- Оптовые отгрузки (`Demand`)
- Перемещения между точками (`Transfer`)
- Лояльность — программы и карты
- Промокоды / акции
- ABC-анализ
- Аудит организации (`/audit-log`)
- Несколько типов цен (не только retail)
- Bulk-операции в таблицах + сохранённые пресеты фильтров
- Telegram-бот владельца (ежедневная сводка)
- SSO (вход через Google / Microsoft)
- Выбор языка
- Виджеты «Топ товаров» и «Маржа» на дашборде
На карточках/документах появляются дополнительные поля из `Organization`
(«Описание», «Эталонная цена», «Валюта закупки», «НДС», «Услуга»,
«Маркируемый», «Макс. остаток»), которые управляются существующими
org-level `Show*` флагами.
## Как SuperAdmin включает / выключает
### Через API
```http
PUT /api/super-admin/organizations/{id}/advanced-mode
Authorization: Bearer <token>
Content-Type: application/json
{ "enabled": true }
```
Ответ `200 OK`:
```json
{ "id": "...", "isAdvancedMode": true, "changed": true }
```
Повторный вызов с тем же состоянием → `changed: false` и запись в
аудит **не** делается (идемпотентность).
Переключение архивной организации → `409 Conflict`.
Эндпоинт разрешён только роли `SuperAdmin`; админ орги получает `403`.
### Через SuperAdmin UI
1. Открыть `/super-admin/organizations`.
2. В списке у каждой строки колонка **«Режим»** — бейдж «Простой»
(slate) или «Расширенный» (violet).
3. В экшн-колонке рядом с «Архивировать» — иконка-искра. Клик →
модалка подтверждения с описанием последствий.
4. Подтверждение → `PUT` на эндпоинт выше. После успеха список
автоматически перегружается.
### Запись в журнал
Каждое реальное переключение пишется в `super_admin_audit_log`:
```json
{
"actionType": "EnableAdvancedMode", // или DisableAdvancedMode
"organizationId": "...",
"description": "Включен расширенный режим «Org Name»",
"changesJson": { "before": false, "after": true },
"ipAddress": "...",
"superAdminUserId": "..."
}
```
Просмотр: `/super-admin/audit-log?organizationId=...` или UI
«SuperAdmin → Журнал».
## Что происходит с данными при выключении
**Ничего не удаляется.** Серверный фильтр
`[RequiresAdvancedMode]` возвращает `403 ProblemDetails` на скрытых
эндпоинтах; данные остаются в БД. При повторном включении всё снова
видно и доступно без миграций и восстановлений.
Пример `ProblemDetails` при 403:
```json
{
"type": "https://food-market.kz/errors/advanced-mode-required",
"title": "Функция доступна в расширенном режиме.",
"detail": "Этот раздел недоступен в простом режиме магазина. Обратитесь к администратору платформы, чтобы включить расширенный режим.",
"status": 403,
"instance": "/api/sales/demands",
"code": "advanced-mode-required"
}
```
Для UI это достаточный маркер, чтобы отличить этот 403 от обычного
«нет прав» и отрисовать страницу «Недоступно в простом режиме» вместо
общего сообщения.
## Как это устроено на бэкенде (кратко)
- `Organization.IsAdvancedMode` (bool, default `false`) — миграция
`20261004100000_Phase29a_IsAdvancedMode`.
- `[RequiresAdvancedMode]` — атрибут MVC
(`TypeFilterAttribute` → `AdvancedModeFilter : IAsyncAuthorizationFilter`),
читает флаг по `org_id`-claim через `AppDbContext`.
SuperAdmin bypass; аноним пропускается (отработает `[Authorize]`).
Кэш in-memory 30 с, инвалидация после переключения.
- Список скрытых контроллеров / действий —
см. `docs/simple-mode-progress.md` (шаг 3).
- `/api/me` расширен полем `advancedMode: boolean`.
Веб:
- `useMe()` отдаёт `advancedMode`.
- `AppLayout.buildNav(roles, advancedMode)` фильтрует меню.
- `AdvancedModeGuard` оборачивает скрытые маршруты и показывает
«Недоступно в простом режиме» вместо белого экрана / 403 в консоли.
- Карточка товара, контрагенты и приёмка в простом режиме прячут
advanced-поля; значения существующих записей сохраняются и при
переключении режима снова видны.
## Тесты
- Unit: `tests/food-market.UnitTests/AdvancedModeFilterTests.cs` (6/6).
- Integration: `tests/food-market.IntegrationTests/AdvancedModeTests.cs` (7/7).
- E2E: `tests/e2e/scenarios/stage-simple-mode.yml` (7/7 на стейдже).