hm_ai_qc_report_tool/templates/pdf_export.html
nickviljoen 96d0bf95e1 Reporting updated.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-14 09:14:00 +02:00

315 lines
9.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>QC Report - Job {{ job_number }}</title>
<style>
.print-notice {
background: #e3f2fd;
border: 2px solid #2196f3;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
@media print {
.print-notice { display: none; }
}
body {
font-family: Arial, sans-serif;
margin: 20px;
color: #333;
}
h1, h2, h3 {
color: #2c3e50;
}
.header {
border-bottom: 3px solid #3498db;
padding-bottom: 10px;
margin-bottom: 20px;
}
.summary {
background-color: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.summary-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
margin-top: 10px;
}
.summary-item {
text-align: center;
padding: 10px;
background: white;
border-radius: 5px;
}
.summary-value {
font-size: 24px;
font-weight: bold;
display: block;
}
.summary-label {
font-size: 12px;
color: #666;
text-transform: uppercase;
}
.file-section {
page-break-inside: avoid;
margin-bottom: 30px;
border: 1px solid #ddd;
border-radius: 5px;
padding: 15px;
}
.file-header {
background-color: #3498db;
color: white;
padding: 10px;
margin: -15px -15px 15px -15px;
border-radius: 5px 5px 0 0;
}
.check-item {
margin-bottom: 15px;
padding: 10px;
border-left: 4px solid #ddd;
background-color: #f8f9fa;
}
.check-item.passed {
border-left-color: #27ae60;
}
.check-item.error {
border-left-color: #e74c3c;
background-color: #fce4e4;
}
.check-item.warning {
border-left-color: #f39c12;
background-color: #fff8e1;
}
.status-badge {
display: inline-block;
padding: 3px 8px;
border-radius: 3px;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
}
.status-passed {
background-color: #27ae60;
color: white;
}
.status-error {
background-color: #e74c3c;
color: white;
}
.status-warning {
background-color: #f39c12;
color: white;
}
.status-skipped {
background-color: #95a5a6;
color: white;
}
.check-details {
margin-top: 8px;
font-size: 12px;
}
.check-details strong {
color: #2c3e50;
}
.error-list {
background-color: #fff;
border: 1px solid #e74c3c;
padding: 10px;
margin-top: 15px;
border-radius: 5px;
}
.footer {
margin-top: 30px;
padding-top: 15px;
border-top: 2px solid #ddd;
font-size: 11px;
color: #666;
text-align: center;
}
.errors-only-banner {
background-color: #fce4e4;
border: 2px solid #e74c3c;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
text-align: center;
}
.errors-only-banner h3 {
color: #e74c3c;
margin: 0 0 5px 0;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
table td {
padding: 5px;
border-bottom: 1px solid #ddd;
}
table td:first-child {
font-weight: bold;
width: 30%;
}
</style>
</head>
<body>
<div class="print-notice">
<p><strong>💡 Tip:</strong> To save as PDF, use your browser's Print function (Ctrl/Cmd + P) and select "Save as PDF"</p>
</div>
<div class="header">
<h1>QC Report Summary</h1>
<h2>Job Number: {{ job_number }}</h2>
<p><strong>Generated:</strong> {{ generated_at }}</p>
</div>
{% if errors_only %}
<div class="errors-only-banner">
<h3>⚠️ ERROR REPORTS ONLY</h3>
<p>This export contains only files with errors. Files that passed all checks are excluded.</p>
</div>
{% endif %}
<div class="summary">
<h3>Overall Summary</h3>
<div class="summary-grid">
<div class="summary-item">
<span class="summary-value">{{ aggregated.total_files }}</span>
<span class="summary-label">Files Checked</span>
</div>
<div class="summary-item">
<span class="summary-value">{{ aggregated.total_checks }}</span>
<span class="summary-label">Total Checks</span>
</div>
<div class="summary-item">
<span class="summary-value" style="color: #27ae60;">{{ aggregated.summary.passed }}</span>
<span class="summary-label">Passed</span>
</div>
<div class="summary-item">
<span class="summary-value" style="color: #e74c3c;">{{ aggregated.summary.error }}</span>
<span class="summary-label">Errors</span>
</div>
<div class="summary-item">
<span class="summary-value" style="color: #f39c12;">{{ aggregated.summary.warning }}</span>
<span class="summary-label">Warnings</span>
</div>
<div class="summary-item">
<span class="summary-value" style="color: #95a5a6;">{{ aggregated.summary.skipped }}</span>
<span class="summary-label">Skipped</span>
</div>
</div>
</div>
{% if aggregated.files_with_errors %}
<div class="error-list">
<h3 style="color: #e74c3c;">Files with Errors ({{ aggregated.files_with_errors|length }})</h3>
<ul>
{% for file in aggregated.files_with_errors %}
<li>
<strong>{{ file.filename }}</strong> - {{ file.error_count }} error(s)
</li>
{% endfor %}
</ul>
</div>
{% endif %}
<h2 style="margin-top: 30px;">Detailed Reports</h2>
{% for report in reports %}
<div class="file-section">
<div class="file-header">
<h3 style="margin: 0;">{{ report.filename }}</h3>
{% if report.timestamp %}
<small>Generated: {{ report.timestamp }}</small>
{% endif %}
</div>
{% if report.error %}
<div class="check-item error">
<strong>Error:</strong> {{ report.error }}
</div>
{% else %}
<table>
<tr>
<td>Total Checks:</td>
<td>{{ report.summary.total }}</td>
</tr>
<tr>
<td>Passed:</td>
<td style="color: #27ae60;">{{ report.summary.passed }}</td>
</tr>
<tr>
<td>Errors:</td>
<td style="color: #e74c3c;">{{ report.summary.error }}</td>
</tr>
<tr>
<td>Warnings:</td>
<td style="color: #f39c12;">{{ report.summary.warning }}</td>
</tr>
<tr>
<td>Skipped:</td>
<td style="color: #95a5a6;">{{ report.summary.skipped }}</td>
</tr>
</table>
<h4 style="margin-top: 20px;">Check Results:</h4>
{% for check in report.checks %}
<div class="check-item {{ check.status }}">
<div>
<span class="status-badge status-{{ check.status }}">{{ check.status_text }}</span>
<strong>{{ check.name }}</strong>
</div>
{% if check.description %}
<div style="margin-top: 5px; color: #666; font-size: 12px;">
{{ check.description }}
</div>
{% endif %}
{% if check.error_message %}
<div style="margin-top: 10px; color: #e74c3c; font-weight: bold;">
Error: {{ check.error_message }}
</div>
{% endif %}
{% if check.results %}
<div class="check-details">
<strong>Results:</strong>
<ul style="margin: 5px 0; padding-left: 20px;">
{% for key, value in check.results.items() %}
<li>
<strong>{{ key }}:</strong>
{% if value is mapping %}
<ul style="margin-left: 20px;">
{% for k, v in value.items() %}
<li>{{ k }}: {{ v }}</li>
{% endfor %}
</ul>
{% else %}
{{ value }}
{% endif %}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% endfor %}
{% endif %}
</div>
{% endfor %}
<div class="footer">
<p>QC Report Dashboard - Generated {{ generated_at }}</p>
<p>This report was automatically generated from Box.com QC reports</p>
</div>
</body>
</html>