ff-admin-server/src/controller/admin/unit/inspectionController.ts

392 lines
14 KiB
TypeScript

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";
import InspectionPointService from "../../../service/unit/inspection/inspectionPointService";
import InspectionPointResultService from "../../../service/unit/inspection/inspectionPointResultService";
/**
* @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<any> {
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<any> {
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<any> {
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<any> {
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 getInspectionPointUpload(req: Request, res: Response): Promise<any> {
const inspectionId = req.params.id;
const inspectionPointId = req.params.pointId;
let result = await InspectionPointResultService.getForInspectionAndPoint(inspectionId, inspectionPointId);
let filepath = FileSystemHelper.formatPath("inspection", inspectionId, result.value);
if (result.inspectionPoint.others === "pdf") {
res.sendFile(filepath, {
headers: {
"Content-Type": "application/pdf",
},
});
} else {
let image = await sharp(filepath).png().toBuffer();
res.set({
"Content-Type": "image/png",
});
res.send(image);
}
}
/**
* @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<any> {
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<any> {
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<any> {
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<any> {
const inspectionId = req.params.id;
const pointResults = JSON.parse(req.body.results) as Array<{ inspectionPointId: string; value: string }>;
const pointFiles = req.files as Array<Express.Multer.File>;
let inspection = await InspectionService.getById(inspectionId);
let updateResults: Array<CreateOrUpdateInspectionPointResultCommand> = 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<any> {
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<any> {
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);
}