Модуль «Логістика та консолідація» — інструкція менеджера-впроваджувача¶
Серія: інструкції для менеджера-продавця та впроваджувача модулів DOP. Документ 3 з ланцюга. Сусіди: 01 — Облік зерна · 02 — Авто-транспорт. Навігація — README.
Кому: менеджеру, що продає та впроваджує DOP. Приклади — на демо-даних ТОВ «Зерноплюс» (анонімізований НІБУЛОН); інженерний опис даних — blueprint засіювання.
Backend-код:
logistic(оптимізатор консолідації) +shipcore_rail(рейкове плече). Розділ в UI: «Логістика».
1. Що це за модуль і навіщо¶
Логістика та консолідація — модуль планування постачання вантажу в точку консолідації (порт) за найменшою собівартістю. Серце модуля — оптимізатор: для заданого контракту (наприклад, 100 000 т пшениці в Миколаїв) він сам вирішує, звідки брати зерно (зі своїх елеваторів за собівартістю чи докуповувати ззовні) і яким плечем везти (вагон чи авто), мінімізуючи загальну landed-вартість.
Цільовий клієнт: агрохолдинги та трейдери з мережею елеваторів і експортними контрактами; експедитори, що збирають збірний вантаж із кількох пунктів у порт.
Модуль розв'язує задачу логіста: «треба зібрати 100 тис. т у порту до дати X — як зробити це найдешевше, поєднавши власні запаси й закупівлю, вагони й машини».
Болі клієнта, які закриває модуль¶
| Біль | Як закриває DOP |
|---|---|
| «Скільки везти з якого елеватора?» рахують в Excel вручну | Оптимізатор будує план: джерело → плече → вартість, від найдешевшого |
| Не видно, чи дешевше везти своє зерно чи докупити ближче до порту | Власний запас (собівартість) і зовнішні пропозиції в одному порівнянні landed-вартості |
| Вагон чи авто — вирішують «на відчуття» | Автовибір плеча по landed-вартості (близько — авто, далеко — вагон) |
| План збору й факт прибуття в порт не звіряються | Дошка накопичення партії: план/факт тоннажу, статус кожного плеча, відлік до ETD судна |
| Дефіцит власного зерна виявляється пізно | План одразу показує shortfall і чим його закрити |
Орієнтири¶
Supply-chain optimization (Llamasoft/Coupa), TMS-консолідація, зернотрейдингові origination- платформи. DOP дає least-cost sourcing під конкретний контракт, зшитий із залишками елеваторів (модуль зерна) та виконанням плечей (авто/ЖД).
2. Ключові поняття (словник для менеджера)¶
- План накопичення партії (
LotAccumulationPlan) — план зібрати N тонн одного класу зерна в порту під контракт. Має ціль, статус (чернетка→оптимізовано→виконання→завершено) і розраховані оптимізатором підсумки (зібрано/ціль, загальна вартість, середня ₴/т). - Замовлення збору (
CollectionOrder) — одне плече плану: джерело (свій силос або зовнішня пропозиція), вид транспорту (вагон/авто), тонни і розклад собівартості (зерно + перевалка + транспорт = landed-вартість/т). - Пропозиція закупівлі (
GrainSupplyOffer) — зовнішній офер: постачальник, клас, пункт, відстань до порту, доступні тонни, ціна/т. Це кандидати «докупити на стороні». - Landed-вартість — повна вартість тонни «на борту» в порту = вартість зерна + перевалка + транспортне плече. Саме її мінімізує оптимізатор.
3. Що налаштувати перед стартом¶
| Що | Звідки / як | Призначення |
|---|---|---|
| Власний запас | з модуля зерна (заповнення силосів Silo.current_fill_tons) |
джерела «своє зерно за собівартістю» |
| Зовнішні пропозиції | довідник GrainSupplyOffer |
джерела «докупити», з відстанню та ціною |
| Road-тариф | essentials.ContractSpecification (per_ton_km) — з модуля авто |
вартість авто-плеча |
| ЖД-тариф | поки демо-припущення (₴/т-км константа) | вартість рейкового плеча (окрема модель ЖД-тарифу — roadmap) |
| Відстані елеваторів до порту | демо-довідник по майданчиках | вибір плеча та вартість |
Чесно клієнту: оптимізатор least-cost для зернового sourcing'у — реальний і демонстрований. Ширший мультимодальний форвардинг (фрахт-контракти, відправки, бронювання суден, плани розвозу в секції «Логістика») — roadmap, поки демо-наповнення.
4. Документообіг (повна схема)¶
КОНТРАКТ (модуль зерна) ──▶ ПЛАН КОНСОЛІДАЦІЇ ──[Оптимізувати]──▶ ЗАМОВЛЕННЯ ЗБОРУ
GrainContract LotAccumulationPlan CollectionOrder × N
(100к т пшениці (ціль, порт, вікно) (джерело + плече +
в Миколаїв) │ landed-вартість)
│ optimizer.optimize_lot_accumulation_plan
│ • кандидати: свої силоси (собівартість)
│ + зовнішні офери (ціна)
│ • вартість плеча: авто vs вагон → дешевше
│ • greedy: від найдешевшої landed-вартості до цілі
▼
┌───────────────────────┴───────────────────────┐
▼ ▼
ВЛАСНІ ЕЛЕВАТОРИ ДОКУПІВЛЯ ЗЗОВНІ
(Silo, модуль зерна) (GrainSupplyOffer)
│ │
└───────────── виконання плечей ──────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
АВТО-ПЛЕЧЕ РЕЙКОВЕ ПЛЕЧЕ
ТТН (модуль авто) ЖД-накладна (shipcore_rail)
TransportInvoice RailwayWaybill (hopper-вагони
→ ст. Миколаїв, дислокація вагонів)
│
▼
ДОШКА КОНСОЛІДАЦІЇ (процес)
план/факт тоннажу, статус плечей, відлік до ETD
Об'єкти модуля¶
- План накопичення партії (
LotAccumulationPlan, документ) — ціль + порт + вікно збору + розраховані підсумки. Дія «Оптимізувати» запускає алгоритм. - Замовлення збору (
CollectionOrder, підтаблиця) — рядки-плечі (вивід оптимізатора, редагуються не вручну, а перерахунком). - Пропозиції закупівлі (
GrainSupplyOffer, довідник) — зовнішні офери. - Дошка накопичення партії (процес) — візуальний прогрес плану.
- Рейкове плече (
shipcore_rail): ЖД-накладна на hopper-вагони → станція Миколаїв, дислокація вагонів; авто-плече — ТТН з модуля авто (документ 02).
Алгоритм оптимізатора (як пояснити клієнту)¶
- Збирає кандидатів: свої силоси з потрібним класом (вартість = собівартість зерна) + зовнішні офери (вартість = ціна офера).
- Для кожного рахує обидва плеча (авто й вагон) і бере дешевше: близькі (≲73 км) — авто, далекі — вагон.
landed = зерно + перевалка + транспорт.- Greedy: сортує за landed-вартістю, набирає від найдешевшого до цілі. Своє зерно поряд із портом виграє першим; дефіцит закриває докупівля.
🔍 Як оптимізатор рахує — детально (простими словами)¶
Це для випадку, коли клієнт питає «а звідки ви взяли ці цифри?». Можна пояснити так.
Крок 1. Звідки залишки на елеваторах. Оптимізатор не вигадує скільки зерна на складі — він бере реальний поточний залишок силосу, який веде модуль зерна: приймання зерна (ваговий талон → приходний документ) додає тонни, відвантаження й усушка віднімають, переміщення силос-у-силос — переносять. Тобто це той самий залишок, що менеджер бачить у звіті позиції силосів. Ціна власного зерна — це його собівартість (з партії на складі), а не ринкова.
Крок 2. З чого складається вартість доставки тонни. У кожного плеча дві частини: фіксований «старт» (не залежить від відстані) і їзда (що далі — то дорожче). Аналогія: таксі проти поїзда. Таксі сів і поїхав — старт дешевий, але кожен км кусається. Поїзд — спершу дорожчий квиток (подача вагона, маневри), зате далеко їхати майже задарма.
| Плече | Фіксований старт (₴/т) | Їзда (₴ за тонну за км) |
|---|---|---|
| 🚚 Авто | 85 (перевалка на машину) | 4.20 — дорого |
| 🚂 Залізниця | 95 (перевалка) + 180 (подача вагона) = 275 | 1.60 — втричі дешевше |
Формули (де d — відстань до порту в км):
- авто = 85 + 4.20 · d
- залізниця = 275 + 1.60 · d
Крок 3. Близько — авто, далеко — вагон. Бо в авто дешевий старт, але дорога їзда, а в залізниці навпаки. Десь вони зрівнюються — на ~73 км:
| Відстань до порту | 🚚 Авто | 🚂 Залізниця | Дешевше |
|---|---|---|---|
| 30 км | 211 ₴/т | 323 ₴/т | 🚚 авто |
| ~73 км | ≈392 ₴/т | ≈392 ₴/т | однаково |
| 200 км | 925 ₴/т | 595 ₴/т | 🚂 залізниця |
Тому в плані елеватори біля Миколаєва їдуть машинами, а Дніпро/Кривий Ріг (300+ км) — вагонами. Це не «на відчуття», а порахована точка беззбитковості двох тарифів.
Крок 4. Повна вартість тонни «на борту» (landed).
landed = ціна зерна + перевалка + дорога. Для кожного джерела (свого силосу чи зовнішнього
офера) оптимізатор бере дешевше плече і отримує одну підсумкову цифру — landed-вартість/т.
Крок 5. Набираємо ціль від найдешевшого. Усі джерела шикуються за landed-вартістю від меншої до більшої, і оптимізатор бере по черзі, поки не набере ціль контракту. Своє дешеве зерно поряд із портом іде першим; коли власного не вистачає — добирає зовнішніми оферами. Якщо джерел узагалі замало — план чесно показує дефіцит (shortfall), щоб логіст вчасно знайшов, де докупити.
⚠️ Чесно клієнту про цифри тарифів. Ставки вище (85, 95, 180, 1.60, 4.20) — поки демо-припущення, узгоджені для показу. Залізнична — взагалі константа (реальної моделі ЖД-фрахту в системі ще нема — це roadmap). Підставимо реальні тарифи клієнта — і логіка та сама, лише межа «73 км» зсунеться. Сам принцип (старт + їзда → дешевше плече → набір від найдешевшого) залишиться незмінним.
5. Потоки інформації (звідки/куди)¶
На вході: контракт (модуль зерна) задає ціль; заповнення силосів (модуль зерна) = власний запас; зовнішні офери; road-тариф (модуль авто) і ЖД-припущення.
Усередині: оптимізатор → замовлення збору з повним розкладом собівартості → підсумки плану.
На виході: плечі матеріалізуються у ТТН (авто, док 02) і ЖД-накладні (рейка);
далі зерно йде на відвантаження (модуль зерна) і морський експорт (shipcore_sea).
6. Наскрізний демо-сценарій (на даних Зерноплюс)¶
Засівається seed_grain_lot_accumulation (після того, як зерновий сід наповнив елеватори, а
seed_railway_waybills створив транспортні плечі):
- План накопичення партії — пшениця 100 000 т у Миколаїв. Відкрити план, натиснути «Оптимізувати».
- Результат оптимізації (реальні цифри сіду): власні елеватори 57 250 т + докупівля 42 750 т, дефіцит 0, середня landed-вартість 8 784 ₴/т, 14 плечей. Показати, що рядки відсортовані від найдешевшого; найближчі елеватори — авто, далекі — вагони.
- Другий план — ячмінь 40 000 т: власні 23 200 т + докупівля 16 800 т.
- Дошка накопичення партії — план/факт тоннажу, статус плечей, відлік до ETD судна.
- Виконання плечей — рейкові ЖД-накладні на hopper-вагони → ст. Миколаїв (рейка) + авто-ТТН (док 02), прив'язані до відвантажень зерна.
Місце в наскрізному ланцюзі: оптимізатор — «мозок» між складом (модуль зерна, де лежить власне зерно) і транспортом (авто/ЖД, що везе в порт), а далі — морський експорт і фінал (рахунок $23 млн → собівартість → податок на прибуток; див. blueprint).
7. Чек-лист впровадження¶
- ☐ Власний запас доступний (модуль зерна заповнив силоси).
- ☐ Зовнішні пропозиції (
GrainSupplyOffer): постачальники, відстані, ціни. - ☐ Road-тариф (
ContractSpecificationper_ton_km) — з модуля авто. - ☐ Відстані елеваторів до порту (демо-довідник; у проді — з маршрутизації).
- ☐ Контракт (модуль зерна) як ціль плану.
- ☐ Пробний цикл: створити план → «Оптимізувати» → перевірити власне+докупівля та вибір плеча → дошка консолідації.
- ☐ Виконання: матеріалізація плечей у ТТН (авто) + ЖД-накладні (рейка).
8. Точки інтеграції та зв'язок із серією¶
| Сусідній модуль | Зв'язок | Документ серії |
|---|---|---|
Облік зерна (shipcore_grain) |
Контракт = ціль; заповнення силосів = власний запас; план → відвантаження | 01 — Облік зерна |
Авто-транспорт (fleet) |
Road-тариф/CPM → вартість плеча; авто-плече → ТТН | 02 — Авто-транспорт |
Залізниця (shipcore_rail) |
Рейкове плече → ЖД-накладна (hopper) + дислокація вагонів | у складі цього документа |
Морський експорт (shipcore_sea) |
Після збору в порту — рейс/чартер/коносамент | окремий документ серії |
9. Інтеграція у F1-довідку (план)¶
Розрізання на статті (skill add-help-article, фреймворк frontend/core/.../Help):
- Документи: план консолідації (+ дія «Оптимізувати»), ЖД-накладна.
- Довідники: пропозиції закупівлі зерна.
- Процеси: дошка консолідації.
- Оглядова стаття модуля = §1–§5 (з акцентом на алгоритм оптимізатора §4).
Двомовні *.md + *.ua.md; ланцюгові посилання на зерно/авто → internal-links F1.
Сусіди в серії: 01 — Облік зерна · 02 — Авто-транспорт. Інженерний опис даних: blueprint засіювання Зерноплюс · технічний bundle оптимізатора: consolidation-optimizer.