import { Request, Response } from "express"; import InspectionService from "../../../service/unit/inspection/inspectionService"; import InspectionFactory from "../../../factory/admin/unit/inspection/inspection"; import { CreateInspectionCommand, DeleteInspectionCommand, FinishInspectionCommand, UpdateInspectionCommand, } from "../../../command/unit/inspection/inspectionCommand"; import InspectionCommandHandler from "../../../command/unit/inspection/inspectionCommandHandler"; import BadRequestException from "../../../exceptions/badRequestException"; import ForbiddenRequestException from "../../../exceptions/forbiddenRequestException"; import { CreateOrUpdateInspectionPointResultCommand } from "../../../command/unit/inspection/inspectionPointResultCommand"; import InspectionPointResultCommandHandler from "../../../command/unit/inspection/inspectionPointResultCommandHandler"; import { InspectionPointEnum } from "../../../enums/inspectionEnum"; import multer from "multer"; import { FileSystemHelper } from "../../../helpers/fileSystemHelper"; import { PdfExport } from "../../../helpers/pdfExport"; import { PDFDocument } from "pdf-lib"; import sharp from "sharp"; /** * @description get all inspections sorted by id not having newer inspection * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getAllInspectionsSortedNotHavingNewer(req: Request, res: Response): Promise { let offset = parseInt((req.query.offset as string) ?? "0"); let count = parseInt((req.query.count as string) ?? "25"); let noLimit = req.query.noLimit === "true"; let [inspections, total] = await InspectionService.getAllSortedNotHavingNewer({ offset, count, noLimit }); res.json({ inspections: InspectionFactory.mapToBaseNext(inspections), total: total, offset: offset, count: count, }); } /** * @description get all inspections running * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getAllInspectionsRunning(req: Request, res: Response): Promise { let offset = parseInt((req.query.offset as string) ?? "0"); let count = parseInt((req.query.count as string) ?? "25"); let noLimit = req.query.noLimit === "true"; let [inspections, total] = await InspectionService.getAllRunning({ offset, count, noLimit }); res.json({ inspections: InspectionFactory.mapToBaseMinified(inspections), total: total, offset: offset, count: count, }); } /** * @description get all inspections for related id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getAllInspectionsForRelated(req: Request, res: Response): Promise { let relation = req.params.related as "vehicle" | "equipment" | "wearable"; let relationId = req.params.relatedId as string; let offset = parseInt((req.query.offset as string) ?? "0"); let count = parseInt((req.query.count as string) ?? "25"); let noLimit = req.query.noLimit === "true"; let where; if (relation == "equipment") { where = { equipmentId: relationId }; } else if (relation == "vehicle") { where = { vehicleId: relationId }; } else { where = { wearableId: relationId }; } let [inspections, total] = await InspectionService.getAllForRelated(where, { offset, count, noLimit }); res.json({ inspections: InspectionFactory.mapToBaseMinified(inspections), total: total, offset: offset, count: count, }); } /** * @description get inspection by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getInspectionPrintoutById(req: Request, res: Response): Promise { const inspectionId = req.params.id; let inspection = await InspectionService.getById(inspectionId); if (inspection.finishedAt == null) throw new ForbiddenRequestException("this inspection has not been finished yet and it so does not have a printout"); let filepath = FileSystemHelper.formatPath("inspection", inspection.id, "printout.pdf"); res.sendFile(filepath, { headers: { "Content-Type": "application/pdf", }, }); } /** * @description get inspection by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function getInspectionById(req: Request, res: Response): Promise { const inspectionId = req.params.id; let inspection = await InspectionService.getById(inspectionId); res.json(InspectionFactory.mapToSingle(inspection)); } /** * @description create inspection * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function createInspection(req: Request, res: Response): Promise { const context = req.body.context; const inspectionPlanId = req.body.inspectionPlanId; const relatedId = req.body.relatedId; const assigned = req.body.assigned; const nextInspection = req.body.nextInspection || null; if (assigned != "equipment" && assigned != "vehicle" && assigned != "wearable") throw new BadRequestException("set assigned to equipment or vehicle or wearable"); let existsUnfinished = await InspectionService.existsUnfinishedInspectionToPlan( inspectionPlanId, assigned, relatedId ); if (existsUnfinished) throw new ForbiddenRequestException("there is already an unfinished inspection existing"); let createInspection: CreateInspectionCommand = { context, nextInspection, inspectionPlanId, relatedId, assigned, }; let inspectionId = await InspectionCommandHandler.create(createInspection); res.status(200).send(inspectionId); } /** * @description update inspection by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function updateInspectionById(req: Request, res: Response): Promise { const inspectionId = req.params.id; const context = req.body.context; const nextInspection = req.body.nextInspection || null; let updateInspection: UpdateInspectionCommand = { id: inspectionId, context, nextInspection, }; await InspectionCommandHandler.update(updateInspection); res.sendStatus(204); } /** * @description update inspection by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function updateInspectionResults(req: Request, res: Response): Promise { const inspectionId = req.params.id; const pointResults = JSON.parse(req.body.results) as Array<{ inspectionPointId: string; value: string }>; const pointFiles = req.files as Array; let inspection = await InspectionService.getById(inspectionId); let updateResults: Array = pointResults.map((pr) => ({ inspectionPointId: pr.inspectionPointId, value: inspection.inspectionVersionedPlan.inspectionPoints.find((ip) => ip.id == pr.inspectionPointId).type == InspectionPointEnum.file && pr.value == "set" ? pointFiles.find((f) => f.filename.startsWith(pr.inspectionPointId))?.filename : pr.value, inspectionId, })); await InspectionPointResultCommandHandler.createOrUpdateMultiple(updateResults); res.sendStatus(204); } /** * @description finish inspection by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function finishInspection(req: Request, res: Response): Promise { const inspectionId = req.params.id; let inspection = await InspectionService.getById(inspectionId); function getValueToInspectionPoint(inspectionPointId: string) { return inspection.pointResults.find((c) => c.inspectionPointId == inspectionPointId)?.value; } let everythingFilled = inspection.inspectionVersionedPlan.inspectionPoints.every((p) => { if (p.type == InspectionPointEnum.file) { return getValueToInspectionPoint(p.id); } else if (p.type == InspectionPointEnum.oknok) { let value = getValueToInspectionPoint(p.id); return (["true", "false"].includes(value) ? (value as "true" | "false") : "") != ""; } else { return !!getValueToInspectionPoint(p.id); } }); if (!everythingFilled) throw new ForbiddenRequestException("fill out every field before finishing inspection"); let formattedInspection = InspectionFactory.mapToSingle(inspection); let title = `Prüf-Ausdruck_${[formattedInspection.related.code ?? "", formattedInspection.related.name].join("_")}_${ formattedInspection.inspectionPlan.title }_${new Date(formattedInspection.finished ?? "").toLocaleDateString("de-de")}`; let inspectionPoints = []; for (const ip of formattedInspection.inspectionVersionedPlan.inspectionPoints.sort( (a, b) => (a.sort ?? 0) - (b.sort ?? 0) )) { let value = formattedInspection.checks.find((c) => c.inspectionPointId == ip.id).value; let image = ""; if (ip.type == InspectionPointEnum.file && ip.others == "img") { const imagePath = FileSystemHelper.formatPath("inspection", inspection.id, value); let pngImageBytes = await sharp(imagePath).png().toBuffer(); image = `data:image/png;base64,${pngImageBytes.toString("base64")}`; } else if (ip.type == InspectionPointEnum.oknok) { value = value ? "OK" : "Nicht OK"; } inspectionPoints.push({ title: ip.title, description: ip.description, type: ip.type, min: ip.min, max: ip.max, others: ip.others, value: value, image: image, }); } let pdf = await PdfExport.renderFile({ template: "inspection", title, saveToDisk: false, data: { inspector: `${req.lastname}, ${req.firstname}`, context: formattedInspection.context || "---", createdAt: formattedInspection.created, finishedAt: formattedInspection.finished ?? new Date(), nextInspection: formattedInspection.nextInspection, related: formattedInspection.related, plan: formattedInspection.inspectionPlan, planVersion: formattedInspection.inspectionVersionedPlan.version, planTitle: formattedInspection.inspectionPlan.title, checks: inspectionPoints, }, }); const finalDocument = await PDFDocument.create(); const printout = await PDFDocument.load(pdf); const copiedPages = await finalDocument.copyPages(printout, printout.getPageIndices()); copiedPages.forEach((page) => finalDocument.addPage(page)); let resultsForAppend = inspectionPoints.filter((ip) => ip.type == InspectionPointEnum.file && ip.others == "pdf"); if (resultsForAppend.length !== 0) { const appendixPage = finalDocument.addPage(); const { width, height } = appendixPage.getSize(); appendixPage.drawText("Anhang:", { x: 50, y: height - 50, size: 24, }); } for (const appendix of resultsForAppend) { const appendixPdfBytes = FileSystemHelper.readFileAsBase64("inspection", inspection.id, appendix.value); const appendixPdf = await PDFDocument.load(appendixPdfBytes); const appendixPages = await finalDocument.copyPages(appendixPdf, appendixPdf.getPageIndices()); appendixPages.forEach((page) => finalDocument.addPage(page)); /** print image const imagePath = FileSystemHelper.formatPath("inspection", inspection.id, checkValue); let pngImageBytes = await sharp(imagePath).png().toBuffer(); let image = await finalDocument.embedPng(pngImageBytes); let dims = image.scale(1); if (image) { const page = finalDocument.addPage(); const { width, height } = page.getSize(); const x = (width - dims.width) / 2; const y = (height - dims.height) / 2; page.drawImage(image, { x, y, width: dims.width, height: dims.height, }); } */ } const mergedPdfBytes = await finalDocument.save(); FileSystemHelper.writeFile(`inspection/${inspection.id}`, `printout.pdf`, mergedPdfBytes); let finish: FinishInspectionCommand = { id: inspectionId, }; await InspectionCommandHandler.finish(finish); res.sendStatus(204); } /** * @description delete inspection by id * @param req {Request} Express req object * @param res {Response} Express res object * @returns {Promise<*>} */ export async function deleteInspectionById(req: Request, res: Response): Promise { const inspectionId = req.params.id; let deleteInspectionData = await InspectionService.getById(inspectionId); if (deleteInspectionData.finishedAt != null) { throw new ForbiddenRequestException("Cannot delete as inspection is already finished"); } let deleteInspection: DeleteInspectionCommand = { id: inspectionId, }; await InspectionCommandHandler.delete(deleteInspection); res.sendStatus(204); }