enhance: optional inspection points
This commit is contained in:
parent
314d607fa8
commit
7907ddb7e9
13 changed files with 238 additions and 144 deletions
|
@ -11,7 +11,7 @@ export interface CreateInspectionPlanCommand {
|
|||
export interface UpdateInspectionPlanCommand {
|
||||
id: string;
|
||||
title: string;
|
||||
inspectionInterval: PlanTimeDefinition;
|
||||
inspectionInterval?: PlanTimeDefinition;
|
||||
remindTime?: PlanTimeDefinition;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ export interface CreateInspectionPointCommand {
|
|||
min?: number;
|
||||
max?: number;
|
||||
others?: string;
|
||||
optional: boolean;
|
||||
sort: number;
|
||||
versionedPointId?: string;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ export default abstract class InspectionPointCommandHandler {
|
|||
min: createInspectionPoint.min,
|
||||
max: createInspectionPoint.max,
|
||||
sort: createInspectionPoint.sort,
|
||||
optional: createInspectionPoint.optional,
|
||||
versionedPlanId: createInspectionPoint.versionedPointId,
|
||||
})
|
||||
.execute()
|
||||
|
@ -55,7 +56,7 @@ export default abstract class InspectionPointCommandHandler {
|
|||
versionedPlanId,
|
||||
}))
|
||||
)
|
||||
.orUpdate(["title", "description", "min", "max", "others", "sort"], ["id"])
|
||||
.orUpdate(["title", "description", "min", "max", "others", "sort", "optional"], ["id"])
|
||||
.execute();
|
||||
|
||||
if (remove.length != 0)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { In } from "typeorm";
|
||||
import { dataSource } from "../../../data-source";
|
||||
import { inspectionPointResult } from "../../../entity/unit/inspection/inspectionPointResult";
|
||||
import DatabaseActionException from "../../../exceptions/databaseActionException";
|
||||
|
@ -51,4 +52,22 @@ export default abstract class InspectionPointResultCommandHandler {
|
|||
throw new DatabaseActionException("CREATE or UPDATE", "inspectionPointResult", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description remove all results by inspection and ids
|
||||
*/
|
||||
static async removeByInspectionAndPoints(inspectionId: string, inspectionPointIds: Array<string>) {
|
||||
return await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(inspectionPointResult)
|
||||
.where({ inspectionId, inspectionPointId: In(inspectionPointIds) })
|
||||
.execute()
|
||||
.then((res) => {
|
||||
return res;
|
||||
})
|
||||
.catch((err) => {
|
||||
throw new DatabaseActionException("DELETE", "inspectionPointResult", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Request, Response } from "express";
|
||||
import e, { Request, Response } from "express";
|
||||
import InspectionService from "../../../service/unit/inspection/inspectionService";
|
||||
import InspectionFactory from "../../../factory/admin/unit/inspection/inspection";
|
||||
import {
|
||||
|
@ -19,6 +19,7 @@ import { PDFDocument } from "pdf-lib";
|
|||
import sharp from "sharp";
|
||||
import InspectionPointResultService from "../../../service/unit/inspection/inspectionPointResultService";
|
||||
import InspectionPlanService from "../../../service/unit/inspection/inspectionPlanService";
|
||||
import { InspectionHelper } from "../../../helpers/inspectionHelper";
|
||||
|
||||
/**
|
||||
* @description get all inspections sorted by id not having newer inspection
|
||||
|
@ -230,18 +231,37 @@ export async function updateInspectionResults(req: Request, res: Response): Prom
|
|||
const pointFiles = req.files as Array<Express.Multer.File>;
|
||||
|
||||
let inspection = await InspectionService.getById(inspectionId);
|
||||
let inspectionPoints = inspection.inspectionVersionedPlan.inspectionPoints;
|
||||
let inspectionResults = await InspectionPointResultService.getAllForInspection(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,
|
||||
}));
|
||||
let updateResults: Array<CreateOrUpdateInspectionPointResultCommand> = pointResults.map((pr) => {
|
||||
let value = pr.value;
|
||||
if (inspectionPoints.find((ip) => ip.id == pr.inspectionPointId).type == InspectionPointEnum.file) {
|
||||
if (pr.value == "set") value = pointFiles.find((f) => f.filename.startsWith(pr.inspectionPointId))?.filename;
|
||||
else value = inspectionResults.find((ir) => ir.inspectionPointId == pr.inspectionPointId)?.value ?? "";
|
||||
}
|
||||
return {
|
||||
inspectionPointId: pr.inspectionPointId,
|
||||
value: value,
|
||||
inspectionId,
|
||||
};
|
||||
});
|
||||
await InspectionPointResultCommandHandler.createOrUpdateMultiple(updateResults);
|
||||
|
||||
let removeElements = inspectionResults.filter(
|
||||
(ir) => !pointResults.some((ur) => ur.inspectionPointId == ir.inspectionPointId)
|
||||
);
|
||||
for (const element of removeElements) {
|
||||
if (element.inspectionPoint.type == InspectionPointEnum.file)
|
||||
try {
|
||||
FileSystemHelper.deleteFile("inspection", inspectionId, element.value);
|
||||
} catch (err) {}
|
||||
}
|
||||
await InspectionPointResultCommandHandler.removeByInspectionAndPoints(
|
||||
inspectionId,
|
||||
removeElements.map((re) => re.inspectionPointId)
|
||||
);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
||||
|
@ -254,127 +274,11 @@ export async function updateInspectionResults(req: Request, res: Response): Prom
|
|||
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);
|
||||
}
|
||||
await InspectionHelper.printPdf(inspectionId, {
|
||||
id: req.userId,
|
||||
firstname: req.firstname,
|
||||
lastname: req.lastname,
|
||||
});
|
||||
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.finishedAt ?? "").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 == "true" ? "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.finishedAt ?? 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,
|
||||
user: {
|
||||
id: req.userId,
|
||||
firstname: req.firstname,
|
||||
lastname: req.lastname,
|
||||
},
|
||||
};
|
||||
await InspectionCommandHandler.finish(finish);
|
||||
|
||||
res.sendStatus(204);
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@ export class inspectionPlan {
|
|||
@Column({ type: "varchar", length: 255, nullable: true, default: null })
|
||||
remindTime?: PlanTimeDefinition;
|
||||
|
||||
@Column({ type: "boolean", default: false })
|
||||
allInRange: boolean;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ export default abstract class InspectionPlanFactory {
|
|||
title: record.title,
|
||||
inspectionInterval: record.inspectionInterval,
|
||||
remindTime: record.remindTime,
|
||||
allInRange: record.allInRange,
|
||||
version: record?.latestVersionedPlan?.version ?? 0,
|
||||
created: record.createdAt,
|
||||
inspectionPoints: record.latestVersionedPlan
|
||||
|
|
|
@ -60,6 +60,18 @@ Handlebars.registerHelper("json", function (context) {
|
|||
return JSON.stringify(context);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("showDashAsFallback", function (aString) {
|
||||
return aString ?? "---";
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("eq", function (p, q, options) {
|
||||
return p == q ? options.fn(this) : options.inverse(this);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("and", function (p, q) {
|
||||
return !!p && !!q;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("or", function (p, q) {
|
||||
return !!p || !!q;
|
||||
});
|
||||
|
|
159
src/helpers/inspectionHelper.ts
Normal file
159
src/helpers/inspectionHelper.ts
Normal file
|
@ -0,0 +1,159 @@
|
|||
import { PDFDocument } from "pdf-lib";
|
||||
import sharp from "sharp";
|
||||
import { FinishInspectionCommand } from "../command/unit/inspection/inspectionCommand";
|
||||
import InspectionCommandHandler from "../command/unit/inspection/inspectionCommandHandler";
|
||||
import { inspection } from "../entity/unit/inspection/inspection";
|
||||
import { InspectionPointEnum } from "../enums/inspectionEnum";
|
||||
import ForbiddenRequestException from "../exceptions/forbiddenRequestException";
|
||||
import InspectionFactory from "../factory/admin/unit/inspection/inspection";
|
||||
import InspectionService from "../service/unit/inspection/inspectionService";
|
||||
import { InspectionViewModel } from "../viewmodel/admin/unit/inspection/inspection.models";
|
||||
import { FileSystemHelper } from "./fileSystemHelper";
|
||||
import { PdfExport } from "./pdfExport";
|
||||
|
||||
export abstract class InspectionHelper {
|
||||
public static validateInspectionData(inspection: inspection) {
|
||||
return inspection.inspectionVersionedPlan.inspectionPoints.every((p) => {
|
||||
if (p.type == InspectionPointEnum.oknok) {
|
||||
let value = this.getInspectionPointResult(inspection, p.id);
|
||||
return (["true", "false"].includes(value) ? (value as "true" | "false") : "") != "" || p.optional;
|
||||
} else {
|
||||
return !!this.getInspectionPointResult(inspection, p.id) || p.optional;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static getInspectionPointResult(inspection: inspection, inspectionPointId: string) {
|
||||
return inspection.pointResults.find((c) => c.inspectionPointId == inspectionPointId)?.value;
|
||||
}
|
||||
|
||||
public static async formatInspectionPoints(formattedInspection: InspectionViewModel) {
|
||||
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 (!value || value == "") {
|
||||
value = "---";
|
||||
} else if (ip.type == InspectionPointEnum.file && ip.others == "img") {
|
||||
const imagePath = FileSystemHelper.formatPath("inspection", formattedInspection.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 == "true" ? "OK" : "Nicht OK";
|
||||
}
|
||||
inspectionPoints.push({
|
||||
title: ip.title,
|
||||
description: ip.description,
|
||||
type: ip.type,
|
||||
min: ip.min,
|
||||
max: ip.max,
|
||||
others: ip.others,
|
||||
optional: ip.optional,
|
||||
value: value,
|
||||
image: image,
|
||||
});
|
||||
}
|
||||
return inspectionPoints;
|
||||
}
|
||||
|
||||
public static buildData(
|
||||
formattedInspection: InspectionViewModel,
|
||||
inspectionPoints: Array<any>,
|
||||
user: { id: string; firstname: string; lastname: string }
|
||||
) {
|
||||
return {
|
||||
inspector: `${user.lastname}, ${user.firstname}`,
|
||||
context: formattedInspection.context || "---",
|
||||
createdAt: formattedInspection.created,
|
||||
finishedAt: formattedInspection.finishedAt ?? new Date(),
|
||||
nextInspection: formattedInspection.nextInspection,
|
||||
related: formattedInspection.related,
|
||||
plan: formattedInspection.inspectionPlan,
|
||||
planVersion: formattedInspection.inspectionVersionedPlan.version,
|
||||
planTitle: formattedInspection.inspectionPlan.title,
|
||||
checks: inspectionPoints,
|
||||
};
|
||||
}
|
||||
|
||||
public static async printPdf(inspectionId: string, user: { id: string; firstname: string; lastname: string }) {
|
||||
let inspection = await InspectionService.getById(inspectionId);
|
||||
|
||||
let check = this.validateInspectionData(inspection);
|
||||
if (!check)
|
||||
throw new ForbiddenRequestException(
|
||||
"fill out every field before finishing inspection - may not be filled out correct"
|
||||
);
|
||||
|
||||
let formattedInspection = InspectionFactory.mapToSingle(inspection);
|
||||
let title = `Prüf-Ausdruck_${[formattedInspection.related.code ?? "", formattedInspection.related.name].join(
|
||||
"_"
|
||||
)}_${formattedInspection.inspectionPlan.title}_${new Date(formattedInspection.finishedAt ?? "").toLocaleDateString(
|
||||
"de-de"
|
||||
)}`;
|
||||
|
||||
let inspectionPoints = await this.formatInspectionPoints(formattedInspection);
|
||||
|
||||
let data = this.buildData(formattedInspection, inspectionPoints, user);
|
||||
|
||||
let pdf = await PdfExport.renderFile({
|
||||
template: "inspection",
|
||||
title,
|
||||
saveToDisk: false,
|
||||
data: data,
|
||||
});
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
const mergedPdfBytes = await finalDocument.save();
|
||||
FileSystemHelper.writeFile(`inspection/${inspection.id}`, `printout.pdf`, mergedPdfBytes);
|
||||
|
||||
let finish: FinishInspectionCommand = {
|
||||
id: inspectionId,
|
||||
user,
|
||||
};
|
||||
await InspectionCommandHandler.finish(finish);
|
||||
}
|
||||
}
|
||||
|
||||
/** 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,
|
||||
});
|
||||
}
|
||||
*/
|
|
@ -7,10 +7,6 @@ export class UnitExtendImagesAndInspection1753777774744 implements MigrationInte
|
|||
name = "UnitExtendImagesAndInspection1753777774744";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.addColumn(
|
||||
inspection_plan_table.name,
|
||||
new TableColumn({ name: "allInRange", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) })
|
||||
);
|
||||
await queryRunner.addColumn(
|
||||
inspection_point_table.name,
|
||||
new TableColumn({ name: "optional", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) })
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { In } from "typeorm";
|
||||
import { dataSource } from "../../../data-source";
|
||||
import { inspectionPointResult } from "../../../entity/unit/inspection/inspectionPointResult";
|
||||
import DatabaseActionException from "../../../exceptions/databaseActionException";
|
||||
|
@ -21,6 +22,7 @@ export default abstract class InspectionPointResultService {
|
|||
throw new DatabaseActionException("SELECT", "inspectionPointResult", err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get inspectionPointResults by inspection and point
|
||||
* @returns {Promise<Array<inspectionPointResult>>}
|
||||
|
|
|
@ -27,12 +27,17 @@
|
|||
{{#if this.description}} > {{this.description}}
|
||||
<br />
|
||||
{{/if}}
|
||||
<small>(Typ: {{this.type}})</small>
|
||||
<small>(Typ: {{this.type}})</small><br />
|
||||
{{#if this.optional}}
|
||||
<small>(optional)</small><br />
|
||||
{{/if}} {{#eq this.type "number"}}{{#if (or this.min this.max)}}
|
||||
<small>(Bereich: {{showDashAsFallback this.min}} bis {{showDashAsFallback this.max}})</small>
|
||||
{{/if}}{{/eq}}
|
||||
</td>
|
||||
<td style="max-width: 70%; width: 70%; padding: 10px 5px; word-break: break-word">
|
||||
{{#eq this.type "file"}} {{#eq this.others "img"}}
|
||||
{{#eq this.value "---"}} --- {{else}} {{#eq this.type "file"}} {{#eq this.others "img"}}
|
||||
<img style="width: 100%; height: auto" src="{{ this.image }}" />
|
||||
{{else}} siehe Anhang {{/eq}} {{else}} {{this.value}} {{/eq}}
|
||||
{{else}} siehe Anhang {{/eq}} {{else}} {{showDashAsFallback this.value}} {{/eq}}{{/eq}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
|
|
@ -29,7 +29,6 @@ export type InspectionPlanViewModel = {
|
|||
title: string;
|
||||
inspectionInterval: PlanTimeDefinition;
|
||||
remindTime: PlanTimeDefinition;
|
||||
allInRange: boolean;
|
||||
version: number;
|
||||
created: Date;
|
||||
inspectionPoints: InspectionPointViewModel[];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue