06/08 Add Inspector filter in Reports page
This commit is contained in:
+30
-7
@@ -56,10 +56,14 @@ def index():
|
|||||||
customer_facility_ids = get_customer_scope(current_user) # None = unrestricted
|
customer_facility_ids = get_customer_scope(current_user) # None = unrestricted
|
||||||
is_inspector = current_user.role == 'inspector'
|
is_inspector = current_user.role == 'inspector'
|
||||||
|
|
||||||
# Pre-compute the set of inspection IDs conducted by this inspector.
|
# Inspector filter — admin / director / project_manager only
|
||||||
# Used in _scope_issue to avoid adding a join to queries that already
|
inspector_filter = None
|
||||||
# have their own joins (e.g. issue_severity, issue_status group-by queries).
|
if current_user.role in ('admin', 'director', 'project_manager'):
|
||||||
inspector_inspection_ids = []
|
inspector_filter = request.args.get('inspector_id', type=int) or None
|
||||||
|
|
||||||
|
# Pre-compute inspection ID sets used by _scope_issue to avoid join conflicts.
|
||||||
|
inspector_inspection_ids = [] # own inspections (inspector role)
|
||||||
|
filter_inspection_ids = None # filtered inspector's inspections (admin/dir/PM)
|
||||||
if is_inspector:
|
if is_inspector:
|
||||||
inspector_inspection_ids = [
|
inspector_inspection_ids = [
|
||||||
row[0] for row in
|
row[0] for row in
|
||||||
@@ -67,10 +71,19 @@ def index():
|
|||||||
.filter(Inspection.inspector_id == current_user.id)
|
.filter(Inspection.inspector_id == current_user.id)
|
||||||
.all()
|
.all()
|
||||||
]
|
]
|
||||||
|
elif inspector_filter:
|
||||||
|
filter_inspection_ids = [
|
||||||
|
row[0] for row in
|
||||||
|
db.session.query(Inspection.id)
|
||||||
|
.filter(Inspection.inspector_id == inspector_filter)
|
||||||
|
.all()
|
||||||
|
]
|
||||||
|
|
||||||
def _scope_insp(q):
|
def _scope_insp(q):
|
||||||
if is_inspector:
|
if is_inspector:
|
||||||
return q.filter(Inspection.inspector_id == current_user.id)
|
return q.filter(Inspection.inspector_id == current_user.id)
|
||||||
|
if inspector_filter:
|
||||||
|
q = q.filter(Inspection.inspector_id == inspector_filter)
|
||||||
if customer_facility_ids is not None:
|
if customer_facility_ids is not None:
|
||||||
if not customer_facility_ids:
|
if not customer_facility_ids:
|
||||||
return q.filter(False)
|
return q.filter(False)
|
||||||
@@ -79,12 +92,13 @@ def index():
|
|||||||
|
|
||||||
def _scope_issue(q):
|
def _scope_issue(q):
|
||||||
if is_inspector:
|
if is_inspector:
|
||||||
# Scope to issues flagged during this inspector's own inspections.
|
|
||||||
# Uses a pre-computed ID list (subquery) to avoid join conflicts
|
|
||||||
# with queries that already carry their own joins/group-by clauses.
|
|
||||||
if not inspector_inspection_ids:
|
if not inspector_inspection_ids:
|
||||||
return q.filter(False)
|
return q.filter(False)
|
||||||
return q.filter(Issue.inspection_id.in_(inspector_inspection_ids))
|
return q.filter(Issue.inspection_id.in_(inspector_inspection_ids))
|
||||||
|
if filter_inspection_ids is not None:
|
||||||
|
if not filter_inspection_ids:
|
||||||
|
return q.filter(False)
|
||||||
|
return q.filter(Issue.inspection_id.in_(filter_inspection_ids))
|
||||||
if customer_facility_ids is not None:
|
if customer_facility_ids is not None:
|
||||||
if not customer_facility_ids:
|
if not customer_facility_ids:
|
||||||
return q.filter(False)
|
return q.filter(False)
|
||||||
@@ -128,6 +142,8 @@ def index():
|
|||||||
Inspection.status == 'completed',
|
Inspection.status == 'completed',
|
||||||
Inspection.overall_score.isnot(None),
|
Inspection.overall_score.isnot(None),
|
||||||
)
|
)
|
||||||
|
if inspector_filter:
|
||||||
|
fac_score_q = fac_score_q.filter(Inspection.inspector_id == inspector_filter)
|
||||||
if customer_facility_ids is not None:
|
if customer_facility_ids is not None:
|
||||||
fac_score_q = fac_score_q.filter(
|
fac_score_q = fac_score_q.filter(
|
||||||
Facility.id.in_(customer_facility_ids) if customer_facility_ids else False
|
Facility.id.in_(customer_facility_ids) if customer_facility_ids else False
|
||||||
@@ -193,6 +209,11 @@ def index():
|
|||||||
Issue.reported_at <= end,
|
Issue.reported_at <= end,
|
||||||
)).order_by(Issue.reported_at.desc()).limit(10).all()
|
)).order_by(Issue.reported_at.desc()).limit(10).all()
|
||||||
|
|
||||||
|
inspectors = []
|
||||||
|
if current_user.role in ('admin', 'director', 'project_manager'):
|
||||||
|
inspectors = User.query.filter_by(role='inspector', active=True)\
|
||||||
|
.order_by(User.full_name, User.username).all()
|
||||||
|
|
||||||
return render_template('reports/index.html',
|
return render_template('reports/index.html',
|
||||||
start=start, end=end,
|
start=start, end=end,
|
||||||
total_inspections=total_inspections,
|
total_inspections=total_inspections,
|
||||||
@@ -206,6 +227,8 @@ def index():
|
|||||||
top_inspectors=[{'username': r.username, 'count': r.count, 'avg_score': round(float(r.avg_score), 2) if r.avg_score else None} for r in top_inspectors],
|
top_inspectors=[{'username': r.username, 'count': r.count, 'avg_score': round(float(r.avg_score), 2) if r.avg_score else None} for r in top_inspectors],
|
||||||
critical_issues=critical_issues,
|
critical_issues=critical_issues,
|
||||||
is_inspector=is_inspector,
|
is_inspector=is_inspector,
|
||||||
|
inspectors=inspectors,
|
||||||
|
inspector_filter=inspector_filter,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,19 @@
|
|||||||
<input type="date" name="end" class="form-control form-control-sm"
|
<input type="date" name="end" class="form-control form-control-sm"
|
||||||
value="{{ end.strftime('%Y-%m-%d') }}">
|
value="{{ end.strftime('%Y-%m-%d') }}">
|
||||||
</div>
|
</div>
|
||||||
|
{% if inspectors %}
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label small mb-1">Inspector</label>
|
||||||
|
<select name="inspector_id" class="form-select form-select-sm">
|
||||||
|
<option value="">All Inspectors</option>
|
||||||
|
{% for u in inspectors %}
|
||||||
|
<option value="{{ u.id }}" {% if inspector_filter == u.id %}selected{% endif %}>
|
||||||
|
{{ u.display_name }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<button class="btn btn-sm btn-primary">Apply</button>
|
<button class="btn btn-sm btn-primary">Apply</button>
|
||||||
<a href="{{ url_for('reports.index') }}" class="btn btn-sm btn-outline-secondary">Reset</a>
|
<a href="{{ url_for('reports.index') }}" class="btn btn-sm btn-outline-secondary">Reset</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user