- kb/quickstart: убраны .msi/«ключ организации»/«импорт по API-токену» —
импорт из файла Excel/CSV, из других систем «в разработке»; касса Windows и
Linux «скоро», вход по адресу сервера + логин + PIN.
- blog/cash-with-scales: убран дублирующий <h1> в теле (как в launch/quick-start).
- kb/faq + og: неподтверждённое «до 100 000 товаров» → нейтрально «большие
каталоги / тысячи позиций» (точного лимита в коде нет; есть RequestSizeLimit 20МБ).
- Конструктор: цена «₸/мес» на кнопке «Выбрать конфигурацию» не переносится
(whitespace-nowrap).
- Форма регистрации: инлайн-ссылки «офертой»/«политикой» — увеличенная зона
нажатия (py-1) без сдвига вёрстки.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Проверка на живом test.food-market.kz после деплоя: React #418 ушёл, дефолтный
«Бизнес» 10 000, чужих систем учёта 0 (Kaspi/маркетплейсы только «в разработке»),
типографика KB, sitemap со слэшами, мобильные правки (Android «Назад», ползунки
−/+, состав панели), честные /status и /kb/billing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Шапка: десктоп-меню с xl (чтобы на ~1050px не ломалось в 2 строки); CTA без
переноса; в мобильной панели добавлены «Интеграции», «Статус», «Что нового»;
Android «Назад» закрывает панель (pushState/popstate), Esc/тап/крестик остаются.
- Конструктор «Бизнес»: ползунки удобнее на тач — крупная ручка, touch-action
pan-y (вертикальный скролл не двигает значение), кнопки −/+; бейдж
«Популярный» (как на главной) и «90 дней бесплатно».
- Кнопка «Настроить тариф» на главной → /pricing#configurator со скроллом к
конструктору; на /pricing убран ложный пункт «Импорт из других систем» у «Старт».
- Типографика markdown (h2/h3, списки, таблицы, ссылки) вынесена в global.css —
/kb/* больше не плоский текст; эмодзи-фолбэк; увеличенная зона нажатия у
инлайн-ссылок; снят дублирующий inline-стиль в blog/[slug].
- Футер: «Status» → «Статус».
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ?plan= и параметры конфигуратора читаются в useEffect ПОСЛЕ гидрации, поэтому
первый клиентский рендер совпадает с SSR-разметкой — ошибка React #418
(hydration mismatch) на /signup?plan=business&shops=… больше не возникает.
- plan=business без параметров → выбирается «Бизнес» с дефолтной конфигурацией
1/1/1/5 = 10 000 ₸; plan=network → «Сеть»; неизвестный план → «Старт».
- Клик по плитке тарифа обновляет URL (history.replaceState), ссылку можно
сохранить/поделиться.
- Плитка «Старт» теперь «5 000 ₸/мес»; цены плиток без переноса (whitespace-nowrap).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Чужие СИСТЕМЫ УЧЁТА (МойСклад, 1С) убраны со всего публичного сайта: тексты,
KB, блог, FAQ, og-картинки, meta. Платёжные системы и маркетплейсы (Kaspi,
Wildberries, Ozon и т.п.) оставлены только как честная пометка «в разработке»
на /integrations и главной.
- /integrations, /import, главная, about, features, pricing, blog, kb/faq:
«перенос из МойСклад/1С» → «импорт каталога из файлов Excel/CSV»; импорт из
других систем учёта — «в разработке, в личном кабинете магазина».
- kb/pos-setup: касса для Windows и Linux, вход по адресу сервера + логин + PIN,
установка «скоро»; чековые принтеры 58/80 мм (ESC/POS).
- kb/billing: переписан под реальность — биллинг-UI/подписки в продукте нет
(заглушка до Phase 4); оплата вручную через поддержку, онлайн-оплата «в
разработке»; убраны несуществующие «Настройки→Подписка→История», e-mail-
напоминания, баннер, формула кредита, SLA. Цены «тг» → «₸».
- kb/faq: бэкапы «каждые 24 ч» → «регулярно»; «TLS 1.3» → «TLS»; формулировка
про ЗРК смягчена; «триал» → «бесплатный период».
- /status: убраны фиктивные зелёные индикаторы (мониторинга нет) — честная
пометка «в разработке» + контакты для инцидентов.
- /changelog: убран внутренний жаргон (Phase N, SuperAdmin, retention, tenant,
inline) — человеческие формулировки.
- og.mjs: сабтайтлы без чужих брендов; касса Windows и Linux; «триал»→«бесплатно».
- sitemap.xml: канонические URL со слэшем + статьи KB и блога.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs/site-fixes-2026-10-10/{index.html,REPORT.md,screenshots}; tools/site-fixes-verify.mjs
(Playwright-проверка: signup plan/конфигурация/цена, мобильное меню, без промисов/REPLACE_ME).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
На реальном объёме перенесённого магазина список движений отдавал >2.5с из-за COUNT по
3-table join. Count теперь по stock_movements с фильтрами (join не меняет число строк).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PosStore.FindAllByBarcode; SaleViewModel.ScanCandidates/IsScanPickerOpen + PickScanCandidate
- SaleView: модалка выбора; сервер by-barcode уже отдаёт items, веб-приёмка уже показывает выбор
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- docs/migration-debts-top20.md: топ-20 долгов (контрагент-уровень) + находка (paymentout agent=орг)
- MoneyAccountsPage: строка «Начальный остаток при переносе из МойСклад на <дата>» для МС-счетов
- systemd food-market-migration-delta.timer (каждые 10 мин) — непрерывная дельта до перехода
- прогресс: раздел «Исправления по ревью» (все 4 пункта)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- create: артикул-коллизия → суффикс msId (перенести карточку, не падать на unique)
- create/update: ШК не уникален → добавляем код каждой карточке (пары товар|код против
повторов), дубли ловит «Проверка данных»
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DevDataSeeder по умолчанию (dev/stage) сидирует демо-орг; на проде SEED_DEMO_DATA=false
отключает демо-орг/demo-admin/привязку, сохраняя SuperAdmin+роли+глобальные ед.изм.+SystemSettings.
Нужно для чистого (пустого) старта реального магазина.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ProbeRunner: COM-порты (имя/VID/PID/описание через WMI), open→close (занят/свободен без
удержания), опрос весов Масса-К+CAS 9600 (таймаут 1.5с), принтеры Windows (имя/порт/драйвер,
БЕЗ печати), HID-клавиатуры (возможные сканеры). --port COMx — один порт; занятый не трогаем.
- --test-print "<принтер>": отдельный флаг, ESC/POS тест-чек «ТЕСТ ALL MARKET» через spooler
(winspool RAW). Без флага ничего не печатается.
- WinExe → AttachConsole(parent) для видимого вывода; --out пишет чистый UTF-8 JSON.
- System.Management (WMI, только Windows, под guard'ами). Проверено на Win11 VM: выход <10с,
COM1/принтер/HID определяются, test-print на несуществующий принтер — мягкая ошибка (код 4).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- reconcile: выручка по документам (точно до копейки), plotseries как справка; чеки сходятся
- delta_sync: camelCase ключи job (created/skipped), повторный опрос, audit tolerant — дельта
подтверждена (новый чек из МС подтянут: created 1)
- НАЙДЕНО: 30000 строк stocks без движений (прежний прямой сид) → пересобрать из движений
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- StreamDocumentsAsync: Uri.EscapeDataString всего выражения updated>=<дата> (>= → %3E%3D),
не только даты — иначе часть форм 400/неоднозначна
- delta_sync: повторное чтение job после Succeeded (устранить гонку счётчиков), audit в try
- reconcile: розница демо/возвраты раздельно, URL-энкод фильтра чеков по месяцам
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- scripts/migration/delta_sync.py: раз в N мин updated>=lastSync по всем типам,
удаления через /audit, состояние в ~/.fm-watchdog, перекрытие окна 2 мин
- docs/migration-runbook.md: фазы A/B/C, откат на МойСклад, надёжность, ограничения токена
- reconcile.py: секции балансов счетов (report/money/byaccount) и долгов (403-ограничение)
- progress: Parts 5/6/7 закрыты
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- остатки по товару через Product.MoySkladExternalId, read-only SQL stage
- выручка из report/sales/plotseries (÷100, МСК-месяцы), чеки из meta.size по filter moment
- наши — retail_sales без возвратов, Date+3ч → МСК-месяц
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ImportRetailReturnsAsync (retailsalesreturn): связь с чеком по externalId demand, +остаток
- ImportInventoriesAsync (inventory): Completed без движений, BookQty/ActualQty из calculated/quantity
- Все 7 импортёров принимают updatedFromMsk → filter=updated>= (МСК) для дельты
- Контроллер: ?updatedFrom=<МСК> прокинут во все типы
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
loss 3068/3068, purchasereturn 550/550, enter 72/72 — сходятся точно. Приёмки 7130
(Δ -1 к живому МС). Розничные продажи — перенос продолжается (резюм по offset).
scripts/migration/reconcile.py сравнивает МойСклад vs ALL MARKET (read-only) →
docs/migration-reconciliation.md. Счётчики МС растут (живой аккаунт) → нужна дельта.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
startOffset у всех документных импортов + эндпоинт ?offset=N: при продолжении
пропускаем уже перенесённые через offset API (а не перечитывая сотни страниц).
Идемпотентный skip по msId держит границу.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
По проверенному шаблону приёмок (идемпотентно по msId, резюмируемо, МСК→UTC, тиыны,
дизамбигуация номеров, SaveChanges по документу, движения остатков):
- enter (+остаток), loss (−остаток, WriteOff), purchasereturn (−остаток, SupplierReturn),
retaildemand (−остаток, RetailSale; оплата нал/безнал из cashSum/noCashSum, кассир=owner).
- Общие помощники LoadMaps/Aggregate. Эндпоинт POST /import-supplies?type=enter|loss|
purchasereturn|retaildemand (фон, job с нужным kind).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Номера МойСклада повторяются по годам, а у нас (OrganizationId, Number) уникален →
дубли роняли импорт. Сохраняем оригинальный номер где можно, при коллизии —
«<номер>-<год>[-N]». Оригинал всегда в MoySkladExternalId.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Сбой SaveChanges одного документа оставлял сущности tracked → все последующие
падали (каскад), импорт застревал. Теперь в catch — ChangeTracker.Clear().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Батч из 50 приёмок с общим товаром давал дубль строки stocks (ApplyMovementAsync
создавал новую строку, не видя ещё не сохранённую). Теперь: SaveChanges после КАЖДОГО
документа (следующий видит закоммиченные остатки) + агрегация позиций по товару в
документе (средневзвешенная цена) + ChangeTracker.Clear (не копим граф на 7k докумов).
Идемпотентно по msId — повторный запуск продолжает с места.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
МойСклад отдаёт sum/cashSum/price как число с точкой (900000.0) → long не парсился
(«JSON value could not be converted to System.Int64»). Поля DTO → decimal. Плюс
GET /api/admin/moysklad/jobs/{id} для наблюдения за прогрессом/ошибками переноса.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Тяжёлый expand=positions.assortment раскрывал весь товар в каждой позиции → страница
гигантская и зависала. assortment.meta.href в позиции есть и без раскрытия. Таймаут
HttpClient МойСклада поднят до 130с (страница иногда > 100с).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part 2 (документы) — проверенный шаблон на приёмках:
- Phase41: MoySkladExternalId у counterparties/stores/units/retail_points/employees и
документов (supplies/enters/losses/inventories/supplier_returns/retail_sales/
cash_shifts/money_transactions) + индексы. Свойства на доменных сущностях.
- MoySkladClient.StreamDocumentsAsync: документы в хронологии (order=moment,asc), expand
позиций/связей (limit=100), обработка 429/сбоев.
- MoySkladDocumentImportService.ImportSuppliesAsync: идемпотентно по msId, резюмируемо
(skip перенесённых), moment МСК→UTC, суммы из тиынов, поставщик по externalId контрагента,
товары по externalId, проведение → движения остатков (StockService). Журнал ошибок.
- Импорт контрагентов теперь пишет MoySkladExternalId (нужно для ссылок в документах).
- Эндпоинт POST /api/admin/moysklad/import-supplies (фон, job). Остальные типы — по шаблону.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Пайплайн справочников проверен на реальном аккаунте: орг «FOOD MARKET» на стенде,
контрагенты 628 (МС 627) и группы 53 перенесены, товары (31k) импортируются в фоне.
Документы (110k), сверка и дельта — спроектированы (migration-design.md), основной
объём впереди (многочасовой прогон). global.json не трогал; в МойСклад только чтение.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Решение владельца 09.10: полный перенос магазина из МойСклада в ALL MARKET с историей.
- scripts/migration/ms_inventory.py — read-only инвентаризация источника.
- docs/migration-source-inventory.md: орг «FOOD MARKET», ~31k товаров, 627 контрагентов,
~110k документов (97 707 чеков, 7 125 приёмок, 3 068 списаний…), 7 558 строк остатков,
1 склад/точка/орг, касса наличных, 1 тип цены; gap-анализ модели + цели сверки.
- docs/migration-design.md: идемпотентность по msId, хронология документов, МСК→UTC,
тиыны, резюмируемость, порядок этапов, сверка, дельта, runbook.
- docs/migration-progress.md: план Part 1–7.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Доработаны хендлеры браузерного прогона (пагинация со сбросом поиска, обобщённое
создание/сохранение/удаление, период-фильтры, доп. сид: чек/приёмка/оприходование/
списание/инвентаризация/возврат). Экстрактор ловит строковый фолбэк заголовка колонки.
docs/uat-coverage.html — цифры по экрану/приоритету/общим. Цели (P1–P3 ≥95%, P4 ≥70%)
пока НЕ достигнуты (переход на ALL MARKET в приоритете) — остаток задокументирован в
docs/uat-coverage-progress.md, продолжим после перехода.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Найдено Mac-Claude на стенде:
1. Генератор внутреннего EAN-13 давал «02…» (ведущий 0 → зона UPC-A, может совпасть
с реальным товаром). InternalBarcode.PickPrefix теперь берёт 2x из restricted-
circulation 20–29 (без ведущего нуля), не пересекаясь с весовыми префиксами орг;
«02» — только крайний резерв. Юнит-тест обновлён.
2. «Проверка данных» на Демо показывала все 0 и lastCheckedAt=null — ночной cron ещё
не отрабатывал после пересева. Добавлен разовый BackgroundJob.Enqueue(DataQualityJob)
при старте: после деплоя/пересева счётчики считаются сразу по всем организациям.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- tools/extract-controls.ts: статически из web/src/pages достаёт все интерактивные
элементы каждого экрана (поиск/фильтры/сортировки/пагинация/экспорт/тумблеры/
действия) → docs/uat-coverage.expected.json (36 экранов, 195 элементов; приоритеты).
- scenarios/stage-ui-uat-coverage.spec.ts: читает expected, в браузере задействует
каждый элемент (фиксирует запрос с параметром/действие), пишет reports/uat-covered.json.
- tools/build-coverage.ts: сводит → docs/uat-coverage.{json,html} с % по экрану/
приоритету/общим (цель P1–P3 ≥95%, P4 ≥70%).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>