Блокировка закупок: Как запретить снабженцам покупать «в запас»

Разбираем архитектурное решение ModernERP Pro, которое на программном уровне блокирует создание Заказов Поставщику (PO), если они не привязаны к реальной потребности производства.

Вы внедрили стратегию MTO (Make-to-Order). Ваш алгоритм идеально высчитывает дефицит. Но в конце месяца вы открываете баланс и видите, что склад снова переполнен неликвидным металлом, а денег на счету нет.

Почему это происходит? Потому что в большинстве учетных систем кнопка «Создать заказ поставщику» доступна всегда. Снабженец, движимый желанием «подстраховаться» или получить скидку за объем, игнорирует расчетный дефицит и покупает с запасом.

Свобода в закупках — это кассовый разрыв для завода. Система должна не рекомендовать, а запрещать.

Hard Block: Архитектура запрета

В ModernERP Pro мы убрали возможность создавать `PurchaseOrder` (Заказ Поставщику) "из воздуха". Вы не можете просто зайти в раздел Закупок, нажать "Плюс" и набить корзину материалами.

Единственный способ инициировать закупку сырья (`Material`) — это пройти через жесткий процесс валидации.

Шаг 1: Автоматическая генерация PurchaseRequisition (Заявка)

Когда статус производственного заказа меняется на `APPROVED`, алгоритм расчета дефицита анализирует складские остатки. Если не хватает 100 кг стали, система сама генерирует внутреннюю сущность `PurchaseRequisition` (Заявку на закупку) на эти 100 кг. В этой заявке жестко прописана связь с конкретным `ProductionOrder`.

Шаг 2: Конвертация, а не создание

В кабинете снабженца нет кнопки «Создать заказ на металл». У него есть интерфейс обработки заявок. Он выбирает заявки, выбирает поставщика и нажимает кнопку «Конвертировать в PurchaseOrder». Даже если снабженец попытается схитрить и увеличить количество, контроллер выдаст ошибку валидации.

Исключения: Сущность Consumble (Расходники)

Конечно, никто не закупает изоленту, сверла, ветошь или перчатки строго под заказ клиента. Ожидание поставки пачки саморезов парализует работу всего цеха.

Для таких позиций в архитектуре ModernERP Pro предусмотрена отдельная сущность — Consumble (Расходник). Это принципиальное архитектурное отличие от «сырья».

🛠 Полиморфизм в контроллере закупок

Если посмотреть в PurchaseOrderController, можно увидеть, как система разделяет потоки. Сырье (Material) жестко идет в себестоимость по спецификации, а расходники (Consumble) закупаются независимо, по стратегии Min/Max или прямым запросом цеха:

// Метод приемки на склад понимает разницу между типами ТМЦ
$item = $purchaseOrder->getMaterial()
    ?? $purchaseOrder->getDetail()
    ?? $purchaseOrder->getConsumble();

// Приходование остатков идет полиморфно
$movement->setItem($item);

Такой подход позволяет нам полностью блокировать ручные закупки `Material`, защищая MTO-стратегию, но при этом оставлять снабженцу свободу для оперативного пополнения `Consumble`.

Бизнес-результат

Внедрив такую жесткую блокировку и разделение сущностей, вы достигаете трех целей:

  1. Защита оборотного капитала: Ни один рубль не может быть потрачен на основное сырье без привязки к конкретному оплаченному заказу клиента.
  2. Точность себестоимости: Расходники (`Consumble`) списываются на накладные расходы цеха, а дорогой металл (`Material`) идет строго в Cost Roll-up изделия.
  3. Ликвидация неликвида: Склад сырья больше не забивается "страховочными" запасами.
  4. Прозрачность снабжения: Снабженец превращается из «покупателя» в диспетчера поставок. Его KPI больше не зависит от скидок за объем, он зависит от соблюдения сроков поставки по утвержденным заявкам.
Инвестируйте деньги в развитие производства, а не в пылящийся на складе металл.

Чек-лист: 10 дыр в цеху, через которые утекает ваша прибыль

Не готовы к аудиту? Начните с самодиагностики. Мы собрали 10 неочевидных признаков того, что мастера водят вас за нос, а НЗП съедает оборотку предприятия.

  • Как за 5 минут проверить, есть ли на складе неликвиды.
  • 3 неудобных вопроса мастеру, чтобы вскрыть приписки.
  • Тест на «узкое горлышко»: почему склад готовой продукции пуст.
Откроем материал сразу. Без рассылок.