Skip to content

Commit 134e4e6

Browse files
authored
COMP-724 requirment grid source and conditions (#669)
1 parent 983679f commit 134e4e6

File tree

5 files changed

+77
-80
lines changed

5 files changed

+77
-80
lines changed

compliance-api/src/compliance_api/schemas/inspection_requirement_grid.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ class InspectionRequirementGridItemSchema(Schema):
5252
ir_number = fields.Str(
5353
metadata={"description": "The inspection requirement number"}
5454
)
55-
requirement_number = fields.List(
56-
fields.Str(),
57-
metadata={"description": "The list of requirement numbers"}
58-
)
5955
requirement_source = fields.Nested(
6056
KeyValueSchema, metadata={"description": "The requirement source"}
6157
)
@@ -76,6 +72,12 @@ class InspectionRequirementGridItemSchema(Schema):
7672
fields.Nested(KeyValueSchema),
7773
metadata={"description": "The list of requirement sources"},
7874
)
75+
condition_numbers = fields.Str(
76+
metadata={"description": "The condition numbers as a comma separated string"},
77+
)
78+
requirement_sources_names = fields.Str(
79+
metadata={"description": "The requirement source names as a comma separated string"},
80+
)
7981

8082

8183
class InspectionRequirementFilterSchema(BaseSchema):

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

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,6 @@ def _create_excel_from_dataframe(data_frame):
400400
# Get existing columns and headers
401401
existing_columns, headers = _get_excel_columns_and_headers(data_frame)
402402

403-
# Format requirement_number column as comma-separated values instead of array
404-
if 'requirement_number' in data_frame.columns:
405-
data_frame['requirement_number'] = data_frame['requirement_number'].apply(
406-
lambda x: ', '.join(str(item) for item in x if item is not None) if isinstance(x, list) and x else ''
407-
)
408-
409403
# Create Excel file in memory
410404
output = BytesIO()
411405
with pd.ExcelWriter(output, engine="openpyxl") as writer:
@@ -429,8 +423,8 @@ def _get_excel_columns_and_headers(data_frame):
429423
("enforcement_action.name", "Enforcement Action"),
430424
("enforcement_number", "Enforcement Document #"),
431425
("status.name", "Enforcement Status"),
432-
("requirement_number", "Condition #"),
433-
("requirement_source.name", "Requirement Source"),
426+
("condition_numbers", "Condition #"),
427+
("requirement_sources_names", "Requirement Source"),
434428
("ir_number", "IR Number"),
435429
("date_issued", "Date Issued"),
436430
("primary_officer.name", "Primary Officer"),
@@ -1535,30 +1529,6 @@ def _convert_enum_to_object(enum_value):
15351529
}
15361530

15371531

1538-
def _convert_enum_string_to_object(enum_string, enum_class_map):
1539-
"""Convert enum string back to proper enum object structure."""
1540-
if not enum_string:
1541-
return None
1542-
1543-
# Try to find the enum in any of the provided enum classes
1544-
for enum_class in enum_class_map:
1545-
try:
1546-
for enum_item in enum_class:
1547-
if enum_item.name == enum_string:
1548-
return {
1549-
"id": enum_item.name,
1550-
"name": enum_item.value,
1551-
}
1552-
except (AttributeError, TypeError, ValueError):
1553-
continue
1554-
1555-
# If no enum found, return as string
1556-
return {
1557-
"id": enum_string,
1558-
"name": enum_string,
1559-
}
1560-
1561-
15621532
def _make_requirement_detail_object(requirements: list):
15631533
"""Make requirement detail object."""
15641534

@@ -1602,21 +1572,18 @@ def parse_requirement_sources(sources):
16021572
item["progress"] = progress
16031573
if requirement["requirement_source_details"]:
16041574
first_requirement_details = requirement["requirement_source_details"][0]
1605-
requirement_numbers = []
16061575
req_sources = []
1576+
condition_num_string = ""
1577+
source_string = ""
16071578
for detail in requirement["requirement_source_details"]:
16081579
if detail.requirement_source not in req_sources:
16091580
req_sources.append(detail.requirement_source)
1610-
number_field = ServiceUtils.get_requirement_source_number_field(detail)
1611-
prefixes = ["Condition ", "Section "]
1612-
if number_field:
1613-
requirement_numbers.append(
1614-
next(
1615-
(number_field.split(prefix)[1] for prefix in prefixes if prefix in number_field),
1616-
None
1617-
)
1618-
)
1619-
item["requirement_number"] = requirement_numbers
1581+
number_field = ServiceUtils.get_requirement_grid_source_number_field(detail)
1582+
name_field = ServiceUtils.get_requirement_grid_source_name_field(detail)
1583+
condition_num_string += f", {number_field}" if condition_num_string else number_field or ""
1584+
source_string += f", {name_field}" if source_string else name_field
1585+
item["condition_numbers"] = condition_num_string
1586+
item["requirement_sources_names"] = source_string
16201587
item["requirement_source"] = first_requirement_details.requirement_source
16211588
requirement_details.append(item)
16221589
return requirement_details

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

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
from .epic_track_service.track_service import TrackService
3838

3939

40-
class ServiceUtils:
40+
class ServiceUtils: # pylint: disable=too-many-public-methods
4141
"""ServiceUtils class."""
4242

4343
@staticmethod
@@ -494,6 +494,61 @@ def get_requirement_source_number_field(detail_obj: InspectionReqSourceDetailMod
494494
)
495495
return None
496496

497+
@staticmethod
498+
def get_requirement_grid_source_number_field(
499+
detail_obj: InspectionReqSourceDetailModel
500+
): # pylint: disable=too-many-return-statements
501+
"""Identify the number field based on the requirement source id for the requirements grid."""
502+
requirement_source = RequirementSourceEnum(detail_obj.requirement_source_id)
503+
section_sources = {
504+
RequirementSourceEnum.ACT_2018,
505+
RequirementSourceEnum.ACT_2002,
506+
RequirementSourceEnum.CERTIFIED_PROJECT_DESCRIPTION
507+
}
508+
condition_sources = {
509+
RequirementSourceEnum.EAC_CERTIFICATE,
510+
RequirementSourceEnum.SCHEDULE_B,
511+
}
512+
amendment_sources = {
513+
RequirementSourceEnum.EAC_AMENDMENT,
514+
}
515+
order_sources = {
516+
RequirementSourceEnum.ORDER,
517+
}
518+
regulation_sources = {
519+
RequirementSourceEnum.REGULATION,
520+
}
521+
exemption_sources = {
522+
RequirementSourceEnum.EXEMPTION_ORDER,
523+
}
524+
agreement_sources = {
525+
RequirementSourceEnum.COMPLIANCE_AGREEMENT,
526+
}
527+
if requirement_source in section_sources:
528+
return getattr(detail_obj, "section_number", "")
529+
if requirement_source in condition_sources:
530+
return getattr(detail_obj, "condition_number", "")
531+
if requirement_source in amendment_sources:
532+
return getattr(detail_obj, "amendment_number", "")
533+
if requirement_source in order_sources:
534+
return getattr(detail_obj.order, "order_number", "")
535+
if requirement_source in regulation_sources:
536+
return getattr(detail_obj, "regulation_number", "")
537+
if requirement_source in exemption_sources:
538+
return getattr(detail_obj, "clause_number", "")
539+
if requirement_source in agreement_sources:
540+
return getattr(detail_obj, "compliance_number", "")
541+
return getattr(detail_obj, "section_number", "")
542+
543+
@staticmethod
544+
def get_requirement_grid_source_name_field(detail_obj: InspectionReqSourceDetailModel):
545+
"""Get the requirement source name."""
546+
if detail_obj.requirement_source_id == RequirementSourceEnum.CERTIFIED_PROJECT_DESCRIPTION.value:
547+
return "Schedule A"
548+
if detail_obj.requirement_source_id == RequirementSourceEnum.SCHEDULE_B.value:
549+
return "Schedule B"
550+
return detail_obj.requirement_source.name
551+
497552
@staticmethod
498553
def check_requirement_for_enforcement_action(
499554
requirement_ids: list[int], enforcement_action_id: int

compliance-web/src/components/App/RequirementsGrid/RequirementsGridUtils.tsx

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,6 @@ export const useConvertFiltersToQueryParams = (
134134
export const useRequirementsGridColumns = (
135135
dataDependencies: RequirementsGridDataDependencies
136136
): MRT_ColumnDef<InspectionRequirementGrid>[] => {
137-
const RequirementSourceNames = useMemo(() => ({
138-
SCHEDULE_B: "Schedule B - Table of Conditions",
139-
SCHEDULE_A: "Schedule A - Certified Project Description",
140-
}), []);
141-
142-
const RequirementSourceNameMap: Record<string, string> = useMemo(() => ({
143-
[RequirementSourceNames.SCHEDULE_B]: "Schedule B",
144-
[RequirementSourceNames.SCHEDULE_A]: "Schedule A",
145-
}), [RequirementSourceNames.SCHEDULE_B, RequirementSourceNames.SCHEDULE_A]);
146-
147137
const { topics, complianceFindings, enforcementActions, requirementSources } =
148138
dataDependencies;
149139

@@ -226,7 +216,7 @@ export const useRequirementsGridColumns = (
226216
size: 80,
227217
},
228218
{
229-
accessorFn: (row) => (row.requirement_number ?? []).join(", "),
219+
accessorFn: (row) => row?.condition_numbers || "",
230220
id: "req_src_num",
231221
header: "Condition #",
232222
filterFn: "contains",
@@ -236,25 +226,7 @@ export const useRequirementsGridColumns = (
236226
size: 80,
237227
},
238228
{
239-
accessorFn: (row) => {
240-
return (
241-
row.requirement_sources
242-
?.map((source) => {
243-
if (source.name === RequirementSourceNames.SCHEDULE_B) {
244-
return RequirementSourceNameMap[
245-
RequirementSourceNames.SCHEDULE_B
246-
];
247-
}
248-
if (source.name === RequirementSourceNames.SCHEDULE_A) {
249-
return RequirementSourceNameMap[
250-
RequirementSourceNames.SCHEDULE_A
251-
];
252-
}
253-
return source.name;
254-
})
255-
.join(", ") ?? ""
256-
);
257-
},
229+
accessorFn: (row) => row?.requirement_sources_names || "",
258230
id: "req_src",
259231
header: "Source",
260232
filterVariant: "multi-select",
@@ -286,7 +258,7 @@ export const useRequirementsGridColumns = (
286258
filterFn: "greaterThanOrEqual",
287259
size: 120,
288260
},
289-
], [complianceFindings, enforcementActions, requirementSources, RequirementSourceNames, RequirementSourceNameMap, topics]);
261+
], [complianceFindings, enforcementActions, requirementSources, topics]);
290262
};
291263

292264
export const enforcementStatusOptions = [

compliance-web/src/models/InspectionRequirementGrid.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ export interface InspectionRequirementGrid {
1717
sort_order: number;
1818
date_issued: string;
1919
ir_number: string;
20-
requirement_number: string[];
2120
requirement_sources: RequirementSource[];
2221
approved_by: StaffUser;
2322
approved_by_id: number;
2423
progress?: Option;
2524
status?: Option;
2625
enforcement_number?: string;
26+
condition_numbers?: string;
27+
requirement_sources_names?: string;
2728
}
2829

2930
export interface InspectionRequirementGridQueryParams extends BaseTableQueryParams {

0 commit comments

Comments
 (0)