Перейти к содержимому

POS (точка продажи)

Назначение

Кассовые операции: POS-терминалы, кассовые смены, чеки (продажи и возвраты). Учёт всех продаж в реальном времени — от открытия смены до приёмки итогов управляющим.

3 контроллера, ~12 эндпоинтов.


Сценарии

POS-терминалы

Актор: Управляющий / Администратор

Рабочее место кассира (физический терминал или планшет).

При создании: название (уникальное в корпорации), код, привязка к подразделению (опционально).

Кассовая смена

Жизненный цикл:

OPEN ─── закрытие ──► CLOSED ─── приёмка ──► ACCEPTED
│ NOT_ACCEPTED
└── проверка ──► REQUIRES_CHECK ──► ACCEPTED
NOT_ACCEPTED

Открытие

Актор: Кассир

  1. Выбор терминала, начальный баланс кассы
  2. Проверка: нет открытой смены на терминале
  3. Расчёт учётной даты:
    • Если текущее время < начало учётного дня (напр. 06:00) → учётная дата = вчера
    • Иначе → учётная дата = сегодня
  4. Генерация номера смены
  5. Статус → OPEN

Бизнес-правила (агрегат CashShiftAggregate, instance + static):

  • Одна открытая смена на терминал (validateNoOpenShift)
  • Начальный баланс ≥ 0

Закрытие

Актор: Кассир

  1. Проверка: все чеки закрыты (validateAllReceiptsClosed)
  2. Агрегация итогов: totalSales, totalReturns, totalCash, totalCard, totalCashless
  3. Указание closedBy
  4. Статус → CLOSED

Приёмка

Актор: Управляющий

Проверяет итоги и принимает решение:

  • ACCEPTED — суммы сходятся
  • NOT_ACCEPTED — расхождения (недостача, ошибки)
  • REQUIRES_CHECK — нужно разобраться

Из REQUIRES_CHECK → ACCEPTED или NOT_ACCEPTED.

Правила: приёмка только из CLOSED или REQUIRES_CHECK (validateCanAccept).

Кассовый чек

Актор: Кассир / Официант

Типы операций:

  • SALE — продажа
  • RETURN — возврат (ссылается на оригинальный чек)

Структура:

Чек #42 (SALE)
├── Официант: Иванов И.И.
├── Кассир: Петрова А.А.
├── Позиции:
│ ├── Стейк Рибай × 2 — 3 200р (скидка 200р → 3 000р)
│ ├── Цезарь × 1 — 650р
│ └── Американо × 2 — 500р
├── Итого: 4 350р − 200р = 4 150р
└── Оплаты:
├── Карта — 3 000р
└── Наличные — 1 150р

Сплит-оплата: один чек — несколько методов (наличные + карта + бонусы).

Возврат:

  • Ссылка на оригинальный чек
  • Нельзя возврат на самого себя
  • В отчётах — суммы со знаком минус

Бизнес-правила (агрегат PosReceiptAggregate, static):

  • Минимум одна позиция
  • Количество > 0, цена ≥ 0
  • Скидка ≥ 0
  • Сумма оплаты > 0
  • Все суммы неотрицательны

Учётная дата

Рестораны работают до 2–4 ночи. Настройка время начала учётного дня определяет, к какому дню относится операция.

Пример (начало = 06:00):

ВремяУчётная дата
23:00 5 марта5 марта
03:00 6 марта5 марта (до 06:00 — «вчера»)
07:00 6 марта6 марта

Реализуется через calculateAccountingDate() с поддержкой timezone.


Связи с другими контекстами

НаправлениеЧтоЗачем
Организация → POSTimezone, учётный деньРасчёт учётной даты смены
Организация → POSСотрудникиПроверка принадлежности к корпорации
Кадры → POSСотрудникиКто открыл/закрыл смену, официант/кассир чека
Меню → POSНоменклатураПозиции чеков
Закупки → POSМетоды оплатыОплаты в чеках
POS → ОтчётностьЧеки, позиции, оплатыИсточник для отчётов по выручке
Бухгалтерия → POSТипы внесений/изъятийКассовые операции (инкассация, размен)

Сущности

СущностьОписание
POS-терминал (PosTerminal)Рабочее место кассира. Название, код, подразделение
Кассовая смена (CashShift)Рабочий период: открытие → чеки → закрытие → приёмка. Итоги по продажам/возвратам/методам
Кассовый чек (PosReceipt)Продажа или возврат. Позиции + оплаты. Привязан к смене и сотрудникам
Позиция чека (PosReceiptItem)Номенклатура, количество, цена, скидка, итого
Оплата чека (PosPayment)Метод, сумма, время, авторизовавший. Сплит — несколько оплат на чек