Skip to content

Commit d980b19

Browse files
committed
Merge branch 'develop' of https://github.com/dinesh-aot/EPIC.compliance into fixes
2 parents c7cf3c3 + 9ffad7b commit d980b19

File tree

11 files changed

+101
-76
lines changed

11 files changed

+101
-76
lines changed

compliance-api/src/compliance_api/models/inspection/inspection_req_detail_image.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from sqlalchemy import Boolean, Column, ForeignKey, Index, Integer, String
44

5+
from compliance_api.models.inspection.inspection_req_source_detail import InspectionReqSourceDetail
56
from compliance_api.utils.constant import DELETE_DIC_PARAMS
67

78
from ..base_model import BaseModelVersioned
@@ -76,13 +77,17 @@ def update_image(cls, image_id, image_data, session=None):
7677
return image_detail
7778

7879
@classmethod
79-
def find_all_images_by_req_detail_id(cls, req_detail_id):
80-
"""Get all images by req_detail_id."""
80+
def find_all_req_detail_images_by_req(cls, req_id):
81+
"""Get all images by req_detail_ids."""
8182
return (
82-
cls.query.filter_by(
83-
req_detail_id=req_detail_id,
84-
is_active=True,
85-
is_deleted=False,
83+
cls.query.join(
84+
InspectionReqSourceDetail,
85+
cls.req_detail_id == InspectionReqSourceDetail.id
86+
)
87+
.filter(
88+
InspectionReqSourceDetail.requirement_id == req_id,
89+
cls.is_active.is_(True),
90+
cls.is_deleted.is_(False),
8691
)
8792
.order_by(cls.id)
8893
.all()

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def get(inspection_id, requirement_id):
216216

217217
@cors_preflight("GET, OPTIONS")
218218
@API.route(
219-
"/<int:requirement_id>/requirement-detail/<int:detail_id>/images",
219+
"/<int:requirement_id>/requirement-source-images",
220220
methods=["OPTIONS", "GET"],
221221
)
222222
class InspectionReqSourceImages(Resource):
@@ -225,15 +225,15 @@ class InspectionReqSourceImages(Resource):
225225
@staticmethod
226226
@ApiHelper.swagger_decorators(
227227
API,
228-
endpoint_description="Get all images for a requirement source detail",
228+
endpoint_description="Get all images for a requirement source",
229229
)
230230
@auth.require
231231
@API.response(code=200, description="Success", model=[inspesction_req_image_schema])
232232
@API.response(404, "Not Found")
233-
def get(inspection_id, requirement_id, detail_id):
234-
"""Get all images by requirement detail id."""
233+
def get(inspection_id, requirement_id):
234+
"""Get all images by requirement id."""
235235
images = InspectionRequirementService.get_all_requirement_detail_images(
236-
inspection_id, requirement_id, detail_id
236+
inspection_id, requirement_id
237237
)
238238
return InspectionReqDetailImageSchema(many=True).dump(images), HTTPStatus.OK
239239

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ class EnforcementItemSchema(BaseSchema):
299299
inspection_id = fields.Integer(
300300
allow_none=True, metadata={"description": "Associated inspection ID"}
301301
)
302+
ir_number = fields.String(
303+
allow_none=True, metadata={"description": "Inspection record number"}
304+
)
302305

303306
# Generic number field for all enforcement item types
304307
number = fields.String(

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,8 @@ def _build_enforcement_query(inspection_ids: list):
877877
"""Build the enforcement actions query with all joins."""
878878
return (
879879
db.session.query(
880+
# Inspection
881+
InspectionModel.ir_number,
880882
# Orders
881883
OrderModel.id.label("order_id"),
882884
OrderModel.order_number,
@@ -1050,6 +1052,7 @@ def _build_order_item(row) -> dict:
10501052
return {
10511053
"id": row.order_id,
10521054
"inspection_id": row.order_inspection_id,
1055+
"ir_number": row.ir_number,
10531056
"number": row.order_number,
10541057
"status": status_obj,
10551058
}
@@ -1067,6 +1070,7 @@ def _build_warning_letter_item(row) -> dict:
10671070
return {
10681071
"id": row.warning_letter_id,
10691072
"inspection_id": row.warning_letter_inspection_id,
1073+
"ir_number": row.ir_number,
10701074
"number": row.warning_letter_number,
10711075
"status": status_obj,
10721076
}
@@ -1084,6 +1088,7 @@ def _build_violation_ticket_item(row) -> dict:
10841088
return {
10851089
"id": row.violation_ticket_id,
10861090
"inspection_id": row.violation_ticket_inspection_id,
1091+
"ir_number": row.ir_number,
10871092
"number": row.vt_number,
10881093
"status": status_obj,
10891094
}
@@ -1101,6 +1106,7 @@ def _build_admin_penalty_item(row) -> dict:
11011106
return {
11021107
"id": row.admin_penalty_id,
11031108
"inspection_id": row.admin_penalty_inspection_id,
1109+
"ir_number": row.ir_number,
11041110
"number": row.administrative_penalty_number,
11051111
"status": status_obj,
11061112
}
@@ -1118,6 +1124,7 @@ def _build_charge_rec_item(row) -> dict:
11181124
return {
11191125
"id": row.charge_rec_id,
11201126
"inspection_id": row.charge_rec_inspection_id,
1127+
"ir_number": row.ir_number,
11211128
"number": row.charge_recommendation_number,
11221129
"status": status_obj,
11231130
}
@@ -1135,6 +1142,7 @@ def _build_restorative_justice_item(row) -> dict:
11351142
return {
11361143
"id": row.restorative_justice_id,
11371144
"inspection_id": row.restorative_justice_inspection_id,
1145+
"ir_number": row.ir_number,
11381146
"number": row.restorative_justice_number,
11391147
"status": status_obj,
11401148
}

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

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -306,24 +306,13 @@ def get_all_images_by_inspection(cls, inspection_id):
306306

307307
@classmethod
308308
def get_all_requirement_detail_images(
309-
cls, inspection_id, requirement_id, detail_id
309+
cls, inspection_id, requirement_id
310310
):
311311
"""Get all images for a requirement source detail."""
312312
ServiceUtils.inspection_exist_check(inspection_id)
313313
_requirement_check(requirement_id)
314-
# Verify the detail belongs to the requirement
315-
detail = InspectionReqSourceDetailModel.query.filter_by(
316-
id=detail_id,
317-
requirement_id=requirement_id,
318-
is_active=True,
319-
is_deleted=False,
320-
).first()
321-
if not detail:
322-
raise ResourceNotFoundError(
323-
f"Requirement detail with id {detail_id} not found for requirement {requirement_id}"
324-
)
325-
images = InspectionReqDetailImageModel.find_all_images_by_req_detail_id(
326-
detail_id
314+
images = InspectionReqDetailImageModel.find_all_req_detail_images_by_req(
315+
requirement_id
327316
)
328317
images = _set_signed_url(images)
329318
return images

compliance-web/src/components/App/Inspections/Profile/Requirements/RequirementDrawer.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
} from "./RequirementUtils";
3333
import * as yup from "yup";
3434
import { useRequirementStore } from "./requirementStore";
35+
import { useQueryClient } from "@tanstack/react-query";
3536

3637
type RequirementDrawerProps = {
3738
inspectionData: Inspection;
@@ -57,6 +58,7 @@ const RequirementDrawer: React.FC<RequirementDrawerProps> = ({
5758
index,
5859
isRegulatoryConsideration = false,
5960
}) => {
61+
const queryClient = useQueryClient();
6062
const { appHeaderHeight } = useMenuStore();
6163
const [inspectionRequirementData, setInspectionRequirementData] = useState<
6264
InspectionRequirementFormData | undefined
@@ -118,9 +120,16 @@ const RequirementDrawer: React.FC<RequirementDrawerProps> = ({
118120
}, [onSubmit, resetForm]);
119121

120122
const onUpdateSuccess = useCallback(() => {
123+
queryClient.invalidateQueries({
124+
queryKey: [
125+
"requirement-source-images",
126+
inspectionData.id,
127+
requirement?.id ?? 0,
128+
],
129+
});
121130
onSubmit("Changes saved successfully!", false);
122131
setIsImageChanged(false);
123-
}, [onSubmit, setIsImageChanged]);
132+
}, [onSubmit, setIsImageChanged, queryClient, inspectionData, requirement]);
124133

125134
const onDeleteSuccess = useCallback(() => {
126135
onSubmit("Requirement deleted successfully!", true);

compliance-web/src/components/App/Inspections/Profile/Requirements/RequirementFormRight.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { FC, useEffect, useMemo, useState } from "react";
2222
import { useRequirementStore } from "./requirementStore";
2323
import { CaseFile } from "@/models/CaseFile";
2424
import { MODAL_WIDTHS } from "@/utils/constants";
25+
import { useRequirementSourceImages } from "@/hooks/useInspectionRequirements";
2526

2627
interface RequirementFormRightProps {
2728
onDataChange: (data: RequirementSourceFormData[]) => void;
@@ -47,6 +48,10 @@ const RequirementFormRight: FC<RequirementFormRightProps> = ({
4748
RequirementSourceFormData[]
4849
>(requirementSourceFormDataList);
4950
const { data: appendixList } = useAppendicesData(inspectionId);
51+
const { data: requirementSourceImages } = useRequirementSourceImages(
52+
inspectionId,
53+
requirementId
54+
);
5055
const { setIsDataChanged } = useRequirementStore();
5156

5257
useEffect(() => {
@@ -172,8 +177,6 @@ const RequirementFormRight: FC<RequirementFormRightProps> = ({
172177
onSubmit={handleOnAddSubmit}
173178
caseFile={caseFile}
174179
appendixList={appendixList}
175-
inspectionId={inspectionId}
176-
requirementId={requirementId}
177180
/>
178181
),
179182
width: MODAL_WIDTHS.REQUIREMENT_SOURCE,
@@ -191,8 +194,11 @@ const RequirementFormRight: FC<RequirementFormRightProps> = ({
191194
caseFile={caseFile}
192195
requirementSourceFormData={data}
193196
appendixList={appendixList}
194-
inspectionId={inspectionId}
195-
requirementId={requirementId}
197+
requirementSourceImages={
198+
requirementSourceImages?.filter(
199+
(image) => image.req_detail_id === data.id
200+
) ?? []
201+
}
196202
isSectionModal={index > 0}
197203
/>
198204
),
@@ -246,8 +252,7 @@ const RequirementFormRight: FC<RequirementFormRightProps> = ({
246252
requirementSource={data.requirementSource}
247253
order={data.order}
248254
appendixList={appendixList}
249-
inspectionId={inspectionId}
250-
requirementId={requirementId}
255+
requirementSourceImages={requirementSourceImages ?? []}
251256
isSectionModal={true}
252257
/>
253258
),
@@ -374,6 +379,7 @@ const RequirementFormRight: FC<RequirementFormRightProps> = ({
374379
onDeleteRelatedDocumentSection={
375380
handleDeleteRequirementRelatedDocumentSection
376381
}
382+
requirementSourceImages={requirementSourceImages}
377383
isRequirementEditable={isRequirementEditable}
378384
/>
379385
))}

compliance-web/src/components/App/Inspections/Profile/Requirements/RequirementSource/RequirementSourceCard.tsx

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import ParagraphWithReadMore from "@/components/Shared/ParagraphWithReadMore";
2828
import { RequirementSourceEnum } from "@/utils/constants";
2929
import RequirementRelatedDocumentCard from "./RequirementRelatedDocumentCard";
3030
import { requirementSourceNumberType } from "../RequirementUtils";
31+
import { RequirementImage } from "@/models/Image";
3132

3233
type RequirementSourceCardProps = {
3334
data: RequirementSourceFormData[];
@@ -46,6 +47,7 @@ type RequirementSourceCardProps = {
4647
onDeleteRelatedDocumentSection: (
4748
data: RequirementRelatedDocumentSectionData
4849
) => void;
50+
requirementSourceImages?: RequirementImage[];
4951
isRequirementEditable?: boolean;
5052
};
5153

@@ -60,6 +62,7 @@ const RequirementSourceCard: FC<RequirementSourceCardProps> = memo(
6062
onAddRelatedDocumentSection,
6163
onDeleteRelatedDocumentSection,
6264
onEditRelatedDocumentSection,
65+
requirementSourceImages,
6366
isRequirementEditable = true,
6467
}) => {
6568
const [isExpanded, setIsExpanded] = useState(true);
@@ -272,15 +275,39 @@ const RequirementSourceCard: FC<RequirementSourceCardProps> = memo(
272275
Description:
273276
</Typography>
274277
<ParagraphWithReadMore
275-
key={item.description?.html}
278+
key={`req-scc-desc-${item.id}`}
276279
maxHeight={84}
277280
isFormatted={true}
278281
renderTypography={
279-
<Typography
280-
variant="subtitle2"
281-
component={"div"}
282+
<Box
282283
dangerouslySetInnerHTML={{
283-
__html: item.description?.html ?? "",
284+
__html: (() => {
285+
const baseHtml = item.description?.html ?? "";
286+
const relatedImages = requirementSourceImages?.filter(
287+
(image) => image.req_detail_id === item.id
288+
);
289+
if (!relatedImages || relatedImages.length === 0) {
290+
return baseHtml;
291+
}
292+
const imageHtml = relatedImages
293+
.map((image) => {
294+
const altText = image.original_file_name ?? "";
295+
const caption = image.caption ? `<p style="margin-top: 8px; font-size: 0.875rem; color: #666; font-style: italic;">${image.caption}</p>` : "";
296+
return `
297+
<div style="margin-top: 8px;">
298+
<img
299+
src="${image.url}"
300+
alt="${altText}"
301+
style="max-width: 100%; height: auto; display: block; border-radius: 4px;"
302+
/>
303+
${caption}
304+
</div>
305+
`;
306+
})
307+
.join("");
308+
309+
return baseHtml + imageHtml;
310+
})(),
284311
}}
285312
/>
286313
}

compliance-web/src/components/App/Inspections/Profile/Requirements/RequirementSource/RequirementSourceModal.tsx

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import { CaseFile } from "@/models/CaseFile";
2121
import { useCaseFileByNumber } from "@/hooks/useCaseFiles";
2222
import { formatAuthorization } from "@/utils/appUtils";
2323
import { RequirementImage } from "@/models/Image";
24-
import ImagesRequirementSource from "../Images/ImagesRequirementSource";
25-
import { useRequirementDetailImages } from "@/hooks/useInspectionRequirements";
24+
import ImagesRequirementSource from "@/components/App/Inspections/Profile/Requirements/Images/ImagesRequirementSource";
2625

2726
type RequirementSourceModalProps = {
2827
onSubmit: (data: RequirementSourceFormData) => void;
@@ -31,8 +30,7 @@ type RequirementSourceModalProps = {
3130
requirementSource?: RequirementSource;
3231
order?: InspectionOrder;
3332
appendixList?: Appendix[];
34-
inspectionId: number;
35-
requirementId: number;
33+
requirementSourceImages?: RequirementImage[];
3634
isSectionModal?: boolean;
3735
};
3836

@@ -96,21 +94,13 @@ const RequirementSourceModal: React.FC<RequirementSourceModalProps> = ({
9694
requirementSource,
9795
order,
9896
appendixList,
99-
inspectionId,
100-
requirementId,
97+
requirementSourceImages,
10198
isSectionModal = false,
10299
}) => {
103100
const { data: requirementSourceList } = useRequirementSourcesData();
104101
const { data: orderList } = useInspectionOrdersProjectwiseData(caseFile.id);
105102
const { data: caseFileData } = useCaseFileByNumber(caseFile.case_file_number);
106-
107-
// Fetch requirement detail images in edit mode (when requirementSourceFormData has an id)
108-
const detailId = requirementSourceFormData?.id;
109-
const { data: fetchedImages } = useRequirementDetailImages(
110-
inspectionId,
111-
requirementId,
112-
detailId
113-
);
103+
114104
const defaultValues = useMemo<RequirementSourceFormData>(() => {
115105
return (
116106
requirementSourceFormData ?? {
@@ -237,14 +227,8 @@ const RequirementSourceModal: React.FC<RequirementSourceModalProps> = ({
237227
}, [selectedRequirementSource, setValue, caseFileData]);
238228

239229
const [uploadedImages, setUploadedImages] = useState<RequirementImage[]>(
240-
requirementSourceFormData?.images ?? []
230+
requirementSourceImages ?? []
241231
);
242-
// Update uploadedImages when fetched images are available (edit mode)
243-
useEffect(() => {
244-
if (fetchedImages && detailId && uploadedImages.length == 0) {
245-
setUploadedImages(fetchedImages);
246-
}
247-
}, [fetchedImages, detailId, uploadedImages]);
248232

249233
const onSubmitHandler = (data: RequirementSourceSchemaType) => {
250234
const formData = data as RequirementSourceFormData;
@@ -311,7 +295,7 @@ const RequirementSourceModal: React.FC<RequirementSourceModalProps> = ({
311295
/>
312296
)}
313297
{selectedRequirementSource && (
314-
<Stack direction={"row"} gap={2}>
298+
<>
315299
{!isSectionModal && (
316300
<ControlledTextField
317301
name="requirementSourceTitle"
@@ -345,7 +329,7 @@ const RequirementSourceModal: React.FC<RequirementSourceModalProps> = ({
345329
fullWidth
346330
/>
347331
)}
348-
</Stack>
332+
</>
349333
)}
350334
<ControlledAutoComplete
351335
name="appendix"

0 commit comments

Comments
 (0)