Jul 9 - Update Report - Avg Score by Facility by contract

This commit is contained in:
2026-07-09 11:55:10 -04:00
parent 40ac335f5a
commit 138e44c47d
3 changed files with 90 additions and 24 deletions
+26 -3
View File
@@ -13,6 +13,7 @@ from app.models.inspection import Inspection, InspectionTemplate
from app.models.facility import Facility, Area
from app.models.issue import Issue
from app.models.user import User
from app.models.project import Project
from app.utils.decorators import supervisor_required
from app.utils.scope import get_customer_scope
from app.utils.audit import log_action, ACTION_EXPORT
@@ -141,9 +142,11 @@ def index():
)
avg_score = _scope_insp(avg_score).scalar()
# Scores by facility (for bar chart)
# Scores by facility (for bar chart) — includes project_id so the report
# can group/filter facilities by Contract client-side.
fac_score_q = db.session.query(
Facility.name,
Facility.project_id,
func.avg(Inspection.overall_score).label('avg_score'),
func.count(Inspection.id).label('count'),
).join(Inspection, Facility.id == Inspection.facility_id)\
@@ -159,9 +162,16 @@ def index():
fac_score_q = fac_score_q.filter(
Facility.id.in_(customer_facility_ids) if customer_facility_ids else False
)
facility_scores = fac_score_q.group_by(Facility.id, Facility.name)\
facility_scores = fac_score_q.group_by(Facility.id, Facility.name, Facility.project_id)\
.order_by(func.avg(Inspection.overall_score).desc()).all()
# Resolve contract names for the facilities present.
_proj_ids = {r.project_id for r in facility_scores if r.project_id}
_proj_names = (
{p.id: p.name for p in Project.query.filter(Project.id.in_(_proj_ids)).all()}
if _proj_ids else {}
)
# Prior-period facility scores for period-over-period delta badges
period_len = end - start
prior_end = start
@@ -255,12 +265,24 @@ def index():
inspectors = User.query.filter_by(role='inspector', active=True)\
.order_by(User.full_name, User.username).all()
facility_scores_list = [{'name': r.name, 'avg_score': round(float(r.avg_score), 2), 'count': r.count} for r in facility_scores]
facility_scores_list = [{
'name': r.name,
'avg_score': round(float(r.avg_score), 2),
'count': r.count,
'project_id': r.project_id or 0,
'contract': _proj_names.get(r.project_id, 'No Contract'),
} for r in facility_scores]
# Attach prior avg and delta to each facility score dict for the template table
for row in facility_scores_list:
row['prior_avg'] = prior_scores_map.get(row['name'])
row['delta'] = facility_deltas.get(row['name'])
# Distinct contracts present, for the "Avg Score by Facility" contract filter.
score_contracts = sorted(
{(r['project_id'], r['contract']) for r in facility_scores_list},
key=lambda t: (t[1] or '').lower(),
)
return render_template('reports/index.html',
start=start, end=end,
total_inspections=total_inspections,
@@ -268,6 +290,7 @@ def index():
flagged=flagged,
avg_score=round(float(avg_score), 2) if avg_score else None,
facility_scores=facility_scores_list,
score_contracts=score_contracts,
daily_scores=[{'day': str(r.day), 'avg': round(float(r.avg), 2), 'count': r.count} for r in daily_scores],
issue_severity=[{'severity': r.severity, 'count': r.count} for r in issue_severity],
issue_status=[{'status': r.status, 'count': r.count} for r in issue_status],