06/12 Redesign Reports page

This commit is contained in:
2026-06-12 12:47:56 -04:00
parent f1413e0a5d
commit 8cc1770c10
9 changed files with 1329 additions and 27 deletions
+161
View File
@@ -93,6 +93,27 @@ def _build_styles():
add('FooterStyle', parent='Normal',
fontSize=7, textColor=C_SLATE, fontName='Helvetica',
alignment=TA_CENTER)
# ── Summary PDF styles ────────────────────────────────────────────────
add('SummaryTitle', parent='Normal',
fontSize=18, textColor=C_DARK, fontName='Helvetica-Bold', spaceAfter=2)
add('ReportSubtitle', parent='Normal',
fontSize=11, textColor=C_SLATE, fontName='Helvetica', spaceAfter=2)
add('Meta', parent='Normal',
fontSize=8, textColor=C_SLATE, fontName='Helvetica', spaceAfter=1)
add('ScoreValue', parent='Normal',
fontSize=22, textColor=C_BLUE, fontName='Helvetica-Bold',
alignment=TA_CENTER, spaceAfter=0)
add('ScoreLabel', parent='Normal',
fontSize=7.5, textColor=C_SLATE, fontName='Helvetica',
alignment=TA_CENTER, spaceAfter=0)
add('SectionHeader', parent='Normal',
fontSize=10, textColor=C_DARK, fontName='Helvetica-Bold',
spaceBefore=8, spaceAfter=4)
add('TableHeader', parent='Normal',
fontSize=8.5, textColor=C_WHITE, fontName='Helvetica-Bold',
alignment=TA_CENTER, spaceAfter=0)
add('TableCell', parent='Normal',
fontSize=8.5, textColor=C_DARK, fontName='Helvetica', spaceAfter=0)
return base
@@ -1385,4 +1406,144 @@ def generate_inspections_list_pdf(inspections, filter_summary: str = '') -> byte
story.append(tbl)
doc.build(story, onFirstPage=_page_cb, onLaterPages=_page_cb)
# ── Facility Customer Summary PDF ─────────────────────────────────────────────
def generate_facility_summary_pdf(facility, days, start, now,
total_inspections, avg_score,
area_scores, open_issues, resolved_count):
"""Customer-facing one-page PDF summary for a facility."""
styles = _build_styles()
buf = io.BytesIO()
doc = SimpleDocTemplate(
buf, pagesize=letter,
leftMargin=0.75 * inch, rightMargin=0.75 * inch,
topMargin=0.75 * inch, bottomMargin=0.75 * inch,
)
page_w = letter[0] - 1.5 * inch
story = []
story.append(Paragraph(facility.name, styles['SummaryTitle']))
story.append(Paragraph('Facility Performance Summary', styles['ReportSubtitle']))
story.append(Paragraph(
'Period: {} to {} ({} days)'.format(
start.strftime('%b %d, %Y'), now.strftime('%b %d, %Y'), days),
styles['Meta'],
))
if getattr(facility, 'address', None):
story.append(Paragraph(facility.address, styles['Meta']))
story.append(Spacer(1, 0.15 * inch))
story.append(HRFlowable(width='100%', thickness=1, color=C_BORDER))
story.append(Spacer(1, 0.15 * inch))
score_str = '{}%'.format(avg_score) if avg_score is not None else ''
score_color = (C_GREEN if avg_score and avg_score >= 80
else C_YELLOW if avg_score and avg_score >= 60 else C_RED)
def _kpi(label, value, col=C_BLUE):
hex_str = '%06x' % (col.hexval() & 0xFFFFFF)
return [Paragraph('<font color="#{}">'
'<b>{}</b></font>'.format(hex_str, value),
styles['ScoreValue']),
Paragraph(label, styles['ScoreLabel'])]
kpi_tbl = Table([[
_kpi('Inspections Completed', str(total_inspections)),
_kpi('Avg Score', score_str, score_color),
_kpi('Open Issues', str(len(open_issues)),
C_RED if open_issues else C_GREEN),
_kpi('Resolved This Period', str(resolved_count), C_GREEN),
]], colWidths=[page_w / 4] * 4)
kpi_tbl.setStyle(TableStyle([
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('INNERGRID', (0, 0), (-1, -1), 0.5, C_BORDER),
('BOX', (0, 0), (-1, -1), 0.5, C_BORDER),
('BACKGROUND', (0, 0), (-1, -1), C_LIGHT),
('TOPPADDING', (0, 0), (-1, -1), 8),
('BOTTOMPADDING', (0, 0), (-1, -1), 8),
]))
story.append(kpi_tbl)
story.append(Spacer(1, 0.2 * inch))
_P = lambda t: Paragraph(t, styles['TableCell'])
_H = lambda t: Paragraph('<b>{}</b>'.format(t), styles['TableHeader'])
if area_scores:
story.append(Paragraph('Score by Area', styles['SectionHeader']))
story.append(Spacer(1, 0.05 * inch))
tbl_data = [[_H('Area'), _H('Avg Score'), _H('Inspections')]]
for a in area_scores:
avg = round(float(a.avg), 1)
col = C_GREEN if avg >= 80 else C_YELLOW if avg >= 60 else C_RED
hex_str = '%06x' % (col.hexval() & 0xFFFFFF)
tbl_data.append([
_P(a.name),
Paragraph('<font color="#{}">'
'<b>{}%</b></font>'.format(hex_str, avg),
styles['TableCell']),
_P(str(a.count)),
])
area_tbl = Table(tbl_data,
colWidths=[page_w * 0.55, page_w * 0.25, page_w * 0.20],
repeatRows=1)
area_tbl.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), C_DARK),
('ROWBACKGROUNDS', (0, 1), (-1, -1), [C_WHITE, C_LIGHT]),
('INNERGRID', (0, 0), (-1, -1), 0.25, C_BORDER),
('BOX', (0, 0), (-1, -1), 0.5, C_BORDER),
('ALIGN', (1, 0), (-1, -1), 'CENTER'),
('TOPPADDING', (0, 0), (-1, -1), 4),
('BOTTOMPADDING', (0, 0), (-1, -1), 4),
('LEFTPADDING', (0, 0), (-1, -1), 6),
('RIGHTPADDING', (0, 0), (-1, -1), 6),
]))
story.append(area_tbl)
story.append(Spacer(1, 0.2 * inch))
story.append(Paragraph('Open Issues', styles['SectionHeader']))
story.append(Spacer(1, 0.05 * inch))
if open_issues:
tbl_data = [[_H('Severity'), _H('Area'), _H('Description'), _H('Reported')]]
for issue in open_issues:
sev_col = SEVERITY_COLORS.get(issue.severity, C_SLATE)
hex_str = '%06x' % (sev_col.hexval() & 0xFFFFFF)
desc = issue.description or ''
tbl_data.append([
Paragraph('<font color="#{}">'
'<b>{}</b></font>'.format(hex_str, (issue.severity or '').title()),
styles['TableCell']),
_P(issue.area.name if issue.area else ''),
_P(desc[:100] + ('...' if len(desc) > 100 else '')),
_P(issue.reported_at.strftime('%Y-%m-%d') if issue.reported_at else ''),
])
iss_tbl = Table(tbl_data,
colWidths=[page_w * 0.14, page_w * 0.20,
page_w * 0.50, page_w * 0.16],
repeatRows=1)
iss_tbl.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), C_DARK),
('ROWBACKGROUNDS', (0, 1), (-1, -1), [C_WHITE, C_LIGHT]),
('INNERGRID', (0, 0), (-1, -1), 0.25, C_BORDER),
('BOX', (0, 0), (-1, -1), 0.5, C_BORDER),
('VALIGN', (0, 0), (-1, -1), 'TOP'),
('TOPPADDING', (0, 0), (-1, -1), 4),
('BOTTOMPADDING', (0, 0), (-1, -1), 4),
('LEFTPADDING', (0, 0), (-1, -1), 6),
('RIGHTPADDING', (0, 0), (-1, -1), 6),
]))
story.append(iss_tbl)
else:
story.append(Paragraph('No open issues — all clear.', styles['Meta']))
story.append(Spacer(1, 0.2 * inch))
story.append(HRFlowable(width='100%', thickness=0.5, color=C_BORDER))
story.append(Spacer(1, 0.05 * inch))
story.append(Paragraph(
'Generated {} — Confidential'.format(now.strftime('%B %d, %Y %I:%M %p')),
styles['Meta'],
))
doc.build(story)
return buf.getvalue()
return buf.getvalue()