- Versioned product specification table (Unrefined Shea Butter v1.0 seed) with spec-based QC evaluation replacing hard-coded thresholds - Structured QC results with test methods and four-eyes verification (submitter cannot self-approve) - reportlab IXG Quality Summary PDF auto-generated on quality approval, SHA-256 hashed; original independent lab PDF kept authoritative - CertificateOfAnalysis version/status/hash/approval/supersede lifecycle; commercial release publishes to buyers and triggers notification - EUDR evidence workflow: Facility, OriginZone, CollectorGroup, HarvestIntake, IntakeBatchLineage, DueDiligenceCase, EUDREvidence, RiskAssessment, MitigationAction, DueDiligenceStatementReference with rule-based completeness check and risk assessment (no AI legal conclusions) - Ops portal: QC Approvals, CoA Reviews, EUDR Compliance screens - Buyer portal: /portal/compliance page - 22 automated tests covering four-eyes, CAPA, PDF+hash, publish/notify, EUDR blocks and buyer isolation
65 lines
3.8 KiB
HTML
65 lines
3.8 KiB
HTML
{% extends 'ops/base_ops.html' %}
|
|
{% block title %}CoA Review - IXG Operations{% endblock %}
|
|
{% block content %}
|
|
|
|
<div class=page-header d-flex justify-content-between align-items-center>
|
|
<h2>CoA Review: {{ coa.batch.batch_reference }}</h2>
|
|
<a href={% url 'ops:coa_review_list' %} class=btn btn-sm btn-outline-secondary><i class=bi bi-arrow-left></i> Back</a>
|
|
</div>
|
|
|
|
{% if messages %}
|
|
{% for m in messages %}<div class="alert alert-{{ m.tags }} py-2">{{ m }}</div>{% endfor %}
|
|
{% endif %}
|
|
|
|
<div class=row g-3>
|
|
<div class=col-md-7>
|
|
<div class=stat-card>
|
|
<h6 class=mb-3>Certificate Details</h6>
|
|
<table class=table table-sm table-borderless mb-0>
|
|
<tr><td class=text-secondary>Batch</td><td><a href={% url 'ops:batch_detail' coa.batch.pk %}>{{ coa.batch.batch_reference }}</a></td></tr>
|
|
<tr><td class=text-secondary>Status</td><td><span class=badge {% if coa.status == 'published' %}bg-success{% elif coa.status == 'superseded' %}bg-secondary{% else %}bg-warning text-dark{% endif %}>{{ coa.get_status_display }}</span></td></tr>
|
|
<tr><td class=text-secondary>Version</td><td>v{{ coa.version }}</td></tr>
|
|
<tr><td class=text-secondary>Specification</td><td>{{ coa.spec_version|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>Issuer</td><td>{{ coa.issuer|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>Issue Date</td><td>{{ coa.issue_date|date:'d/m/Y'|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>Quality Approved By</td><td>{{ coa.quality_approved_by.full_name|default:coa.quality_approved_by.email|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>Quality Approved At</td><td>{{ coa.quality_approved_at|date:'d/m/Y H:i'|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>Released At</td><td>{{ coa.released_at|date:'d/m/Y H:i'|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>Published At</td><td>{{ coa.published_at|date:'d/m/Y H:i'|default:'-' }}</td></tr>
|
|
<tr><td class=text-secondary>SHA-256</td><td><code>{{ coa.sha256_hash|default:'-' }}</code></td></tr>
|
|
<tr><td class=text-secondary>Summary PDF</td><td><a href="{{ coa.file_url }}" target=_blank class=text-decoration-none><i class=bi bi-file-earmark-pdf></i> {{ coa.file_name }}</a></td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class=col-md-5>
|
|
<div class=stat-card mb-3>
|
|
<h6 class=mb-3>Source Documents</h6>
|
|
<p class=small text-muted>Independent laboratory report (authoritative):</p>
|
|
{% if coa.source_document %}
|
|
<a href="{{ coa.source_document.file_url }}" target=_blank class=text-decoration-none><i class=bi bi-file-earmark-pdf></i> {{ coa.source_document.file_name }}</a>
|
|
{% else %}
|
|
<p class=text-muted mb-0>No lab report linked. <a href={% url 'ops:document_list' %}>Upload</a> the original laboratory PDF for the batch.</p>
|
|
{% endif %}
|
|
{% if lab_documents %}
|
|
<hr>
|
|
<p class=small text-muted mb-1>All lab documents for batch:</p>
|
|
{% for d in lab_documents %}<div><a href="{{ d.file_url }}" target=_blank class=text-decoration-none><i class=bi bi-file-earmark-pdf></i> {{ d.file_name }}</a></div>{% endfor %}
|
|
{% endif %}
|
|
</div>
|
|
<div class=stat-card>
|
|
<h6 class=mb-3>Commercial Release</h6>
|
|
{% if coa.status == 'pending_approval' %}
|
|
<form method=post>
|
|
{% csrf_token %}
|
|
<input type=hidden name=action value=approve>
|
|
<p class=text-muted>Publishing exposes the summary PDF to authorised buyers and triggers buyer notification.</p>
|
|
<button type=submit class="btn btn-success w-100"><i class=bi bi-send></i> Approve & Publish</button>
|
|
</form>
|
|
{% else %}
|
|
<p class=text-muted mb-0">Commercial release approved. Buyer document and notification created.</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|