feat: initial dairy report generator

- chart1: линейный график цены + себестоимость + 3 сценария + маржа (bottom panel)
- chart5: сгруппированные бары сценарий маржинальности
- document.js: сборка DOCX (header/footer DT-style, KPI, callout, tables, images)
- index.js: параметрический entry point generateReport(config)
- examples/russia.js: полный пример для РФ
- palette.js: DT-палитра синхронизирована с DESIGN_DAIRYTRENDS.md

Tested: node examples/russia.js → 44KB DOCX, validation PASSED
This commit is contained in:
Alexey Pavlov
2026-06-08 14:57:51 +03:00
commit 00f80dc5cc
10 changed files with 1848 additions and 0 deletions
+208
View File
@@ -0,0 +1,208 @@
/**
* Example: общероссийский отчёт DT
*
* Запуск: node examples/russia.js
* Результат: /tmp/DT_Russia_Example.docx
*/
const fs = require('fs')
const path = require('path')
const { generateReport } = require('../src')
async function main () {
console.log('Генерирую пример: Российская Федерация')
const buf = await generateReport({
subject: {
name: 'Российской Федерации',
shortName: 'Россия',
type: 'region',
},
period: {
historicalFrom: '2024-01-01',
historicalTo: '2026-05-31',
forecastTo: '2026-12-31',
},
data: {
// Цены (агрегаты по DT-индексу)
prices: [
{ date: '2024-01-15', price: 31.05 }, { date: '2024-04-15', price: 31.40 },
{ date: '2024-07-15', price: 31.60 }, { date: '2024-10-15', price: 31.81 },
{ date: '2025-01-15', price: 31.98 }, { date: '2025-02-26', price: 38.94 },
{ date: '2025-04-15', price: 39.79 }, { date: '2025-07-15', price: 39.57 },
{ date: '2025-10-15', price: 39.51 }, { date: '2025-12-15', price: 39.39 },
{ date: '2026-01-15', price: 39.33 }, { date: '2026-02-15', price: 34.45 },
{ date: '2026-04-01', price: 34.01 }, { date: '2026-05-15', price: 34.20 },
],
// Себестоимость (расчётная)
costs: [
{ date: '2024-01-15', cost: 28.5 }, { date: '2024-04-15', cost: 28.7 },
{ date: '2024-07-15', cost: 28.9 }, { date: '2024-10-15', cost: 29.2 },
{ date: '2025-01-15', cost: 29.4 }, { date: '2025-04-15', cost: 29.8 },
{ date: '2025-07-15', cost: 30.1 }, { date: '2025-10-15', cost: 30.5 },
{ date: '2026-01-15', cost: 30.8 }, { date: '2026-04-01', cost: 31.0 },
],
// Прогноз 3 сценария
scenarios: {
base: [
{ date: '2026-04-01', price: 34.01 },
{ date: '2026-06-30', price: 34.5 },
{ date: '2026-09-30', price: 33.5 },
{ date: '2026-12-31', price: 32.0 },
],
opt: [
{ date: '2026-04-01', price: 34.01 },
{ date: '2026-06-30', price: 36.5 },
{ date: '2026-09-30', price: 35.5 },
{ date: '2026-12-31', price: 34.5 },
],
pess: [
{ date: '2026-04-01', price: 34.01 },
{ date: '2026-06-30', price: 32.5 },
{ date: '2026-09-30', price: 31.0 },
{ date: '2026-12-31', price: 29.5 },
],
},
// Барчарт маржи внизу chart1
marginBars: [
{ label: 'I 24', value: 8.5, isForecast: false },
{ label: 'II 24', value: 9.6, isForecast: false },
{ label: 'III 24', value: 9.5, isForecast: false },
{ label: 'IV 24', value: 9.4, isForecast: false },
{ label: 'I 25', value: 9.0, isForecast: false },
{ label: 'II 25', value: 12.8, isForecast: false },
{ label: 'III 25', value: 12.5, isForecast: false },
{ label: 'IV 25', value: 12.4, isForecast: false },
{ label: 'I 26', value: 11.9, isForecast: false },
{ label: 'II 26*', value: 8.5, isForecast: true },
{ label: 'III 26*', value: 5.0, isForecast: true },
{ label: 'IV 26*', value: 1.5, isForecast: true },
],
// Сценарии маржи (chart5)
scenarioMargins: [
{ label: 'II кв. 2026', opt: 15.7, base: 10.0, pess: 1.5 },
{ label: 'III кв. 2026', opt: 12.5, base: 6.5, pess: -4.8 },
{ label: 'IV кв. 2026', opt: 7.8, base: 1.6, pess: -11.7 },
],
// KPI на обложке
kpi: [
{ value: '34,1 ₽/кг', label: 'DT Index (май 2026)' },
{ value: '+24%', label: 'Рост цен 2025 vs 2024' },
{ value: '23 региона', label: 'В базе DT' },
{ value: '16%', label: 'Ключевая ставка ЦБ' },
],
// Допущения сценариев
scenarioAssumptions: [
{ name: 'Базовый', price: '33,534,5 руб./кг', costGrowth: '+5%', rationale: 'Продолжение текущих трендов' },
{ name: 'Оптимистичный', price: '36,037,5 руб./кг', costGrowth: '+3%', rationale: 'Восстановление спроса, ослабление рубля' },
{ name: 'Пессимистичный', price: '30,032,0 руб./кг', costGrowth: '+8%', rationale: 'Давление переработчиков, рост затрат' },
],
// Ретроспективная таблица
retrospective: {
columns: [
{ label: 'Квартал', width: 2200 },
{ label: '2024', width: 1700 },
{ label: '2025', width: 1700 },
{ label: 'III кв. 2026', width: 1800 },
{ label: 'Изм. г/г', width: 2466 },
],
rows: [
['I квартал', '31,14', '36,97', '36,04', { text: '↓ 2,5%', align: 1 }],
['II квартал', '31,47', '39,77', '34,11', { text: '↓ 14,2%', align: 1 }],
['III квартал','31,63', '39,57', 'прогноз', '—'],
['IV квартал', '31,86', '39,49', 'прогноз', '—'],
[{ text: 'Среднегодовая', bold: true }, { text: '31,6', bold: true }, { text: '39,4', bold: true }, { text: '34,5 (оц.)', bold: true }, { text: '↓ 12,4%', bold: true }],
]
},
// Прогнозная таблица
forecastTable: {
columns: [
{ label: 'Квартал', width: 1700 },
{ label: 'Цена руб./кг', width: 1700 },
{ label: 'Себест. руб./кг', width: 1700 },
{ label: 'Маржа %', width: 1700 },
{ label: 'Пр-во тыс. т', width: 1500 },
{ label: 'Сценарий', width: 1566 },
],
rows: [
['II кв. 2026', '35,0', '31,5', '10,0', '175', 'Базовый'],
['III кв. 2026', '34,0', '31,8', '6,5', '168', 'Базовый'],
['IV кв. 2026', '32,5', '32,0', '1,6', '160', 'Базовый'],
['II кв. 2026', '37,0', '31,2', '15,7', '178', { text: 'Оптимистичный', color: '1D9E75' }],
['III кв. 2026', '36,0', '31,5', '12,5', '170', { text: 'Оптимистичный', color: '1D9E75' }],
['IV кв. 2026', '34,5', '31,8', '7,8', '163', { text: 'Оптимистичный', color: '1D9E75' }],
['II кв. 2026', '33,0', '32,5', '1,5', '172', { text: 'Пессимистичный', color: 'C0272D' }],
['III кв. 2026', '31,5', '33,0', '-4,8', '165', { text: 'Пессимистичный', color: 'C0272D' }],
['IV кв. 2026', '30,0', '33,5', '-11,7', '158', { text: 'Пессимистичный', color: 'C0272D' }],
]
},
},
text: {
mainConclusion: 'После резкого скачка в феврале–марте 2025 г. (с 32,2 до 39,8 руб./кг) национальный DT-индекс перешёл к плавному снижению. В 2026 г. коридор сузился до 33–35 руб./кг. Региональный разброс высок: от 22 руб./кг (Чувашия) до 49 руб./кг (Кабардино-Балкария). Базовый сценарий: среднегодовая цена 33,5–34,5 руб./кг, маржа 510%.',
conclusions: [
'Национальный DT-индекс в мае 2026 — 34,1 руб./кг: на 16% ниже пика 2025 г. (39,9 руб./кг), но на 10% выше средней 2024 г. (31,6 руб./кг).',
'Региональный спред 2026 рекордный: 27 руб./кг (Чувашия 22 руб./кг vs Кабардино-Балкария 49 руб./кг).',
'Лидеры по цене: СКФО и западное ЦФО/СЗФО (Брянская, Псковская, Ленинградская обл.) — 40–50 руб./кг.',
'Аутсайдеры: Республика Татарстан, Самарская, Нижегородская, Ивановская обл. — 28–31 руб./кг.',
'Ключевой риск — ставка ЦБ 16%: замораживает инвестиции в животноводческую инфраструктуру.',
],
intro: [
'Период анализа: 2024 г. — май 2026 г. Отчёт охватывает всю территорию Российской Федерации по данным 23 активных региональных панелей системы Dairy Trends (DT).',
'Основные источники: данные Dairy Trends (DT) — еженедельные цены на сырое молоко; статистика Росстата; макроэкономические индикаторы ЦБ РФ; данные GDT и МСХ Беларуси как ориентиры ЕАЭС.',
'Ключевая ставка ЦБ РФ — 16% (май 2026). Рост цен на электроэнергию: +17–24% в 2025 году, +320% в I кв. 2026. Комбикорма: +12% в 2025.',
],
methodology: [
'Экстраполяция трендов с учётом сезонности (квартальные коэффициенты за 2024–2025 гг.).',
'Корректировка на макроиндексы: электроэнергия +4–6% в квартал, комбикорма +5–8% за год.',
'Сценарный анализ: три сценария с разными допущениями по динамике цены и затрат.',
],
retrospectiveSummary: 'В 2024 году национальный DT-индекс показал стабильный медленный рост: 30,97 → 31,93 руб./кг (+3% за год). В феврале–марте 2025 произошёл резкий скачок: за 10 дней индекс вырос с 32,2 до 38,9 руб./кг (+21%). К апрелю достиг плато 39,8 руб./кг, удерживалось до декабря 2025. В январе–мае 2026 — нисходящая коррекция до 34,1 руб./кг (–13,5% с начала года).',
forecastSummary: 'В базовом сценарии большинство производителей сохранят маржу 5–10%. В оптимистичном (цена до 36–37 руб./кг) даже менее эффективные хозяйства выйдут в плюс. В пессимистичном убытки накопят 30–40% предприятий.',
risks: [
'Погодные условия — засуха поднимет цены на комбикорма на 15–20%.',
'Регуляторные риски — изменение импортных пошлин ЕАЭС, белорусские фиксированные цены.',
'Кредитное сжатие — ставка ЦБ 16% уже заморозила инвестиционные программы ряда хозяйств.',
'Валютный фактор — укрепление рубля снижает конкурентоспособность на экспортных рынках.',
],
recommendations: {
'Для руководителей хозяйств': [
'Снижайте себестоимость через повышение надоя (цель: >9 000 кг/год) и оптимизацию кормления.',
'Не наращивайте поголовье без долгосрочных контрактов. Инвестируйте в роботизацию доения.',
'Хеджируйте цену форвардными контрактами на 30–40% объёма (приоритет — осень).',
],
'Для менеджеров по продажам кормов и оборудования': [
'Приоритет: клиенты с II >80, OH >70.',
'Прогноз спроса: +2–3% в тоннах. Логистические окна: май и сентябрь.',
'Ужесточайте контроль дебиторки с предприятиями группы В.',
],
'Для инвесторов': [
'M&A: фермы группы В по цене 0,5–0,7 годовой выручки с последующей модернизацией.',
'IRR новой фермы 1 200 коров — 9–11% при цене 34–35 руб./кг, что ниже WACC 14–15%. Без господдержки нецелесообразно.',
],
},
},
})
const outPath = path.join('/tmp', 'DT_Russia_Example.docx')
fs.writeFileSync(outPath, buf)
console.log(`✓ Готово: ${outPath} (${(buf.length/1024).toFixed(0)} KB)`)
}
main().catch(e => { console.error(e); process.exit(1) })