/** * index.js — главный entry point генератора отчётов */ const { chart1_priceAndMargin } = require('./charts/chart1') const { chart2_leaders } = require('./charts/chart2') const { chart3_ebitdaByOrg } = require('./charts/chart3') const { chart4_regionCompare } = require('./charts/chart4') const { chart5_scenarioMargins } = require('./charts/chart5') const { buildDocument } = require('./generators/document') const { PALETTE } = require('./data/palette') /** * Главная функция генерации отчёта. * * @param {Object} config — параметры отчёта * @returns {Promise} — 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} · Прогноз маржинальности по сценариям · %` }) } if (data.leaders && data.leaders.items) { charts.chart2 = await chart2_leaders({ items: data.leaders.items, title: data.leaders.title || 'Топ-производители по чистой прибыли', unit: data.leaders.unit || 'млн руб.', ...(data.leaders.volumeItems ? { volumeItems: data.leaders.volumeItems, volumeTitle: data.leaders.volumeTitle || 'Объём переработки', volumeUnit: data.leaders.volumeUnit || 'тыс. тонн', } : {}), regionLabel: `${subject.name} · ${data.leaders.title || 'Лидеры рынка'} · ${data.leaders.unit || 'млн руб.'}` }) } if (data.ebitda) { charts.chart3 = await chart3_ebitdaByOrg({ items: data.ebitda.groups || data.ebitda, unit: (data.ebitda.unit) || 'EBITDA-маржа, %', regionLabel: `${subject.name} · Эффективность по группам хозяйств · %` }) } if (data.regionComparison) { charts.chart4 = await chart4_regionCompare({ left: data.regionComparison.left, right: data.regionComparison.right, independentScales: data.regionComparison.independentScales || false, unit: data.regionComparison.unit || 'руб./кг', regionLabel: `${subject.name} · Сравнение регионов · ${data.regionComparison.unit || 'руб./кг'}` }) } // 2) Собираем DOCX return buildDocument({ subject, period, data, text, meta, charts }) } module.exports = { generateReport, PALETTE, // Экспортируем внутренности для возможности кастомизации charts: { chart1_priceAndMargin, chart2_leaders, chart3_ebitdaByOrg, chart4_regionCompare, chart5_scenarioMargins, } }