Files
dairy-report-generator/src/index.js
T
Alexey Pavlov 0625d75aa6 feat: chart4 — два режима (независимые шкалы vs общая)
independentScales=true (для регионов типа Вологды):
  - Левая и правая панели с разными показателями (надой vs цена)
  - Каждая со своей шкалой Y и Y-лейблами
  - Y-лейблы с тире (как в оригинале: '9500 –')
  - highlight=красный, остальные=серые

independentScales=false (для ФО, по умолчанию):
  - Общая шкала, зелёный/оранжевый/жёлтый
2026-06-08 22:52:06 +03:00

96 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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<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} · Прогноз маржинальности по сценариям · %`
})
}
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,
}
}