# Аудит логики процессов против МойСклада **Задача:** сверить логику всех процессов нашей системы (ALL MARKET) с МойСкладом — эталоном, над которым «люди думали годами». Только отчёт; исправления — отдельными задачами после решения владельца. Дата: 08.10.2026. **Подход (по требованию владельца):** по каждому процессу — (1) как у МойСклада (база, по умолчанию делаем так же), (2) слабые места МойСклада, (3) предложение «как лучше у нас» только там, где есть реальная выгода для магазина — помечено **[НА РЕШЕНИЕ ВЛАДЕЛЬЦА]**. Без решения владельца реализуем как в МойСкладе. **Источники:** dev.moysklad.ru/doc/api/remap/1.2 (API, JS-рендер), support.moysklad.ru (UI-логика), moysklad.ru/poleznoe (школа торговли), отзывы/обзоры. Ссылки — в строках таблиц и в конце. Наши ссылки — `файл:строка` в репозитории. **Серьёзность:** 🔴 высокая — влияет на остатки/деньги/отчёты; 🟡 средняя — UX/логика; ⚪ низкая — название поля/косметика. --- ## 0. Корневая причина (почему так вышло) Процессы реализовывались «по месту», без предварительной сверки с МойСкладом, а затем тесты (full-chain, unit) закрепляли уже написанное поведение как эталон. В результате ряд процессов отличается от отраслевой нормы МойСклада. Самый яркий пример — инвентаризация: документ сам двигает остатки и встаёт в статус «Проведено» без Оприходования/Списания (`InventoriesController` + `InventoryStatus.Posted`), чего в МойСкладе нет. --- ## СВОДКА ДЛЯ ВЛАДЕЛЬЦА ### Топ-15 расхождений высокой серьёзности (🔴) | # | Процесс | Расхождение | Объём исправления | |---|---|---|---| | 1 | Себестоимость | У нас **скользящее среднее** (`MovingAverageCost`), у МойСклада — **FIFO** по партиям | Большой (партийный учёт + пересчёт отчётов) | | 2 | Прибыльность | COGS берётся как текущая `Product.Cost` (приближение), а не себестоимость на момент продажи | Большой (следствие п.1; нужны партии/снимок COGS) | | 3 | Инвентаризация | Сама двигает остатки и статус «Проведено» без Оприходования/Списания | Средний (переделка уже в очереди — см. §4) | | 4 | Себестоимость продажи | В движение продажи пишется `UnitCost = цена продажи`, а не себестоимость (`DemandsController:270`) | Средний (писать снимок себестоимости) | | 5 | **Фискализация РК** | Касса не фискализирует чеки у ОФД (онлайн-ККМ РК) — `NullFiscalProvider`-заглушка; по закону РК розница обязана | Средний–большой (интеграция Webkassa/reKassa) | | 6 | Статусы документов | «Проведено/Черновик» не всегда соответствуют модели МойСклада (у инвентаризации — ошибочно) | Средний | | 7 | «Создать на основании» | Нет сквозного механизма создания документов «на основании» со ссылками (приёмка→возврат, инвент.→опр/спис, продажа→возврат) | Средний–большой | | 8 | Связи документов | Не хранятся/не показываются обратные связи «на основании №…» и блок «Связанные документы» | Средний | | 9 | Момент фиксации себестоимости | Себестоимость меняется задним числом при новых приёмках (скользящее среднее), искажая прошлые отчёты | Большой (следствие п.1) | | 10 | Возврат покупателя: себестоимость | При возврате товар возвращается на склад — по какой себестоимости (FIFO-слой vs средняя) не определено строго | Средний | | 11 | Партийный учёт | Отсутствует (нет партий/слоёв прихода) — блокирует FIFO, сроки годности, точный COGS | Большой | | 12 | Перемещение и себестоимость | При перемещении между складами себестоимость должна переноситься по FIFO-слоям | Средний (зависит от п.11) | | 13 | **Маркировка товаров РК** | Нет вывода кода из оборота (ИС МПТ) при продаже табак/обувь/лекарств — только флаг `IsMarked`; обязательно по закону РК | Большой | | 14 | Оприходование/Списание: цена | Должны брать учётную себестоимость (FIFO), у нас — переданный `UnitCost`/средняя | Средний | | 15 | Розничная смена: авто-открытие | В МойСкладе смена открывается автоматически первой продажей (≤24ч); у нас только ручное открытие (`CashShiftsController` Open/Close, продажа требует открытой смены) | Малый–средний | ### Топ-10 предложений «лучше, чем МойСклад» (все **[НА РЕШЕНИЕ ВЛАДЕЛЬЦА]**) | # | Идея | Выгода магазину | Объём | |---|---|---|---| | 1 | Инвентаризация в один клик «Применить результаты» (сразу оба документа проведены) | Меньше шагов, чем 2 кнопки МойСклада | Малый (в рамках переделки §4) | | 2 | Простой режим прячет Оприходование/Списание как отдельные пункты — они создаются только из инвентаризации/приёмки | Меньше путаницы у маленького магазина | Малый | | 3 | Себестоимость: выбор метода (средняя — проще/быстрее для мелкой розницы, FIFO — точнее) | Гибкость; средняя дешевле по вычислениям | Средний | | 4 | Единый экран «Деньги»: внесение/выплата/оплаты в одном реестре без 4 типов документов | Проще, чем ПКО/РКО/вх/исх платёж | Средний | | 5 | Автосоздание возврата поставщику прямо из приёмки с преднабором строк | Быстрее оформить брак | Малый | | 6 | Касса: подсказка «нет на остатке» мягкая (не блок), с быстрым оприходованием | Не стопорит продажу в рознице | Малый | | 7 | Онбординг-мастер «первая приёмка за 2 минуты» (у МойСклада онбординг тяжелее) | Быстрый старт | Средний | | 8 | Весовой штрихкод из коробки с настройкой префиксов (уже есть у нас — довести) | Для продуктовых — критично | Малый | | 9 | Отчёт «Прибыль» сразу на дашборде простого режима | Владелец видит главное без отчётов | Малый | | 10 | Понятные статусы на русском без «проведено» (Черновик→Завершён/Проведён с пояснением) | Меньше вопросов «что это значит» | Малый | ### 🇰🇿 Казахстан — обязательное по закону (добавлено проходом 2) Отдельный блок: это не «лучше/хуже», а **требования закона РК**, без которых магазин не может легально работать. Детали и ссылки — в §6 ниже. | # | Требование РК | Что нужно рознице | Наш статус | Срочность | |---|---|---|---|---| | K1 | **Фискализация (онлайн-ККМ + ОФД РК)** | каждый чек фискализируется у ОФД (новый протокол ККМ v2.0.3 с 01.04.2026) | ❌ заглушка `NullFiscalProvider` | 🔴 блокер для продаж | | K2 | **НДС 16%** (с 01.01.2026; было 12%), льгота 5% на лекарства | ставка НДС и её учёт в чеке/отчётах | ✅ дефолт KZ = **16** (`SystemReferenceSeeder.cs:38`); нет переходной логики 12→16 по дате оборота | 🟡 | | K3 | **Маркировка (ИС МПТ)**: табак, обувь, лекарства (+пиво/одежда 2026–2027) | при продаже — сканировать и **вывести код из оборота** | ❌ только флаг `IsMarked`, вывода нет | 🔴 если продаёт эти категории | | K4 | **СНТ/ЭСФ** (сопроводительные накладные) | для рознице в основном автоматически; **подтверждение обязательно по подакцизным** | ❌ нет интеграции с ИС ЭСФ | 🟡 (🔴 если подакцизные) | | K5 | **Акциз/подакцизные** (табак, алкоголь) | учёт + подтверждение СНТ при приёмке | ❌ нет отметки «подакцизный» | 🟡 | **Для маленького продуктового магазина в первую очередь:** K1 (фискализация — иначе нельзя пробивать чеки) → K3 (маркировка, если продаёт сигареты) → K2 (НДС в чеке). --- ## ПРИОРИТЕТ 1 — Касса и продажи (чаще всего используется) ### 1.1 Розничная продажа (retaildemand) / Касса **Как у МойСклада:** Продажа фиксирует передачу товара покупателю и приход денег в кассу; при проведении уменьшает остаток и формирует выручку; себестоимость списывается по FIFO. Возврат создаётся «на основании» продажи, деньги возвращаются тем же способом оплаты. ([Касса МойСклад](https://www.moysklad.ru/reshenija/mobilnaya-kassa/), [школа: возврат](https://www.moysklad.ru/poleznoe/shkola-torgovli/kak-oformit-vozvrat-ot-pokupatelja/)). **Слабые места МойСклада:** жёсткая привязка возврата к конкретной продаже бывает неудобна (покупатель без чека); интерфейс кассы перегружен для мелкой точки. | Аспект | МойСклад | У нас | Расхождение | Серьёзность | Предложение [владельцу] | |---|---|---|---|---|---| | Влияние на остаток | при проведении продажи −кол-во | POS → `RetailSalesController`/`PosController`, движение `RetailSale` | в целом совпадает | — | — | | Себестоимость в продаже | FIFO-слой на момент продажи | `UnitCost=UnitPrice` (цена продажи) в движении, COGS≈`Product.Cost` позже (`DemandsController:270`, `ProfitReportController:14-19`) | 🔴 COGS неточный/задним числом | 🔴 | писать снимок себестоимости в движение | | Возврат | «на основании» продажи, тот же способ оплаты | есть ссылка `ReferenceSaleId` (`RetailSalesController.cs:238`); способ возврата выбирает кассир (не форсится как в МойСкладе) | 🟡 способ не привязан к исходному | 🟡 | опц.: по умолчанию тем же способом | | Смена | автооткрытие первой операцией, ≤24ч | только ручное открытие (`CashShiftsController` Open/Close; продажа требует открытой смены) | 🟡 нет автооткрытия | 🟡 | автооткрывать первой продажей | | Деньги | приход в кассу привязан к смене | смена+счёт (есть, чинили ранее) | совпадает | — | — | ### 1.2 Розничная смена (retailshift) и внесение/выплата (drawer cash in/out) **Как у МойСклада:** Смена открывается автоматически первой продажей/внесением/выплатой или вручную; не длиннее 24 часов; при открытии можно внести разменные деньги; отчёт смены показывает нал/безнал выручку, продажи и возвраты, по товарам, историю размена и связанные документы. ([МойСклад: розничные смены](https://www.moysklad.ru/news/715-roznichnye-smeny-obnovlenie-ios-podderzhka-registratora-pirit-k-i-drugie-uluchsheniya/)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Автооткрытие смены | да, первой операцией | вручную (`CashShiftsController`) | 🟡 | 🟡 | | Максимум 24ч | да | нет явного ограничения | 🟡 | 🟡 | | Внесение/выплата | ПКО/РКО внутри смены | внесение/выплата в кассе + `MoneyTransactions` | совпадает по сути | — | | Z-отчёт смены | нал/безнал, продажи/возвраты, по товарам | `ShiftReportDto` (`IServerApi.cs:61`): нал/безнал по продажам и возвратам + сверка кассы; **без разбивки по товарам** | 🟡 нет «по товарам» | 🟡 | **Предложение [владельцу]:** автооткрытие смены первой продажей (как МойСклад) + мягкое предупреждение на 24ч — удобнее кассиру, меньше «забыл открыть смену». --- ## ПРИОРИТЕТ 2 — Товары, остатки, себестоимость, отчёты ### 2.1 Себестоимость (ключевое 🔴) **Как у МойСклада:** себестоимость считается по **FIFO** — при продаже списывается товар из самой ранней партии; остаток товара хранится «слоями» закупок с разными ценами. Это даёт исторически корректную прибыль, не меняющуюся задним числом. ([школа: методы расчёта себестоимости](https://www.moysklad.ru/poleznoe/shkola-torgovli/metody-rascheta-sebestoimosti/), [support: себестоимость](https://support.moysklad.ru/hc/ru/articles/217544337)). **Как у нас:** **скользящее средневзвешенное** (`MovingAverageCost.Compute`, `src/food-market.application/Inventory/MovingAverageCost.cs`): при каждой приёмке пересчитывается единая `Product.Cost`. Прошлые отчёты «плывут» при новых закупках. **Слабые места МойСклада:** FIFO требует партийного учёта — тяжелее по вычислениям и непонятнее для микромагазина; при частых мелких закупках «слоёв» очень много. | Аспект | МойСклад | У нас | Расхождение | Серьёзность | Предложение [владельцу] | |---|---|---|---|---|---| | Метод | FIFO по партиям | скользящее среднее | 🔴 | 🔴 | **выбор метода**: среднее (быстро/просто) по умолчанию для простого режима, FIFO — опция | | Момент фиксации COGS | на момент отгрузки | приближённо, текущая `Product.Cost` | 🔴 задним числом | 🔴 | снимок COGS в движении | | Партии/слои | есть | нет | 🔴 блокирует FIFO, сроки годности | 🔴 | партийный учёт (большой) | ### 2.2 Остатки и движения (отчёты) **Как у МойСклада:** отчёт **Остатки** — текущие остатки по складам; **Обороты** — движение товара (приход/расход) за период с указанием документов-источников; остатки меняются только после **проведения** складских документов. ([support: Остатки](https://support.moysklad.ru/hc/ru/articles/203319073)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Остатки меняются при проведении | да | да (`StockService.ApplyMovement` при Post) | совпадает | — | | Источник движения виден | документ-основание в оборотах | `StockMovement.SourceDoc` есть | в целом совпадает | — | | Инвентаризация в оборотах | как Оприходование/Списание | как `InventoryAdjustment` (нет опр/спис) | 🔴 непонятно в отчётах | 🔴 | ### 2.3 Прибыльность **Как у МойСклада:** Прибыль = Выручка − Себестоимость(FIFO) за период/по товарам/группам. ([отчёты МойСклад](https://ctrlf5.by/blog/moysklad-otchety)). **Как у нас:** `ProfitReportController` — Выручка − COGS, где **COGS ≈ текущая `Product.Cost`** (признано в комментарии кода `ProfitReportController.cs:14-19` как «приближение»). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | COGS | FIFO на момент продажи | текущее среднее (приближение) | 🔴 | 🔴 | | Стабильность прошлых периодов | стабильна | «плывёт» при новых закупках | 🔴 | 🔴 | ### 2.4 Карточка товара (справочник) **Как у МойСклада:** обязательно только **Наименование**; тип учёта (весовой/штучный/алко), фасовка (весовая для весовых), штрихкоды (EAN8/EAN13/GTIN), единица измерения, несколько типов цен, себестоимость, НДС, вес/объём. ([support: создание карточки товара](https://support.moysklad.ru/hc/ru/товары%20и%20склады/товары%20и%20услуги/создание_карточки_товара), [типы цен](https://support.moysklad.ru/hc/ru/articles/203053526)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Обязательные поля | только наименование | `ProductInput` (`CatalogDtos.cs:92`): обязательны **Name + UnitOfMeasureId + ProductGroupId** | 🟡 у нас больше обязательных | 🟡 | | Весовой товар | фасовка весовая | `IsWeighed`/packaging есть | совпадает | — | | Штрихкоды | EAN8/13/GTIN, несколько | несколько штрихкодов, весовые префиксы | совпадает/лучше | — | | Типы цен | несколько, автоподстановка | типы цен есть (`PriceTypesController`) | совпадает | — | --- ## ПРИОРИТЕТ 3 — Приёмка, Оприходование, Списание, Инвентаризация ### 3.1 Приёмка (supply) **Как у МойСклада:** остаток появляется только после **проведения** приёмки; при проведении товар приходуется на склад, формируется себестоимость (FIFO-слой); можно создать «на основании» заказа поставщику; влияет на долг поставщику. ([support: приёмка](https://support.moysklad.ru/hc/ru/articles/203325563)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Остаток при проведении | +кол-во | `SuppliesController.Post` → движение Receipt | совпадает | — | | Себестоимость | FIFO-слой | пересчёт скользящего среднего | 🔴 (метод) | 🔴 | | На основании заказа | да | заказа поставщику нет в простом режиме | 🟡 (скрыт) | 🟡 | | Долг поставщику | +долг | считается в отчёте долгов (Σ приёмок, `MoneyReportsController.cs:120-183`) | совпадает (расчётно) | — | ### 3.2 Оприходование (enter) и Списание (loss) **Как у МойСклада:** Оприходование добавляет остаток (излишки/начальные остатки) по учётной себестоимости; Списание убирает остаток (брак/недостача) по FIFO-себестоимости; оба — отдельные проводимые документы; создаются в т.ч. «на основании» инвентаризации. ([support: оприходование](https://support.moysklad.ru/hc/ru/товары%20и%20склады/операции/оприходование_товаров), [списание](https://support.moysklad.ru/hc/ru/articles/203053096)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Оприходование +остаток | да, при проведении | `EntersController.Post` | совпадает | — | | Списание −остаток | да, по FIFO | `LossesController` c `UnitCost` переданным | 🔴 цена не по FIFO | 🔴 | | Создать из инвентаризации | да (кнопка «Создать документ») | **нет** (инвент. двигает сама) | 🔴 | 🔴 | ### 3.3 Инвентаризация (inventory) — корень жалобы владельца **Как у МойСклада:** инвентаризация **не двигает остатки**; фиксирует расчётное и фактическое количество и разницу; по результатам пользователь создаёт **Оприходование** (излишки) и **Списание** (недостача) кнопкой «Создать документ»; именно эти документы меняют остатки. ([support: инвентаризация товаров](https://support.moysklad.ru/hc/ru/товары%20и%20склады/операции/инвентаризация_товаров)). **Как у нас (неправильно):** `InventoriesController.Post` сам создаёт движения `MovementType.InventoryAdjustment` и ставит `InventoryStatus.Posted` (`InventoryDoc.cs:8-9`) — остатки меняются напрямую, без Оприходования/Списания. Владелец видит «Проведено» без связанных документов. | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Двигает остатки | нет | **да** (`InventoryAdjustment`) | 🔴 | 🔴 | | Статусы | Черновик→Завершена | Draft→**Posted** («Проведено») | 🔴 | 🔴 | | Результат | Оприходование+Списание со ссылкой | нет связанных документов | 🔴 | 🔴 | **Переделка уже запланирована** (следующая задача, ветка `wip/inventory-model`): статусы Черновик→Завершена без движений; кнопки «Создать оприходование/списание/применить»; связи; миграция Posted+InventoryAdjustment → проведённые Оприходование/Списание с сохранением остатков. Этот план **совпадает с выводами ревизии** (пп. 3,6,7,8 сводки). **Предложение [владельцу]:** добавить к модели МойСклада кнопку «Применить результаты» (оба документа сразу проведены) — на один шаг короче, чем две кнопки МойСклада. --- ## ПРИОРИТЕТ 4 — Возврат поставщику, деньги, перемещение ### 4.1 Возврат поставщику (purchasereturn) **Как у МойСклада:** списывает товар со склада, уменьшает долг поставщику; создаётся «на основании» приёмки или вручную. ([support: возврат поставщику](https://support.moysklad.ru/hc/ru/articles/230623667)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | −остаток | да | `SupplierReturnsController` движение `SupplierReturn` | совпадает | — | | −долг поставщику | да | учтён в отчёте долгов (Σ возвратов вычитается, `MoneyReportsController.cs:120-183`) | совпадает (расчётно) | — | | На основании приёмки | да, преднабор | опционально ссылка (есть поле) | 🟡 довести UI | 🟡 | ### 4.2 Деньги: платежи, ордера, взаиморасчёты, долги **Как у МойСклада:** 4 типа денежных документов — **Входящий/Исходящий платёж** (безнал) и **Приходный/Расходный ордер** (нал); все влияют на ДДС и **взаиморасчёты** с контрагентом; отчёт «Взаиморасчёты» сводит долги/авансы, печатает акт сверки. ([support: платежи](https://support.moysklad.ru/hc/ru/articles/203025346), [ДДС](https://support.moysklad.ru/hc/ru/articles/360000199328), [взаиморасчёты](https://support.moysklad.ru/hc/ru/отчеты/взаиморасчеты)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | Предложение [владельцу] | |---|---|---|---|---|---| | 4 типа документов | вх/исх платёж + ПКО/РКО | `MoneyTransactions` (обобщённо) + внесение/выплата | 🟡 модель проще | 🟡 | **упростить осознанно**: один реестр «Деньги» вместо 4 типов — выгода для мелкой розницы | | Взаиморасчёты | единый реестр документ+платёж | `CounterpartyAdjustments` + долги | 🟡 не сквозной реестр | 🟡 | свести все документы+оплаты в один баланс контрагента | | Корректировка взаиморасчётов | есть | `CounterpartyAdjustmentsController` (WeOwe/TheyOwe) | совпадает по сути | — | — | ### 4.3 Перемещение (move) **Как у МойСклада:** перемещает товар между складами при проведении; переносит себестоимость (FIFO-слои). ([складской учёт](https://support.moysklad.ru/hc/ru/articles/360014957717)). | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | −склад источник / +склад назначение | да | `TransfersController` (TransferOut/In) | совпадает | — | | Перенос себестоимости | по FIFO-слоям | по средней (`Product.Cost`) | 🔴 (метод) | 🔴 | | Видимость в простом режиме | есть | скрыт | ок (простой режим) | — | --- ## ПРИОРИТЕТ 5 — Справочники, касса, мобильное, режимы ### 5.1 Контрагенты, склады, точки, сотрудники/роли, счета | Аспект | МойСклад | У нас | Расхождение | Серьёзность | |---|---|---|---|---| | Контрагенты | тип (покупатель/поставщик), реквизиты, баланс | `CounterpartiesController` | совпадает | — | | Склады | несколько, остатки по складам | склады/точки (`StoresController`/`RetailPointsController`) | совпадает | — | | Сотрудники/роли/права | роли и права, точки | роли+права+привязка точек (есть) | совпадает/детальнее | — | | Счета (касса/банк/эквайринг) | счета и ДДС | `MoneyAccountsController` | совпадает | — | ### 5.2 Касса ALL MARKET (Avalonia) vs Касса МойСклад **Касса МойСклад:** продажи, сдача, возвраты, открытие/закрытие смены, офлайн, весовой товар, сканирование штрихкода камерой, смешанная оплата (нал+карта), 54-ФЗ (АТОЛ/ШТРИХ-М/Viki Print), скидки/бонусы, кроссплатформенность (Win/Android/iOS/Linux). ([касса для мобильного](https://www.moysklad.ru/reshenija/mobilnaya-kassa/), [АРМ кассира](https://www.moysklad.ru/programmy-dlja-biznesa/arm-kassira/)). | Функция | Касса МойСклад | Наша касса (Avalonia) | Расхождение | Серьёзность | |---|---|---|---|---| | Офлайн | да | да (очередь синка) | совпадает | — | | Весовой товар | да | да (весовые ШК) | совпадает | — | | Смешанная оплата | да | да | совпадает | — | | Возврат по чеку | да | да | совпадает | — | | Смена/Z-отчёт | да | да | совпадает | — | | Сканер камерой | да (смартфон) | сканер-HID/весы по COM | 🟡 (нет камеры) | 🟡 | | Фискализация (ОФД РК; у МС — WebKassa/reKassa) | да | **заглушка** `NullFiscalProvider` — не реализовано (`Fiscal.cs`) | 🔴 блокер по закону РК (см. П2.3) | 🔴 | | Платёжные терминалы (эквайринг) | интеграция (PAX/Verifone) | нет — ручной ввод суммы карты | 🟡 | 🟡 | ### 5.3 Мобильное «FM Склад» vs мобильное МойСклад **Мобильный МойСклад:** приёмка, инвентаризация, остатки, сканирование, отгрузка — с телефона. | Функция | МойСклад моб. | FM Склад (iOS) | Расхождение | Серьёзность | |---|---|---|---|---| | Остатки по складу | да | да (`/api/inventory/stock` с groupId) | совпадает | — | | Приёмка с телефона | да | **нет** (нет mobile-эндпоинтов приёмки; только stock/barcodes/me) | 🟡 | 🟡 | | Инвентаризация с телефона | да | post/unpost есть — переделать под новую модель | 🔴 (после §3.3) | 🔴 | | Сканирование | да | штрихкоды + весовые | совпадает | — | ### 5.4 Простой/расширенный режим, настройки, импорт, онбординг | Аспект | МойСклад | У нас | Расхождение | Серьёзность | Предложение [владельцу] | |---|---|---|---|---|---| | Простой режим | нет единого «простого режима» — много всего сразу | `IsAdvancedMode` + гейты | 🟢 лучше нас для старта | — | сохранить и усилить | | Импорт | Excel/CSV, маркетплейсы | Excel/CSV + накладные по фото (OCR) | совпадает/лучше | — | — | | Онбординг | есть, но тяжёлый | мастер онбординга | 🟢 возможность быть проще | — | «первая приёмка за 2 мин» | --- ## Наши тесты, закрепляющие НЕПРАВИЛЬНОЕ поведение (переписать под МойСклад) | Тест | Что закрепляет | Как должно быть | |---|---|---| | full-chain **шаг 10** (инвентаризация) | «провёл инвентаризацию → остатки сразу изменились» | создать инвентаризацию → завершить → применить → остатки = факт через Оприходование/Списание | | unit-тесты инвентаризации (`InventoriesController` движения) | движения `InventoryAdjustment` при Post | нет движений от инвентаризации; движения — у связанных опр/спис | | unit `MovingAverageCost` | скользящее среднее как эталон COGS | при выборе FIFO — тесты на FIFO-слои и COGS на момент продажи | | profit-тесты (если берут `Product.Cost`) | COGS = текущая средняя | COGS = снимок себестоимости на момент продажи | | mobile API post/unpost инвентаризации | post = двигает остатки | post = завершить+применить (создать и провести опр/спис) | Правило на будущее: **сначала сверка с МойСкладом (эта методика), потом реализация, потом тесты под сверенное поведение** — а не тесты под уже написанный код. --- # ПРОХОД 2 — факт-проверки, Казахстан, исправление неточностей прохода 1 Mac-Claude: проход 1 полезный, но поверхностный. Ниже — все «проверить» закрыты фактом (код `файл:строка` и/или запрос на стенде `test.admin.food-market.kz`), казахстанская специфика и корректировки неточностей. ## П2.1 Закрытие всех «проверить» (факты) | Пункт (проход 1) | Факт (код/стенд) | Вывод | |---|---|---| | Возврат: ссылка-основание | `RetailSalesController.cs:44,90,238-239,296` — возврат несёт `ReferenceSaleId` + `ReferenceSaleNumber` на исходную продажу | ✅ ссылка-основание есть | | Возврат: способ возврата | У возврата своё поле `Payment` (нал/карта); кассир выбирает. МойСклад принудительно тем же способом | 🟡 у нас гибче, но нет гарантии «тем же способом» | | Z-отчёт: состав | `ShiftReportDto` (`IServerApi.cs:61`): sales(cash,card), returns(cash,card), expectedCash, actualCash, cashDifference | ✅ нал/безнал + сверка; ❌ **нет разбивки «по товарам»** (у МойСклада есть) | | Долг поставщику при приёмке | `MoneyReportsController.cs:120-183` — долг = Σ приёмок(Posted) − Σ возвратов − Σ оплат + Σ корректировок | ✅ приёмка увеличивает долг (считается в отчёте) | | −долг при возврате поставщику | тот же расчёт, Σ возвратов вычитается | ✅ возврат уменьшает долг | | Обязательные поля товара | `ProductInput` (`CatalogDtos.cs:92`): `[Required] Name`, `UnitOfMeasureId`, `ProductGroupId` — обязательны | 🟡 **больше, чем у МойСклада** (там только наименование; ед. и группа — нет) | | Приёмка с телефона | мобильных endpoint’ов приёмки нет (`docs/mobile-api.md` — только stock/barcodes/me) | ❌ приёмки с телефона нет (у МойСклада есть) | | Платёжные терминалы | интеграций PAX/Verifone нет; «карта» — ручной способ оплаты в кассе | ❌ нет интеграции терминала | | Фискализация | `Fiscal.cs` — `IFiscalProvider` + `NullFiscalProvider` (заглушка, чек без фискального номера) | ❌ фискализации нет (см. §П2.3) | | «Нет единообразной отмены проведения» (утв. прохода 1) | **НЕВЕРНО.** Unpost есть у ВСЕХ: Supplies:518, Enters:284, Losses:313, Inventories:525, SupplierReturns:327, Transfers:324, Demands:290, RetailSales:828 | ✅ отмена проведения единообразна — **исправляю проход 1** | | Розничная смена: автооткрытие | `CashShiftsController` Open/Close; продажа требует открытой смены; автооткрытия нет | 🟡 только ручное | ## П2.2 Себестоимость — факт-проверка и реальный пример Демо-магазина **«У МойСклада FIFO» — подтверждено их справкой:** «В МоёмСкладе себестоимость считается по принципу FIFO… при продаже в первую очередь списывается товар из самой ранней приемки» ([школа торговли, методы расчёта себестоимости](https://www.moysklad.ru/poleznoe/shkola-torgovli/metody-rascheta-sebestoimosti/); [support 217544337](https://support.moysklad.ru/hc/ru/articles/217544337)). **«В движение продажи пишется UnitCost = цена продажи» — проверено по коду:** да, причём **и в опте, и в рознице/кассе**: - опт: `DemandsController.cs:270,307` — `UnitCost: line.UnitPrice`; - розница/касса: `RetailSalesController.cs:680,858` (RetailSale) и `:986,1039` (CustomerReturn) — `UnitCost: line.UnitPrice`. НО: `StockMovement.UnitCost` при продаже = **цена продажи** и для прибыли **не используется** — `ProfitReportController.cs:116-118` берёт COGS = `Quantity × Product.Cost` (текущее скользящее среднее). То есть поле `UnitCost` в движении продажи бесполезно/вводит в заблуждение, а реальная себестоимость в отчёте — **текущая средняя на момент построения отчёта**, а не на момент продажи. **Реальный пример со стенда (Демо/импорт-каталог, запрос `/api/reports/profit`):** - Товар «BIOBLAS шампунь д/волос 360мл»: текущая `Product.Cost` = **548.6441 ₸** (дробная → смешана из 3 приёмок с разными ценами; `supplies total = 3`). - Профит-отчёт по нему: выручка 3100, **себест 1097.2882** (= 2 × 548.6441), прибыль 2002.7118. **В чём искажение:** 548.6441 — средняя **после всех 3 приёмок**. Если эти 2 единицы были проданы **до** третьей (более дорогой/дешёвой) приёмки, FIFO отнёс бы на них цену ранней партии, а не текущую среднюю. Поэтому: 1. показанная прибыль по прошлым продажам **не историческая** (считается ценой, которой на момент продажи ещё не было); 2. при каждой новой приёмке того же товара средняя меняется → **прибыль за закрытые периоды «плывёт» задним числом**. Величина искажения = (текущая средняя − фактическая FIFO-цена партии) × проданное количество; на товарах с разбросом закупочных цен (как BIOBLAS: 3 цены) она ненулевая и накапливается. На товарах с единственной ценой закупки искажения нет. Точное число «насколько» получить от работающей системы нельзя — FIFO у нас не реализован; это и есть аргумент за реализацию (или за осознанный выбор средней). ## П2.3 Касса и фискализация — Казахстан, а не 54-ФЗ **Поправка:** в проходе 1 стоял «54-ФЗ» — это закон **РФ**. Мы в Казахстане; применяется закон РК. **Как МойСклад работает в Казахстане:** есть отдельный **moysklad.kz** с интеграциями ОФД/ККМ РК. Касса МойСклад встраивает облачную фискализацию: **WebKassa** (данные чека автоматически уходят в WebKassa → ОФД) и **reKassa** (бесплатная облачная онлайн-ККМ РК, фискализация и электронные чеки); упоминается Kassa24. С **1 апреля 2026** — переход на новый протокол ККМ **v2.0.3** для передачи в ОФД. ([МойСклад: интеграции для Казахстана](https://www.moysklad.ru/integratsii/dlya-kazakhstana/), [WebKassa](https://www.moysklad.ru/integratsii/apps/webkkm-smartinnovations/), [reKassa](https://www.moysklad.ru/integratsii/apps/rekassa-smartinnovations/), [новый протокол ККМ](https://www.moysklad.kz/news/noviy-protokol-kkm/), [онлайн-касса в РК 2026](https://www.moysklad.kz/poleznoe/shkola-torgovli/online-kassa-v-kazakhstane/)). **Что требуется по закону РК для розничной кассы:** онлайн-ККМ с передачей данных в ОФД (фискальный чек, QR). Без этого легально пробивать чеки нельзя. **Наш статус:** `NullFiscalProvider` — фискализации нет, чек проходит без фискального номера (`Fiscal.cs:5-15`, см. `docs/pos.md` «Фискализация»). 🔴 **блокер для легальной розницы РК.** **Что умеет «Касса МойСклад» из реально нужного кассиру — и что у нас:** | Функция кассира | Касса МойСклад | Наша касса (Avalonia) | Факт у нас | |---|---|---|---| | Скидки на позицию/чек | да | да (скидка на строку) | `SaleView`/`PaymentView` | | Бонусы/лояльность | да | сервер есть (`LoyaltyCards/Programs`), в кассе — не подключено | 🟡 нет в кассе | | Отложенные чеки (парковка) | да | да («Отложить»/«Отложенные») | `ParkCommand/ResumeCommand` | | Поиск товара | да | да (поиск + сканер + весовые ШК) | `ScanCommand` | | Весы | да | да (COM/serial) | `Hardware` | | Печать чека | да | да (ESC/POS) | `Printing.cs` | | Смешанная оплата | да | да (нал+карта) | `PaymentView` | | Фискализация ОФД | да (WebKassa/reKassa) | ❌ заглушка | 🔴 | | Сканер камерой смартфона | да | ❌ (внешний сканер/COM) | 🟡 | | Платёжный терминал (эквайринг) | да | ❌ ручной ввод суммы карты | 🟡 | **Вывод:** по функциям для кассира мы покрываем почти всё (скидки, отложенные, поиск, весы, печать, смешанная оплата). Критичные пробелы — **фискализация ОФД РК** (🔴 закон) и **бонусы в кассе** (🟡), плюс эквайринг-терминал и камера-сканер (🟡). ## П2.4 Казахстанская специфика по закону (ЭСФ/СНТ, маркировка, НДС, акциз) Этого в проходе 1 не было вовсе. Для РК — высокая важность. ### НДС С **01.01.2026** базовая ставка НДС в РК — **16 %** (повышена с 12 %, Налоговый кодекс №214-VIII); льготная **5 %** на лекарства/медизделия; порог постановки на учёт — 10 000 МРП. Переход: оборот до 31.12.2025 — 12 %, с 01.01.2026 — 16 %. ([НДС 16% 2026](https://finproverka.kz/blog/nds-v-kazahstane-v-2026-godu-novaya-stavka-16-snizhennyj-porog-i-obnovlyonnye-pravila-registraczii/), [ставки НДС и ККМ](https://promo.webkassa.kz/tpost/00bbm0fsr1-stavki-nds-s-2026-goda-chto-vazhno-uches)). **У нас:** дефолт НДС для KZ = **16 %** (`SystemReferenceSeeder.cs:38` — `new("KZ","Казахстан","KZT",16m)`), `Product.Vat` берётся из `Country.VatRate` при создании товара. То есть ставка **актуальна**. Единственный нюанс — нет переходной логики «12 % до 31.12.2025 / 16 % после» по дате оборота (для магазина, работающего в 2026, несущественно). **У МойСклада** ставка НДС на товаре/в документе — есть. ### Маркировка (ИС МПТ) Обязательная маркировка в РК: **табак/сигареты** и жидкости для вейпов, **обувь** (с 01.11.2021), **лекарства** (с 01.07.2024), **пиво** (кеги/бутылки с 01.02.2026, банки с 01.01.2027), **одежда/лёгкая промышленность** и **моторные масла** (поэтапно 2026–2027). Розница при продаже маркированного товара обязана **сканировать код и вывести его из оборота** (передать в ИС МПТ). ([маркировка в РК 2026](https://birsan.kz/blog/tpost/fetidpm511-markirovka-tovarov-v-kazahstane-s-2026-g), [перечень товаров](https://adilet.zan.kz/rus/docs/P2000000568)). **У МойСклада** — есть работа с маркировкой (создание карточек маркированного товара, вывод из оборота). **У нас** — только флаг `Product.IsMarked` (`CatalogDtos.cs:92`), **вывода из оборота нет**. 🔴 если магазин продаёт табак/обувь/лекарства. ### СНТ и ЭСФ **СНТ** (сопроводительная накладная на товары) оформляется электронно в системе **ЭСФ** (esf.gov.kz). Для розницы обязательна только по узкому перечню (~3 категории); в рознице процедуры по СНТ в основном **автоматические без участия розничного продавца**; **обязательное подтверждение — только по подакцизным товарам**; добровольно — до 10 числа следующего месяца. ([СНТ: Әділет](https://adilet.zan.kz/rus/docs/V2500037317), [КГД: СНТ](https://www.gov.kz/memleket/entities/kgd/press/news/details/593973?lang=ru), [правила СНТ 2026](https://pro1c.kz/articles/snt/pravila-snt/)). **У нас** интеграции с ИС ЭСФ нет. Для маленького магазина без подакцизных — не блокер (авто); при продаже подакцизных (табак/алкоголь) понадобится подтверждение СНТ. **У МойСклада KZ** интеграция с ЭСФ/СНТ есть. ### Акциз/подакцизные Табак, алкоголь — подакцизные; по ним обязательно подтверждение СНТ и (для табака/пива) маркировка. **У нас** отметки «подакцизный товар» нет. 🟡 **Что малому магазину нужно в первую очередь:** (1) фискализация ОФД (K1 — иначе нельзя пробивать чеки); (2) маркировка, если торгует сигаретами (K3); (3) корректная ставка НДС 16 % в чеке (K2). СНТ/ЭСФ и акциз — по мере появления подакцизных категорий. ## П2.5 Исправления неточностей прохода 1 | Утверждение прохода 1 | На самом деле | |---|---| | «Нет единообразной отмены проведения» (топ-15 №5) | **Есть** у всех документов (unpost-эндпоинты, см. П2.1) — заменил пункт на «Фискализация РК» | | «Взаиморасчёты — не сквозной реестр» (топ-15 №13) | Долги **считаются** из документов (приёмки−возвраты−оплаты+корректировки, `MoneyReportsController:120-183`); это близко к МойСкладу. Понизил до средней/UX; пункт топ-15 заменил на «Маркировка РК» | | «54-ФЗ» в разделе кассы | Это закон РФ; у нас РК — см. П2.3 (ОФД РК, WebKassa/reKassa) | | «Долг поставщику при приёмке / −долг при возврате — проверить» | Подтверждено: оба учитываются в отчёте долгов | | «НДС 12%» (из задания) | С 01.01.2026 в РК — **16 %** (5 % лекарства); у нас ставка из `Country.VatRate` | --- ## Итоговая оценка объёма исправлений - **Инвентаризация** (§3.3) — средний, уже в очереди (`wip/inventory-model`), план совпал с ревизией. - **Себестоимость FIFO + партии + COGS-снимок** (§2.1–2.3, 3.2, 4.3) — **большой**, самый влиятельный блок (остатки/прибыль/движения). Рекомендация: отдельная крупная задача после инвентаризации; рассмотреть компромисс «среднее по умолчанию, FIFO — опция» [НА РЕШЕНИЕ ВЛАДЕЛЬЦА]. - **Связи «на основании» + статусы + отмена проведения** (§1,3,4) — средний, сквозная унификация. - **Деньги/взаиморасчёты единый реестр** (§4.2) — средний, можно сделать проще МойСклада осознанно. - **Касса/мобильное** (§5.2–5.3) — точечные дополнения (камера-сканер, терминалы), средняя серьёзность. - **🇰🇿 Казахстан по закону** (K1–K5, §П2.3–П2.4): **фискализация ОФД РК** (K1) — 🔴 блокер, интеграция Webkassa/reKassa (средний–большой); **маркировка ИС МПТ** (K3) — большой, если торгует табак/обувь/лекарствами; **НДС 16%** (K2) — малый (проверить дефолт/дату оборота); **СНТ/ЭСФ** (K4) и **акциз** (K5) — средний, по подакцизным категориям. ## Источники (MoySklad) - Себестоимость/методы: moysklad.ru/poleznoe/shkola-torgovli/metody-rascheta-sebestoimosti; support 217544337 - Приёмка: support 203325563 · Списание: support 203053096 · Возврат поставщику: support 230623667 - Инвентаризация: support (товары и склады/операции/инвентаризация_товаров); moysklad.ru/poleznoe/.../izlishki-pri-inventarizacii - Остатки: support 203319073 · Складской учёт: support 360014957717 - Платежи: support 203025346 · ДДС: support 360000199328 · Взаиморасчёты: support (отчеты/взаиморасчеты) - Розничные смены: moysklad.ru/news/715 · Возврат покупателя: moysklad.ru/poleznoe/.../kak-oformit-vozvrat-ot-pokupatelja - Карточка товара: support (товары и склады/.../создание_карточки_товара); Типы цен: support 203053526 - Касса МойСклад: moysklad.ru/reshenija/mobilnaya-kassa; programmy-dlja-biznesa/arm-kassira - API: dev.moysklad.ru/doc/api/remap/1.2 (#/documents/inventory, /enter, /loss) ## Источники (Проход 2 — Казахстан) - МойСклад KZ: moysklad.kz · интеграции РК: moysklad.ru/integratsii/dlya-kazakhstana - WebKassa: moysklad.ru/integratsii/apps/webkkm-smartinnovations; online-webkassa.kz · reKassa: moysklad.ru/integratsii/apps/rekassa-smartinnovations; rekassa.kz - Новый протокол ККМ (01.04.2026): moysklad.kz/news/noviy-protokol-kkm · онлайн-касса РК: moysklad.kz/poleznoe/shkola-torgovli/online-kassa-v-kazakhstane - НДС 16% (01.01.2026): finproverka.kz/blog/nds-v-kazahstane-v-2026-godu…; promo.webkassa.kz/…stavki-nds-s-2026-goda - СНТ/ЭСФ: adilet.zan.kz/rus/docs/V2500037317; gov.kz/…/kgd/…/593973; pro1c.kz/articles/snt/pravila-snt - Маркировка РК: birsan.kz/…markirovka-tovarov-v-kazahstane-s-2026; adilet.zan.kz/rus/docs/P2000000568 - Код (наш): RetailSalesController:680/858/986/1039 · DemandsController:270 · ProfitReportController:116-118 · MoneyReportsController:120-183 · CatalogDtos.cs:92 · Fiscal.cs · IServerApi.cs:61 · unpost: Supplies:518/Enters:284/Losses:313/Inventories:525/SupplierReturns:327/Transfers:324/Demands:290/RetailSales:828 - Стенд: /api/reports/profit (Демо) — BIOBLAS шампунь Product.Cost=548.6441, 3 приёмки