food-market/CHANGELOG.md
nns f56c6efab1 feat(s17): onboarding wizard + help kb + feedback + diagnostic + whats-new
Sprint 17 — onboarding-контур: 4-шаг wizard, контекстный help, in-app
feedback, admin self-diagnostic, /whats-new из CHANGELOG.md.

Ключевые цифры:
- Wizard: 4 шага + skip каждого, 7 e2e тестов ✓ за 20 секунд.
- Diagnostic: 7 параллельных проверок, ~80ms на stage.
- Bundle impact: initial +4 KB gzip (только FeedbackWidget +
  HelpTooltip + EmptyStateWithDemo в основном bundle; страницы lazy).
- Regression-suite: 35 → 42 flows + 60 → 66 visual snapshots.

Backend (новые endpoint'ы):
- /api/admin/diagnostic/run — 7 параллельных проверок (DB, SMTP,
  MinIO, Hangfire, диск, сертификаты, бэкап). Task.WhenAll, ~80ms.
- /api/feedback — POST {category, message}, email на FromEmail +
  Telegram (если SupportTelegram:* настроены). Rate-limit 5/час.
- /api/whats-new — парсер CHANGELOG.md, возвращает {buildVersion,
  items}. Dockerfile.api копирует CHANGELOG.md в content-root +
  пишет VERSION из GIT_SHA build-arg.

Frontend:
- /onboarding-wizard — 4-step builder, состояние в useState,
  localStorage.fm.wizardCompleted после завершения.
- <HelpTooltip topic="key"/> — popover на каждой странице, mapping
  src/lib/help-topics.ts (13 keys).
- /help — knowledge base, 7 markdown topics через import.meta.glob,
  mini-renderer без heavy deps, fuzzy search.
- /whats-new — список из /api/whats-new, иконки по типу (feat/fix).
- /admin/diagnostic — Admin/SuperAdmin only, 🟢/🟡/🔴 индикаторы.
- <FeedbackWidget> в sidebar footer + ссылки на /help и /whats-new.
- <EmptyStateWithDemo> placeholder для будущих видео-демо.

scripts/generate-changelog.sh — git log feat:/fix: за 90 дней
→ CHANGELOG.md (307 строк сгенерировано).

Wizard UX-screenshots в docs/sprint17-screenshots/ (6 PNG: 4 шага +
help + diagnostic).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 17:04:26 +05:00

308 lines
22 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.

# CHANGELOG
Auto-generated from git log feat:/fix: (last 90 days).
## 2026-06-07
- **feat**: security headers + rate-limits + sensitive-ops audit + session revoke + Grafana (s13)
- **feat**: ОФД-scaffolding — IFiscalProvider + 4 провайдера + UI/тесты (s11)
## 2026-06-06
- **feat**: dark mode полировка + Cmd+K палитра + аудит-spec (s10-4)
- **feat**: глобальная Cmd+K палитра + GET /api/search/global (s10-3)
- **feat**: year-demo seeder + 4 dashboard виджета + week-stats (s10)
## 2026-06-04
- **fix**: IP-limit 60/min, locale ru-RU в playwright, исправлены payload'ы verify-spec'ов (stage-tests)
- **fix**: per-username 5/мин + per-IP 30/мин — brute-force на конкретный аккаунт ловится, CI/NAT не страдают (rate-limit)
- **fix**: rate-limit 5/min на /connect/token, nginx route /metrics+/swagger, Swagger в Production через IncludeSwagger (stage)
## 2026-05-31
- **fix**: bump cache version + filter SignalR-race errors in PWA test (pwa)
- **fix**: SW не вмешивается в /hubs/* — SignalR negotiate сломался (pwa)
- **feat**: PWA owner read-only + mobile tweaks + S9 stage specs (pwa+mobile+s9)
- **fix**: убрать unused imports (TS6133) (loyalty)
- **feat**: P2-12 + P2-13 — лояльность и промокоды (Sprint 9 п.1-2) (loyalty+promotions)
- **feat**: IObjectStorage abstraction (Local + MinIO) — P2-15 (storage)
- **feat**: react-i18next ru/en + language switcher (P2-6a — базовая) (i18n)
- **feat**: OwnerDailySummaryJob + bot binding (P2-14) (telegram)
- **feat**: SignalR hub /hubs/notifications per-org + dashboard live (realtime)
## 2026-05-30
- **fix**: после create — invalidate list query (не показывался сразу) (employees)
- **fix**: error display через humanizeError, не «Request failed» (employees)
- **fix**: уберём cache-touch после Delete — просто navigate (catalog)
- **fix**: после Delete не refetch'аем удалённый товар (catalog)
- **fix**: ProductEditPage — race на currencies.data + читаемая ошибка (catalog)
- **fix**: Modal — role=dialog + aria-modal + aria-label на крестике (a11y)
- **fix**: useShortcuts — бэр-клавиши не зависят от Shift (web)
- **feat**: keyboard shortcuts на edit + list страницах + «?» overlay (web)
- **feat**: Breadcrumbs на edit-страницах (Каталог / Товары / Молоко 3.2%) (web)
- **feat**: Empty states с CTA на list-страницах (web)
- **feat**: loading skeletons вместо «Загрузка…» в DataTable + edit-pages (web)
- **feat**: toast-система — error на 4xx/5xx + success на мутации (через meta) (web)
- **feat**: ConfirmDialog компонент + useConfirm hook вместо window.confirm() (web)
- **feat**: demo-data seeder для test.admin.food-market.kz (stage)
## 2026-05-29
- **fix**: operationId + schemaId — генерация OpenAPI работает (swagger)
- **fix**: 3 фикса по итогам stage-тестирования (reports)
- **fix**: EF8 nav-collection bug в Enters/Losses/Transfers/SupplierReturns/Inventories.Update (docs)
- **fix**: EF8 nav-collection bug в Products.Update + unique IX на Article (catalog)
## 2026-05-28
- **feat**: TOTP 2FA для админов через AuthenticatorTokenProvider (P2-4) (auth)
- **feat**: MediatR partial — 3 handler-образца (TD-1) (cqrs)
- **feat**: структурные log-fields в Serilog (TD-4) (logging)
- **feat**: FluentValidation + ValidationFilter для DTO (TD-2) (validation)
- **feat**: RowVersion на документах через Postgres xmin (TD-6) (concurrency)
- **feat**: persisted ImportJobRegistry в БД (TD-5) (import-jobs)
- **feat**: HTML-шаблоны MailKit + invite/weekly/low-stock джобы (P1-22) (email)
- **feat**: per-tenant журнал мутаций OrgAuditLog (P1-18) (audit)
- **feat**: оптовая отгрузка контрагенту-юрлицу (P1-5) (demands)
- **feat**: Prometheus метрики /metrics + бизнес-счётчики (P1-17) (observability)
- **feat**: GET /sync и POST /sales с двойной идемпотентностью (P1-12b) (pos-api)
- **feat**: контракты POS v1 в food-market.shared (P1-12a) (pos-shared)
- **feat**: улучшенный Swagger + TS-клиент через openapi-typescript (P1-19) (openapi)
- **feat**: ABC-анализ по Парето (P1-11) (reports)
- **feat**: отчёт «Прибыль» (выручка COGS) (P1-10) (reports)
- **feat**: отчёт «Остатки на дату» с реконструкцией (P1-9) (reports)
- **feat**: отчёт «Продажи» с группировками и экспортом (P1-8) (reports)
- **feat**: dashboard + scheduled cleanup джобы (P1-16) (hangfire)
- **feat**: возврат поставщику (P1-7) (supplier-returns)
- **feat**: возврат от покупателя (CustomerReturn) (P1-6) (returns)
- **feat**: инвентаризация с CSV-импортом факта (P1-4) (inventories)
- **feat**: атомарное перемещение между складами (P1-3) (transfers)
- **feat**: списание со склада с указанием причины (P1-2) (losses)
- **feat**: оприходование товара без поставщика (P1-1) (enters)
## 2026-05-27
- **feat**: авто-бэкап БД+uploads — systemd timer/service + скрипт (P0-6) (deploy)
- **feat**: prod X509-ключи OpenIddict с persistent self-signed (P0-1) (auth)
- **feat**: permission-based авторизация по флагам роли (P0-5) (authz)
- **feat**: health-пробы /health/live и /health/ready (P0-4) (api)
- **feat**: rate-limit /connect/token и /api/auth/signup (P0-3) (api)
## 2026-05-26
- **fix**: change-owner требует reason ≥ 10 символов (superadmin)
- **fix**: увольнение/деактивация гасит логин связанного User (employees)
- **fix**: сериализуемое проведение приёмки против lost update остатков (supplies)
- **fix**: FK-guard удаления контрагента + валидация полей товара (catalog)
- **fix**: refresh-token rotation немедленно инвалидирует старый токен (auth)
## 2026-05-23
- **fix**: защита денег и инварианта остатков на posting-операциях (documents)
- **fix**: SuperAdmin edit-mode override обходит [Authorize(Roles=Admin)] (security)
- **fix**: чиним P0-блокеры разворачивания на чистой БД (migrations)
## 2026-05-18
- **fix**: обновить node:20-alpine → 22-alpine (pnpm 11 требует Node ≥22) (docker)
- **fix**: validatePassword проверяет заглавную и цифру (соответствует хинту) (validation)
- **fix**: onBlur валидация через e.target.value, ре-валидация вместо сброса ошибки в onChange (signup)
## 2026-05-17
- **feat**: onBlur валидация полей во всех формах (ux)
## 2026-05-08
- **fix**: блок пустого Draft на UI + бэк уже отказывает (retail-sale)
- **feat**: системная ProductGroup «Все товары» при создании org (bootstrap)
- **fix**: обязательные FK-Guid проверяются на 400 + DbUpdateException → 400 (validation)
- **fix**: блок overselling в Post — 409 если qty>остатка (retail-sale)
- **fix**: добавить [Migration] атрибут для Phase5c — без него Migrate() не находит миграцию (migrations)
- **fix**: серверная KZ-ФЛК на всех endpoint'ах принимающих phone (phone)
- **fix**: Cashier/Storekeeper больше не видят /api/organization/employees + Identity-роль маппится из orgRole (auth)
- **feat**: infrastructure + first full-cycle scenario + baseline report (e2e)
## 2026-05-06
- **feat**: forgot/reset password — endpoints + UI + IP rate-limit (auth)
- **feat**: UI /super-admin/platform-settings + тестовая отправка (platform)
- **feat**: IEmailSender + MailKit + PlatformSettingsController (platform)
- **feat**: PlatformSettings entity + миграция (singleton SMTP-конфиг) (platform)
- **feat**: фильтр sidebar и route-guard по ролям пользователя (roles)
- **feat**: двухступенчатое удаление — «уволить» → «удалить» (employees)
- **feat**: TextInput с type=email — авто-pattern для TLD-проверки (forms)
- **feat**: MoneyInput для поля «Оклад» в карточке сотрудника (forms)
- **feat**: убрать «ИНН» из UI — РК использует ИИН/БИН (localization)
- **feat**: системная роль — read-only форма прав вместо alert (roles)
- **feat**: три системные роли — Admin/Cashier/Storekeeper (roles)
## 2026-05-03
- **fix**: сохранять позицию курсора после нормализации (phone)
- **fix**: нативное редактирование, фильтр не-цифр через onBeforeInput (phone)
- **fix**: редактирование на месте курсора, как в обычном поле (phone)
- **fix**: полностью переписать на простую модель — цифры как single source of truth (phone)
- **fix**: блокировать ввод не-цифр на уровне keyDown (phone)
- **fix**: не считать «7» из префикса как введённую цифру (phone)
- **feat**: единый PhoneInput с зашитым «+7» и ФЛК Казахстана (phone)
- **feat**: телефон обязателен + ФЛК Казахстана (77XXXXXXXXX) (signup)
- **fix**: убрать «моргание» при клике на орг — переход теперь по double-click (super-admin)
## 2026-05-02
- **fix**: docker-public — актуализировать PUBLIC_*_URL под новые домены (ci)
- **fix**: кнопка «Войти» вела на 410-Gone zat.kz (public)
- **feat**: новый логотип food-market wordmark + apple mark (brand)
## 2026-04-30
- **feat**: миграция на food-market.kz / admin.food-market.kz (domains)
## 2026-04-28
- **feat**: полное управление сотрудниками любой орги (super-admin)
- **feat**: AsyncSelect — серверный поиск в дропдаунах вместо pageSize=500 (ui)
- **fix**: SuperAdmin платформы без OrganizationId + отдельный Admin для Demo Market (auth)
## 2026-04-27
- **feat**: главный администратор — терминология + защита роли/активности (employees)
- **feat**: бейдж «Владелец» + блокировка удаления с объяснением (employees)
- **fix**: пароль/orphan signup/tenant-guard toast/dashboard счётчик
- **fix**: нейтральный placeholder в поле названия организации (public)
- **fix**: закрыть критические дыры — orphan login, self-delete, owner-delete, override-баннер (auth)
- **feat**: русская локализация и строгий email с TLD (validation)
- **fix**: убрать русские имена/ИП из placeholder регистрации (public)
## 2026-04-26
- **feat**: Phase 6 — публичный сайт на food-market.zat.kz, админка на app. (deploy)
- **feat**: Phase 6 — публичный маркетинговый сайт food-market.public на Astro (public)
- **feat**: настраиваемый retention period для архивных орг (super-admin)
- **fix**: убрать цикл редиректа, регресс override после пакета задач (super-admin)
- **fix**: Phase4d таблица называется units_of_measure, не units (migration)
- **feat**: двухуровневые справочники Группы и Ед.измерения (системные + tenant) (directories)
- **feat**: системные роли read-only + русские имена + чистка дубликата у admin (roles)
- **feat**: перенести справочник Стран в системную консоль (super-admin)
- **fix**: SuperAdmin override должен применять tenant filter выбранной орги (tenancy)
- **feat**: рабочий quick-switch + UI-блокировка мутаций в read-only (super-admin)
- **feat**: Phase 2b — отдельный SuperAdminLayout и разделение от tenant-админки (super-admin)
- **feat**: Phase 3 — edit-mode с reason + audit-trail (super-admin)
- **feat**: Phase 2 — read-only «открыть как…» context switch (super-admin)
- **feat**: /quiet и /loud команды для управления PreToolUse прогресс-лентой (bridge)
- **fix**: новая org через UI получает полный bootstrap (как Demo) (super-admin)
- **feat**: PreToolUse hook for Telegram progress feed + rate-limited batching (infra)
- **fix**: grant SuperAdmin role to admin@food-market.local (seed)
- **feat**: super-admin section + setup wizard + auto-redirect (web)
- **feat**: super-admin endpoints (orgs CRUD + setup-status + audit-log + dashboard) (api)
- **feat**: Organization.IsArchived/AccountOwner + SuperAdminAuditLog + migration (domain)
- **feat**: add Salary, TaxNumber, Description, ImageUrl + radio role picker (employee)
- **feat**: permissions matrix grouped by section + clone-from-template flow (roles)
- **fix**: keep only Admin + Cashier as system, demote others to custom + migration (roles)
- **feat**: event-driven Telegram bridge — webhook + Stop hook (infra)
- **fix**: drop Employee.Navigation(RetailPointAssignments) to fix snapshot order (migrations)
- **feat**: welcome dashboard with first-steps cards (onboarding)
- **feat**: Employees + Roles pages with permissions matrix (web)
- **feat**: EmployeesController + EmployeeRolesController + invite-with-temp-password (api)
- **feat**: system roles per organization + map admin → Employee (seed)
- **feat**: Employee, EmployeeRole, RolePermissions entities + migration (domain)
- **fix**: dropdown opens as floating overlay (Portal + absolute) (searchable-select)
- **fix**: theme styles + default to today for new docs (date-field)
- **feat**: replace native input with react-datepicker — polished UX (date-field)
- **fix**: polish calendar UX — dropdown nav, today/clear footer, ru weekdays (date-field)
- **fix**: compact calendar popup — shadcn-style sizing (date-field)
- **fix**: cap width + ru locale + DD.MM.YYYY format (date-fields)
- **fix**: show both article and barcode in line subtitle (supply-lines)
- **fix**: sticky input at viewport bottom + auto-scroll on add (supply-quick-add)
- **fix**: dropdown opens upward + show only N results + create-new at bottom (supply-quick-add)
- **feat**: drop supplier field, reorder sections, add cost column (product-card+list)
- **fix**: keep input focused after scan / clear on add (supply-quick-add)
- **fix**: dropdown not rendering — Portal + fixed position (supply-quick-add)
- **feat**: inline line quick-add — scanner + autocomplete + create-on-fly (supply)
- **feat**: products quick-search + by-barcode endpoints (api)
- **fix**: колонка «Розничная» использует имя системного PriceType (supply)
- **feat**: «Проведено» внутри формы + обязательная дата и ≥1 позиция (supply)
- **fix**: catch-up Phase3b_AddShowDescriptionOnProduct (migrations)
- **feat**: inline-create option in searchable Select (ui)
- **feat**: searchable Select component (drop-in) (ui)
- **feat**: drop ShelfLifeDays + recompose classification + auto-article + barcode trash hide (product-card)
- **fix**: IsRequired применяется сразу, без перезагрузки страницы (price-types)
## 2026-04-25
- **fix**: человечная ошибка 400 + блок Save при незаполненных IsRequired ценах (product-edit)
- **fix**: correct is-system seeder + require value > 0 + system-price filter/sort (price-types)
- **feat**: inputs по справочнику PriceType — без dropdown'a (product-prices)
- **feat**: компонент + inline-наценка в таблице групп (percent-input)
- **feat**: срок годности (shelfLifeDays) + фильтр от/до (product+filters)
- **feat**: чекбокс «Проведено» с confirm + системная розничная в списке (supply+products-list)
- **feat**: drop IsActive, add ShelfLifeDays, restore PriceType IsSystem/IsRequired (phase3b)
- **feat**: supply line retail override column (web)
- **feat**: price types CRUD visibility + group markup table (web)
- **feat**: product card pricing UI + settings toggles (web)
- **feat**: recalc-retail endpoint + 30-day reference price refresh job (api)
- **feat**: supply posting hook for cost & markup (api)
- **feat**: pricing model rename and new fields (Phase3a) (domain)
- **fix**: merge barcodes/prices по ключу + 409 на concurrency (products/update)
- **fix**: toFixed(2) при allowFractional=true для правильного отображения (money-input)
- **fix**: сохранять промежуточный ввод точки в draft (money-input)
- **fix**: корректное обновление allowFractionalPrices без перелогина (money-input)
- **fix**: уважать AllowFractionalPrices в формах редактирования (money-input)
- **feat**: pre-check на Create/Update + warnings импорта + admin endpoint (barcode-uniqueness)
- **feat**: AllowFractionalPrices — переключатель дробных цен (org-settings)
- **feat**: группа обязательна, ≥1 штрихкод, умные дефолты на новом (product)
- **feat**: MoneyInput/NumberInput + select-пагинация + Range на бэкенде (forms)
## 2026-04-24
- **feat**: авто-генерация числового артикула при создании (products)
- **feat**: настройка ShowMinMaxStock для мин/макс остатков (org-settings)
- **feat**: галки «Услуга»/«Маркируемый» скрываются по умолчанию (org-settings)
- **feat**: авто-генерация EAN-13 при добавлении штрихкода (barcode)
- **feat**: server-side sort by column header click (tables)
- **feat**: валюта read-only, тянется из страны (как НДС) (org-settings)
- **feat**: ставка в стране + опц. переопределение на товаре (vat)
- **feat**: загрузка на диск сервера + галерея с лайтбоксом (product-images)
- **feat**: enum Packaging (штучный/весовой/разливной) вместо IsWeighed (product)
- **feat**: Country↔Currency, Organization.DefaultCurrency/MultiCurrency/DefaultVat + UI настроек (org-settings)
- **fix**: сделать Token опциональным (other-system/test)
## 2026-04-23
- **feat**: async jobs с прогрессом + токен в настройках (other-system-import)
- **fix**: per-page retry + чаще SaveChanges (other-system/import)
- **feat**: tree-of-groups + фильтры как в OtherSystem (catalog/products)
- **feat**: import archived entities too (as IsActive=false) (other-system)
- **fix**: reconcile stage schema — drop TrackingType, add IsMarked (db)
- **feat**: temp cleanup buttons + fix OtherSystem import duplicates (admin)
- **feat**: strict OtherSystem schema — реплика потерянного f7087e9
- **fix**: убираем выдумку Kind полностью — у OtherSystem этого поля нет (other-system)
- **fix**: не выдумывать Kind=Both для импортированных контрагентов (other-system)
- **feat**: Telegram <-> tmux bridge + local docker-registry unit (ops)
- **feat**: sales chart + KPIs (как «Показатели» в сторонняя система) (dashboard)
## 2026-04-22
- **fix**: bootstrap admin + demo org on stage/prod too, not just Dev (seeder)
- **fix**: always apply EF migrations on startup, not only in Development (api)
- **fix**: widen Article + Barcode.Code to 500 chars for real-world catalogs (catalog)
## 2026-04-21
- **fix**: accept fractional prices (decimal, not long) in DTOs (other-system)
- **fix**: add User-Agent header + enable HTTP auto-decompression (other-system)
- **fix**: drop Accept-Encoding: gzip to avoid JSON parse failure (other-system)
- **fix**: set Accept header as raw string to bypass .NET normalization (other-system)
- **fix**: exact Accept header value per OtherSystem requirement (code 1062) (other-system)
- **fix**: trailing slash on BaseUrl so HttpClient keeps /1.2/ in path (other-system)
- **fix**: OtherSystem admin endpoint uses policy-based auth on role claim directly (auth)
- **fix**: return 401 instead of 302 for API challenges; persist dev signing key across restarts (auth)
- **fix**: drop FM square badge from Logo; better 404 diagnostics on OtherSystem page (web)
- **feat**: rebrand to FOOD MARKET green (#00B207) per mobile app logo (web)
- **fix**: remove TanStack devtools palm icon; restore user profile on dashboard (web)
- **fix**: pin API dev port to 5081 (match Vite proxy config)