Реальный сценарий владельца: весов с печатью этикеток нет, штрихкоды весовых —
обычные коды «27xxxxx» в карточке. Исправлены два бага:
- поиск по ШК матчил весовой PLU по АРТИКУЛУ (вода арт.12345 → 1,5 кг) — убрано,
поиск по штрихкоду больше нигде не матчит по артикулу;
- разбор весовых этикеток был дефолт-ON (WeightedBarcodeSettings.Enabled,
Organization.WeightBarcodeEnabled) и ловил обычные коды — теперь дефолт OFF.
- ByBarcode: сначала точное совпадение штрихкода (вкл. короткие «27xxxxx»),
разбор этикетки — только если включён в орг И точного ШК нет.
- Phase40: WeightBarcodeEnabled DEFAULT false + выключение у существующих орг;
WeightedCodeFormat('short'|'ean13')/WeightedCodePrefix(27)/WeightedCodeDigits(5).
- Генератор ШК нового весового товара: короткий «<prefix>+N цифр» (27xxxxx, next-free)
или EAN-13 по настройке; уникальность.
- Настройки орг отдают/принимают формат кода весовых.
- Sync отдаёт unitShort («шт»/«кг»/«л») рядом с unitCode (ОКЕИ) — shared UnitShort.
- Тесты: MobileApi (exact-only по умолчанию; не матчит артикул; PLU как ШК при вкл) 9/9;
unit WeightedBarcode/UnitShort 16/16.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
stage-ui-uat-mobile проходит по 16 спискам P1-P4 на 390px (каталог/контрагенты/
склад/приёмки/продажи/деньги/отчёты/сотрудники): без h-scroll, console-ошибок и 5xx.
Отчёт дополнен: UI-гейтинг по ролям (menu-walk 3/3), окно кассы Windows 11.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Снято на win11-kassa-test VM (foodmarket.Pos.exe --demo, software-рендер,
захват из интерактивной сессии). Заголовок окна «ALL MARKET · Касса», крупное
лого all market, «Касса» рядом, экран продажи целиком, таскбар Windows 11.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ValidationFilter (FluentValidation-путь): русский заголовок «Проверьте
правильность заполнения» через ModelErrorTranslator вместо дефолтного англ.
«One or more validation errors occurred» (сообщения полей уже были русскими).
- stage-ui-uat-mobile.spec.ts: P1-экраны на 390px без h-scroll/console/5xx +
проверка «Остатки» (артикул/штрихкод, тумблер «показать нулевые»).
- docs/uat-report-2026-10-09.md: матрица покрытия (уже-зелёное vs проверено
сейчас) по требованию владельца; галерея скринов reports/uat-mobile/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Независимо считает ожидаемый набор строк/итог (не «200 OK»): свежая temp-орг,
контролируемый сид (внук-со-стоком/ребёнок-ноль/родитель-минус/поиск/услуга в
3-уровневой группе), сверка для каждого контрола. Покрыто: stock includeZero,
negativeOnly, groupId/productGroupId (3 уровня вложенности), store-specific,
поиск по артикулу/штрихкоду, сортировка по количеству, пагинация (разбиение),
экспорт-с-фильтром; catalog groupId/productGroupId/isService. 21/21 ✓ на стенде.
Добавлено в nightly (step 3c) и quality-watchdog (step 12) на хосте.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RetailOversellingTests ждал 409 на продажу сверх остатка — устаревшая политика.
По решению владельца 08.10 продажа в минус разрешена и создаёт предупреждение об
отрицательном остатке. Тест переписан: проведение успешно, остаток уходит в минус,
создан negative-stock alert. Плюс обновлён docs/filters-sweep-progress.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Остатки строились ОТ таблицы Stocks (JOIN Products), поэтому товары без строки
Stock (ни разу не приходованные) не попадали в список вообще, а includeZero лишь
снимал фильтр Quantity!=0 у существующих строк. То же в отчёте «Остатки на дату»,
в экспорте и в фильтре по группе (iOS получал total 0).
- GetStock/ExportStock: выборка ОТ Products (не-услуги, не-архивные) с остатком
коррелированным подзапросом (товар без Stock = 0). Склад выбран → строка склада;
без склада → агрегат «Все склады». Нулевые видны при includeZero; negativeOnly и
пагинация/сортировка/поиск/экспорт работают и для нулевых. Остаток/ед./штрихкод
дотягиваются batch-запросом по id страницы (EF8 не переводит подзапросы в SELECT+ORDER BY).
- Отчёт «Остатки на дату»: includeZero добавляет товары без движений (Qty 0);
фильтр по группе теперь с вложенностью.
- groupId/productGroupId — синонимы с вложенными группами на всех списках остатков
и в каталоге (List + Export). Раньше catalog?productGroupId молча игнорировался.
- Штрихкод рядом с артикулом в списке/экспорте — различать одноимённые товары
(4× «BIOBLAS шампунь» с разными артикулами из МойСклада — не удалять).
- Demo (30 894 товара): без флага 12, includeZero → 30 894, <500мс/страница.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
now-pos-sale.png / now-pos-login.png были сняты 17:41, до фикса 3a0f9e2 (18:07).
Переснято с текущего UI: лого ALL MARKET ~140px, «Касса» через разделитель,
бейдж «Отложенные 2» целиком внутри кнопки.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hangfire DataQualityJob (ночью 02:20 UTC) считает по орг. счётчики проблем: без группы
(корень/«Без группы»), без цены продажи, без штрихкода (кроме услуг), дубль штрихкода,
возможный дубль имя+единица; товары в минусе — ссылкой на центр (не дублируем). Результаты
в data_quality_results (Phase43), живые детальные списки — по запросу.
API /api/data-quality: сводка, {check}/products, recompute, dismiss («это разные товары»),
bulk set-group/set-price/generate-barcodes, PUT settings (отключение проверок). unknown-cost
отложен до FIFO; PLU убран (поправка владельца). Integration-тест: счётчики/список/bulk/dismiss.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
POST /api/purchases/supplier-returns/from-supply/{supplyId}: черновик возврата с
преднабором строк из проведённой приёмки (товар/кол-во/цена), поставщик/склад/валюта
и ссылка ReferenceSupplyId. Integration-тест: преднабор + связь.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
П.7: типы денег названы привычно — «Приход наличных (ПКО)», «Расход наличных (РКО)»,
«Входящий/Исходящий платёж», «Перевод между счетами».
П.8: блок «Прибыль за сегодня/месяц» на дашборде (во всех режимах, /api/dashboard/margin),
с пометкой «приблизительно; точно после FIFO».
П.9: общий DocStatusBadge (Черновик/Проведён/Завершена) с tooltip «что это значит»,
применён на списках Приёмок/Продаж/Инвентаризаций.
П.6: проверено — Оприходование/Списание в простом режиме не прячутся (отдельные пункты).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Правки владельца 08.10 (п.4 паритета):
- Сохранить можно при наличии Наименования. Единица не обязательна в запросе →
дефолт «шт»; группа → корень. Штрихкод ОБЯЗАТЕЛЕН у любого товара: нет в запросе/
импорте → автогенерация внутреннего EAN-13 (верная контр. цифра, префикс не
пересекается с весовыми/ценовыми префиксами орг. — InternalBarcode).
- Цена продажи не обязательна для сохранения; но ПРОДАТЬ без неё нельзя — касса и
розничная продажа дают «У товара «X» нет цены продажи» (можно ввести вручную).
- Быстрое создание из кассы/приёмки: POST /api/catalog/products/quick (имя + опц.
штрихкод/цена/весовой).
- Снят FluentValidation NotEqual(Guid.Empty) на единицу (контроллер подставляет дефолт).
Тесты: unit InternalBarcode 3/3 (валидный EAN-13, не парсится как весовой, обходит
префиксы); integration 3/3 (создание по одному имени, продажа без цены → 400, quick).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- docs/moysklad-pos-startup.md: прямой замер «Кассы МойСклад» (Celeron N4120, 99–113 с
до готовности; каталог перезаписывается целиком, полный JSON+FTS) — подтверждённые
причины, не догадки.
- docs/pos-progress.md: раздел «Мгновенный старт» — что сделано (касса из локальной базы +
фоновый синк, дельта остатков, gzip-каталог ×7.3, синк вне UI-потока) + таблица замеров
(Linux/стенд + Win11 VM + 1 ядро как прокси Celeron). Цель <2 с тёплый старт на слабом
CPU достигнута (<1 с). Серверный кэш снимка осознанно не делали (риск памяти, путь
«раз на установку»).
- deploy/pos-install.ps1: установщик Windows (исключение Defender + прогрев + ярлык);
холодный старт 10 с → 4,5 с. deploy/pos-win-measure.ps1 — скрипт замеров на VM.
- docs/pos.md: обновлён раздел первого запуска + варианты/стоимость подписи exe (не покупали).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Пасс 3: касса (индикатор+предупреждение+офлайн), Web Push (VAPID), e2e колокольчика.
Итог: unit 299/299, integration 4/4, POS 4/4, e2e-браузер 2/2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Таблица токенов устройств (device_tokens, Phase40) + POST/DELETE /api/me/device-tokens
для регистрации iOS/Android/Web push-токенов. Контракт IPushSender.SendAsync; в DI
включён StubPushSender (пишет в лог) — реальный APNs/FCM/VAPID подменит заглушку, когда
появятся ключи, без правок вызывающего кода. Описано в docs/mobile-api.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Решение владельца 08.10: продавать/списывать в минус РАЗРЕШЕНО, но с постоянным
предупреждением и требованием провести инвентаризацию.
- Снята блокировка «недостаточно остатка» (409 oversell): розница, касса (POS-синк),
опт-отгрузка, списание, перемещение, возврат поставщику, отмена приёмки. Деньги
(минус счёта) — по-прежнему запрещены (другое правило).
- NegativeStockAlert (сущность + миграция Phase39): создаётся/обновляется при уходе
остатка < 0 (единая точка — StockService), авто-закрытие при возврате ≥ 0. Частичный
уникальный индекс: один открытый алерт на (org, store, product). Причина: тип/номер
документа/автор/время.
- API /api/negative-stock: список (с подсказкой «возможно, не проведена приёмка П-…»),
/count (для баннеров), /recount (черновик инвентаризации по минусам склада). Отчёт
«Остатки» — фильтр negativeOnly.
- Веб: постоянный баннер «N товаров в минусе — нужна инвентаризация» (сворачивается,
крестиком не закрыть) + «Пересчитать эти товары»; в остатках — красная пометка и
фильтр «Только минусы».
- Тесты: integration 2/2 (минус разрешён → алерт → recount → авто-закрытие; фильтр);
full-chain шаг 9/13 переписаны (oversell/отмена приёмки → проведено + предупреждение).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Было: unpost при проведённых связанных Оприходовании/Списании молча снимал их с
проведения и УДАЛЯЛ (204, номера исчезали). Хуже МойСклада, теряется история.
- unpost при ПРОВЕДЁННЫХ связанных → 409 с номерами О-/С- и текстом «Сначала
отмените результаты». Если связанные только черновики — удаляем черновики
(не влияли на остатки) и возвращаем инвентаризацию в черновик.
- Новое POST /{id}/cancel-results (InventoryEdit + EnterEdit/LossEdit): снимает
связанные Оприходование/Списание с проведения, НЕ удаляя (остаются черновиками,
видны в «Связанных документах», истории, аудите); остатки возвращаются; для
Оприходования — гард на уход остатка в минус. Аудит InventoryCancelResults.
- Веб: кнопка «Отменить результаты» (при проведённых связанных) + диалог со
списком документов и влиянием на остатки; «Вернуть в черновик» переформулирован.
- docs/mobile-api.md: unpost больше не удаляет проведённые (409), добавлен cancel-results.
- Тесты: integration (409 + cancel-results оставляет черновики + повторное
проведение) + full-chain шаг 10.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Галерея docs/site-screenshots/ — задеплоенные страницы test.food-market.kz
с новыми честными текстами (главная, касса, импорт, возможности, перенос и
интеграции, тарифы, для продуктовых, о нас). Удалён кадр удалённой вертикали.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Убраны обещания того, чего нет: фискализация ОФД/Kaspi Pay (skeleton) →
«в разработке»; ЕГАИС/акцизы/модификаторы/серии-сроки/размерные сетки →
удалены 5 выдуманных страниц-вертикалей (остался продуктовый); CRM/публичный
API убраны; «О нас» без выдуманной истории и команды. Касса — Windows и Linux
(не .msi), «Скачать» → «скоро». Импорт — CSV/1С-CSV/МойСклад. Лояльность — в
админке, не в кассе. Интеграции — честный блок «есть / в разработке».
Язык владельца магазина, без жаргона (дашборд, нативно, вертикали, фишки,
триал, SLA, CRM, Unlimited, кейсы) и пафоса. Заголовок кассы: «Быстрая касса,
которая работает и без интернета». Цены тарифов не менялись.
По правкам Mac-Claude после ревью docs/site-copy-draft.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Проверил каждое утверждение сайта по коду/стенду: фискализация ОФД/Kaspi Pay —
skeleton (нет), ЕГАИС/акцизы/модификаторы/серии-сроки/размерные сетки/гарантии —
нет, CRM — нет, лояльность — в админке не в кассе, импорт — CSV/1С-CSV/МойСклад,
касса — Windows+Linux (zip/AppImage, не .msi), «О нас» — выдуманная история.
Замеры скорости кассы: холодный старт 82 мс, инициализация 625 мс (< 1 c), поиск
по ШК 36 мс. Черновик переписанных текстов — docs/site-copy-draft.md (было→стало).
НЕ выкладывается до «ок» Mac-Claude.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1. Английские строки в админке → русский: ru.json dashboard.title «Dashboard»→
«Сводка», common.live/offline «live/offline»→«онлайн/офлайн»; дашборд-виджеты
defaultValue «Low-stock alerts»→«Низкий остаток», «Live-обновление»→«Обновляется
в реальном времени».
2. Каталог: системная группа «Все товары» больше не дублирует корень дерева
(ProductGroupDto.IsSystem + ProductGroupTree прячет системные группы).
3. Валюта: розничная цена в каталоге теперь «₸», а не «KZT» (символ вместо кода).
4. Касса на сайте: вместо HTML-макета — НАСТОЯЩИЙ экран Avalonia-кассы
(--screenshots) с витринными данными «Магазин у дома», кассир Виктория Ким, с
логотипом; убран префикс «Магазин » в шапке (не было двойного «Магазин Магазин»).
HTML-макет удалён из публичного пайплайна.
5. Витрина: фасовка/единица товара выводится из названия (кг→весовой, иначе
штучный) — нет «Авокадо 1шт весовой» / «Бешбармак 1кг штучный».
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Скриншоты задеплоенных страниц test.food-market.kz (главная/касса/импорт/
тарифы/вертикали/о компании) для проверки на глаз. Все новые скриншоты ALL MARKET
на витринных данных отрисовываются корректно.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Пересняты скриншоты публичного сайта в интерфейсе ALL MARKET на витринной
организации «Магазин у дома» (200 товаров, ~30 дней продаж, чистые данные
без e2e/test-мусора). Светлая тема, 1440×900 @2x, WebP + srcset, alt по-русски.
- screenshots.mjs: стенд + витринный владелец, 14 экранов (дашборд/каталог/
карточка/приёмки/остатки/инвентаризация/деньги/отчёты/контрагенты), скрытие
баннеров стенда/«что нового»/MoM-дельты, резолв AsyncSelect-подписей
- optimize-screenshots.mjs: PNG→WebP (1x 1440w / 2x 2880w) через canvas, все ≤300КБ
- pos-mockup/pos-mockup.html: светлая касса ALL MARKET «Магазин у дома» (продажа+оплата)
- index.astro: hero-дашборд + каталог + новый блок «Касса»; pos.astro: продажа+оплата
- ShowcaseSeeder: стартовый завоз всех товаров (нет отрицательных остатков)
- deploy/showcase-seed.sh: RESET=1 пересоздаёт витрину с нуля
- исходные PNG не коммитятся (.gitignore), доставка — только WebP
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ShowcaseSeeder — чистые данные для публичных скриншотов: 200 товаров без
Article-маркеров, реальные EAN-13, боевой формат номеров документов
(П-2026-…, ПР-2026-…), 3 поставщика, счета (касса/Kaspi/эквайринг),
сотрудники с нормальными именами, ~30 дней продаж, приёмки, 2 списания,
1 завершённая инвентаризация. Без e2e/test/Y1/DEMO в видимых данных.
- POST /api/admin/seed-demo?showcase=1 (DemoSeedController)
- повторяемый deploy/showcase-seed.sh (signup + seed, идемпотентно)
- YearDemoSeeder: data-массивы → internal для переиспользования
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- InventoryEditPage: «Завершить подсчёт» вместо «Провести»; на завершённой — кнопки
«Создать оприходование излишков» / «Создать списание недостачи» (блокируются, если нет
разницы или документ уже создан) + блок «Связанные документы» + «Вернуть в черновик».
- InventoriesPage: статус «Завершена»; колонка «Результат» (опр./спис. № или «не применено»).
- Enter/LossEditPage: «На основании инвентаризации №…» со ссылкой.
- types.ts: InventoryStatus Draft/Completed; related в InventoryDto; результат в списке;
inventoryDocId/Number в Enter/Loss DTO.
- docs/inventory-moysklad-reference.md (сверка), inventory-model-progress.md,
supply-inventory.md («Как провести инвентаризацию», 5 шагов), mobile-api.md (compat post/unpost).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Замечание владельца: инвентаризация стояла «Проведено» без оприходования/списания.
Переделано по МойСкладу (docs/inventory-moysklad-reference.md):
- InventoryStatus Draft→Completed (было Posted; значение 1 то же). Инвентаризация
остатки НЕ двигает: endpoint complete замораживает строки без движений.
- create-enter (излишки diff>0) / create-loss (недостача diff<0) — создают черновики
Оприходования/Списания со строками разницы + ссылка InventoryDocId. Повторно нельзя (409).
- Кнопки «Применить результаты» НЕТ (поправка Mac-Claude — не одобрено владельцем).
- unpost («вернуть в черновик») отменяет проведение и удаляет связанные документы.
- post/unpost — временная совместимость для мобильного «FM Склад» (post = завершить +
создать и провести оба документа); помечено в docs/mobile-api.md.
- Enter/Loss: поле InventoryDocId (+ миграция Phase38) + в DTO «на основании инвентаризации №…».
- InventoryResult (application) — чистая разбивка diff→излишки/недостача (unit-тесты:
разница/сумма/только посчитанные строки/округление).
- InventoryMigrationController (dry-run/apply): старые Posted+InventoryAdjustment →
связанные проведённые документы переметкой движений (не задваивает), с проверкой
неизменности остатков. Скрипт deploy/migrate-inventory-to-docs.sh (backup + запуск).
- Демо-сидеры: инвентаризации теперь Completed без прямых движений.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Дополнен docs/moysklad-logic-audit.md (+ .html) разделом «Проход 2»:
- Все «проверить» закрыты фактом (код файл:строка и/или запрос на стенде):
возврат→ReferenceSaleId; Z-отчёт без «по товарам»; долг поставщику считается
(MoneyReportsController:120-183); обязательные поля товара Name+Unit+Group;
приёмка с телефона/терминалы/фискализация — нет; отмена проведения ЕСТЬ у всех
документов (исправление прохода 1); смена — только ручное открытие.
- Себестоимость: подтверждён FIFO у МойСклада; у нас средняя; реальный пример Демо
(BIOBLAS, Product.Cost=548.6441 из 3 приёмок) — показано искажение прибыли.
- Казахстан (новое): фискализация ОФД РК (заглушка у нас; МойСклад — WebKassa/reKassa),
НДС 16% с 2026 (дефолт KZ уже 16, SystemReferenceSeeder:38), маркировка ИС МПТ
(только флаг IsMarked), СНТ/ЭСФ, акциз. Блок «Казахстан — обязательное по закону».
- Сводка обновлена: топ-15 скорректирован (фискализация/маркировка РК вместо неверных
пунктов), добавлен KZ-блок. Касса МойСклад vs наша — по функциям кассира.
Только отчёт, без правок кода.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Сверка всех процессов простого режима + справочников/кассы/мобильного/отчётов с
МойСкладом (API dev.moysklad.ru + support.moysklad.ru + школа торговли). Для каждого:
как в МойСкладе (ссылки) | как у нас (файл:строка) | расхождение | серьёзность |
слабые места МойСклада | предложение «как лучше» [НА РЕШЕНИЕ ВЛАДЕЛЬЦА].
Главные находки (🔴): себестоимость у нас скользящее среднее vs FIFO у МойСклада;
прибыль берёт COGS приближённо (Product.Cost), а не на момент продажи; инвентаризация
сама двигает остатки и статус «Проведено» без оприходования/списания. Также — какие
наши тесты закрепляют неправильное поведение и должны быть переписаны.
docs/moysklad-logic-audit.md — полный отчёт; .html — краткая версия для владельца.
Только отчёт, без правок кода.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- now-web-login-stage.png: вход на test.admin.food-market.kz после деплоя —
баннер стенда, быстрый вход, логотип ALL MARKET, без тостов ошибок.
- rollback-logo-foodmarket.png: подтверждение отката (лого Food Market).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Отчёт по ревью безопасности (сидер/префилл/ротация пароля стенда), результат
проверки отката в worktree, уточнённые границы (артефакты кассы, маркетинг-скриншоты).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Верхняя полоса: логотип ALL MARKET высотой 48 (ширина ≈140px ≥ минимума
брендбука), «Касса» отделена тонким разделителем (не оторвана).
- Бейдж количества у «Отложенные» теперь целиком внутри кнопки (меньше паддинг
кнопки, плотнее контент) — не обрезается правым краем.
- Перегенерированы скриншоты кассы; обновлён кадр веб-входа в галерее (без тоста,
без префилла пароля).
- Зелёный UI не менялся (--color-brand #00B207, идентичен дорибрендинговому).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>