Skip to content

Commit ec81232

Browse files
authored
[Comp-750] alias enforcements in project compliance and first nations report (#772)
1 parent d74eef1 commit ec81232

File tree

4 files changed

+297
-67
lines changed

4 files changed

+297
-67
lines changed

compliance-api/src/compliance_api/services/report/first_nation.py

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from compliance_api.models.inspection.inspection_option import InspectionAttendanceOption
99
from flask import current_app
1010
from sqlalchemy import and_, func
11-
from sqlalchemy.orm import selectinload
11+
from sqlalchemy.orm import aliased, selectinload
1212

1313
from compliance_api.models import db
1414
from compliance_api.models.administrative_penalty import AdministrativePenalty
@@ -151,6 +151,14 @@ def _to_excel(
151151
def _build_inspections_tab_query(self):
152152
"""Build base query for First Nation Report."""
153153

154+
# Create aliases for enforcement document models
155+
order_alias = aliased(Order)
156+
warning_letter_alias = aliased(WarningLetter)
157+
violation_ticket_alias = aliased(ViolationTicket)
158+
administrative_penalty_alias = aliased(AdministrativePenalty)
159+
charge_recommendation_alias = aliased(ChargeRecommendation)
160+
restorative_justice_alias = aliased(RestorativeJustice)
161+
154162
requirement_order_subquery = get_requirement_order_sub_query()
155163
requirement_warning_letter_subquery = get_requirement_warning_letter_sub_query()
156164
requirement_violation_ticket_subquery = get_requirement_violation_ticket_sub_query()
@@ -178,19 +186,19 @@ def _build_inspections_tab_query(self):
178186
InspectionReqEnforcementMap.enforcement_action_id.label("enforcement_action_id"),
179187
EnforcementActionOption.name.label("enforcement_action"),
180188
# Enforcement statuses
181-
Order.order_status.label("order_status"),
182-
WarningLetter.status.label("warning_letter_status"),
183-
ViolationTicket.status.label("violation_ticket_status"),
184-
AdministrativePenalty.referral_status.label("admin_penalty_status"),
185-
ChargeRecommendation.status.label("charge_rec_status"),
186-
RestorativeJustice.status.label("restorative_justice_status"),
189+
order_alias.order_status.label("order_status"),
190+
warning_letter_alias.status.label("warning_letter_status"),
191+
violation_ticket_alias.status.label("violation_ticket_status"),
192+
administrative_penalty_alias.referral_status.label("admin_penalty_status"),
193+
charge_recommendation_alias.status.label("charge_rec_status"),
194+
restorative_justice_alias.status.label("restorative_justice_status"),
187195
# Enforcement document numbers
188-
Order.order_number.label("order_number"),
189-
WarningLetter.warning_letter_number.label("warning_letter_number"),
190-
ViolationTicket.ticket_number.label("violation_ticket_number"),
191-
AdministrativePenalty.administrative_penalty_number.label("admin_penalty_number"),
192-
ChargeRecommendation.charge_recommendation_number.label("charge_rec_number"),
193-
RestorativeJustice.restorative_justice_number.label("restorative_justice_number"),
196+
order_alias.order_number.label("order_number"),
197+
warning_letter_alias.warning_letter_number.label("warning_letter_number"),
198+
violation_ticket_alias.ticket_number.label("violation_ticket_number"),
199+
administrative_penalty_alias.administrative_penalty_number.label("admin_penalty_number"),
200+
charge_recommendation_alias.charge_recommendation_number.label("charge_rec_number"),
201+
restorative_justice_alias.restorative_justice_number.label("restorative_justice_number"),
194202
InspectionRecord.date_issued.label("ir_date_issued"),
195203
StaffUser,
196204
Inspection.inspection_status.label("inspection_status"),
@@ -225,48 +233,48 @@ def _build_inspections_tab_query(self):
225233
requirement_order_subquery.c.inspection_requirement_id == InspectionRequirement.id
226234
)
227235
.outerjoin(
228-
Order,
229-
Order.id == requirement_order_subquery.c.order_id
236+
order_alias,
237+
order_alias.id == requirement_order_subquery.c.order_id
230238
)
231239
.outerjoin(
232240
requirement_warning_letter_subquery,
233241
requirement_warning_letter_subquery.c.inspection_requirement_id == InspectionRequirement.id
234242
)
235243
.outerjoin(
236-
WarningLetter,
237-
WarningLetter.id == requirement_warning_letter_subquery.c.warning_letter_id
244+
warning_letter_alias,
245+
warning_letter_alias.id == requirement_warning_letter_subquery.c.warning_letter_id
238246
)
239247
.outerjoin(
240248
requirement_violation_ticket_subquery,
241249
requirement_violation_ticket_subquery.c.inspection_requirement_id == InspectionRequirement.id
242250
)
243251
.outerjoin(
244-
ViolationTicket,
245-
ViolationTicket.id == requirement_violation_ticket_subquery.c.violation_ticket_id
252+
violation_ticket_alias,
253+
violation_ticket_alias.id == requirement_violation_ticket_subquery.c.violation_ticket_id
246254
)
247255
.outerjoin(
248256
requirement_admin_penalty_subquery,
249257
requirement_admin_penalty_subquery.c.inspection_requirement_id == InspectionRequirement.id
250258
)
251259
.outerjoin(
252-
AdministrativePenalty,
253-
AdministrativePenalty.id == requirement_admin_penalty_subquery.c.administrative_penalty_id
260+
administrative_penalty_alias,
261+
administrative_penalty_alias.id == requirement_admin_penalty_subquery.c.administrative_penalty_id
254262
)
255263
.outerjoin(
256264
requirement_charge_rec_subquery,
257265
requirement_charge_rec_subquery.c.inspection_requirement_id == InspectionRequirement.id
258266
)
259267
.outerjoin(
260-
ChargeRecommendation,
261-
ChargeRecommendation.id == requirement_charge_rec_subquery.c.charge_recommendation_id
268+
charge_recommendation_alias,
269+
charge_recommendation_alias.id == requirement_charge_rec_subquery.c.charge_recommendation_id
262270
)
263271
.outerjoin(
264272
requirement_restorative_justice_subquery,
265273
requirement_restorative_justice_subquery.c.inspection_requirement_id == InspectionRequirement.id
266274
)
267275
.outerjoin(
268-
RestorativeJustice,
269-
RestorativeJustice.id == requirement_restorative_justice_subquery.c.restorative_justice_id
276+
restorative_justice_alias,
277+
restorative_justice_alias.id == requirement_restorative_justice_subquery.c.restorative_justice_id
270278
)
271279
.filter(
272280
InspectionRequirement.is_active.is_(True),

compliance-api/src/compliance_api/services/report/project_compliance.py

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
from flask import current_app
99
from sqlalchemy import and_, func
10-
from sqlalchemy.orm import selectinload
10+
from sqlalchemy.orm import aliased, selectinload
1111

1212
from compliance_api.models import db
1313
from compliance_api.models.administrative_penalty import AdministrativePenalty, DecisionEnum
1414
from compliance_api.models.charge_recommendation import ChargeRecommendation
1515
from compliance_api.models.compliance_finding import ComplianceFindingOption
16-
from compliance_api.models.enforcement_action import EnforcementActionOption
16+
from compliance_api.models.enforcement_action import EnforcementActionOption, EnforcementActionOptionEnum
1717
from compliance_api.models.inspection.inspection import Inspection
1818
from compliance_api.models.inspection.inspection_option import InspectionInitiationOption, InspectionTypeOption
1919
from compliance_api.models.inspection.inspection_req_enforcement_map import InspectionReqEnforcementMap
@@ -124,6 +124,14 @@ def _to_excel(
124124
def _build_inspection_requirements_query(self, project_id: int):
125125
"""Build base query for Project Compliance History Report."""
126126

127+
# Alias all enforcement types to join on ALL linked enforcement actions.
128+
order_alias = aliased(Order)
129+
warning_letter_alias = aliased(WarningLetter)
130+
violation_ticket_alias = aliased(ViolationTicket)
131+
admin_penalty_alias = aliased(AdministrativePenalty)
132+
restorative_justice_alias = aliased(RestorativeJustice)
133+
charge_rec_alias = aliased(ChargeRecommendation)
134+
127135
requirement_order_subquery = get_requirement_order_sub_query()
128136
requirement_warning_letter_subquery = get_requirement_warning_letter_sub_query()
129137
requirement_violation_ticket_subquery = get_requirement_violation_ticket_sub_query()
@@ -148,26 +156,30 @@ def _build_inspection_requirements_query(self, project_id: int):
148156
InspectionReqEnforcementMap.enforcement_action_id.label("enforcement_action_id"),
149157
EnforcementActionOption.name.label("enforcement_action"),
150158
# Enforcement statuses
151-
Order.order_status.label("order_status"),
152-
WarningLetter.status.label("warning_letter_status"),
153-
ViolationTicket.status.label("violation_ticket_status"),
154-
AdministrativePenalty.referral_status.label("admin_penalty_status"),
155-
ChargeRecommendation.status.label("charge_rec_status"),
156-
RestorativeJustice.status.label("restorative_justice_status"),
159+
order_alias.order_status.label("order_status"),
160+
warning_letter_alias.status.label("warning_letter_status"),
161+
violation_ticket_alias.status.label("violation_ticket_status"),
162+
admin_penalty_alias.referral_status.label("admin_penalty_status"),
163+
charge_rec_alias.status.label("charge_rec_status"),
164+
restorative_justice_alias.status.label("restorative_justice_status"),
157165
# Enforcement document numbers
158-
Order.order_number.label("order_number"),
159-
WarningLetter.warning_letter_number.label("warning_letter_number"),
160-
ViolationTicket.ticket_number.label("violation_ticket_number"),
161-
AdministrativePenalty.administrative_penalty_number.label("admin_penalty_number"),
162-
ChargeRecommendation.charge_recommendation_number.label("charge_rec_number"),
163-
RestorativeJustice.restorative_justice_number.label("restorative_justice_number"),
164-
AdministrativePenalty.decision.label("ap_dm_decision"),
165-
AdministrativePenalty.penalty_amount.label("ap_penalty_amount"),
166+
order_alias.order_number.label("order_number"),
167+
warning_letter_alias.warning_letter_number.label("warning_letter_number"),
168+
violation_ticket_alias.ticket_number.label("violation_ticket_number"),
169+
admin_penalty_alias.administrative_penalty_number.label("admin_penalty_number"),
170+
charge_rec_alias.charge_recommendation_number.label("charge_rec_number"),
171+
restorative_justice_alias.restorative_justice_number.label("restorative_justice_number"),
172+
admin_penalty_alias.decision.label("ap_dm_decision"),
173+
admin_penalty_alias.penalty_amount.label("ap_penalty_amount"),
166174
InspectionRecord.date_issued.label("ir_date_issued"),
167175
StaffUser,
168176
Inspection.inspection_status.label("inspection_status"),
169177
)
170-
.join(Inspection, InspectionRequirement.inspection_id == Inspection.id)
178+
.join(Inspection, and_(
179+
InspectionRequirement.inspection_id == Inspection.id,
180+
Inspection.is_active.is_(True),
181+
Inspection.is_deleted.is_(False)
182+
))
171183
.outerjoin(
172184
inspection_type_subquery,
173185
inspection_type_subquery.c.inspection_id == Inspection.id
@@ -184,7 +196,11 @@ def _build_inspection_requirements_query(self, project_id: int):
184196
InspectionReqEnforcementMap.is_active.is_(True),
185197
InspectionReqEnforcementMap.is_deleted.is_(False)
186198
))
187-
.join(InspectionRecord, InspectionRecord.inspection_id == Inspection.id)
199+
.join(InspectionRecord, and_(
200+
InspectionRecord.inspection_id == Inspection.id,
201+
InspectionRecord.is_active.is_(True),
202+
InspectionRecord.is_deleted.is_(False)
203+
))
188204
.outerjoin(
189205
EnforcementActionOption,
190206
InspectionReqEnforcementMap.enforcement_action_id == EnforcementActionOption.id
@@ -195,56 +211,52 @@ def _build_inspection_requirements_query(self, project_id: int):
195211
requirement_order_subquery.c.inspection_requirement_id == InspectionRequirement.id
196212
)
197213
.outerjoin(
198-
Order,
199-
Order.id == requirement_order_subquery.c.order_id
214+
order_alias,
215+
order_alias.id == requirement_order_subquery.c.order_id
200216
)
201217
.outerjoin(
202218
requirement_warning_letter_subquery,
203219
requirement_warning_letter_subquery.c.inspection_requirement_id == InspectionRequirement.id
204220
)
205221
.outerjoin(
206-
WarningLetter,
207-
WarningLetter.id == requirement_warning_letter_subquery.c.warning_letter_id
222+
warning_letter_alias,
223+
warning_letter_alias.id == requirement_warning_letter_subquery.c.warning_letter_id
208224
)
209225
.outerjoin(
210226
requirement_violation_ticket_subquery,
211227
requirement_violation_ticket_subquery.c.inspection_requirement_id == InspectionRequirement.id
212228
)
213229
.outerjoin(
214-
ViolationTicket,
215-
ViolationTicket.id == requirement_violation_ticket_subquery.c.violation_ticket_id
230+
violation_ticket_alias,
231+
violation_ticket_alias.id == requirement_violation_ticket_subquery.c.violation_ticket_id
216232
)
217233
.outerjoin(
218234
requirement_admin_penalty_subquery,
219235
requirement_admin_penalty_subquery.c.inspection_requirement_id == InspectionRequirement.id
220236
)
221237
.outerjoin(
222-
AdministrativePenalty,
223-
AdministrativePenalty.id == requirement_admin_penalty_subquery.c.administrative_penalty_id
238+
admin_penalty_alias,
239+
admin_penalty_alias.id == requirement_admin_penalty_subquery.c.administrative_penalty_id
224240
)
225241
.outerjoin(
226242
requirement_charge_rec_subquery,
227243
requirement_charge_rec_subquery.c.inspection_requirement_id == InspectionRequirement.id
228244
)
229245
.outerjoin(
230-
ChargeRecommendation,
231-
ChargeRecommendation.id == requirement_charge_rec_subquery.c.charge_recommendation_id
246+
charge_rec_alias,
247+
charge_rec_alias.id == requirement_charge_rec_subquery.c.charge_recommendation_id
232248
)
233249
.outerjoin(
234250
requirement_restorative_justice_subquery,
235251
requirement_restorative_justice_subquery.c.inspection_requirement_id == InspectionRequirement.id
236252
)
237253
.outerjoin(
238-
RestorativeJustice,
239-
RestorativeJustice.id == requirement_restorative_justice_subquery.c.restorative_justice_id
254+
restorative_justice_alias,
255+
restorative_justice_alias.id == requirement_restorative_justice_subquery.c.restorative_justice_id
240256
)
241257
.filter(
242258
InspectionRequirement.is_active.is_(True),
243259
InspectionRequirement.is_deleted.is_(False),
244-
InspectionRecord.is_active.is_(True),
245-
InspectionRecord.is_deleted.is_(False),
246-
Inspection.is_active.is_(True),
247-
Inspection.is_deleted.is_(False),
248260
Inspection.project_id == project_id,
249261
Inspection.start_date >= self.start_date if self.start_date else True,
250262
Inspection.start_date <= self.end_date if self.end_date else True,
@@ -265,6 +277,8 @@ def _format_inspection_requirements_data(data):
265277
raw_enforcement_status = ServiceUtils.get_enforcement_status_by_type(row)
266278
primary_officer = row.StaffUser
267279
req_source_details = inspection_requirement.requirement_source_details
280+
is_ap_penalty = row.enforcement_action_id \
281+
and row.enforcement_action_id == EnforcementActionOptionEnum.ADMINISTRATIVE_PENALTY_RECOMMENDATION.value
268282

269283
condition_num_string = ""
270284
source_string = ""
@@ -288,9 +302,9 @@ def _format_inspection_requirements_data(data):
288302
"compliance_finding": row.compliance_finding,
289303
"enforcement_action": row.enforcement_action,
290304
"enforcement_status": raw_enforcement_status.value if raw_enforcement_status else None,
291-
"ap_dm_decision": row.ap_dm_decision.value if row.ap_dm_decision else None,
305+
"ap_dm_decision": row.ap_dm_decision.value if is_ap_penalty and row.ap_dm_decision else None,
292306
"ap_penalty_amount": row.ap_penalty_amount
293-
if row.ap_penalty_amount and row.ap_dm_decision == DecisionEnum.AP_ISSUED else None,
307+
if is_ap_penalty and row.ap_dm_decision == DecisionEnum.AP_ISSUED else None,
294308
"enforcement_document_number": ServiceUtils.get_enforcement_number_by_type(row),
295309
"condition_number": condition_num_string,
296310
"requirement_source": source_string,

compliance-api/src/compliance_api/services/service_utils.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,8 @@ def get_requirement_grid_source_number_field(
506506
section_sources = {
507507
RequirementSourceEnum.ACT_2018,
508508
RequirementSourceEnum.ACT_2002,
509-
RequirementSourceEnum.CERTIFIED_PROJECT_DESCRIPTION
509+
RequirementSourceEnum.CERTIFIED_PROJECT_DESCRIPTION,
510+
RequirementSourceEnum.COMPLIANCE_AGREEMENT,
510511
}
511512
condition_sources = {
512513
RequirementSourceEnum.EAC_CERTIFICATE,
@@ -524,9 +525,6 @@ def get_requirement_grid_source_number_field(
524525
exemption_sources = {
525526
RequirementSourceEnum.EXEMPTION_ORDER,
526527
}
527-
agreement_sources = {
528-
RequirementSourceEnum.COMPLIANCE_AGREEMENT,
529-
}
530528
if requirement_source in section_sources:
531529
return getattr(detail_obj, "section_number", "")
532530
if requirement_source in condition_sources:
@@ -539,8 +537,6 @@ def get_requirement_grid_source_number_field(
539537
return getattr(detail_obj, "regulation_number", "")
540538
if requirement_source in exemption_sources:
541539
return getattr(detail_obj, "clause_number", "")
542-
if requirement_source in agreement_sources:
543-
return getattr(detail_obj, "compliance_number", "")
544540
return getattr(detail_obj, "section_number", "")
545541

546542
@staticmethod

0 commit comments

Comments
 (0)