# Касса МойСклад — reference для POS food-market Сверка перед проектированием кассы (задача владельца). Источник: `https://dev.moysklad.ru/doc/api/remap/1.2/documents/` — розничные документы. Скрейп через headless Playwright (tests/e2e, chromium): SPA МойСклада грузит разделы по фрагменту нестабильно (часть якорей → «Файл не найден»), поэтому ниже — сводка модели по известной семантике МойСклада + успешно считанные разделы (внесение/выплата денег). Нам нужна не калька API, а поведение кассы. ## Сущности розницы (МойСклад) - **Розничная смена** `retailshift` — открывается на точке продаж (ККМ/`retailStore`). Поля: `open`/`close` (bool), `proceedsCash`/`proceedsNoCash` (выручка нал/безнал), `balanceStart` (размен), `balanceEnd`, суммы продаж/возвратов. Пока смена открыта — к ней привязываются продажи/возвраты/внесения/выплаты. - **Розничная продажа** `retaildemand` — чек. Привязан к смене (`retailShift`) и точке. Оплата: `cashSum` (нал) + безнал; позиции `positions` (товар, цена, кол-во, скидка). - **Возврат розничной продажи** `retailsalesreturn` — возврат покупателю, со ссылкой на исходную продажу (`demand`) или без неё, нал/безнал, частичный. - **Внесение денег** `retaildrawercashin` — приход наличных в кассу ККМ внутри смены (размен/инкассация внутрь). Увеличивает наличные в ящике. - **Выплата денег** `retaildrawercashout` — изъятие наличных из кассы ККМ (инкассация наружу/расход). Уменьшает наличные в ящике. ## Деньги и остатки - Касса = `balanceStart` (размен) + Σ продаж нал − Σ возвратов нал + Σ внесений − Σ выплат. - Безнал (карта) идёт на эквайринг/расчётный счёт отдельно. - Закрытие смены: фиксируется факт наличных; расхождение (излишек/недостача) видно в отчёте. - X-отчёт — промежуточный (без закрытия), Z-отчёт — при закрытии смены. ## Как ложится на food-market - У нас уже есть серверный модуль «Деньги» с точно такой моделью (движения смены материализуются при закрытии — см. `docs/money.md`). POS НЕ дублирует эту логику: - смену открывает/закрывает через `POST api/money/shifts/open|{id}/close`; - внесение/выплату — `POST api/money/shifts/{id}/drawer` (In/Out); - продажи уходят батчем в `api/pos/v1/sales` (идемпотентно), сервер создаёт `RetailSale` (Posted), привязанный к открытой смене точки; возвраты — так же (IsReturn + ReferenceSaleId); - остаток кассы/эквайринга и Z-отчёт считает сервер (`api/money/reports`, `api/money/shifts/{id}/report`). - Весовой товар: МойСклад — `weighed`; у нас `Packaging=2` (весовой). Весовой ШК с префиксом 20–29 парсит POS локально (код товара + вес/цена). - Фискализация (ОФД KZ) — отдельно; в POS только интерфейс-заглушка `IFiscalProvider`.