Что описывает эта страница
Раздел отвечает за расходные материалы мастерской и их складской учёт. Здесь два тесно связанных объекта: Складской ресурс — сам расходник с запасом и остатком, и Ресурс задачи мастерской — строка привязки ресурса (или единицы инвентаря) к конкретной ремонтной задаче. Отдельный Сервис складского учёта отвечает за то, чтобы остаток корректно уменьшался при использовании расходника в задаче и возвращался при отмене. Главная идея: остаток на складе — это «живое» число, которое автоматически меняется по мере того, как расходники добавляются в ремонтные задачи и убираются из них. При этом все проверки (хватает ли остатка, допустимо ли дробное количество) выполняются под блокировкой строки, чтобы два одновременных списания не «ушли в минус».Модель данных
Складской ресурс
Расходный материал с учётом запаса. Хранит полный объём закупки и текущий доступный остаток.
Тип учёта определяет поведение количеств:
- Штучный (целые единицы) — количество всегда округляется до целого, дробные значения запрещены (например, «3 фильтра», но не «3,5»).
- Количественный (дробный) — допускается произвольное дробное значение (например, «2,75 литра краски»).
Удаление ресурса — мягкое: при удалении через интерфейс запись лишь помечается как удалённая и пропадает из списков и из выборки для чтения/редактирования. Сама строка и её остаток сохраняются в базе.
Ресурс задачи мастерской
Строка, которая связывает складской ресурс либо единицу/группу инвентаря с конкретной ремонтной задачей, фиксируя количество, стоимость позиции и статус подтверждения.Позиция может ссылаться на складской расходник, на единицу инвентаря или на группу инвентаря — поля независимы и все допускают пустое значение. Складской остаток трогается только тогда, когда заполнен именно складской ресурс; для «инвентарных» позиций списание со склада не выполняется.
Складской учёт: списание, возврат, пересчёт
Все операции над остатком собраны в едином Сервисе складского учёта. Каждая из них выполняется в транзакции и перед изменением остатка берёт блокировку строки ресурса — то есть до конца операции другая параллельная операция не сможет одновременно изменить этот же остаток. Это защищает от гонок при одновременном списании.Списание
Уменьшает остаток ресурса на заданное количество. Порядок проверок:- Если ресурс не указан или количество не положительное — операция ничего не делает и молча завершается.
- Строка ресурса блокируется и перечитывается из базы (берётся актуальный остаток, а не тот, что был в памяти).
- Для штучного ресурса проверяется целостность количества: дробное значение приводит к ошибке «дробное количество недопустимо».
- Если доступный остаток меньше запрошенного — возникает ошибка «недостаточно остатка» с указанием имени ресурса, доступного и требуемого количества.
- Иначе остаток уменьшается на запрошенное количество и сохраняется.
Возврат
Возвращает количество в остаток. Новый остаток вычисляется как текущий остаток плюс возвращаемое количество, но не выше общего количества ресурса — то есть остаток никогда не превысит полный запас на складе. Пустой ресурс или неположительное количество игнорируются.Пересчёт
Применяется при правке позиции: сначала выполняется возврат старого количества старого ресурса, затем списание нового количества нового ресурса. Так корректно обрабатывается и смена ресурса, и изменение количества в уже существующей строке. Обе операции идут в одной транзакции, поэтому если новое списание не проходит (не хватает остатка или дробное штучное количество), уже сделанный возврат откатывается вместе с ним.Где и когда меняется остаток
Это ключевой и неочевидный момент раздела: списание/возврат остатка привязаны к разным точкам жизненного цикла позиции.- Списание и пересчёт вызываются только внутри формата при создании и правке позиции через API. То есть остаток уменьшается ровно в момент, когда позицию добавляют к задаче или редактируют через соответствующий адрес.
- Возврат вызывается автоматически при удалении позиции. Поэтому когда удаляют саму ремонтную задачу, её позиции удаляются каскадно, для каждой срабатывает возврат, и остаток корректно возвращается на склад.
Обработка ошибок склада
Сервис складского учёта намеренно не знает про HTTP и бросает собственные, «фреймворко-независимые» исключения — «недостаточно остатка» и «дробное количество недопустимо». Превращение их в понятный ответ API происходит на границе формата: вызовы списания и пересчёта обёрнуты в трансляцию складских ошибок, которая переводит их в обычную ошибку валидации с текстом на русском:- нехватка остатка → сообщение вида «Недостаточно «
название». Доступно: …, требуется: …»; - дробное количество для штучного ресурса → «
названиеучитывается в целых единицах».
Как это используется
Справочник складских ресурсов
Список и создание ресурсов доступны аутентифицированным пользователям; из выборки всегда исключены мягко удалённые записи. При создании нового ресурса действует правило: если остаток явно не задан, он приравнивается к общему количеству — «свежий» запас изначально доступен целиком. Удаление ресурса переводит его в состояние «удалён» (мягкое удаление), а не стирает физически. Для штучных ресурсов при сохранении справочника дробная часть у общего количества и остатка отбрасывается (значения приводятся к целым). Дополнительно проверяется, что остаток не отрицателен и не превышает общее количество.Позиции задачи
Позиции читаются и создаются в контексте конкретной задачи (задача берётся из адреса запроса, а не из тела). При создании позиции, если она ссылается на единицу инвентаря, помимо стандартных проверок выполняется собственная проверка на дубликат по сочетанию «задача + единица инвентаря + группа инвентаря», и при совпадении возвращается ошибка. Для позиций без единицы инвентаря эта проверка не выполняется. После сохранения строки происходит списание остатка привязанного складского ресурса; при правке — пересчёт (возврат старого, списание нового).Проверка дубликата при сохранении (по задаче, единице и группе инвентаря) и жёсткое ограничение уникальности в базе (по компании, единице инвентаря и задаче) — это два разных барьера с немного разным набором полей. Оба срабатывают только при заполненной единице инвентаря. Ограничение базы — окончательная гарантия целостности; проверка формата даёт более раннее и понятное сообщение об ошибке.
Связанные страницы
Глоссарий: Ресурсы и склад
Полный перечень полей складского ресурса и позиции задачи мастерской.
Мастерская (ремонтные задачи)
Обзорная страница модуля мастерской и навигация по всем его разделам.
Воронка и задачи
Kanban-воронки, этапы и ремонтные задачи с их статусами, порядком и агрегатами по списку.
Услуги
Привязка услуг из каталога к ремонтным задачам с тарифом, ценой и длительностью.
Стоимость и оплаты
Автоагрегация цены задачи из ресурсов и услуг и суммы оплат из платежей, плюс статусы оплаты.
Метрика прибыли
Проецирование прибыли по ресурсам и услугам завершённой задачи в общую таблицу метрик.
Автосмена состояния инвентаря
Автоматический перевод инвентаря в целевое состояние при движении задачи по воронке.