Module: Production & Assembly (Виробництво та Збірка)¶
Статус: ✅ Production MVP + Full UI + Analytics (2026-04-27, Phases A–H).
Модуль відповідає за управління процесами перетворення сировини та компонентів у готову продукцію, розрахунок собівартості, аналітику завантаження складу, забезпеченості замовлень і собівартісних відхилень.
Архітектурний принцип¶
Списання матеріалів + прихід готової продукції — примітив Essentials, реалізований через документ Manufacturing (backend/essentials/models/manufacturing.py). Аддон production/ — тонкий плануючий шар: BOM + WorkOrder + variance/WIP accounting + звіти. Якщо аддон вимкнути, виробничий flow працює через ручні Manufacturing документи.
✅ Реалізовано¶
Phase A — Essentials Manufacturing¶
Manufacturing+ManufacturingInputLine+ManufacturingOutputLine(TransactionModel) з атомарним двостороннім flow.post_manufacturing: FIFO write-off inputs черезbatch_service.deduct_fifo+ receive output batches черезreceive_batchз actual cost =Σ(inputs.total_cost) × output_qty / Σ(outputs.qty). PostingGroup:Dt output / Ct inventory.unpost_manufacturing: власні reverse-функції, що фільтрують StockTransaction заtransaction_type(mixed ISSUE+RECEIPT).- Інваріант:
StockTransaction+Batch+ItemWarehouseStock+PostingGroup= збігаються до копійки. - Коригування залишків — через існуючий
DocumentOperation(окремий flow). - REST:
/api/v1/essentials/manufacturing/+ actionspost_document,unpost_document.
Phase B — Production → Manufacturing bridge¶
WorkOrder.manufacturing_documentFK на Essentials Manufacturing (SET_NULL).complete_work_orderстворює Manufacturing з BOM, викликаєpost_manufacturing, зберігає FK.- Idempotent: повторний complete видаляє попередній Manufacturing і створює новий.
unpost_work_order→ unpost + delete Manufacturing.
Phase C — WIP + Standard cost + Variance¶
BOM.standard_cost_per_unit(Decimal) +BOMLine.standard_input_cost(per-BOM override).ProductionSettingssingleton per tenant:variance_account,wip_account.Manufacturing.wip_account(nullable) → якщо set, двохетапний flow:Dt WIP / Ct Inventory, потімDt Output / Ct WIP(WIP net = 0 після completion, 4 entries замість 2).- Variance як окремий PostingGroup з
document_type='WorkOrderVariance': якщоactual > standard→Dt Variance / Ct Output, якщоactual < standard→Dt Output / Ct Variance.
Phase D — Item type extension¶
Item.item_typeрозширено:product,material,raw_material,semi_product,finished_goods,service,set.
Phase E — Multi-level BOM + Work Centers + Scrap¶
explode_bom(bom, multiplier)— рекурсивно розгортає multi-level BOM до leaf-level raw materials з cycle detection (ValidationError на A→B→A). REST:GET /api/v1/production/boms/{id}/explode/?qty=N.aggregate_requirements(...)— групування по item_id.BOMLine.scrap_pct— нормативний % браку, що інфлює required quantity на completion.WorkOrder.actual_output_qty— фактичний випуск (override planned) для yield shortfall.- Нові masterdata:
WorkCenter(capacity, cost/hour, department),Operation(setup/run times, work_center),BOMRouting(sequence of operations per BOM).
Phase F — Frontend config + QC placeholder¶
config/production.ts— групи Master Data, Processes, Reports, Settings.- Manufacturing додано до Essentials Sales operations.
Item.requires_qcполе — заготівка для Quality integration.
Phase G — Custom UI forms + Reports (сесія 2026-04-27)¶
Кастомні форми замість генеричних:
- WorkOrder — WorkOrderForm.tsx: shell через
useDocumentForm+ DocumentFormShell, bundle-fetchform-data/form-refs, preflight-check (BOM/qty/warehouse/accounts), toast з номером створеного Manufacturing, quick-jump pill → Manufacturing form. - BOM — BOMForm.tsx:
useMasterDataForm+ inline BOMLine editor, «Розгорнути» action (GET explode endpoint). - WorkCenter / Operation / BOMRouting — компактні форми з обчислюваними preview (daily cost, time for 10/100 units, grouped by BOM).
- Кастомні списки для всіх 5 сутностей з правильними колонками (capacity, times, sequence, linked manufacturing number).
- ProductionSettings перенесено у загальний
/settings?section=productionhub (замість окремого пункту меню).
Shortcut-посилання на Essentials:
- У Production sidebar з'явилися швидкі посилання на
Items,Warehouses,Chart of Accounts,Organizations,Departments,Manufacturing— без дублювання даних, лише UX-доступ з контексту виробництва. - Manufacturing posting redirect — гвинтик на WorkOrder відкриває Manufacturing postings (бо WO сам по собі не має PostingGroup окрім variance).
5 аналітичних звітів:
| Звіт | Файл | Суть |
|---|---|---|
| Warehouse utilization | WarehouseUtilizationReport.tsx |
SVG візуалізація — полиці хлібу / силоси / склади-будівлі. % = вага-в-наявності / warehouse.capacity_weight_kg (real) або відносний (fallback). Клікабельні імена складів. |
| Order readiness | OrderReadinessReport.tsx |
Картки з RingProgress per open WorkOrder; explode BOM × current stock → readiness %; shortfall bars per material. KPI: ready/partial/blocked. |
| Production queue | ProductionQueueReport.tsx |
Swimlane: лейни = WorkCenter групами по підрозділах. Блоки = кроки маршруту WorkOrder по датах. Монохром grays + тільки червоним підсвічено late. Filter by department. |
| Planned cost | CostAnalysisReport.tsx |
Drill-down таблиця: materials → scrap → routing → computed vs BOM standard. Per-BOM з Expand/Collapse, клікабельне ім'я BOM. Всі фони однакові, variance лише текстом зелений/червоний. |
| Actual cost | ActualCostAnalysisReport.tsx |
Для періоду: агрегат по Manufacturing docs групованих по source_bom_id. Materials — реальна FIFO. Labor — план з BOMRouting (факт не трекається). Drill-down до кожного Manufacturing документа з клікабельним номером. |
| Stock balances | StockBalancesReport.tsx |
Excel-подібна таблиця item × warehouse з sub-headers Qty/Amount. Sort, search, filter material/product/warehouse, hide-zeros toggle. |
Phase H — Економічна логіка (сесія 2026-04-27)¶
Seeder з двома сценаріями (core/seeders/production.py):
- Bakery (short-cycle) — 5 BOM (хліб, багет, булочки), 3 WC (тістоміс/піч/пакування), 5 operations, 4 routing steps per recipe. ~60 детермінованих WO.
- Steel workshop (long-cycle) — 3 multi-level BOM (панель → каркас 6×12 / 12×24), 5 WC (різка/зварка/підготовка/фарбування/складання), 10 operations. 8 long-cycle WO spanning 6 місяців.
- Material receipts — 2 GoodsReceipts на всі сировини ~60 днів тому, щоб FIFO мав з чого списувати.
- Warehouse capacity — задає capacity_weight_kg / capacity_volume_m3 для demo складів.
- Idempotent — детерміновані номери (BK-YYMMDD-NN) + cleanup legacy-random-suffix WO + repost-при-зміні-account + legacy-aggregate-posting detection.
Per-line PostingEntry в Manufacturing (manufacturing_service.py):
- Рефакторинг _post_atomic — замість 2-4 агрегованих PostingEntry тепер одна PostingEntry на КОЖЕН матеріал з quantity + product FK.
- Для 7 inputs + 1 output → 16 entries у WIP-потоці (було 4).
- Проводки стали читабельними: «Ct 3000 Raw Materials — Wheat flour 12 кг = 264 грн».
3-рівневий пріоритет планової ціни:
1. BOMLine.standard_input_cost (own override for this BOM)
2. ItemPrice[price_type=PLAN_COST] — окремий прайс-лист «Планова собівартість»
3. Item.price — catalog fallback
- Новий PriceType
PLAN_COSTстворюється seeder-ом, 15 материалів мають ItemPrice цього типу. - BOMLineSerializer повертає
input_item_planning_price+input_item_price— фронтенд бачить обидва. - BOM-форма показує колонку «Ціна/од» з ярликом джерела:
22.00 (планова)/22.00 (своя)/22.00 (з номенклатури). - Обидва звіти (Planned cost і Actual cost materials-standard) використовують той самий helper
_effective_unit_price.
Warehouse capacity + real fill %:
- Нові поля Warehouse.capacity_weight_kg + capacity_volume_m3 (nullable).
- Item.weight / Item.volume (already existed) — тепер використовуються у report: on_hand_qty × item.weight = current_weight_kg.
- Warehouse Utilization: якщо capacity задано → real % (вага-в-наявності / capacity); якщо не задано → fallback на relative (column max). Tooltip показує формулу розрахунку.
Тести¶
- Essentials: 72 тести (Manufacturing: 8 — core invariant, re-post, unpost, atomic rollback, блокування правки posted).
- Production: 23 тести (base + variance/WIP + multi-level/scrap/routing).
- Разом: 95 passing.
Основні REST-endpoint'и¶
Довідники та документи¶
GET/POST /api/v1/production/boms/+/bom-lines/+/work-orders/+/work-centers/+/operations/+/bom-routings/GET /api/v1/production/settings/— singleton за-tenant-омPOST /api/v1/production/work-orders/{id}/post_document/(alias for/complete/)POST /api/v1/production/work-orders/{id}/unpost_document/(alias for/cancel/)GET /api/v1/production/boms/{id}/explode/?qty=N— multi-level explosionGET /api/v1/production/boms/{id}/form-data/+/form-refs/— bundled UI data
Звіти¶
GET /api/v1/production/reports/warehouse-utilization/GET /api/v1/production/reports/order-readiness/?status=planned,in_progressGET /api/v1/production/reports/queue/?department=<id>GET /api/v1/production/reports/cost-analysis/?bom_id=<id>— plannedGET /api/v1/production/reports/actual-cost-analysis/?date_from=&date_to=&bom_id=GET /api/v1/production/reports/stock-balances/?item_type=material|product&warehouse_id=<id>&hide_zero=true
Структура меню Виробництва¶
Виробництво
├── Довідники
│ ├── Виробничі довідники
│ │ ├── Специфікації (BOM)
│ │ ├── Робочі центри
│ │ ├── Технологічні операції
│ │ └── Маршрути BOM
│ └── Спільні довідники (shortcuts з Essentials)
│ ├── Номенклатура
│ ├── Склади
│ ├── План рахунків
│ ├── Організації
│ └── Підрозділи
├── Процеси
│ └── Виробничі документи
│ ├── Виробничі замовлення (WorkOrder)
│ └── Виробництво (Manufacturing shortcut)
└── Звіти
├── Дашборди
│ ├── Завантаження складу
│ ├── Забезпеченість замовлень
│ └── Черга виробництва
└── Аналітика
├── Залишки по складах
├── Планова собівартість
└── Фактична собівартість
Налаштування виробництва — у /settings?section=production
🔬 Технічний борг¶
Жорсткі ліміти поточної реалізації¶
- Фактичну працю не трекаємо.
ActualCostAnalysisдля Labor завжди показує план (BOMRouting × Operation.time × WorkCenter.cost_per_hour). Потрібна модельManufacturingLaborLineабо інтеграція з HRM-таймшитами, щоб фіксувати реальні людино-години на кожне проведення. - PostingEntry quantity на per-line — не FIFO per-item. Коли один item з'являється в кількох рядках одного Manufacturing (edge case — зараз в моделі не заборонено),
stx_aggповерне сумарну вартість, а ми ділимо її на рядки як вагу. Зазвичай неважливо (редагуй input лінії щоб не дублювати item), але треба пам'ятати. - Warehouse.capacity — тільки для звіту. Немає логіки «відмовити GoodsReceipt якщо склад переповнено». Треба продумати behavior — hard-block чи soft-warning чи ledger.
- Capacity тільки weight/volume. Немає полиць/зон/slot-bin. Для «реального» WMS треба окрема модель
WarehouseZone+Slot. - ProductionSettings — один singleton на tenant. При multi-factory буде проблема (variance/WIP accounts однакові для всіх цехів).
- BOM не версіонується history-way. Якщо змінити BOM.lines після проведення WO — попередні Manufacturing-доки не «заморозять» свою версію BOM. Актуальний BOM завжди актуальний. Для аудиту потрібно snapshoting.
- Auto-cascade subassembly WO не реалізовано. Якщо caркас 12×24 вимагає 18 панелей, а їх нема на складі — WO просто падає на FIFO shortage. Треба створювати auto-WO для subassembly.
- Seeder прив'язаний до кодів матеріалів. Якщо codes змінити — seeder не знайде. Треба зробити матчинг за
item_type+namepattern.
Якість коду¶
_post_atomicв manufacturing_service = ~300 рядків. Можна декомпозувати на кроки (FIFO → output → posting → variance).- Cost-analysis і Actual-cost-analysis ділять логіку
_bom_std_materials/_bom_std_labor— винесено в helpers. Добре. computeFillPctу WarehouseUtilizationReport — клієнтський дубль backend-логіки. Треба вирішити де має бути розрахунок — там або там (зараз обидва місця).
Seed-data проблеми¶
- У demo-тенанті
Item.price== ItemPrice[PLAN_COST].price (однакові значення). Для production-like тесту треба зробити розрив — тоді буде очевидно що пріоритет працює. - Warehouse capacity для всіх складів — «round numbers» (30000 / 15000 / 20000 кг). Для реалізму варто різні (12347, 8902 тощо).
🔮 Deferred / Ideas¶
P1 — наступна сесія (високий пріоритет)¶
- [ ] Labor tracking на Manufacturing. Нова модель
ManufacturingLaborLine(document, operation, operator, hours, rate). UI: додати вкладку «Праця» в формі Manufacturing. Звіт Actual cost буде показувати реальний labor замість plan. - [ ] Auto-cascade subassembly WO. При
complete_work_order: якщоinput_itemсам має активний BOM і немає на складі — створити вкладений WO автоматично, зв'язати черезparent_work_order_id. Prevent infinite recursion (уже є в explode_bom). - [ ] BOM snapshoting. При
Manufacturing.post— клон BOM.lines уManufacturingBOMSnapshotдля повної відтворюваності аудитом. Cost Analysis (actual) буде використовувати snapshot, не поточний BOM.
P2 — середньострокова перспектива¶
- [ ] Capacity planning з календарем. Сторінка-дашборд «Завантаження WC на тиждень». Перетягування WO між датами (react-dnd). На backend:
WorkOrder.scheduled_start+scheduled_end,WorkCenterCalendarмодель з робочими/вихідними днями. - [ ] Quality Control integration. Модель
QualityInspection(manufacturing_output_line, status, inspector, notes).Item.requires_qcтригер → output batch у «QC hold» локації до approval. Integration point —essentials_qualityplugin (вже є hook-пункт уmanufacturing_service). - [ ] Price-variance breakdown. Розщеплення material variance на:
- Price variance = (actual_price − std_price) × actual_qty
- Quantity variance = std_price × (actual_qty − std_qty) Формула з classical management accounting. У UI — два окремі рядки у summary.
- [ ] Кастомна форма Warehouse з capacity. Зараз capacity_weight / capacity_volume редагуються лише через generic MasterDataForm. Треба кастомна форма з валідацією + доп. полями
zone_count,operating_hours,temperature_controlled.
P3 — стратегічні фічі¶
- [ ] Real subcontracting. Мануфактуру виконує зовнішній виконавець. Новий flow:
WorkOrder.external_vendor(Client FK), матеріали відправляються Transfer-документом, готова продукція — приходить як GoodsReceipt із BOM-референсом. - [ ] Shop Floor UI / Kiosk mode. Планшет у цеху: оператор відкриває поточний крок маршруту → вводить фактичний час → наступний крок. Інтеграція з Labor tracking (P1).
- [ ] Multi-facility ProductionSettings. Заміна singleton на
ProductionSettings(facility)з unique_together(tenant, facility).Facility— нова модель, FK з Organization. - [ ] Actual Cost із capacity-утилізацією. Overhead algorithm: якщо WC використовується на 80% від capacity, overhead rate normalized; якщо 30% — overhead стає дорожчий (ідле-час).
P4 — «було б непогано»¶
- [ ] Графічний BOM-конструктор (drag-n-drop або tree-view). Поточні generic CRUD + custom forms справляються, але для складних multi-level рецептів було б зручно.
- [ ] Excel-імпорт BOM. Завантажив .xlsx з шаблоном → створилися BOM + BOMLine.
- [ ] Gantt-chart WorkOrder execution. На backend уже є
scheduled_start/end(якщо P2 буде), можна зображати через mantine-charts.
Історія ключових версій¶
| Дата | Фаза | Що додано |
|---|---|---|
| 2026-04-23 | A-F | Манufacturing + WorkOrder + WIP + Variance + Multi-level BOM + Work Centers + Scrap + Frontend config. 95 тестів passing. |
| 2026-04-27 | G-H | Кастомні UI-форми для всіх 5 сутностей + 5 аналітичних звітів + per-line PostingEntry + 3-рівневий пріоритет цін (BOMLine override > PLAN_COST price type > Item.price) + Warehouse capacity + seeder з 2 сценаріями + SVG-візуалізація «Полиці / Силоси / Склади». |
Пов'язані плани¶
- Reports & Print strategy: planning/reports-and-print-strategy.md
- Essentials module: dop/modules/horizontal/essentials/README.md
- BACKLOG (автоматично генерується): BACKLOG.md — агрегація всіх
## 🔮 Deferredсекцій.