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
+57
View File
@@ -0,0 +1,57 @@
/**
* index.js — главный entry point генератора отчётов
*/
const { chart1_priceAndMargin } = require('./charts/chart1')
const { chart5_scenarioMargins } = require('./charts/chart5')
const { buildDocument } = require('./generators/document')
const { PALETTE } = require('./data/palette')
/**
* Главная функция генерации отчёта.
*
* @param {Object} config — параметры отчёта
* @returns {Promise<Buffer>} — DOCX как буфер
*/
async function generateReport (config) {
const {
subject, // { name, shortName, type: 'region'|'farm'|'company' }
period, // { historicalFrom, historicalTo, forecastTo }
data, // { prices, costs, scenarios, kpi, leaders?, ebitda?, regionComparison? }
text, // { mainConclusion, conclusions, risks, recommendations }
meta = {} // { reportDate, brand: 'DairyTrends' }
} = config
// 1) Рендерим графики параллельно
const charts = {}
if (data.prices && data.costs && data.scenarios) {
charts.chart1 = await chart1_priceAndMargin({
priceData: data.prices,
costData: data.costs,
scenarios: data.scenarios,
marginBars: data.marginBars || [],
regionLabel: `${subject.name} · Закупочная цена и себестоимость молока · руб./кг · ${period.historicalFrom.slice(0,4)}${period.forecastTo.slice(0,4)}`
})
}
if (data.scenarioMargins) {
charts.chart5 = await chart5_scenarioMargins({
quarters: data.scenarioMargins,
regionLabel: `${subject.name} · Прогноз маржинальности по сценариям · %`
})
}
// 2) Собираем DOCX
return buildDocument({ subject, period, data, text, meta, charts })
}
module.exports = {
generateReport,
PALETTE,
// Экспортируем внутренности для возможности кастомизации
charts: {
chart1_priceAndMargin,
chart5_scenarioMargins,
}
}