06/12 Add features: 1. Vendor/Contractor assignment 2. Period-over-period comparison 3. Trend Alerts (cron)
This commit is contained in:
@@ -76,6 +76,20 @@
|
||||
<dt class="col-sm-3">Assigned To</dt>
|
||||
<dd class="col-sm-9">{{ issue.assigned_user.display_name if issue.assigned_user else '— Unassigned —' }}</dd>
|
||||
|
||||
{% if issue.vendor_name %}
|
||||
<dt class="col-sm-3">Contractor</dt>
|
||||
<dd class="col-sm-9">
|
||||
<i class="bi bi-person-gear text-secondary me-1"></i>
|
||||
<strong>{{ issue.vendor_name }}</strong>
|
||||
{% if issue.vendor_contact %}
|
||||
<span class="text-muted ms-2">{{ issue.vendor_contact }}</span>
|
||||
{% endif %}
|
||||
{% if issue.vendor_notes %}
|
||||
<div class="text-muted small mt-1" style="white-space:pre-wrap;">{{ issue.vendor_notes }}</div>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
|
||||
{% if issue.resolved_at %}
|
||||
<dt class="col-sm-3">Resolved</dt>
|
||||
<dd class="col-sm-9">{{ issue.resolved_at.strftime('%Y-%m-%d %H:%M') }}</dd>
|
||||
@@ -350,6 +364,29 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if current_user.role in ['admin','director','project_manager'] %}
|
||||
<hr class="my-3">
|
||||
<p class="fw-semibold small mb-2">
|
||||
<i class="bi bi-person-gear me-1 text-secondary"></i>External Contractor
|
||||
</p>
|
||||
<div class="mb-2">
|
||||
{{ form.vendor_name.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.vendor_name(class="form-control form-control-sm",
|
||||
placeholder="Contractor or vendor name",
|
||||
value=issue.vendor_name or '') }}
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
{{ form.vendor_contact.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.vendor_contact(class="form-control form-control-sm",
|
||||
placeholder="Phone or email",
|
||||
value=issue.vendor_contact or '') }}
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{{ form.vendor_notes.label(class="form-label small fw-semibold mb-1") }}
|
||||
{{ form.vendor_notes(class="form-control form-control-sm", rows=2,
|
||||
placeholder="Notes about what the contractor is handling…") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<button type="submit" class="btn btn-primary w-100">Save Update</button>
|
||||
</form>
|
||||
{% if issue.status in ['in_progress', 'resolved'] and current_user.role not in ['customer'] %}
|
||||
|
||||
@@ -117,6 +117,68 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ── Facility period-over-period comparison table ── #}
|
||||
{% if facility_scores %}
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header bg-light d-flex align-items-center gap-2">
|
||||
<h6 class="mb-0"><i class="bi bi-building"></i> Facility Score Comparison</h6>
|
||||
<span class="text-muted small">vs. prior equal-length period</span>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Facility</th>
|
||||
<th class="text-end">Current Period</th>
|
||||
<th class="text-end">Prior Period</th>
|
||||
<th class="text-end">Change</th>
|
||||
<th class="text-end">Inspections</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in facility_scores %}
|
||||
<tr>
|
||||
<td class="fw-semibold">{{ row.name }}</td>
|
||||
<td class="text-end">
|
||||
<span class="badge bg-{{ 'success' if row.avg_score >= 90 else 'warning text-dark' if row.avg_score >= 70 else 'danger' }}">
|
||||
{{ '%.1f'|format(row.avg_score|float) }}%
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-end text-muted">
|
||||
{% if row.prior_avg is not none %}
|
||||
{{ '%.1f'|format(row.prior_avg|float) }}%
|
||||
{% else %}
|
||||
<span class="text-muted">—</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-end">
|
||||
{% if row.delta is not none %}
|
||||
{% if row.delta > 0 %}
|
||||
<span class="badge bg-success-subtle text-success border border-success fw-semibold">
|
||||
<i class="bi bi-arrow-up-short"></i>+{{ '%.1f'|format(row.delta|float) }}
|
||||
</span>
|
||||
{% elif row.delta < 0 %}
|
||||
<span class="badge bg-danger-subtle text-danger border border-danger fw-semibold">
|
||||
<i class="bi bi-arrow-down-short"></i>{{ '%.1f'|format(row.delta|float) }}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary-subtle text-secondary border fw-semibold">
|
||||
<i class="bi bi-dash"></i> 0.0
|
||||
</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted small">No prior data</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-end text-muted small">{{ row.count }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# ── Top inspectors table ── #}
|
||||
{% if top_inspectors %}
|
||||
<div class="row mb-4">
|
||||
|
||||
Reference in New Issue
Block a user