7.9 KiB
BRIEFING: DairyTrends Report Generator — состояние на 08.06.2026
Что сделано
Репозиторий
https://git.zeroday.su/admin/dairy-report-generator — основной проект генератора.
Живёт на dev сервере: /var/www/dairy-report-generator/
Структура проекта
src/
data/palette.js — DT-палитра (синхронизирована с DESIGN_DAIRYTRENDS.md)
charts/chart1.js — Главный график: цена + себестоимость + 3 сценария + маржа
charts/chart5.js — Сгруппированные бары сценариев маржинальности
generators/document.js — Сборка DOCX: header, footer, KPI, callout, tables, images
index.js — Entry point: generateReport(config) → Buffer
examples/
russia.js — Полный рабочий пример для РФ
Что работает
node examples/russia.js→ генерирует/tmp/DT_Russia_Example.docx(44KB), validation PASSED- Графики рендерятся через SVG → sharp → PNG и встраиваются в DOCX
- Дизайн: черный хедер DT/DAIRY TRENDS, красные заголовки разделов, callout-блоки с красной полосой, KPI-блок на обложке
- Изображения корректно встраиваются (баг с EMU был исправлен — ImageRun принимает пиксели напрямую)
Что ещё НЕ сделано (следующий шаг)
- chart2 — горизонтальные бары лидеров (переработчики/производители)
- chart3 — EBITDA margin по группам A/B/C
- chart4 — сравнение регионов (два вертикальных барчарта рядом)
- Страница в админке
/admin/dairytrends/reports/в new.dairy-news.ru с:- Вкладка 1: Отчёты — выбор субъекта (регион/хозяйство/компания) + кнопка генерации + скачивание
- Вкладка 2: Картинки через AI — генерация изображений через Anthropic API
- API endpoint
/api/admin/dairytrends/reports/generate— принимает конфиг, возвращает DOCX - Данные из БД — для региональных отчётов тянуть из dn MySQL (
region_index), для ФО из PrismaDairyIndex - МЗЫ-режим — отдельная схема данных для хозяйства (надой, поголовье, себестоимость, закупочная цена)
Как запустить пример
cd /var/www/dairy-report-generator
node examples/russia.js
# → /tmp/DT_Russia_Example.docx
API генератора
const { generateReport } = require('/var/www/dairy-report-generator/src')
const buf = await generateReport({
subject: {
name: 'Вологодской области', // в родительном падеже для заголовков
shortName: 'Вологда',
type: 'region', // 'region' | 'farm' | 'company'
},
period: {
historicalFrom: '2024-01-01',
historicalTo: '2026-05-31',
forecastTo: '2026-12-31',
},
data: {
prices: [{ date: 'YYYY-MM-DD', price: Number }], // фактическая цена
costs: [{ date: 'YYYY-MM-DD', cost: Number }], // себестоимость
scenarios: {
base: [{ date, price }],
opt: [{ date, price }],
pess: [{ date, price }],
},
marginBars: [{ label, value, isForecast }], // для нижней панели chart1
scenarioMargins: [{ label, opt, base, pess }], // для chart5
kpi: [{ value, label }], // 4 блока на обложке
scenarioAssumptions: [{ name, price, costGrowth, rationale }],
retrospective: { columns: [{label,width}], rows: [[...]] },
forecastTable: { columns: [{label,width}], rows: [[...]] },
},
text: {
mainConclusion: '...',
conclusions: ['...'],
intro: ['...'],
methodology: ['...'],
retrospectiveSummary: '...',
forecastSummary: '...',
risks: ['...'],
recommendations: {
'Для руководителей хозяйств': ['...'],
'Для менеджеров по продажам': ['...'],
'Для инвесторов': ['...'],
},
},
})
fs.writeFileSync('report.docx', buf)
Ключевые технические детали
Баг с изображениями (ИСПРАВЛЕН)
ImageRun в docx-js принимает размеры в пикселях, НЕ в EMU.
// ПРАВИЛЬНО:
new ImageRun({ data: buf, transformation: { width: 650, height: 400 }, type: 'png' })
// НЕПРАВИЛЬНО было: width: Math.round(wEmu/9144) → давало 0 или 1px
Рендер SVG → PNG
const sharp = require('sharp')
const buf = await sharp(Buffer.from(svgString)).png({ quality: 95 }).toBuffer()
LibreOffice при конвертации в PDF НЕ рендерит canvas-based изображения, но PNG через sharp работает корректно в Word.
Размеры страницы (A4)
const PAGE_W = 11906 // DXA
const MARGIN = 1020 // ~1.8cm
const CONTENT_W = 9866 // = PAGE_W - MARGIN*2
Стек new.dairy-news.ru (куда интегрировать)
- Next.js 16.2.6, React 19.2.4, TypeScript
- Prisma (PostgreSQL), Tailwind CSS
- Порт 3030, nginx proxy
- Путь:
/var/www/dairynews/ - Существующие разделы админки DT:
/admin/dairytrends/{indices,regions,ratings}/ - Роли для доступа:
ADMIN,EDITOR_STATS,ANALYST_ADMIN - Образец страницы:
src/app/admin/dairytrends/page.tsx— карточки с иконками ti-*
Данные для отчётов
Региональные цены (23 региона)
БД: dn сервер (188.127.243.10), MySQL, база dn_ru
SELECT region_name, date, price FROM region_index
WHERE region_slug = 'vologodskaya-oblast'
ORDER BY date
ФО-агрегаты
БД: dev сервер, PostgreSQL через Prisma
await prisma.dairyIndex.findMany({
where: { type: 'DAIRY_INDEX_RU', regionCode: { not: null } },
orderBy: { date: 'asc' }
})
8 ФО: ЦФО, СЗФО, ЮФО, СКФО, ПФО, УФО, СФО, ДВФО. Итого 349 записей.
МЗЫ (Мяксинский завод / Агромилк)
Данных в БД пока нет — нужно завести вручную или импортировать из Буренки/FarmAI.
Схема: { date, milk_kg, cows, price_per_kg, cost_per_kg, revenue, expenses }
Следующие задачи для нового чата
- Дописать chart2, chart3, chart4 в
/var/www/dairy-report-generator/src/charts/ - Создать страницу
src/app/admin/dairytrends/reports/page.tsxв new.dairy-news.ru - API роут
src/app/api/admin/dairytrends/reports/generate/route.ts - Подключить генератор как local dependency или скопировать src напрямую в dairynews
- Вкладка "Картинки через AI" — форма с промптом, регионом, типом → Anthropic API → показ + скачивание
Пример страницы для начала работы
Образец существующей страницы для повторения стиля:
/var/www/dairynews/src/app/admin/dairytrends/page.tsx
Нужно добавить карточку "Отчёты" в этот файл и создать саму страницу.