Files
2026-07-17 12:57:18 +03:00

131 lines
4.1 KiB
Python

"""PDF: отчёт «Потребление корма»."""
from __future__ import annotations
import io
from flask import Flask
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import mm
from reportlab.platypus import PageBreak, Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle
from app.services.feed_accounting.consumption_report_builder import build_consumption_report
from app.services.feed_accounting.pdf_feed_accounting import _styles
def _table(data: list, font: str, *, font_size: int = 8, repeat_rows: int = 1) -> Table:
tbl = Table(data, repeatRows=repeat_rows)
tbl.setStyle(
TableStyle(
[
("FONTNAME", (0, 0), (-1, -1), font),
("FONTSIZE", (0, 0), (-1, -1), font_size),
("BACKGROUND", (0, 0), (-1, 0), colors.lightgrey),
("GRID", (0, 0), (-1, -1), 0.25, colors.grey),
("VALIGN", (0, 0), (-1, -1), "TOP"),
]
)
)
return tbl
def build_consumption_pdf(app: Flask, date_from: str, date_to: str) -> bytes:
report = build_consumption_report(app, date_from, date_to)
buf = io.BytesIO()
doc = SimpleDocTemplate(
buf,
pagesize=landscape(A4),
leftMargin=10 * mm,
rightMargin=10 * mm,
topMargin=10 * mm,
bottomMargin=10 * mm,
)
styles, font = _styles()
story = [
Paragraph("Потребление корма", styles["Title"]),
Paragraph(f"Период: {date_from}{date_to}", styles["Normal"]),
Spacer(1, 6),
Paragraph("Сводка", styles["Normal"]),
Spacer(1, 4),
]
sum_data = [
[
"Компонент",
"Осталось, кг",
"Расход за период, кг",
"План кг/сут",
"Осталось дней",
"Поступление, кг",
"Всего, кг",
]
]
for row in report.summary:
sum_data.append(
[
row["name"],
row["remaining_kg"],
row["consumed_kg"],
row["planned_per_day_kg"] or "",
row["days_left"] if row["days_left"] is not None else "",
row["inflow_kg"],
row["total_kg"],
]
)
if len(sum_data) == 1:
sum_data.append(["—", "", "", "", "", "", ""])
story.append(_table(sum_data, font))
story.append(PageBreak())
story.append(Paragraph("Расход по дням", styles["Normal"]))
story.append(Spacer(1, 4))
day_labels = [d.strftime("%d.%m") for d in report.days]
daily_data = [["Компонент"] + day_labels + ["Итого"]]
for row in report.daily:
daily_data.append(
[row["name"]]
+ [row["days"].get(d, 0) or "" for d in report.days]
+ [row["total_kg"]]
)
if len(daily_data) == 1:
daily_data.append(["—"] + [""] * (len(report.days) + 1))
story.append(_table(daily_data, font, font_size=6))
story.append(PageBreak())
story.append(Paragraph("Детализация загрузок", styles["Normal"]))
story.append(Spacer(1, 4))
det_data = [
[
"Начало",
"Окончание",
"Рецепт",
"Кормораздатчик",
"Компонент",
"План, кг",
"Факт, кг",
"Перегруз, кг",
"№",
]
]
for row in report.detail:
det_data.append(
[
row["start"],
row["end"],
row["recipe"],
row["dispenser"],
row["component"],
row["target_kg"],
row["actual_kg"],
row["overload_kg"],
row["loading_order"],
]
)
if len(det_data) == 1:
det_data.append(["—", "", "", "", "", "", "", "", ""])
story.append(_table(det_data, font, font_size=7))
doc.build(story)
return buf.getvalue()