ixg_platform/templates/ops/coa_review_list.html
ixgadmin 08096e168f P99C: compliance automation - CoA auto-generation and EUDR due diligence
- 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
2026-08-05 13:58:39 +00:00

58 lines
2.7 KiB
HTML

{% extends 'ops/base_ops.html' %}
{% block title %}CoA Reviews - IXG Operations{% endblock %}
{% block content %}
<div class=page-header d-flex justify-content-between align-items-center>
<h2>Certificate of Analysis Reviews</h2>
<span class=text-secondary>{{ page_obj.paginator.count }} total</span>
</div>
<div class=filter-bar>
<form method=get class=row g-2 align-items-end>
<div class=col-auto>
<select name=status class=form-select form-select-sm>
<option value=>Pending Approval</option>
{% for val, label in status_choices %}
<option value={{ val }} {% if current_status == val %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<div class=col-auto>
<button type=submit class=btn btn-sm btn-primary>Filter</button>
<a href={% url 'ops:coa_review_list' %} class=btn btn-sm btn-outline-secondary>Clear</a>
</div>
</form>
</div>
<div class=stat-card p-0>
<table class=table table-hover mb-0>
<thead>
<tr><th>Batch</th><th>Version</th><th>Status</th><th>Spec</th><th>Quality Approved</th><th>Issued</th><th></th></tr>
</thead>
<tbody>
{% for c in coas %}
<tr>
<td><strong>{{ c.batch.batch_reference }}</strong></td>
<td>v{{ c.version }}</td>
<td><span class=badge {% if c.status == 'published' %}bg-success{% elif c.status == 'superseded' %}bg-secondary{% else %}bg-warning text-dark{% endif %}>{{ c.get_status_display }}</span></td>
<td>{{ c.spec_version|default:'-' }}</td>
<td>{{ c.quality_approved_by.full_name|default:'-' }}</td>
<td>{{ c.issue_date|date:'d/m/Y'|default:'-' }}</td>
<td><a href={% url 'ops:coa_review_detail' c.pk %} class="btn btn-sm {% if c.status == 'pending_approval' %}btn-primary{% else %}btn-outline-secondary{% endif %}">Review</a></td>
</tr>
{% empty %}
<tr><td colspan=7 class=text-muted text-center py-3>No CoA records</td></tr>
{% endfor %}
</tbody>
</table>
</div>
{% if page_obj.paginator.num_pages > 1 %}
<nav class=mt-3><ul class=pagination pagination-sm justify-content-center>
{% if page_obj.has_previous %}<li class=page-item><a class=page-link href=?page=1>&laquo;</a></li><li class=page-item><a class=page-link href=?page={{ page_obj.previous_page_number }}>{{ page_obj.previous_page_number }}</a></li>{% endif %}
<li class=page-item active><span class=page-link>{{ page_obj.number }}</span></li>
{% if page_obj.has_next %}<li class=page-item><a class=page-link href=?page={{ page_obj.next_page_number }}>{{ page_obj.next_page_number }}</a></li><li class=page-item><a class=page-link href=?page={{ page_obj.paginator.num_pages }}>&raquo;</a></li>{% endif %}
</ul></nav>
{% endif %}
{% endblock %}