Compare commits

...

65 commits

Author SHA1 Message Date
fcf37bb4c1 1.8.0-beta1 2025-07-25 12:55:55 +02:00
f05d03ccee extend maintenance table 2025-07-25 12:36:31 +02:00
063b949ae1 extend inspection_plan by wearable and enable optional interval 2025-07-25 12:21:40 +02:00
9b38c6a5e9 schema update 2025-07-25 11:04:53 +02:00
922c6b7df3 Merge branch 'develop' into milestone/ff-admin-unit 2025-07-25 09:28:55 +02:00
8b4ef03419 Merge branch 'develop' into milestone/ff-admin-unit 2025-07-23 10:42:12 +02:00
c2ee4fc6ef provide type related count in getById 2025-07-23 10:41:34 +02:00
b6b0f91d60 update factories to prevent undefined errors 2025-07-23 09:38:13 +02:00
e9c3a30a41 update permission handling 2025-07-23 09:38:01 +02:00
c4e0c4fa28 Merge pull request 'unit/#126-repairs' (#128) from unit/#126-repairs into milestone/ff-admin-unit
Reviewed-on: #128
2025-07-23 07:30:07 +00:00
f812298cb2 edit repair 2025-07-22 13:10:13 +02:00
85fa912024 add repair title to migration 2025-07-21 12:59:39 +02:00
2363933f5a repair create 2025-07-21 12:58:19 +02:00
ecadd8431d extend report by title 2025-07-21 11:01:57 +02:00
4d37571cb6 schema change and base operations 2025-07-19 11:02:07 +02:00
799a719012 Merge branch 'develop' into milestone/ff-admin-unit
# Conflicts:
#	src/data-source.ts
2025-07-19 10:42:49 +02:00
0abd79a94b Merge pull request 'unit/#107-damage-reports' (#125) from unit/#107-damage-reports into milestone/ff-admin-unit
Reviewed-on: #125
2025-07-17 08:50:17 +00:00
2d0f2b50f1 update schema migration 2025-07-17 10:49:40 +02:00
c02487ad3c extend damageReport with noteByWorker 2025-07-17 10:37:26 +02:00
a208cdd158 provide damage image 2025-07-17 09:32:27 +02:00
ca1ca9edc8 update image resolve by entity 2025-07-16 12:44:23 +02:00
0fdb77d7ca pass reports to admin ui 2025-07-16 12:42:54 +02:00
41c3093754 enable public report 2025-07-16 12:24:50 +02:00
8f563d1058 Merge pull request 'unit/#105-use-smartphone-as-barcode-scanner' (#122) from unit/#105-use-smartphone-as-barcode-scanner into milestone/ff-admin-unit
Reviewed-on: #122
2025-07-15 15:00:13 +00:00
70d03553d7 process external scans and check room exists 2025-07-15 16:59:05 +02:00
83ab0c4ea7 admin side scan connection 2025-07-15 15:16:11 +02:00
b29cdae088 add basic socketio to server 2025-07-15 11:52:58 +02:00
45ec6b856a Merge branch 'develop' into milestone/ff-admin-unit 2025-07-14 15:38:32 +02:00
0f7530ca39 Merge pull request 'unit/#102-base-management' (#121) from unit/#102-base-management into milestone/ff-admin-unit
Reviewed-on: #121
2025-07-14 13:36:34 +00:00
a69c3e048e enable backups for unit 2025-07-14 15:28:57 +02:00
9a1bf6dfde provide files for viewing of uploaded files to inspection points 2025-07-12 17:04:29 +02:00
98ce39efc5 print file with appendix 2025-07-12 16:38:14 +02:00
9ef82adef7 inspection finish and print 2025-07-11 14:02:36 +02:00
0f3e4488f4 correct type inspectionPlans request 2025-07-11 09:42:04 +02:00
c42a41d895 count instances to type 2025-07-11 09:33:37 +02:00
705297ba50 next and running inspections 2025-07-10 13:22:29 +02:00
8747baaf2e corrections in plan update and fetch 2025-07-10 10:49:30 +02:00
db3004fa04 update or create inspection versioned plan 2025-07-09 16:01:44 +02:00
95b6cec66d inspection fetch 2025-07-09 12:57:37 +02:00
a0a8edf7af fix get latest inspection plan 2025-07-04 11:57:13 +02:00
d5646753f1 inspection extend fixes 2025-06-13 18:05:55 +02:00
b8b2186c58 extend wearable and enable maintenance 2025-06-13 11:31:34 +02:00
aeb1ccbc42 fix according to move to postgres 2025-06-08 08:02:07 +02:00
f11ed83afc change schema according to migration 2025-06-08 07:55:40 +02:00
e056db053b Merge branch 'milestone/ff-admin-unit' into unit/#102-base-management
# Conflicts:
#	src/data-source.ts
2025-06-08 07:55:20 +02:00
f356a75067 Merge branch 'develop' into milestone/ff-admin-unit 2025-06-08 07:39:36 +02:00
e3db523a0e change according to connection from frontend 2025-06-04 14:30:57 +02:00
2609ecc1bf controller 2025-06-02 13:14:09 +02:00
9f2a08ccc9 define routes 2025-05-31 15:12:16 +02:00
9a1e7e74ca base controller files 2025-05-29 11:00:23 +02:00
0684605093 base router and permissions 2025-05-29 10:52:05 +02:00
7883bb7d7f command Handlers and schema update 2025-05-29 10:31:40 +02:00
0f6401953f add maintenance model, factory and service 2025-05-28 22:51:17 +02:00
cb60d61773 update migration to image count on damageReport 2025-05-28 18:30:24 +02:00
117ced38ab factory and restructure view models 2025-05-28 18:30:00 +02:00
fcbfe560c3 basic services joins 2025-05-28 17:32:07 +02:00
e404989a28 add sort to inspection point 2025-05-28 17:13:39 +02:00
2433120e26 service base 2025-05-28 17:06:56 +02:00
8c81c8f336 db schema connects 2025-05-28 17:06:45 +02:00
baa3b2cc8c add reporter to damage report 2025-05-27 16:01:00 +02:00
d156cc6ad6 base migration and schema optimization 2025-05-26 14:53:25 +02:00
0d8499b828 model clean and consistent naming 2025-05-25 07:01:13 +02:00
3ff44f7370 inspection data model 2025-05-24 13:51:38 +02:00
95d1113ff9 base unit data 2025-05-24 11:31:15 +02:00
15a511f942 add viewmodels from frontend 2025-05-24 11:30:58 +02:00
140 changed files with 8706 additions and 24 deletions

52
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "ff-admin-server", "name": "ff-admin-server",
"version": "1.7.5", "version": "1.8.0-beta1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ff-admin-server", "name": "ff-admin-server",
"version": "1.7.5", "version": "1.8.0-beta1",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"dependencies": { "dependencies": {
"cors": "^2.8.5", "cors": "^2.8.5",
@ -43,6 +43,7 @@
"validator": "^13.15.15" "validator": "^13.15.15"
}, },
"devDependencies": { "devDependencies": {
"@socket.io/admin-ui": "^0.5.1",
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.3", "@types/express": "^5.0.3",
"@types/ip": "^1.1.3", "@types/ip": "^1.1.3",
@ -764,6 +765,39 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/@socket.io/admin-ui": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@socket.io/admin-ui/-/admin-ui-0.5.1.tgz",
"integrity": "sha512-1dlGL2FGm6T+uL1e6iDvbo2eCINwvW7iVbjIblwh5kPPRM1SP8lmZrbFZf4QNJ/cqQ+JLcx49eXGM9WAB4TK7w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/bcryptjs": "^2.4.2",
"bcryptjs": "^2.4.3",
"debug": "~4.3.1"
},
"peerDependencies": {
"socket.io": ">=3.1.0"
}
},
"node_modules/@socket.io/admin-ui/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@socket.io/component-emitter": { "node_modules/@socket.io/component-emitter": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
@ -821,6 +855,13 @@
"devOptional": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/bcryptjs": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
"integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/body-parser": { "node_modules/@types/body-parser": {
"version": "1.19.5", "version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@ -1421,6 +1462,13 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/bcryptjs": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
"dev": true,
"license": "MIT"
},
"node_modules/bindings": { "node_modules/bindings": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",

View file

@ -1,6 +1,6 @@
{ {
"name": "ff-admin-server", "name": "ff-admin-server",
"version": "1.7.5", "version": "1.8.0-beta1",
"description": "Feuerwehr/Verein Mitgliederverwaltung Server", "description": "Feuerwehr/Verein Mitgliederverwaltung Server",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
@ -59,6 +59,7 @@
"validator": "^13.15.15" "validator": "^13.15.15"
}, },
"devDependencies": { "devDependencies": {
"@socket.io/admin-ui": "^0.5.1",
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.3", "@types/express": "^5.0.3",
"@types/ip": "^1.1.3", "@types/ip": "^1.1.3",

View file

@ -0,0 +1,27 @@
export interface CreateDamageReportCommand {
title: string;
description: string;
location: string;
noteByReporter: string;
reportedBy: string;
images: string[];
affectedId?: string;
affected?: "equipment" | "vehicle" | "wearable";
}
export interface UpdateDamageReportCommand {
id: string;
status: string;
noteByWorker: string;
user: { id: string; firstname: string; lastname: string };
done: boolean;
}
export interface UpdateDamageReportRelatedRepairCommand {
id: string;
repairId: string;
}
export interface DeleteDamageReportCommand {
id: string;
}

View file

@ -0,0 +1,163 @@
import { EntityManager, In, UpdateResult } from "typeorm";
import { dataSource } from "../../data-source";
import { damageReport } from "../../entity/unit/damageReport";
import DatabaseActionException from "../../exceptions/databaseActionException";
import {
CreateDamageReportCommand,
UpdateDamageReportCommand,
DeleteDamageReportCommand,
UpdateDamageReportRelatedRepairCommand,
} from "./damageReportCommand";
import DamageReportService from "../../service/unit/damageReportService";
export default abstract class DamageReportCommandHandler {
/**
* @description create damageReport
* @param {CreateDamageReportCommand} createDamageReport
* @returns {Promise<number>}
*/
static async create(createDamageReport: CreateDamageReportCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(damageReport)
.values({
status: "eingereicht",
title: createDamageReport.title,
description: createDamageReport.description,
location: createDamageReport.location,
noteByReporter: createDamageReport.noteByReporter,
reportedBy: createDamageReport.reportedBy,
images: createDamageReport.images,
equipmentId: createDamageReport.affected == "equipment" ? createDamageReport.affectedId : null,
vehicleId: createDamageReport.affected == "vehicle" ? createDamageReport.affectedId : null,
wearableId: createDamageReport.affected == "wearable" ? createDamageReport.affectedId : null,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "damageReport", err);
});
}
/**
* @description update damageReport
* @param {UpdateDamageReportCommand} updateDamageReport
* @returns {Promise<void>}
*/
static async update(updateDamageReport: UpdateDamageReportCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(damageReport)
.set({
status: updateDamageReport.status,
noteByWorker: updateDamageReport.noteByWorker,
closedAt: updateDamageReport.done ? new Date() : null,
closedById: updateDamageReport.done ? updateDamageReport.user.id : null,
closedByString: updateDamageReport.done
? `${updateDamageReport.user.firstname} ${updateDamageReport.user.lastname}`
: null,
})
.where("id = :id", { id: updateDamageReport.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "damageReport", err);
});
}
/**
* @description update damageReport related maintenance
* @param {UpdateDamageReportCommand} updateDamageReport
* @returns {Promise<void>}
*/
static async updateRelatedMaintenance(updateDamageReport: UpdateDamageReportRelatedRepairCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(damageReport)
.set({
repairId: updateDamageReport.repairId,
})
.where("id = :id", { id: updateDamageReport.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "damageReport->maintenance", err);
});
}
/**
* @description update damageReport related maintenance
* @returns {Promise<void>}
*/
static async updateRelatedMaintenanceMulti(repairId: string, reports: Array<string>): Promise<void> {
let [related] = await DamageReportService.getAllForRepair(repairId, { noLimit: true });
return await dataSource
.transaction(async (manager) => {
let added = reports.filter((id) => !related.some((r) => r.id === id));
let removed = related.map((r) => r.id).filter((id) => !reports.includes(id));
await manager
.createQueryBuilder()
.update(damageReport)
.set({
repairId: repairId,
})
.where({ id: In(added) })
.execute();
await manager
.createQueryBuilder()
.update(damageReport)
.set({
repairId: null,
})
.where({ id: In(removed) })
.execute();
})
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "damageReport->maintenance", err);
});
}
/**
* @description update damageReport related maintenance in transaction
* @param {UpdateDamageReportCommand} updateDamageReport
* @returns {Promise<void>}
*/
static async updateRelatedMaintenanceTransaction(
manager: EntityManager,
updateDamageReport: UpdateDamageReportRelatedRepairCommand
): Promise<UpdateResult> {
return await manager
.createQueryBuilder()
.update(damageReport)
.set({
repairId: updateDamageReport.repairId,
})
.where("id = :id", { id: updateDamageReport.id })
.execute();
}
/**
* @description delete damageReport
* @param {DeleteDamageReportCommand} deleteDamageReport
* @returns {Promise<void>}
*/
static async delete(deleteDamageReport: DeleteDamageReportCommand): Promise<void> {
// TODO: remove related images
return await dataSource
.createQueryBuilder()
.delete()
.from(damageReport)
.where("id = :id", { id: deleteDamageReport.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "damageReport", err);
});
}
}

View file

@ -0,0 +1,20 @@
export interface CreateEquipmentCommand {
code?: string;
name: string;
location: string;
commissioned: Date;
equipmentTypeId: string;
}
export interface UpdateEquipmentCommand {
id: string;
code?: string;
name: string;
location: string;
commissioned: Date;
decommissioned?: Date;
}
export interface DeleteEquipmentCommand {
id: string;
}

View file

@ -0,0 +1,74 @@
import { dataSource } from "../../../data-source";
import { equipment } from "../../../entity/unit/equipment/equipment";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { CreateEquipmentCommand, UpdateEquipmentCommand, DeleteEquipmentCommand } from "./equipmentCommand";
export default abstract class EquipmentCommandHandler {
/**
* @description create equipment
* @param {CreateEquipmentCommand} createEquipment
* @returns {Promise<number>}
*/
static async create(createEquipment: CreateEquipmentCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(equipment)
.values({
code: createEquipment.code,
name: createEquipment.name,
location: createEquipment.location,
commissioned: createEquipment.commissioned,
equipmentTypeId: createEquipment.equipmentTypeId,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "equipment", err);
});
}
/**
* @description update equipment
* @param {UpdateEquipmentCommand} updateEquipment
* @returns {Promise<void>}
*/
static async update(updateEquipment: UpdateEquipmentCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(equipment)
.set({
code: updateEquipment.code,
name: updateEquipment.name,
location: updateEquipment.location,
commissioned: updateEquipment.commissioned,
decommissioned: updateEquipment.decommissioned,
})
.where("id = :id", { id: updateEquipment.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "equipment", err);
});
}
/**
* @description delete equipment
* @param {DeleteEquipmentCommand} deleteEquipment
* @returns {Promise<void>}
*/
static async delete(deleteEquipment: DeleteEquipmentCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(equipment)
.where("id = :id", { id: deleteEquipment.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "equipment", err);
});
}
}

View file

@ -0,0 +1,14 @@
export interface CreateEquipmentTypeCommand {
type: string;
description: string;
}
export interface UpdateEquipmentTypeCommand {
id: string;
type: string;
description: string;
}
export interface DeleteEquipmentTypeCommand {
id: string;
}

View file

@ -0,0 +1,72 @@
import { dataSource } from "../../../data-source";
import { equipmentType } from "../../../entity/unit/equipment/equipmentType";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import {
CreateEquipmentTypeCommand,
UpdateEquipmentTypeCommand,
DeleteEquipmentTypeCommand,
} from "./equipmentTypeCommand";
export default abstract class EquipmentTypeCommandHandler {
/**
* @description create equipmentType
* @param {CreateEquipmentTypeCommand} createEquipmentType
* @returns {Promise<number>}
*/
static async create(createEquipmentType: CreateEquipmentTypeCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(equipmentType)
.values({
type: createEquipmentType.type,
description: createEquipmentType.description,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "equipmentType", err);
});
}
/**
* @description update equipmentType
* @param {UpdateEquipmentTypeCommand} updateEquipmentType
* @returns {Promise<void>}
*/
static async update(updateEquipmentType: UpdateEquipmentTypeCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(equipmentType)
.set({
type: updateEquipmentType.type,
description: updateEquipmentType.description,
})
.where("id = :id", { id: updateEquipmentType.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "equipmentType", err);
});
}
/**
* @description delete equipmentType
* @param {DeleteEquipmentTypeCommand} deleteEquipmentType
* @returns {Promise<void>}
*/
static async delete(deleteEquipmentType: DeleteEquipmentTypeCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(equipmentType)
.where("id = :id", { id: deleteEquipmentType.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "equipmentType", err);
});
}
}

View file

@ -0,0 +1,22 @@
export interface CreateInspectionCommand {
context: string;
nextInspection?: Date;
inspectionPlanId: string;
relatedId: string;
assigned: "vehicle" | "equipment" | "wearable";
}
export interface UpdateInspectionCommand {
id: string;
context: string;
nextInspection?: Date;
}
export interface FinishInspectionCommand {
id: string;
user: { id: string; firstname: string; lastname: string };
}
export interface DeleteInspectionCommand {
id: string;
}

View file

@ -0,0 +1,156 @@
import { IsNull, Not } from "typeorm";
import { dataSource } from "../../../data-source";
import { inspection } from "../../../entity/unit/inspection/inspection";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import InspectionService from "../../../service/unit/inspection/inspectionService";
import InspectionVersionedPlanService from "../../../service/unit/inspection/inspectionVersionedPlanService";
import {
CreateInspectionCommand,
UpdateInspectionCommand,
DeleteInspectionCommand,
FinishInspectionCommand,
} from "./inspectionCommand";
export default abstract class InspectionCommandHandler {
/**
* @description create inspection
* @param {CreateInspectionCommand} createInspection
* @returns {Promise<string>}
*/
static async create(createInspection: CreateInspectionCommand): Promise<string> {
let latestVersionedPlan = await InspectionVersionedPlanService.getLatestForInspectionPlan(
createInspection.inspectionPlanId
);
let insertId = "";
return await dataSource
.transaction(async (manager) => {
await manager
.createQueryBuilder()
.update(inspection)
.set({
hasNewer: true,
})
.where({
inspectionPlanId: createInspection.inspectionPlanId,
equipmentId: createInspection.assigned == "equipment" ? createInspection.relatedId : IsNull(),
vehicleId: createInspection.assigned == "vehicle" ? createInspection.relatedId : IsNull(),
wearableId: createInspection.assigned == "wearable" ? createInspection.relatedId : IsNull(),
})
.execute();
await manager
.createQueryBuilder()
.insert()
.into(inspection)
.values({
context: createInspection.context,
nextInspection: createInspection.nextInspection,
inspectionPlanId: createInspection.inspectionPlanId,
inspectionVersionedPlanId: latestVersionedPlan.id,
equipmentId: createInspection.assigned == "equipment" ? createInspection.relatedId : null,
vehicleId: createInspection.assigned == "vehicle" ? createInspection.relatedId : null,
wearableId: createInspection.assigned == "wearable" ? createInspection.relatedId : null,
})
.execute()
.then((result) => {
insertId = result.identifiers[0].id;
});
})
.then(() => {
return insertId;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "inspection", err);
});
}
/**
* @description update inspection
* @param {UpdateInspectionCommand} updateInspection
* @returns {Promise<void>}
*/
static async update(updateInspection: UpdateInspectionCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(inspection)
.set({
context: updateInspection.context,
nextInspection: updateInspection.nextInspection,
})
.where("id = :id", { id: updateInspection.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "inspection", err);
});
}
/**
* @description finish inspection
* @param {FinishInspectionCommand} finishInspection
* @returns {Promise<void>}
*/
static async finish(finishInspection: FinishInspectionCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(inspection)
.set({
finishedAt: new Date(),
finishedById: finishInspection.user.id,
finishedByString: `${finishInspection.user.firstname} ${finishInspection.user.lastname}`,
})
.where("id = :id", { id: finishInspection.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("FINISH", "inspection", err);
});
}
/**
* @description delete inspection
* @param {DeleteInspectionCommand} deleteInspection
* @returns {Promise<void>}
*/
static async delete(deleteInspection: DeleteInspectionCommand): Promise<void> {
let deleteInspectionData = await InspectionService.getById(deleteInspection.id);
return await dataSource
.transaction(async (manager) => {
let latestInspection = await manager
.createQueryBuilder()
.from(inspection, "sub")
.where({
inspectionPlanId: deleteInspectionData.inspectionPlanId,
inspectionVersionedPlanId: deleteInspectionData.inspectionVersionedPlanId,
equipmentId: deleteInspectionData.equipmentId ?? IsNull(),
vehicleId: deleteInspectionData.vehicleId ?? IsNull(),
wearableId: deleteInspectionData.wearableId ?? IsNull(),
})
.andWhere({ id: Not(deleteInspection.id) })
.orderBy("sub.createdAt", "DESC")
.limit(1)
.getOne();
if (latestInspection)
await manager
.createQueryBuilder()
.update(inspection)
.set({
hasNewer: false,
})
.where({ id: latestInspection.id })
.execute();
await manager
.createQueryBuilder()
.delete()
.from(inspection)
.where("id = :id", { id: deleteInspection.id })
.execute();
})
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "inspection", err);
});
}
}

View file

@ -0,0 +1,20 @@
import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspection/inspectionPlan.models";
export interface CreateInspectionPlanCommand {
title: string;
inspectionInterval: PlanTimeDefinition;
remindTime: PlanTimeDefinition;
relatedId: string;
assigned: "vehicle" | "equipment" | "wearable";
}
export interface UpdateInspectionPlanCommand {
id: string;
title: string;
inspectionInterval: PlanTimeDefinition;
remindTime?: PlanTimeDefinition;
}
export interface DeleteInspectionPlanCommand {
id: string;
}

View file

@ -0,0 +1,77 @@
import { dataSource } from "../../../data-source";
import { inspectionPlan } from "../../../entity/unit/inspection/inspectionPlan";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import {
CreateInspectionPlanCommand,
UpdateInspectionPlanCommand,
DeleteInspectionPlanCommand,
} from "./inspectionPlanCommand";
export default abstract class InspectionPlanCommandHandler {
/**
* @description create inspectionPlan
* @param {CreateInspectionPlanCommand} createInspectionPlan
* @returns {Promise<number>}
*/
static async create(createInspectionPlan: CreateInspectionPlanCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(inspectionPlan)
.values({
title: createInspectionPlan.title,
inspectionInterval: createInspectionPlan.inspectionInterval,
remindTime: createInspectionPlan.remindTime,
equipmentTypeId: createInspectionPlan.assigned == "equipment" ? createInspectionPlan.relatedId : null,
vehicleTypeId: createInspectionPlan.assigned == "vehicle" ? createInspectionPlan.relatedId : null,
wearableTypeId: createInspectionPlan.assigned == "wearable" ? createInspectionPlan.relatedId : null,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "inspectionPlan", err);
});
}
/**
* @description update inspectionPlan
* @param {UpdateInspectionPlanCommand} updateInspectionPlan
* @returns {Promise<void>}
*/
static async update(updateInspectionPlan: UpdateInspectionPlanCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(inspectionPlan)
.set({
title: updateInspectionPlan.title,
inspectionInterval: updateInspectionPlan.inspectionInterval,
remindTime: updateInspectionPlan.remindTime,
})
.where("id = :id", { id: updateInspectionPlan.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "inspectionPlan", err);
});
}
/**
* @description delete inspectionPlan
* @param {DeleteInspectionPlanCommand} deleteInspectionPlan
* @returns {Promise<void>}
*/
static async delete(deleteInspectionPlan: DeleteInspectionPlanCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(inspectionPlan)
.where("id = :id", { id: deleteInspectionPlan.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "inspectionPlan", err);
});
}
}

View file

@ -0,0 +1,13 @@
import { InspectionPointEnum } from "../../../enums/inspectionEnum";
export interface CreateInspectionPointCommand {
id?: string;
title: string;
description: string;
type: InspectionPointEnum;
min?: number;
max?: number;
others?: string;
sort: number;
versionedPointId?: string;
}

View file

@ -0,0 +1,74 @@
import { dataSource } from "../../../data-source";
import { inspectionPoint } from "../../../entity/unit/inspection/inspectionPoint";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import InspectionPointService from "../../../service/unit/inspection/inspectionPointService";
import { CreateInspectionPointCommand } from "./inspectionPointCommand";
export default abstract class InspectionPointCommandHandler {
/**
* @description create inspectionPoint
* @param {CreateInspectionPointCommand} createInspectionPoint
* @returns {Promise<number>}
*/
static async create(createInspectionPoint: CreateInspectionPointCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(inspectionPoint)
.values({
title: createInspectionPoint.title,
description: createInspectionPoint.description,
type: createInspectionPoint.type,
min: createInspectionPoint.min,
max: createInspectionPoint.max,
sort: createInspectionPoint.sort,
versionedPlanId: createInspectionPoint.versionedPointId,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "inspectionPoint", err);
});
}
/**
* @description sync points
* @param {string} versionedPlanId
* @param {Array<CreateInspectionPointCommand>} sync
* @returns {Promise<void>}
*/
static async sync(versionedPlanId: string, sync: Array<CreateInspectionPointCommand>): Promise<void> {
let points = await InspectionPointService.getAllForVersionedPlan(versionedPlanId);
await dataSource
.transaction(async (manager) => {
let remove = points.filter((r) => !sync.some((cp) => cp.id == r.id));
await manager
.createQueryBuilder()
.insert()
.into(inspectionPoint)
.values(
sync.map((s) => ({
...s,
id: points.some((p) => p.id == s.id) ? s.id : undefined,
versionedPlanId,
}))
)
.orUpdate(["title", "description", "min", "max", "others", "sort"], ["id"])
.execute();
if (remove.length != 0)
await manager
.createQueryBuilder()
.delete()
.from(inspectionPoint)
.where("id IN (:...ids)", { ids: remove.map((r) => r.id) })
.andWhere({ versionedPlanId })
.execute();
})
.catch((err) => {
throw new DatabaseActionException("SYNC", "inspectionPoint", err);
});
}
}

View file

@ -0,0 +1,5 @@
export interface CreateOrUpdateInspectionPointResultCommand {
inspectionId: string;
inspectionPointId: string;
value: string;
}

View file

@ -0,0 +1,54 @@
import { dataSource } from "../../../data-source";
import { inspectionPointResult } from "../../../entity/unit/inspection/inspectionPointResult";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { CreateOrUpdateInspectionPointResultCommand } from "./inspectionPointResultCommand";
export default abstract class InspectionPointResultCommandHandler {
/**
* @description create inspectionPointResult
* @param {CreateOrUpdateInspectionPointResultCommand} createInspectionPointResult
* @returns {Promise<number>}
*/
static async createOrUpdate(
createInspectionPointResult: CreateOrUpdateInspectionPointResultCommand
): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(inspectionPointResult)
.values({
inspectionId: createInspectionPointResult.inspectionId,
inspectionPointId: createInspectionPointResult.inspectionPointId,
value: createInspectionPointResult.value,
})
.orUpdate(["value"], ["inspectionId", "inspectionPointId"])
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE or UPDATE", "inspectionPointResult", err);
});
}
/**
* @description create inspectionPointResult
* @param {Array<CreateOrUpdateInspectionPointResultCommand>} results
* @returns {Promise<number>}
*/
static async createOrUpdateMultiple(results: Array<CreateOrUpdateInspectionPointResultCommand>): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(inspectionPointResult)
.values(results)
.orUpdate(["value"], ["inspectionId", "inspectionPointId"])
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE or UPDATE", "inspectionPointResult", err);
});
}
}

View file

@ -0,0 +1,3 @@
export interface CreateInspectionVersionedPlanCommand {
inspectionPlanId: string;
}

View file

@ -0,0 +1,62 @@
import { dataSource } from "../../../data-source";
import { inspectionPoint } from "../../../entity/unit/inspection/inspectionPoint";
import { inspectionVersionedPlan } from "../../../entity/unit/inspection/inspectionVersionedPlan";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import InspectionVersionedPlanService from "../../../service/unit/inspection/inspectionVersionedPlanService";
import { CreateInspectionPointCommand } from "./inspectionPointCommand";
import { CreateInspectionVersionedPlanCommand } from "./inspectionVersionedPlanCommand";
export default abstract class InspectionVersionedPlanCommandHandler {
/**
* @description create inspectionVersionedPlan
* @param {CreateInspectionVersionedPlanCommand} createInspectionVersionedPlan
* @returns {Promise<string>}
*/
static async create(
createInspectionVersionedPlan: CreateInspectionVersionedPlanCommand,
inspectionPoints: Array<CreateInspectionPointCommand>
): Promise<string> {
let count = await InspectionVersionedPlanService.countForPlanId(createInspectionVersionedPlan.inspectionPlanId);
let returnId = "";
return await dataSource
.transaction(async (manager) => {
await manager
.createQueryBuilder()
.insert()
.into(inspectionVersionedPlan)
.values({
inspectionPlanId: createInspectionVersionedPlan.inspectionPlanId,
version: count,
})
.execute()
.then((result) => {
returnId = result.identifiers[0].id;
});
await manager
.createQueryBuilder()
.insert()
.into(inspectionPoint)
.values(
inspectionPoints.map((ip) => ({
title: ip.title,
description: ip.description,
type: ip.type,
min: ip.min,
max: ip.max,
others: ip.others,
sort: ip.sort,
versionedPlanId: returnId,
}))
)
.execute();
})
.then(() => {
return returnId;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "inspectionVersionedPlan", err);
});
}
}

View file

@ -0,0 +1,16 @@
export interface CreateMaintenanceCommand {
description: string;
affectedId: string;
affected: "equipment" | "vehicle" | "wearable";
}
export interface UpdateMaintenanceCommand {
id: string;
status: string;
done: boolean;
description: string;
}
export interface DeleteMaintenanceCommand {
id: string;
}

View file

@ -0,0 +1,72 @@
import { dataSource } from "../../data-source";
import { maintenance } from "../../entity/unit/maintenance";
import DatabaseActionException from "../../exceptions/databaseActionException";
import { CreateMaintenanceCommand, UpdateMaintenanceCommand, DeleteMaintenanceCommand } from "./maintenanceCommand";
export default abstract class MaintenanceCommandHandler {
/**
* @description create maintenance
* @param {CreateMaintenanceCommand} createMaintenance
* @returns {Promise<number>}
*/
static async create(createMaintenance: CreateMaintenanceCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(maintenance)
.values({
status: "gestartet",
description: createMaintenance.description,
equipmentId: createMaintenance.affected == "equipment" ? createMaintenance.affectedId : null,
vehicleId: createMaintenance.affected == "vehicle" ? createMaintenance.affectedId : null,
wearableId: createMaintenance.affected == "wearable" ? createMaintenance.affectedId : null,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "maintenance", err);
});
}
/**
* @description update maintenance
* @param {UpdateMaintenanceCommand} updateMaintenance
* @returns {Promise<void>}
*/
static async update(updateMaintenance: UpdateMaintenanceCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(maintenance)
.set({
status: updateMaintenance.status,
done: updateMaintenance.done,
description: updateMaintenance.description,
})
.where("id = :id", { id: updateMaintenance.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "maintenance", err);
});
}
/**
* @description delete maintenance
* @param {DeleteMaintenanceCommand} deleteMaintenance
* @returns {Promise<void>}
*/
static async delete(deleteMaintenance: DeleteMaintenanceCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(maintenance)
.where("id = :id", { id: deleteMaintenance.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "maintenance", err);
});
}
}

View file

@ -0,0 +1,26 @@
export interface CreateRepairCommand {
title: string;
description: string;
responsible: string;
affectedId: string;
affected: "equipment" | "vehicle" | "wearable";
reports: string[];
}
export interface UpdateRepairCommand {
id: string;
title: string;
description: string;
responsible: string;
}
export interface UpdateRepairStatusCommand {
id: string;
status: string;
user: { id: string; firstname: string; lastname: string };
done: boolean;
}
export interface DeleteRepairCommand {
id: string;
}

View file

@ -0,0 +1,117 @@
import { dataSource } from "../../data-source";
import { repair } from "../../entity/unit/repair";
import DatabaseActionException from "../../exceptions/databaseActionException";
import DamageReportCommandHandler from "./damageReportCommandHandler";
import {
CreateRepairCommand,
UpdateRepairCommand,
DeleteRepairCommand,
UpdateRepairStatusCommand,
} from "./repairCommand";
export default abstract class RepairCommandHandler {
/**
* @description create repair
* @param {CreateRepairCommand} createRepair
* @returns {Promise<string>}
*/
static async create(createRepair: CreateRepairCommand): Promise<string> {
let resultId = "";
return await dataSource
.transaction(async (manager) => {
await manager
.createQueryBuilder()
.insert()
.into(repair)
.values({
status: "in Arbeit",
title: createRepair.title,
description: createRepair.description,
responsible: createRepair.responsible,
equipmentId: createRepair.affected == "equipment" ? createRepair.affectedId : null,
vehicleId: createRepair.affected == "vehicle" ? createRepair.affectedId : null,
wearableId: createRepair.affected == "wearable" ? createRepair.affectedId : null,
})
.execute()
.then((result) => {
resultId = result.identifiers[0].id;
});
for (const report of createRepair.reports) {
await DamageReportCommandHandler.updateRelatedMaintenanceTransaction(manager, {
id: report,
repairId: resultId,
});
}
})
.then(() => {
return resultId;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "repair", err);
});
}
/**
* @description update repair
* @param {UpdateRepairCommand} updateRepair
* @returns {Promise<void>}
*/
static async update(updateRepair: UpdateRepairCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(repair)
.set({
title: updateRepair.title,
description: updateRepair.description,
responsible: updateRepair.responsible,
})
.where("id = :id", { id: updateRepair.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "repair", err);
});
}
/**
* @description update repair
* @param {UpdateRepairStatusCommand} updateRepair
* @returns {Promise<void>}
*/
static async updateStatus(updateRepair: UpdateRepairStatusCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(repair)
.set({
status: updateRepair.status,
finishedAt: updateRepair.done ? new Date() : null,
finishedById: updateRepair.done ? updateRepair.user.id : null,
finishedByString: updateRepair.done ? `${updateRepair.user.firstname} ${updateRepair.user.lastname}` : null,
})
.where("id = :id", { id: updateRepair.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "repair", err);
});
}
/**
* @description delete repair
* @param {DeleteRepairCommand} deleteRepair
* @returns {Promise<void>}
*/
static async delete(deleteRepair: DeleteRepairCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(repair)
.where("id = :id", { id: deleteRepair.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "repair", err);
});
}
}

View file

@ -0,0 +1,20 @@
export interface CreateVehicleCommand {
code?: string;
name: string;
location: string;
commissioned: Date;
vehicleTypeId: string;
}
export interface UpdateVehicleCommand {
id: string;
code?: string;
name: string;
location: string;
commissioned: Date;
decommissioned?: Date;
}
export interface DeleteVehicleCommand {
id: string;
}

View file

@ -0,0 +1,73 @@
import { dataSource } from "../../../data-source";
import { vehicle } from "../../../entity/unit/vehicle/vehicle";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { CreateVehicleCommand, UpdateVehicleCommand, DeleteVehicleCommand } from "./vehicleCommand";
export default abstract class VehicleCommandHandler {
/**
* @description create vehicle
* @param {CreateVehicleCommand} createVehicle
* @returns {Promise<number>}
*/
static async create(createVehicle: CreateVehicleCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(vehicle)
.values({
code: createVehicle.code,
name: createVehicle.name,
location: createVehicle.location,
commissioned: createVehicle.commissioned,
vehicleTypeId: createVehicle.vehicleTypeId,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "vehicle", err);
});
}
/**
* @description update vehicle
* @param {UpdateVehicleCommand} updateVehicle
* @returns {Promise<void>}
*/
static async update(updateVehicle: UpdateVehicleCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(vehicle)
.set({
code: updateVehicle.code,
name: updateVehicle.name,
location: updateVehicle.location,
commissioned: updateVehicle.commissioned,
})
.where("id = :id", { id: updateVehicle.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "vehicle", err);
});
}
/**
* @description delete vehicle
* @param {DeleteVehicleCommand} deleteVehicle
* @returns {Promise<void>}
*/
static async delete(deleteVehicle: DeleteVehicleCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(vehicle)
.where("id = :id", { id: deleteVehicle.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "vehicle", err);
});
}
}

View file

@ -0,0 +1,14 @@
export interface CreateVehicleTypeCommand {
type: string;
description: string;
}
export interface UpdateVehicleTypeCommand {
id: string;
type: string;
description: string;
}
export interface DeleteVehicleTypeCommand {
id: string;
}

View file

@ -0,0 +1,68 @@
import { dataSource } from "../../../data-source";
import { vehicleType } from "../../../entity/unit/vehicle/vehicleType";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { CreateVehicleTypeCommand, UpdateVehicleTypeCommand, DeleteVehicleTypeCommand } from "./vehicleTypeCommand";
export default abstract class VehicleTypeCommandHandler {
/**
* @description create vehicleType
* @param {CreateVehicleTypeCommand} createVehicleType
* @returns {Promise<number>}
*/
static async create(createVehicleType: CreateVehicleTypeCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(vehicleType)
.values({
type: createVehicleType.type,
description: createVehicleType.description,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "vehicleType", err);
});
}
/**
* @description update vehicleType
* @param {UpdateVehicleTypeCommand} updateVehicleType
* @returns {Promise<void>}
*/
static async update(updateVehicleType: UpdateVehicleTypeCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(vehicleType)
.set({
type: updateVehicleType.type,
description: updateVehicleType.description,
})
.where("id = :id", { id: updateVehicleType.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "vehicleType", err);
});
}
/**
* @description delete vehicleType
* @param {DeleteVehicleTypeCommand} deleteVehicleType
* @returns {Promise<void>}
*/
static async delete(deleteVehicleType: DeleteVehicleTypeCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(vehicleType)
.where("id = :id", { id: deleteVehicleType.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "vehicleType", err);
});
}
}

View file

@ -0,0 +1,22 @@
export interface CreateWearableCommand {
code?: string;
name: string;
location: string;
commissioned: Date;
wearableTypeId: string;
wearerId?: string;
}
export interface UpdateWearableCommand {
id: string;
code?: string;
name: string;
location: string;
commissioned: Date;
decommissioned?: Date;
wearerId?: string;
}
export interface DeleteWearableCommand {
id: string;
}

View file

@ -0,0 +1,76 @@
import { dataSource } from "../../../data-source";
import { wearable } from "../../../entity/unit/wearable/wearable";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { CreateWearableCommand, UpdateWearableCommand, DeleteWearableCommand } from "./wearableCommand";
export default abstract class WearableCommandHandler {
/**
* @description create wearable
* @param {CreateWearableCommand} createWearable
* @returns {Promise<number>}
*/
static async create(createWearable: CreateWearableCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(wearable)
.values({
code: createWearable.code,
name: createWearable.name,
location: createWearable.location,
commissioned: createWearable.commissioned,
wearableTypeId: createWearable.wearableTypeId,
wearerId: createWearable.wearerId,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "wearable", err);
});
}
/**
* @description update wearable
* @param {UpdateWearableCommand} updateWearable
* @returns {Promise<void>}
*/
static async update(updateWearable: UpdateWearableCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(wearable)
.set({
code: updateWearable.code,
name: updateWearable.name,
location: updateWearable.location,
commissioned: updateWearable.commissioned,
decommissioned: updateWearable.decommissioned,
wearerId: updateWearable.wearerId,
})
.where("id = :id", { id: updateWearable.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "wearable", err);
});
}
/**
* @description delete wearable
* @param {DeleteWearableCommand} deleteWearable
* @returns {Promise<void>}
*/
static async delete(deleteWearable: DeleteWearableCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(wearable)
.where("id = :id", { id: deleteWearable.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "wearable", err);
});
}
}

View file

@ -0,0 +1,14 @@
export interface CreateWearableTypeCommand {
type: string;
description: string;
}
export interface UpdateWearableTypeCommand {
id: string;
type: string;
description: string;
}
export interface DeleteWearableTypeCommand {
id: string;
}

View file

@ -0,0 +1,68 @@
import { dataSource } from "../../../data-source";
import { wearableType } from "../../../entity/unit/wearable/wearableType";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { CreateWearableTypeCommand, UpdateWearableTypeCommand, DeleteWearableTypeCommand } from "./wearableTypeCommand";
export default abstract class WearableTypeCommandHandler {
/**
* @description create wearableType
* @param {CreateWearableTypeCommand} createWearableType
* @returns {Promise<number>}
*/
static async create(createWearableType: CreateWearableTypeCommand): Promise<number> {
return await dataSource
.createQueryBuilder()
.insert()
.into(wearableType)
.values({
type: createWearableType.type,
description: createWearableType.description,
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "wearableType", err);
});
}
/**
* @description update wearableType
* @param {UpdateWearableTypeCommand} updateWearableType
* @returns {Promise<void>}
*/
static async update(updateWearableType: UpdateWearableTypeCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(wearableType)
.set({
type: updateWearableType.type,
description: updateWearableType.description,
})
.where("id = :id", { id: updateWearableType.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "wearableType", err);
});
}
/**
* @description delete wearableType
* @param {DeleteWearableTypeCommand} deleteWearableType
* @returns {Promise<void>}
*/
static async delete(deleteWearableType: DeleteWearableTypeCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(wearableType)
.where("id = :id", { id: deleteWearableType.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "wearableType", err);
});
}
}

View file

@ -0,0 +1,169 @@
import { Request, Response } from "express";
import DamageReportService from "../../../service/unit/damageReportService";
import DamageReportFactory from "../../../factory/admin/unit/damageReport";
import { CreateDamageReportCommand, UpdateDamageReportCommand } from "../../../command/unit/damageReportCommand";
import DamageReportCommandHandler from "../../../command/unit/damageReportCommandHandler";
import BadRequestException from "../../../exceptions/badRequestException";
import { FileSystemHelper } from "../../../helpers/fileSystemHelper";
/**
* @description get all damageReports by status
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllDamageReportsByStatus(req: Request, res: Response): Promise<any> {
let done = req.query.done === "true";
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 [damageReports, total] = await DamageReportService.getAllByStatus(done, { offset, count, noLimit });
res.json({
damageReports: DamageReportFactory.mapToBase(damageReports),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get all damageReports for related id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllDamageReportsForRelated(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 [damageReports, total] = await DamageReportService.getAllForRelated(where, { offset, count, noLimit });
res.json({
damageReports: DamageReportFactory.mapToBase(damageReports),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get damageReport by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getDamageReportById(req: Request, res: Response): Promise<any> {
const damageReportId = req.params.id;
let damageReport = await DamageReportService.getById(damageReportId);
res.json(DamageReportFactory.mapToSingle(damageReport));
}
/**
* @description get reports by Ids
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getDamageReportsByIds(req: Request, res: Response): Promise<any> {
let ids = req.body.ids as Array<string>;
let [damageReports, total] = await DamageReportService.getAll({ noLimit: true, ids });
res.json({
damageReports: DamageReportFactory.mapToBase(damageReports),
total: total,
offset: 0,
count: total,
});
}
/**
* @description provide uploaded image for damage report
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function provideDamageReportImageUpload(req: Request, res: Response): Promise<any> {
const damageReportId = req.params.id;
const filename = req.params.filename;
let filepath = FileSystemHelper.formatPath("damageReport", filename);
res.sendFile(filepath);
}
/**
* @description create damageReport
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createDamageReport(req: Request, res: Response): Promise<any> {
const title = req.body.title;
const description = req.body.description;
const location = req.body.location;
const note = req.body.note;
const reportedBy = req.body.reportedBy;
const images = req.files as Express.Multer.File[];
const affectedId = req.body.affectedId;
const affected = req.body.affected;
if (affected != "equipment" && affected != "vehicle" && affected != "wearable")
throw new BadRequestException("set assigned to equipment or vehicle or wearable");
let createDamageReport: CreateDamageReportCommand = {
title,
description,
location,
noteByReporter: note,
reportedBy,
images: images.map((i) => i.filename),
affectedId,
affected,
};
let damageReportId = await DamageReportCommandHandler.create(createDamageReport);
res.status(200).send(damageReportId);
}
/**
* @description update damageReport by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateDamageReportById(req: Request, res: Response): Promise<any> {
const damageReportId = req.params.id;
const status = req.body.status;
const noteByWorker = req.body.noteByWorker;
const done = req.body.done;
let updateDamageReport: UpdateDamageReportCommand = {
id: damageReportId,
status,
noteByWorker,
done,
user: {
id: req.userId,
firstname: req.firstname,
lastname: req.lastname,
},
};
await DamageReportCommandHandler.update(updateDamageReport);
res.sendStatus(204);
}

View file

@ -0,0 +1,133 @@
import { Request, Response } from "express";
import EquipmentService from "../../../service/unit/equipment/equipmentService";
import EquipmentFactory from "../../../factory/admin/unit/equipment/equipment";
import {
CreateEquipmentCommand,
DeleteEquipmentCommand,
UpdateEquipmentCommand,
} from "../../../command/unit/equipment/equipmentCommand";
import EquipmentCommandHandler from "../../../command/unit/equipment/equipmentCommandHandler";
/**
* @description get all equipments
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllEquipments(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i);
let [equipments, total] = await EquipmentService.getAll({ offset, count, search, noLimit, ids });
res.json({
equipments: EquipmentFactory.mapToBase(equipments),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get equipment by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getEquipmentById(req: Request, res: Response): Promise<any> {
const equipmentId = req.params.id;
let equipment = await EquipmentService.getById(equipmentId);
res.json(EquipmentFactory.mapToSingle(equipment));
}
/**
* @description get equipment by Ids
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getEquipmentsByIds(req: Request, res: Response): Promise<any> {
let ids = req.body.ids as Array<string>;
let [equipments, total] = await EquipmentService.getAll({ noLimit: true, ids });
res.json({
equipments: EquipmentFactory.mapToBase(equipments),
total: total,
offset: 0,
count: total,
});
}
/**
* @description create equipment
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createEquipment(req: Request, res: Response): Promise<any> {
const name = req.body.name;
const code = req.body.code || null;
const location = req.body.location;
const commissioned = req.body.commissioned;
const equipmentTypeId = req.body.equipmentTypeId;
let createEquipment: CreateEquipmentCommand = {
code,
name,
location,
commissioned,
equipmentTypeId,
};
let equipmentId = await EquipmentCommandHandler.create(createEquipment);
res.status(200).send(equipmentId);
}
/**
* @description update equipment by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateEquipmentById(req: Request, res: Response): Promise<any> {
const equipmentId = req.params.id;
const name = req.body.name;
const code = req.body.code || null;
const location = req.body.location;
const commissioned = req.body.commissioned;
const decommissioned = req.body.decommissioned || null;
let updateEquipment: UpdateEquipmentCommand = {
id: equipmentId,
name,
code,
location,
commissioned,
decommissioned,
};
await EquipmentCommandHandler.update(updateEquipment);
res.sendStatus(204);
}
/**
* @description delete equipment by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteEquipmentById(req: Request, res: Response): Promise<any> {
const equipmentId = req.params.id;
let deleteEquipment: DeleteEquipmentCommand = {
id: equipmentId,
};
await EquipmentCommandHandler.delete(deleteEquipment);
res.sendStatus(204);
}

View file

@ -0,0 +1,101 @@
import { Request, Response } from "express";
import EquipmentTypeService from "../../../service/unit/equipment/equipmentTypeService";
import EquipmentTypeFactory from "../../../factory/admin/unit/equipment/equipmentType";
import {
CreateEquipmentTypeCommand,
DeleteEquipmentTypeCommand,
UpdateEquipmentTypeCommand,
} from "../../../command/unit/equipment/equipmentTypeCommand";
import EquipmentTypeCommandHandler from "../../../command/unit/equipment/equipmentTypeCommandHandler";
/**
* @description get all equipmentTypes
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllEquipmentTypes(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let [equipmentTypes, total] = await EquipmentTypeService.getAll({ offset, count, search, noLimit });
res.json({
equipmentTypes: EquipmentTypeFactory.mapToBase(equipmentTypes),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get equipmentType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getEquipmentTypeById(req: Request, res: Response): Promise<any> {
const equipmentTypeId = req.params.id;
let equipmentType = await EquipmentTypeService.getById(equipmentTypeId);
res.json(EquipmentTypeFactory.mapToSingle(equipmentType));
}
/**
* @description create equipmentType
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createEquipmentType(req: Request, res: Response): Promise<any> {
const type = req.body.type;
const description = req.body.description;
let createEquipmentType: CreateEquipmentTypeCommand = {
type,
description,
};
let equipmentTypeId = await EquipmentTypeCommandHandler.create(createEquipmentType);
res.status(200).send(equipmentTypeId);
}
/**
* @description update equipmentType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateEquipmentTypeById(req: Request, res: Response): Promise<any> {
const equipmentTypeId = req.params.id;
const type = req.body.type;
const description = req.body.description;
let updateEquipmentType: UpdateEquipmentTypeCommand = {
id: equipmentTypeId,
type,
description,
};
await EquipmentTypeCommandHandler.update(updateEquipmentType);
res.sendStatus(204);
}
/**
* @description delete equipmentType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteEquipmentTypeById(req: Request, res: Response): Promise<any> {
const equipmentTypeId = req.params.id;
let deleteEquipmentType: DeleteEquipmentTypeCommand = {
id: equipmentTypeId,
};
await EquipmentTypeCommandHandler.delete(deleteEquipmentType);
res.sendStatus(204);
}

View file

@ -0,0 +1,402 @@
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 { FileSystemHelper } from "../../../helpers/fileSystemHelper";
import { PdfExport } from "../../../helpers/pdfExport";
import { PDFDocument } from "pdf-lib";
import sharp from "sharp";
import InspectionPointResultService from "../../../service/unit/inspection/inspectionPointResultService";
import InspectionPlanService from "../../../service/unit/inspection/inspectionPlanService";
/**
* @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;
let inspectionPlan = await InspectionPlanService.getById(inspectionPlanId);
if (inspectionPlan.inspectionInterval && !nextInspection)
throw new BadRequestException("inspection has to have nextInspection date");
if (assigned != "equipment" && assigned != "vehicle" && assigned != "wearable")
throw new BadRequestException("set assigned to equipment or vehicle or wearable");
if (relatedId == null) throw new BadRequestException("provide related 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.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 ? "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);
}
/**
* @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);
}

View file

@ -0,0 +1,216 @@
import { Request, Response } from "express";
import InspectionPlanService from "../../../service/unit/inspection/inspectionPlanService";
import InspectionPlanFactory from "../../../factory/admin/unit/inspection/inspectionPlan";
import {
CreateInspectionPlanCommand,
DeleteInspectionPlanCommand,
UpdateInspectionPlanCommand,
} from "../../../command/unit/inspection/inspectionPlanCommand";
import InspectionPlanCommandHandler from "../../../command/unit/inspection/inspectionPlanCommandHandler";
import BadRequestException from "../../../exceptions/badRequestException";
import TypeTester from "../../../helpers/typeTester";
import InspectionPointService from "../../../service/unit/inspection/inspectionPointService";
import InspectionPointFactory from "../../../factory/admin/unit/inspection/inspectionPoint";
import InspectionService from "../../../service/unit/inspection/inspectionService";
import InspectionVersionedPlanCommandHandler from "../../../command/unit/inspection/inspectionVersionedPlanCommandHandler";
import InspectionPointCommandHandler from "../../../command/unit/inspection/inspectionPointCommandHandler";
/**
* @description get all inspectionPlans
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllInspectionPlans(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i);
let [inspectionPlans, total] = await InspectionPlanService.getAll({
offset,
count,
search,
noLimit,
ids,
});
res.json({
inspectionPlans: InspectionPlanFactory.mapToBase(inspectionPlans),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get all inspectionPlans
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllInspectionPlansForRelated(req: Request, res: Response): Promise<any> {
let relation = req.params.related as "vehicleType" | "equipmentType" | "wearableType";
let relationTypeId = req.params.relatedTypeId as string;
let offset = parseInt((req.query.offset as string) ?? "0");
let count = parseInt((req.query.count as string) ?? "25");
let search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i);
let where;
if (relation == "equipmentType") {
where = { equipmentTypeId: relationTypeId };
} else if (relation == "vehicleType") {
where = { vehicleTypeId: relationTypeId };
} else {
where = { wearableTypeId: relationTypeId };
}
let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated(where, {
offset,
count,
search,
noLimit,
ids,
});
res.json({
inspectionPlans: inspectionPlans,
total: total,
offset: offset,
count: count,
});
}
/**
* @description get inspectionPoints by planid
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getInspectionPointsByPlanId(req: Request, res: Response): Promise<any> {
const inspectionPlanId = req.params.id;
let inspectionPlan = await InspectionPlanService.getById(inspectionPlanId);
if (!inspectionPlan.latestVersionedPlan) {
res.json([]);
} else {
let inspectionPoints = await InspectionPointService.getAllForVersionedPlan(inspectionPlan.latestVersionedPlan.id);
res.json(InspectionPointFactory.mapToBase(inspectionPoints));
}
}
/**
* @description get inspectionPlan by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getInspectionPlanById(req: Request, res: Response): Promise<any> {
const inspectionPlanId = req.params.id;
let inspectionPlan = await InspectionPlanService.getById(inspectionPlanId);
res.json(InspectionPlanFactory.mapToSingle(inspectionPlan));
}
/**
* @description create inspectionPlan
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createInspectionPlan(req: Request, res: Response): Promise<any> {
const title = req.body.title;
const inspectionInterval = req.body.inspectionInterval || null;
const remindTime = req.body.remindTime || null;
const relatedId = req.body.relatedId;
const assigned = req.body.assigned;
TypeTester.testPlanTimeDefinition(inspectionInterval, { key: "inspectionInterval", throwErr: true, allowNull: true });
TypeTester.testPlanTimeDefinition(remindTime, { key: "inspectionInterval", throwErr: true, allowNull: true });
if (assigned != "equipment" && assigned != "vehicle" && assigned != "wearable")
throw new BadRequestException("set assigned to equipmenttype or vehicletype or wearabletype");
if (relatedId == null) throw new BadRequestException("provide related equipmenttype or vehicletype or wearabletype");
let createInspectionPlan: CreateInspectionPlanCommand = {
title,
inspectionInterval,
remindTime,
relatedId,
assigned,
};
let inspectionPlanId = await InspectionPlanCommandHandler.create(createInspectionPlan);
res.status(200).send(inspectionPlanId);
}
/**
* @description update inspectionPlan by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateInspectionPlanById(req: Request, res: Response): Promise<any> {
const inspectionPlanId = req.params.id;
const title = req.body.title;
const inspectionInterval = req.body.inspectionInterval || null;
const remindTime = req.body.remindTime || null;
TypeTester.testPlanTimeDefinition(inspectionInterval, { key: "inspectionInterval", throwErr: true, allowNull: true });
TypeTester.testPlanTimeDefinition(remindTime, { key: "inspectionInterval", throwErr: true, allowNull: true });
let updateInspectionPlan: UpdateInspectionPlanCommand = {
id: inspectionPlanId,
title,
inspectionInterval,
remindTime,
};
await InspectionPlanCommandHandler.update(updateInspectionPlan);
res.sendStatus(204);
}
/**
* @description get inspectionPoints by planid
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateInspectionPointsByPlanId(req: Request, res: Response): Promise<any> {
const inspectionPlanId = req.params.id;
const inspectionPoints = req.body;
let inspectionPlan = await InspectionPlanService.getById(inspectionPlanId);
let usedVersionedPlan = inspectionPlan?.latestVersionedPlan?.id
? await InspectionService.usesVersionedInspectionPlan(inspectionPlan.latestVersionedPlan.id)
: true;
if (usedVersionedPlan) {
await InspectionVersionedPlanCommandHandler.create({ inspectionPlanId }, inspectionPoints);
} else {
await InspectionPointCommandHandler.sync(inspectionPlan.latestVersionedPlan.id, inspectionPoints);
}
res.sendStatus(204);
}
/**
* @description delete inspectionPlan by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteInspectionPlanById(req: Request, res: Response): Promise<any> {
const inspectionPlanId = req.params.id;
let deleteInspectionPlan: DeleteInspectionPlanCommand = {
id: inspectionPlanId,
};
await InspectionPlanCommandHandler.delete(deleteInspectionPlan);
res.sendStatus(204);
}

View file

@ -0,0 +1,119 @@
import { Request, Response } from "express";
import MaintenanceService from "../../../service/unit/maintenanceService";
import MaintenanceFactory from "../../../factory/admin/unit/maintenance";
import { CreateMaintenanceCommand, UpdateMaintenanceCommand } from "../../../command/unit/maintenanceCommand";
import MaintenanceCommandHandler from "../../../command/unit/maintenanceCommandHandler";
import BadRequestException from "../../../exceptions/badRequestException";
/**
* @description get all maintenances by status
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllMaintenancesByStatus(req: Request, res: Response): Promise<any> {
let done = req.query.done === "true";
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 [maintenances, total] = await MaintenanceService.getAllByDone(done, { offset, count, noLimit });
res.json({
maintenances: MaintenanceFactory.mapToBase(maintenances),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get all maintenances for related id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllMaintenancesForRelated(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 [maintenances, total] = await MaintenanceService.getAllForRelated(where, { offset, count, noLimit });
res.json({
maintenances: MaintenanceFactory.mapToBase(maintenances),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get maintenance by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getMaintenanceById(req: Request, res: Response): Promise<any> {
const maintenanceId = req.params.id;
let maintenance = await MaintenanceService.getById(maintenanceId);
res.json(MaintenanceFactory.mapToSingle(maintenance));
}
/**
* @description create maintenance
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createMaintenance(req: Request, res: Response): Promise<any> {
const description = req.body.description;
const affectedId = req.body.affectedId;
const affected = req.body.affected;
if (affected != "equipment" && affected != "vehicle" && affected != "wearable")
throw new BadRequestException("set assigned to equipment or vehicle or wearable");
let createMaintenance: CreateMaintenanceCommand = {
description,
affectedId,
affected,
};
let maintenanceId = await MaintenanceCommandHandler.create(createMaintenance);
res.status(200).send(maintenanceId);
}
/**
* @description update maintenance by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateMaintenanceById(req: Request, res: Response): Promise<any> {
const maintenanceId = req.params.id;
const description = req.body.description;
const status = req.body.status;
const done = req.body.done;
let updateMaintenance: UpdateMaintenanceCommand = {
id: maintenanceId,
description,
status,
done,
};
await MaintenanceCommandHandler.update(updateMaintenance);
res.sendStatus(204);
}

View file

@ -0,0 +1,173 @@
import { Request, Response } from "express";
import RepairService from "../../../service/unit/repairService";
import RepairFactory from "../../../factory/admin/unit/repair";
import {
CreateRepairCommand,
UpdateRepairCommand,
UpdateRepairStatusCommand,
} from "../../../command/unit/repairCommand";
import RepairCommandHandler from "../../../command/unit/repairCommandHandler";
import BadRequestException from "../../../exceptions/badRequestException";
import { FileSystemHelper } from "../../../helpers/fileSystemHelper";
import { UpdateDamageReportRelatedRepairCommand } from "../../../command/unit/damageReportCommand";
import DamageReportCommandHandler from "../../../command/unit/damageReportCommandHandler";
/**
* @description get all repairs by status
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllRepairsByStatus(req: Request, res: Response): Promise<any> {
let done = req.query.done === "true";
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 [repairs, total] = await RepairService.getAllByDone(done, { offset, count, noLimit });
res.json({
repairs: RepairFactory.mapToBase(repairs),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get all repairs for related id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllRepairsForRelated(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 [repairs, total] = await RepairService.getAllForRelated(where, { offset, count, noLimit });
res.json({
repairs: RepairFactory.mapToBase(repairs),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get repair by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getRepairById(req: Request, res: Response): Promise<any> {
const repairId = req.params.id;
let repair = await RepairService.getById(repairId);
res.json(RepairFactory.mapToSingle(repair));
}
/**
* @description create repair
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createRepair(req: Request, res: Response): Promise<any> {
const title = req.body.title;
const description = req.body.description;
const responsible = req.body.responsible;
const reports = req.body.reports;
const affectedId = req.body.affectedId;
const affected = req.body.affected;
if (affected != "equipment" && affected != "vehicle" && affected != "wearable")
throw new BadRequestException("set assigned to equipment or vehicle or wearable");
let createRepair: CreateRepairCommand = {
title,
description,
affectedId,
affected,
responsible,
reports,
};
let repairId = await RepairCommandHandler.create(createRepair);
res.status(200).send(repairId);
}
/**
* @description update repair by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateRepairById(req: Request, res: Response): Promise<any> {
const repairId = req.params.id;
const title = req.body.title;
const description = req.body.description;
const responsible = req.body.responsible;
let updateRepair: UpdateRepairCommand = {
id: repairId,
title,
description,
responsible,
};
await RepairCommandHandler.update(updateRepair);
res.sendStatus(204);
}
/**
* @description update repair by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateRepairReportsById(req: Request, res: Response): Promise<any> {
const repairId = req.params.id;
const reports = req.body.reports as Array<string>;
await DamageReportCommandHandler.updateRelatedMaintenanceMulti(repairId, reports);
res.sendStatus(204);
}
/**
* @description update repair by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateRepairStatusById(req: Request, res: Response): Promise<any> {
const repairId = req.params.id;
const status = req.body.status;
const done = req.body.done;
let updateRepair: UpdateRepairStatusCommand = {
id: repairId,
status,
done,
user: {
id: req.userId,
firstname: req.firstname,
lastname: req.lastname,
},
};
await RepairCommandHandler.updateStatus(updateRepair);
res.sendStatus(204);
}

View file

@ -0,0 +1,133 @@
import { Request, Response } from "express";
import VehicleService from "../../../service/unit/vehicle/vehicleService";
import VehicleFactory from "../../../factory/admin/unit/vehicle/vehicle";
import {
CreateVehicleCommand,
DeleteVehicleCommand,
UpdateVehicleCommand,
} from "../../../command/unit/vehicle/vehicleCommand";
import VehicleCommandHandler from "../../../command/unit/vehicle/vehicleCommandHandler";
/**
* @description get all vehicles
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllVehicles(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i);
let [vehicles, total] = await VehicleService.getAll({ offset, count, search, noLimit, ids });
res.json({
vehicles: VehicleFactory.mapToBase(vehicles),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get vehicle by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getVehicleById(req: Request, res: Response): Promise<any> {
const vehicleId = req.params.id;
let vehicle = await VehicleService.getById(vehicleId);
res.json(VehicleFactory.mapToSingle(vehicle));
}
/**
* @description get vehicle by Ids
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getVehiclesByIds(req: Request, res: Response): Promise<any> {
let ids = req.body.ids as Array<string>;
let [vehicles, total] = await VehicleService.getAll({ noLimit: true, ids });
res.json({
vehicles: VehicleFactory.mapToBase(vehicles),
total: total,
offset: 0,
count: total,
});
}
/**
* @description create vehicle
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createVehicle(req: Request, res: Response): Promise<any> {
const name = req.body.name;
const code = req.body.code || null;
const location = req.body.location;
const commissioned = req.body.commissioned;
const vehicleTypeId = req.body.vehicleTypeId;
let createVehicle: CreateVehicleCommand = {
code,
name,
location,
commissioned,
vehicleTypeId,
};
let vehicleId = await VehicleCommandHandler.create(createVehicle);
res.status(200).send(vehicleId);
}
/**
* @description update vehicle by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateVehicleById(req: Request, res: Response): Promise<any> {
const vehicleId = req.params.id;
const name = req.body.name;
const code = req.body.code || null;
const location = req.body.location;
const commissioned = req.body.commissioned;
const decommissioned = req.body.decommissioned || null;
let updateVehicle: UpdateVehicleCommand = {
id: vehicleId,
code,
name,
location,
commissioned,
decommissioned,
};
await VehicleCommandHandler.update(updateVehicle);
res.sendStatus(204);
}
/**
* @description delete vehicle by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteVehicleById(req: Request, res: Response): Promise<any> {
const vehicleId = req.params.id;
let deleteVehicle: DeleteVehicleCommand = {
id: vehicleId,
};
await VehicleCommandHandler.delete(deleteVehicle);
res.sendStatus(204);
}

View file

@ -0,0 +1,101 @@
import { Request, Response } from "express";
import VehicleTypeService from "../../../service/unit/vehicle/vehicleTypeService";
import VehicleTypeFactory from "../../../factory/admin/unit/vehicle/vehicleType";
import {
CreateVehicleTypeCommand,
DeleteVehicleTypeCommand,
UpdateVehicleTypeCommand,
} from "../../../command/unit/vehicle/vehicleTypeCommand";
import VehicleTypeCommandHandler from "../../../command/unit/vehicle/vehicleTypeCommandHandler";
/**
* @description get all vehicleTypes
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllVehicleTypes(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let [vehicleTypes, total] = await VehicleTypeService.getAll({ offset, count, search, noLimit });
res.json({
vehicleTypes: VehicleTypeFactory.mapToBase(vehicleTypes),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get vehicleType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getVehicleTypeById(req: Request, res: Response): Promise<any> {
const vehicleTypeId = req.params.id;
let vehicleType = await VehicleTypeService.getById(vehicleTypeId);
res.json(VehicleTypeFactory.mapToSingle(vehicleType));
}
/**
* @description create vehicleType
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createVehicleType(req: Request, res: Response): Promise<any> {
const type = req.body.type;
const description = req.body.description;
let createVehicleType: CreateVehicleTypeCommand = {
type,
description,
};
let vehicleTypeId = await VehicleTypeCommandHandler.create(createVehicleType);
res.status(200).send(vehicleTypeId);
}
/**
* @description update vehicleType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateVehicleTypeById(req: Request, res: Response): Promise<any> {
const vehicleTypeId = req.params.id;
const type = req.body.type;
const description = req.body.description;
let updateVehicleType: UpdateVehicleTypeCommand = {
id: vehicleTypeId,
type,
description,
};
await VehicleTypeCommandHandler.update(updateVehicleType);
res.sendStatus(204);
}
/**
* @description delete vehicleType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteVehicleTypeById(req: Request, res: Response): Promise<any> {
const vehicleTypeId = req.params.id;
let deleteVehicleType: DeleteVehicleTypeCommand = {
id: vehicleTypeId,
};
await VehicleTypeCommandHandler.delete(deleteVehicleType);
res.sendStatus(204);
}

View file

@ -0,0 +1,137 @@
import { Request, Response } from "express";
import WearableService from "../../../service/unit/wearable/wearableService";
import WearableFactory from "../../../factory/admin/unit/wearable/wearable";
import {
CreateWearableCommand,
DeleteWearableCommand,
UpdateWearableCommand,
} from "../../../command/unit/wearable/wearableCommand";
import WearableCommandHandler from "../../../command/unit/wearable/wearableCommandHandler";
/**
* @description get all wearables
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllWearables(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i);
let [wearables, total] = await WearableService.getAll({ offset, count, search, noLimit, ids });
res.json({
wearables: WearableFactory.mapToBase(wearables),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get wearable by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getWearableById(req: Request, res: Response): Promise<any> {
const wearableId = req.params.id;
let wearable = await WearableService.getById(wearableId);
res.json(WearableFactory.mapToSingle(wearable));
}
/**
* @description get wearable by Ids
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getWearablesByIds(req: Request, res: Response): Promise<any> {
let ids = req.body.ids as Array<string>;
let [wearables, total] = await WearableService.getAll({ noLimit: true, ids });
res.json({
wearables: WearableFactory.mapToBase(wearables),
total: total,
offset: 0,
count: total,
});
}
/**
* @description create wearable
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createWearable(req: Request, res: Response): Promise<any> {
const name = req.body.name;
const code = req.body.code || null;
const location = req.body.location;
const commissioned = req.body.commissioned;
const wearableTypeId = req.body.wearableTypeId;
const wearerId = req.body.wearerId || null;
let createWearable: CreateWearableCommand = {
code,
name,
location,
commissioned,
wearableTypeId,
wearerId,
};
let wearableId = await WearableCommandHandler.create(createWearable);
res.status(200).send(wearableId);
}
/**
* @description update wearable by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateWearableById(req: Request, res: Response): Promise<any> {
const wearableId = req.params.id;
const name = req.body.name;
const code = req.body.code || null;
const location = req.body.location;
const commissioned = req.body.commissioned;
const decommissioned = req.body.decommissioned || null;
const wearerId = req.body.wearerId || null;
let updateWearable: UpdateWearableCommand = {
id: wearableId,
code,
name,
location,
commissioned,
decommissioned,
wearerId,
};
await WearableCommandHandler.update(updateWearable);
res.sendStatus(204);
}
/**
* @description delete wearable by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteWearableById(req: Request, res: Response): Promise<any> {
const wearableId = req.params.id;
let deleteWearable: DeleteWearableCommand = {
id: wearableId,
};
await WearableCommandHandler.delete(deleteWearable);
res.sendStatus(204);
}

View file

@ -0,0 +1,101 @@
import { Request, Response } from "express";
import WearableTypeService from "../../../service/unit/wearable/wearableTypeService";
import WearableTypeFactory from "../../../factory/admin/unit/wearable/wearableType";
import {
CreateWearableTypeCommand,
DeleteWearableTypeCommand,
UpdateWearableTypeCommand,
} from "../../../command/unit/wearable/wearableTypeCommand";
import WearableTypeCommandHandler from "../../../command/unit/wearable/wearableTypeCommandHandler";
/**
* @description get all wearableTypes
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllWearableTypes(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 search = (req.query.search as string) ?? "";
let noLimit = req.query.noLimit === "true";
let [wearableTypes, total] = await WearableTypeService.getAll({ offset, count, search, noLimit });
res.json({
wearableTypes: WearableTypeFactory.mapToBase(wearableTypes),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get wearableType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getWearableTypeById(req: Request, res: Response): Promise<any> {
const wearableTypeId = req.params.id;
let wearableType = await WearableTypeService.getById(wearableTypeId);
res.json(WearableTypeFactory.mapToSingle(wearableType));
}
/**
* @description create wearableType
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createWearableType(req: Request, res: Response): Promise<any> {
const type = req.body.type;
const description = req.body.description;
let createWearableType: CreateWearableTypeCommand = {
type,
description,
};
let wearableTypeId = await WearableTypeCommandHandler.create(createWearableType);
res.status(200).send(wearableTypeId);
}
/**
* @description update wearableType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateWearableTypeById(req: Request, res: Response): Promise<any> {
const wearableTypeId = req.params.id;
const type = req.body.type;
const description = req.body.description;
let updateWearableType: UpdateWearableTypeCommand = {
id: wearableTypeId,
type,
description,
};
await WearableTypeCommandHandler.update(updateWearableType);
res.sendStatus(204);
}
/**
* @description delete wearableType by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteWearableTypeById(req: Request, res: Response): Promise<any> {
const wearableTypeId = req.params.id;
let deleteWearableType: DeleteWearableTypeCommand = {
id: wearableTypeId,
};
await WearableTypeCommandHandler.delete(deleteWearableType);
res.sendStatus(204);
}

View file

@ -9,6 +9,20 @@ import SettingHelper from "../helpers/settingsHelper";
import sharp from "sharp"; import sharp from "sharp";
import ico from "sharp-ico"; import ico from "sharp-ico";
import { FileSystemHelper } from "../helpers/fileSystemHelper"; import { FileSystemHelper } from "../helpers/fileSystemHelper";
import { SocketConnectionTypes } from "../enums/socketEnum";
import SocketServer from "../websocket";
import BadRequestException from "../exceptions/badRequestException";
import EquipmentService from "../service/unit/equipment/equipmentService";
import VehicleService from "../service/unit/vehicle/vehicleService";
import WearableService from "../service/unit/wearable/wearableService";
import EquipmentFactory from "../factory/admin/unit/equipment/equipment";
import VehicleFactory from "../factory/admin/unit/vehicle/vehicle";
import WearableFactory from "../factory/admin/unit/wearable/wearable";
import { MinifiedEquipmentViewModel } from "../viewmodel/admin/unit/equipment/equipment.models";
import { MinifiedVehicleViewModel } from "../viewmodel/admin/unit/vehicle/vehicle.models";
import { MinifiedWearableViewModel } from "../viewmodel/admin/unit/wearable/wearable.models";
import DamageReportCommandHandler from "../command/unit/damageReportCommandHandler";
import { CreateDamageReportCommand } from "../command/unit/damageReportCommand";
/** /**
* @description get all calendar items by types or nscdr * @description get all calendar items by types or nscdr
@ -54,6 +68,80 @@ export async function getCalendarItemsByTypes(req: Request, res: Response): Prom
} }
} }
/**
* @description check if scanner session exists
* @summary existance is checked by room exists
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function checkScannerRoomExists(req: Request, res: Response): Promise<any> {
let roomId = req.body.roomId;
const socketsInOtherRoom = await SocketServer.server.of(SocketConnectionTypes.scanner).in(roomId).fetchSockets();
const count = socketsInOtherRoom.length;
if (count != 0) {
res.sendStatus(204);
} else {
throw new BadRequestException("room does not exists");
}
}
/**
* @description get equipment, vehicle, wearable by code
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function searchStuffByCode(req: Request, res: Response): Promise<any> {
let code = req.query.code.toString();
let e = await EquipmentService.getAllByCode(code);
let v = await VehicleService.getAllByCode(code);
let w = await WearableService.getAllByCode(code);
res.json([
...EquipmentFactory.mapToBaseMinifed(e),
...VehicleFactory.mapToBaseMinifed(v),
...WearableFactory.mapToBaseMinifed(w),
]);
}
/**
* @description create damagereport to equipment, vehicle, wearable
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createDamageReport(req: Request, res: Response): Promise<any> {
const related = (req.body.related ? JSON.parse(req.body.related) : undefined) as
| undefined
| MinifiedEquipmentViewModel
| MinifiedVehicleViewModel
| MinifiedWearableViewModel;
const title = req.body.title;
const description = req.body.description;
const location = req.body.location;
const note = req.body.note;
const reportedBy = req.body.reportedBy;
const images = req.files as Express.Multer.File[];
let createDamageReport: CreateDamageReportCommand = {
title: title,
description: description,
location: location,
noteByReporter: note,
reportedBy: reportedBy,
images: images.map((i) => i.filename),
affectedId: related ? related.id : undefined,
affected: related ? related.assigned : undefined,
};
await DamageReportCommandHandler.create(createDamageReport);
res.sendStatus(204);
}
/** /**
* @description get configuration of UI * @description get configuration of UI
* @param req {Request} Express req object * @param req {Request} Express req object
@ -68,6 +156,7 @@ export async function getApplicationConfig(req: Request, res: Response): Promise
"club.website": SettingHelper.getSetting("club.website"), "club.website": SettingHelper.getSetting("club.website"),
"app.custom_login_message": SettingHelper.getSetting("app.custom_login_message"), "app.custom_login_message": SettingHelper.getSetting("app.custom_login_message"),
"app.show_link_to_calendar": SettingHelper.getSetting("app.show_link_to_calendar"), "app.show_link_to_calendar": SettingHelper.getSetting("app.show_link_to_calendar"),
"app.show_link_to_damagereport": SettingHelper.getSetting("app.show_link_to_damagereport"),
}; };
res.json(config); res.json(config);

View file

@ -20,6 +20,7 @@ import { member } from "./entity/club/member/member";
import { memberAwards } from "./entity/club/member/memberAwards"; import { memberAwards } from "./entity/club/member/memberAwards";
import { memberExecutivePositions } from "./entity/club/member/memberExecutivePositions"; import { memberExecutivePositions } from "./entity/club/member/memberExecutivePositions";
import { memberQualifications } from "./entity/club/member/memberQualifications"; import { memberQualifications } from "./entity/club/member/memberQualifications";
import { memberEducations } from "./entity/club/member/memberEducations";
import { membership } from "./entity/club/member/membership"; import { membership } from "./entity/club/member/membership";
import { protocol } from "./entity/club/protocol/protocol"; import { protocol } from "./entity/club/protocol/protocol";
import { protocolAgenda } from "./entity/club/protocol/protocolAgenda"; import { protocolAgenda } from "./entity/club/protocol/protocolAgenda";
@ -46,11 +47,26 @@ import { webapiPermission } from "./entity/management/webapi_permission";
import { salutation } from "./entity/configuration/salutation"; import { salutation } from "./entity/configuration/salutation";
import { setting } from "./entity/management/setting"; import { setting } from "./entity/management/setting";
import { education } from "./entity/configuration/education"; import { education } from "./entity/configuration/education";
import { memberEducations } from "./entity/club/member/memberEducations";
import { equipmentType } from "./entity/unit/equipment/equipmentType";
import { equipment } from "./entity/unit/equipment/equipment";
import { vehicleType } from "./entity/unit/vehicle/vehicleType";
import { vehicle } from "./entity/unit/vehicle/vehicle";
import { wearableType } from "./entity/unit/wearable/wearableType";
import { wearable } from "./entity/unit/wearable/wearable";
import { damageReport } from "./entity/unit/damageReport";
import { inspectionPlan } from "./entity/unit/inspection/inspectionPlan";
import { inspectionVersionedPlan } from "./entity/unit/inspection/inspectionVersionedPlan";
import { inspectionPoint } from "./entity/unit/inspection/inspectionPoint";
import { inspection } from "./entity/unit/inspection/inspection";
import { inspectionPointResult } from "./entity/unit/inspection/inspectionPointResult";
import { maintenance } from "./entity/unit/maintenance";
import { BackupAndResetDatabase1749296262915 } from "./migrations/1749296262915-BackupAndResetDatabase"; import { BackupAndResetDatabase1749296262915 } from "./migrations/1749296262915-BackupAndResetDatabase";
import { CreateSchema1749296280721 } from "./migrations/1749296280721-CreateSchema"; import { CreateSchema1749296280721 } from "./migrations/1749296280721-CreateSchema";
import { UpdateNewsletterQueryRelation1752502069178 } from "./migrations/1752502069178-updateNewsletterQueryRelation"; import { UpdateNewsletterQueryRelation1752502069178 } from "./migrations/1752502069178-updateNewsletterQueryRelation";
import { UnitBase1752914551204 } from "./migrations/1752914551204-UnitBase";
import { repair } from "./entity/unit/repair";
configCheck(); configCheck();
@ -108,10 +124,25 @@ const dataSource = new DataSource({
webapi, webapi,
webapiPermission, webapiPermission,
setting, setting,
equipmentType,
equipment,
vehicleType,
vehicle,
wearableType,
wearable,
damageReport,
maintenance,
repair,
inspectionPlan,
inspectionVersionedPlan,
inspectionPoint,
inspection,
inspectionPointResult,
], ],
migrations: [ migrations: [
BackupAndResetDatabase1749296262915, BackupAndResetDatabase1749296262915,
CreateSchema1749296280721, CreateSchema1749296280721,
UnitBase1752914551204,
UpdateNewsletterQueryRelation1752502069178, UpdateNewsletterQueryRelation1752502069178,
], ],
migrationsRun: true, migrationsRun: true,

View file

@ -0,0 +1,108 @@
import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import { equipment } from "./equipment/equipment";
import { wearable } from "./wearable/wearable";
import { vehicle } from "./vehicle/vehicle";
import { repair } from "./repair";
import { getTypeByORM } from "../../migrations/ormHelper";
import { user } from "../management/user";
@Entity()
export class damageReport {
@PrimaryGeneratedColumn("uuid")
id: string;
@CreateDateColumn()
reportedAt: Date;
@Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null })
closedAt?: Date;
@Column({ nullable: true, default: null })
closedById?: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
closedByString?: string;
@Column({ type: "varchar", length: 255 })
status: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "text" })
description: string;
@Column({ type: "text", nullable: true, default: null })
location: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
reportedBy: string;
@Column({ type: "text", nullable: true, default: null })
noteByReporter: string;
@Column({ type: "text", nullable: true, default: null })
noteByWorker: string;
@Column({
type: "text",
nullable: true,
default: null,
transformer: {
from(value: string): Array<string> {
return (value ?? "").split(",").filter((i) => !!i);
},
to(value: Array<string> = []): string {
return value.join(",");
},
},
})
images: string[];
@Column({ nullable: true, default: null })
equipmentId?: string;
@Column({ nullable: true, default: null })
vehicleId?: string;
@Column({ nullable: true, default: null })
wearableId?: string;
@Column({ nullable: true, default: null })
repairId?: string;
@ManyToOne(() => user, {
nullable: true,
onDelete: "SET NULL",
onUpdate: "RESTRICT",
})
closedBy?: user;
@ManyToOne(() => equipment, (e) => e.reports, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
equipment?: equipment;
@ManyToOne(() => vehicle, (v) => v.reports, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
vehicle?: vehicle;
@ManyToOne(() => wearable, (w) => w.reports, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
wearable?: wearable;
@ManyToOne(() => repair, (m) => m.reports, {
nullable: true,
onDelete: "SET NULL",
onUpdate: "RESTRICT",
})
repair?: repair;
}

View file

@ -0,0 +1,50 @@
import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { getTypeByORM } from "../../../migrations/ormHelper";
import { equipmentType } from "./equipmentType";
import { damageReport } from "../damageReport";
import { inspection } from "../inspection/inspection";
import { maintenance } from "../maintenance";
import { repair } from "../repair";
@Entity()
export class equipment {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null, unique: true })
code?: string;
@Column({ type: "varchar", length: 255 })
name: string;
@Column({ type: "varchar", length: 255 })
location: string;
@Column({ type: getTypeByORM("date").type as ColumnType })
commissioned: Date;
@Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null })
decommissioned?: Date;
@Column()
equipmentTypeId: string;
@ManyToOne(() => equipmentType, {
nullable: false,
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
})
equipmentType: equipmentType;
@OneToMany(() => damageReport, (d) => d.equipment, { cascade: ["insert"] })
reports: damageReport[];
@OneToMany(() => repair, (d) => d.equipment, { cascade: ["insert"] })
repairs: repair[];
@OneToMany(() => maintenance, (m) => m.equipment, { cascade: ["insert"] })
maintenances: maintenance[];
@OneToMany(() => inspection, (i) => i.equipment, { cascade: ["insert"] })
inspections: inspection[];
}

View file

@ -0,0 +1,23 @@
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { equipment } from "./equipment";
import { inspectionPlan } from "../inspection/inspectionPlan";
@Entity()
export class equipmentType {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255, unique: true })
type: string;
@Column({ type: "text", nullable: true })
description: string;
@OneToMany(() => equipment, (e) => e.equipmentType, { cascade: ["insert"] })
equipment: equipment[];
@OneToMany(() => inspectionPlan, (ip) => ip.equipmentType, { cascade: ["insert"] })
inspectionPlans: inspectionPlan[];
equipmentCount: number;
}

View file

@ -0,0 +1,96 @@
import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { inspectionPlan } from "./inspectionPlan";
import { inspectionVersionedPlan } from "./inspectionVersionedPlan";
import { getTypeByORM } from "../../../migrations/ormHelper";
import { vehicle } from "../vehicle/vehicle";
import { equipment } from "../equipment/equipment";
import { inspectionPointResult } from "./inspectionPointResult";
import { wearable } from "../wearable/wearable";
import { user } from "../../management/user";
@Entity()
export class inspection {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "text" })
context: string;
@CreateDateColumn()
createdAt: Date;
@Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null })
finishedAt?: Date;
@Column({ nullable: true, default: null })
finishedById?: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
finishedByString?: string;
@Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null })
nextInspection?: Date;
@Column({ type: "boolean", default: false })
hasNewer: boolean;
@Column()
inspectionPlanId: string;
@Column()
inspectionVersionedPlanId: string;
@Column({ nullable: true, default: null })
equipmentId?: string;
@Column({ nullable: true, default: null })
vehicleId?: string;
@Column({ nullable: true, default: null })
wearableId?: string;
@ManyToOne(() => user, {
nullable: true,
onDelete: "SET NULL",
onUpdate: "RESTRICT",
})
finishedBy?: user;
@ManyToOne(() => inspectionPlan, {
nullable: false,
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
})
inspectionPlan: inspectionPlan;
@ManyToOne(() => inspectionVersionedPlan, {
nullable: false,
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
})
inspectionVersionedPlan: inspectionVersionedPlan;
@ManyToOne(() => equipment, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
equipment: equipment;
@ManyToOne(() => vehicle, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
vehicle: vehicle;
@ManyToOne(() => wearable, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
wearable: wearable;
@OneToMany(() => inspectionPointResult, (ipr) => ipr.inspection, { cascade: ["insert"] })
pointResults: inspectionPointResult[];
}

View file

@ -0,0 +1,61 @@
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspection/inspectionPlan.models";
import { inspectionVersionedPlan } from "./inspectionVersionedPlan";
import { equipmentType } from "../equipment/equipmentType";
import { vehicleType } from "../vehicle/vehicleType";
import { wearableType } from "../wearable/wearableType";
@Entity()
export class inspectionPlan {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
inspectionInterval?: PlanTimeDefinition;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
remindTime?: PlanTimeDefinition;
@CreateDateColumn()
createdAt: Date;
@Column({ nullable: true, default: null })
equipmentTypeId?: string;
@Column({ nullable: true, default: null })
vehicleTypeId?: string;
@Column({ nullable: true, default: null })
wearableTypeId?: string;
@ManyToOne(() => equipmentType, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
equipmentType?: equipmentType;
@ManyToOne(() => vehicleType, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
vehicleType?: vehicleType;
@ManyToOne(() => wearableType, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
wearableType?: wearableType;
@OneToMany(() => inspectionVersionedPlan, (ivp) => ivp.inspectionPlan, {
cascade: ["insert"],
})
versionedPlans: inspectionVersionedPlan[];
latestVersionedPlan?: inspectionVersionedPlan;
}

View file

@ -0,0 +1,51 @@
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, Unique } from "typeorm";
import { InspectionPointEnum } from "../../../enums/inspectionEnum";
import { inspectionVersionedPlan } from "./inspectionVersionedPlan";
@Entity()
export class inspectionPoint {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "text" })
description: string;
@Column({
type: "varchar",
length: 255,
transformer: {
to(value: InspectionPointEnum) {
return value.toString();
},
from(value: string) {
return InspectionPointEnum[value as keyof typeof InspectionPointEnum];
},
},
})
type: InspectionPointEnum;
@Column({ type: "int", nullable: true, default: null })
min?: number;
@Column({ type: "int", nullable: true, default: null })
max?: number;
@Column({ type: "varchar", length: 255, default: null })
others?: string;
@Column({ type: "int", default: 0 })
sort: number;
@Column()
versionedPlanId: string;
@ManyToOne(() => inspectionVersionedPlan, {
nullable: false,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
versionedPlan: inspectionVersionedPlan;
}

View file

@ -0,0 +1,29 @@
import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm";
import { inspection } from "./inspection";
import { inspectionPoint } from "./inspectionPoint";
@Entity()
export class inspectionPointResult {
@PrimaryColumn()
inspectionId: string;
@PrimaryColumn()
inspectionPointId: string;
@Column({ type: "text" })
value: string;
@ManyToOne(() => inspection, {
nullable: false,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
inspection: inspection;
@ManyToOne(() => inspectionPoint, {
nullable: false,
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
})
inspectionPoint: inspectionPoint;
}

View file

@ -0,0 +1,31 @@
import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique } from "typeorm";
import { inspectionPlan } from "./inspectionPlan";
import { inspectionPoint } from "./inspectionPoint";
@Entity()
@Unique("unique_version", ["version", "inspectionPlanId"])
export class inspectionVersionedPlan {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "int", default: 0 })
version: number;
@CreateDateColumn()
createdAt: Date;
@Column()
inspectionPlanId: string;
@ManyToOne(() => inspectionPlan, {
nullable: false,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
inspectionPlan: inspectionPlan;
@OneToMany(() => inspectionPoint, (ip) => ip.versionedPlan, {
cascade: ["insert"],
})
inspectionPoints: inspectionPoint[];
}

View file

@ -0,0 +1,92 @@
import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { equipment } from "./equipment/equipment";
import { wearable } from "./wearable/wearable";
import { vehicle } from "./vehicle/vehicle";
import { damageReport } from "./damageReport";
import { getTypeByORM } from "../../migrations/ormHelper";
import { user } from "../management/user";
@Entity()
export class maintenance {
@PrimaryGeneratedColumn("uuid")
id: string;
@CreateDateColumn()
createdAt: Date;
@Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null })
finishedAt?: Date;
@Column({ nullable: true, default: null })
finishedById?: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
finishedByString?: string;
@Column({ type: "varchar", length: 255 })
status: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "text" })
description: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
responsible: string;
@Column({
type: "text",
nullable: true,
default: null,
transformer: {
from(value: string): Array<string> {
return (value ?? "").split(",").filter((i) => !!i);
},
to(value: Array<string> = []): string {
return value.join(",");
},
},
})
images: string[];
@Column({ type: "varchar", length: 255, nullable: true, default: null })
reportDocument?: string;
@Column({ nullable: true, default: null })
equipmentId?: string;
@Column({ nullable: true, default: null })
vehicleId?: string;
@Column({ nullable: true, default: null })
wearableId?: string;
@ManyToOne(() => user, {
nullable: true,
onDelete: "SET NULL",
onUpdate: "RESTRICT",
})
finishedBy?: user;
@ManyToOne(() => equipment, (e) => e.maintenances, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
equipment?: equipment;
@ManyToOne(() => vehicle, (v) => v.maintenances, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
vehicle?: vehicle;
@ManyToOne(() => wearable, (w) => w.maintenances, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
wearable?: wearable;
}

95
src/entity/unit/repair.ts Normal file
View file

@ -0,0 +1,95 @@
import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { equipment } from "./equipment/equipment";
import { wearable } from "./wearable/wearable";
import { vehicle } from "./vehicle/vehicle";
import { damageReport } from "./damageReport";
import { getTypeByORM } from "../../migrations/ormHelper";
import { user } from "../management/user";
@Entity()
export class repair {
@PrimaryGeneratedColumn("uuid")
id: string;
@CreateDateColumn()
createdAt: Date;
@Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null })
finishedAt?: Date;
@Column({ nullable: true, default: null })
finishedById?: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
finishedByString?: string;
@Column({ type: "varchar", length: 255 })
status: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "text" })
description: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null })
responsible: string;
@Column({
type: "text",
nullable: true,
default: null,
transformer: {
from(value: string): Array<string> {
return (value ?? "").split(",").filter((i) => !!i);
},
to(value: Array<string> = []): string {
return value.join(",");
},
},
})
images: string[];
@Column({ type: "varchar", length: 255, nullable: true, default: null })
reportDocument?: string;
@Column({ nullable: true, default: null })
equipmentId?: string;
@Column({ nullable: true, default: null })
vehicleId?: string;
@Column({ nullable: true, default: null })
wearableId?: string;
@ManyToOne(() => user, {
nullable: true,
onDelete: "SET NULL",
onUpdate: "RESTRICT",
})
finishedBy?: user;
@ManyToOne(() => equipment, (e) => e.maintenances, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
equipment?: equipment;
@ManyToOne(() => vehicle, (v) => v.maintenances, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
vehicle?: vehicle;
@ManyToOne(() => wearable, (w) => w.maintenances, {
nullable: true,
onDelete: "CASCADE",
onUpdate: "RESTRICT",
})
wearable?: wearable;
@OneToMany(() => damageReport, (dr) => dr.repair)
reports: damageReport[];
}

View file

@ -0,0 +1,50 @@
import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { getTypeByORM } from "../../../migrations/ormHelper";
import { vehicleType } from "./vehicleType";
import { damageReport } from "../damageReport";
import { inspection } from "../inspection/inspection";
import { maintenance } from "../maintenance";
import { repair } from "../repair";
@Entity()
export class vehicle {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null, unique: true })
code?: string;
@Column({ type: "varchar", length: 255 })
name: string;
@Column({ type: "varchar", length: 255 })
location: string;
@Column({ type: getTypeByORM("date").type as ColumnType })
commissioned: Date;
@Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null })
decommissioned?: Date;
@Column()
vehicleTypeId: string;
@ManyToOne(() => vehicleType, {
nullable: false,
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
})
vehicleType: vehicleType;
@OneToMany(() => damageReport, (d) => d.vehicle, { cascade: ["insert"] })
reports: damageReport[];
@OneToMany(() => repair, (d) => d.vehicle, { cascade: ["insert"] })
repairs: repair[];
@OneToMany(() => maintenance, (m) => m.vehicle, { cascade: ["insert"] })
maintenances: maintenance[];
@OneToMany(() => inspection, (i) => i.vehicle, { cascade: ["insert"] })
inspections: inspection[];
}

View file

@ -0,0 +1,23 @@
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { vehicle } from "./vehicle";
import { inspectionPlan } from "../inspection/inspectionPlan";
@Entity()
export class vehicleType {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255, unique: true })
type: string;
@Column({ type: "text", nullable: true })
description: string;
@OneToMany(() => vehicle, (e) => e.vehicleType, { cascade: ["insert"] })
vehicle: vehicle[];
@OneToMany(() => inspectionPlan, (ip) => ip.vehicleType, { cascade: ["insert"] })
inspectionPlans: inspectionPlan[];
vehicleCount: number;
}

View file

@ -0,0 +1,61 @@
import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { getTypeByORM } from "../../../migrations/ormHelper";
import { wearableType } from "./wearableType";
import { damageReport } from "../damageReport";
import { member } from "../../club/member/member";
import { inspection } from "../inspection/inspection";
import { maintenance } from "../maintenance";
import { repair } from "../repair";
@Entity()
export class wearable {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255, nullable: true, default: null, unique: true })
code?: string;
@Column({ type: "varchar", length: 255 })
name: string;
@Column({ type: "varchar", length: 255 })
location: string;
@Column({ type: getTypeByORM("date").type as ColumnType })
commissioned: Date;
@Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null })
decommissioned?: Date;
@Column()
wearableTypeId: string;
@Column({ nullable: true, default: null })
wearerId?: string;
@ManyToOne(() => wearableType, {
nullable: false,
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
})
wearableType: wearableType;
@ManyToOne(() => member, {
nullable: true,
onDelete: "SET NULL",
onUpdate: "RESTRICT",
})
wearer?: member;
@OneToMany(() => damageReport, (d) => d.wearable, { cascade: ["insert"] })
reports: damageReport[];
@OneToMany(() => repair, (d) => d.wearable, { cascade: ["insert"] })
repairs: repair[];
@OneToMany(() => maintenance, (m) => m.wearable, { cascade: ["insert"] })
maintenances: maintenance[];
@OneToMany(() => inspection, (i) => i.wearable, { cascade: ["insert"] })
inspections: inspection[];
}

View file

@ -0,0 +1,23 @@
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { wearable as wearable } from "./wearable";
import { inspectionPlan } from "../inspection/inspectionPlan";
@Entity()
export class wearableType {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({ type: "varchar", length: 255, unique: true })
type: string;
@Column({ type: "text", nullable: true })
description: string;
@OneToMany(() => wearable, (e) => e.wearableType, { cascade: ["insert"] })
wearable: wearable[];
@OneToMany(() => inspectionPlan, (ip) => ip.wearableType, { cascade: ["insert"] })
inspectionPlans: inspectionPlan[];
wearableCount: number;
}

View file

@ -0,0 +1,6 @@
export enum InspectionPointEnum {
oknok = "oknok",
text = "text",
number = "number",
file = "file",
}

4
src/enums/socketEnum.ts Normal file
View file

@ -0,0 +1,4 @@
export enum SocketConnectionTypes {
scanner = "/scanner",
pscanner = "/public_scanner",
}

View file

@ -15,7 +15,7 @@ export default abstract class MemberFactory {
public static mapToSingle(record: member): MemberViewModel { public static mapToSingle(record: member): MemberViewModel {
return { return {
id: record?.id, id: record?.id,
salutation: SalutationFactory.mapToSingle(record?.salutation), salutation: record?.salutation ? SalutationFactory.mapToSingle(record?.salutation) : null,
firstname: record?.firstname, firstname: record?.firstname,
lastname: record?.lastname, lastname: record?.lastname,
nameaffix: record?.nameaffix, nameaffix: record?.nameaffix,

View file

@ -0,0 +1,69 @@
import { damageReport } from "../../../entity/unit/damageReport";
import { DamageReportAssigned, DamageReportViewModel } from "../../../viewmodel/admin/unit/damageReport.models";
import EquipmentFactory from "./equipment/equipment";
import MaintenanceFactory from "./maintenance";
import RepairFactory from "./repair";
import VehicleFactory from "./vehicle/vehicle";
import WearableFactory from "./wearable/wearable";
export default abstract class DamageReportFactory {
/**
* @description map record to damageReport
* @param {damageReport} record
* @returns {DamageReportViewModel}
*/
public static mapToSingle(record: damageReport): DamageReportViewModel {
let assigned: DamageReportAssigned;
if (record?.equipmentId) {
assigned = {
relatedId: record.equipmentId,
assigned: "equipment",
related: record.equipment ? EquipmentFactory.mapToSingle(record.equipment) : undefined,
};
} else if (record?.vehicleId) {
assigned = {
relatedId: record.vehicleId,
assigned: "vehicle",
related: record.vehicle ? VehicleFactory.mapToSingle(record.vehicle) : undefined,
};
} else if (record?.wearableId) {
assigned = {
relatedId: record.wearableId,
assigned: "wearable",
related: record.wearable ? WearableFactory.mapToSingle(record.wearable) : undefined,
};
} else {
assigned = {
relatedId: undefined,
assigned: undefined,
related: undefined,
};
}
return {
id: record.id,
reportedAt: record.reportedAt,
status: record.status,
closedAt: record.closedAt,
closedBy: record?.closedBy ? record.closedBy.firstname + " " + record.closedBy.lastname : record.closedByString,
title: record.title,
description: record.description,
location: record.location,
noteByReporter: record.noteByReporter,
noteByWorker: record.noteByWorker,
images: record.images,
reportedBy: record?.reportedBy,
...assigned,
repair: record.repair ? RepairFactory.mapToSingle(record.repair) : null,
};
}
/**
* @description map records to damageReport
* @param {Array<damageReport>} records
* @returns {Array<DamageReportViewModel>}
*/
public static mapToBase(records: Array<damageReport>): Array<DamageReportViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,59 @@
import { equipment } from "../../../../entity/unit/equipment/equipment";
import {
EquipmentViewModel,
MinifiedEquipmentViewModel,
} from "../../../../viewmodel/admin/unit/equipment/equipment.models";
import EquipmentTypeFactory from "./equipmentType";
export default abstract class EquipmentFactory {
/**
* @description map record to equipment
* @param {equipment} record
* @returns {EquipmentViewModel}
*/
public static mapToSingle(record: equipment): EquipmentViewModel {
return {
id: record.id,
code: record?.code,
name: record.name,
location: record.location,
commissioned: record.commissioned,
decommissioned: record?.decommissioned,
equipmentTypeId: record?.equipmentTypeId,
equipmentType: record?.equipmentType ? EquipmentTypeFactory.mapToSingle(record.equipmentType) : null,
};
}
/**
* @description map records to equipment
* @param {Array<equipment>} records
* @returns {Array<EquipmentViewModel>}
*/
public static mapToBase(records: Array<equipment>): Array<EquipmentViewModel> {
return records.map((r) => this.mapToSingle(r));
}
/**
* @description map record to minifed equipment
* @param {equipment} record
* @returns {MinifiedEquipmentViewModel}
*/
public static mapToSingleMinified(record: equipment): MinifiedEquipmentViewModel {
return {
id: record.id,
code: record?.code,
name: record.name,
type: record?.equipmentType.type,
assigned: "equipment",
};
}
/**
* @description map records to minified equipment
* @param {Array<equipment>} records
* @returns {Array<MinifiedEquipmentViewModel>}
*/
public static mapToBaseMinifed(records: Array<equipment>): Array<MinifiedEquipmentViewModel> {
return records.map((r) => this.mapToSingleMinified(r));
}
}

View file

@ -0,0 +1,27 @@
import { equipmentType } from "../../../../entity/unit/equipment/equipmentType";
import { EquipmentTypeViewModel } from "../../../../viewmodel/admin/unit/equipment/equipmentType.models";
export default abstract class EquipmentTypeFactory {
/**
* @description map record to equipmentType
* @param {equipmentType} record
* @returns {EquipmentTypeViewModel}
*/
public static mapToSingle(record: equipmentType): EquipmentTypeViewModel {
return {
id: record.id,
type: record.type,
description: record.description,
equipmentCount: record.equipmentCount,
};
}
/**
* @description map records to equipmentType
* @param {Array<equipmentType>} records
* @returns {Array<EquipmentTypeViewModel>}
*/
public static mapToBase(records: Array<equipmentType>): Array<EquipmentTypeViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,145 @@
import { inspection } from "../../../../entity/unit/inspection/inspection";
import {
InspectionNextViewModel,
InspectionRelated,
InspectionViewModel,
MinifiedInspectionViewModel,
} from "../../../../viewmodel/admin/unit/inspection/inspection.models";
import EquipmentFactory from "../equipment/equipment";
import VehicleFactory from "../vehicle/vehicle";
import WearableFactory from "../wearable/wearable";
import InspectionPlanFactory from "./inspectionPlan";
import InspectionPointResultFactory from "./inspectionPointResult";
import InspectionVersionedPlanFactory from "./inspectionVersionedPlan";
export default abstract class InspectionFactory {
/**
* @description map record to inspection
* @param {inspection} record
* @returns {InspectionViewModel}
*/
public static mapRelated(record: inspection): InspectionRelated {
let related: InspectionRelated;
if (record?.equipmentId) {
related = {
relatedId: record.equipmentId,
assigned: "equipment",
related: record.equipment ? EquipmentFactory.mapToSingle(record.equipment) : undefined,
};
} else if (record?.vehicleId) {
related = {
relatedId: record.vehicleId,
assigned: "vehicle",
related: record.vehicle ? VehicleFactory.mapToSingle(record.vehicle) : undefined,
};
} else if (record?.wearableId) {
related = {
relatedId: record.wearableId,
assigned: "wearable",
related: record.wearable ? WearableFactory.mapToSingle(record.wearable) : undefined,
};
} else {
related = {
relatedId: undefined,
assigned: undefined,
related: undefined,
};
}
return related;
}
/**
* @description map record to inspection
* @param {inspection} record
* @returns {InspectionViewModel}
*/
public static mapToSingle(record: inspection): InspectionViewModel {
let related = this.mapRelated(record);
return {
id: record.id,
inspectionPlanId: record.inspectionPlanId,
inspectionPlan: InspectionPlanFactory.mapToSingle(record.inspectionPlan),
inspectionVersionedPlanId: record.inspectionVersionedPlanId,
inspectionVersionedPlan: InspectionVersionedPlanFactory.mapToSingle(record.inspectionVersionedPlan),
context: record.context,
created: record.createdAt,
finishedAt: record?.finishedAt,
finishedBy: record?.finishedBy
? record.finishedBy.firstname + " " + record.finishedBy.lastname
: record.finishedByString,
isOpen: record?.finishedAt == undefined,
nextInspection: record?.nextInspection,
checks: InspectionPointResultFactory.mapToBase(record.pointResults),
...related,
};
}
/**
* @description map records to inspection
* @param {Array<inspection>} records
* @returns {Array<InspectionViewModel>}
*/
public static mapToBase(records: Array<inspection>): Array<InspectionViewModel> {
return records.map((r) => this.mapToSingle(r));
}
/**
* @description map record to minified inspection
* @param {inspection} record
* @returns {MinifiedInspectionViewModel}
*/
public static mapToSingleMinified(record: inspection): MinifiedInspectionViewModel {
let related = this.mapRelated(record);
return {
id: record.id,
inspectionPlanId: record.inspectionPlanId,
inspectionPlan: InspectionPlanFactory.mapToSingle(record.inspectionPlan),
context: record.context,
created: record.createdAt,
finishedAt: record?.finishedAt,
finishedBy: record?.finishedBy
? record.finishedBy.firstname + " " + record.finishedBy.lastname
: record.finishedByString,
isOpen: record?.finishedAt == undefined,
nextInspection: record?.nextInspection,
...related,
};
}
/**
* @description map records to minified inspection
* @param {Array<inspection>} records
* @returns {Array<MinifiedInspectionViewModel>}
*/
public static mapToBaseMinified(records: Array<inspection>): Array<MinifiedInspectionViewModel> {
return records.map((r) => this.mapToSingleMinified(r));
}
/**
* @description map record to next inspection
* @param {inspection} record
* @returns {InspectionNextViewModel}
*/
public static mapToSingleNext(record: inspection): InspectionNextViewModel {
let related = this.mapRelated(record);
return {
id: record.id,
inspectionPlanId: record.inspectionPlanId,
inspectionPlan: InspectionPlanFactory.mapToSingle(record.inspectionPlan),
dueDate: record?.nextInspection,
...related,
};
}
/**
* @description map records to next inspection
* @param {Array<inspection>} records
* @returns {Array<InspectionNextViewModel>}
*/
public static mapToBaseNext(records: Array<inspection>): Array<InspectionNextViewModel> {
return records.map((r) => this.mapToSingleNext(r));
}
}

View file

@ -0,0 +1,69 @@
import { inspectionPlan } from "../../../../entity/unit/inspection/inspectionPlan";
import {
InspectionPlanRelated,
InspectionPlanViewModel,
} from "../../../../viewmodel/admin/unit/inspection/inspectionPlan.models";
import EquipmentFactory from "../equipment/equipment";
import EquipmentTypeFactory from "../equipment/equipmentType";
import VehicleFactory from "../vehicle/vehicle";
import VehicleTypeFactory from "../vehicle/vehicleType";
import WearableTypeFactory from "../wearable/wearableType";
import InspectionPointFactory from "./inspectionPoint";
export default abstract class InspectionPlanFactory {
/**
* @description map record to inspectionPlan
* @param {inspectionPlan} record
* @returns {InspectionPlanViewModel}
*/
public static mapToSingle(record: inspectionPlan): InspectionPlanViewModel {
let related: InspectionPlanRelated;
if (record?.equipmentTypeId) {
related = {
relatedId: record.equipmentTypeId,
assigned: "equipment",
related: record.equipmentType ? EquipmentTypeFactory.mapToSingle(record.equipmentType) : undefined,
};
} else if (record?.vehicleTypeId) {
related = {
relatedId: record.vehicleTypeId,
assigned: "vehicle",
related: record.vehicleType ? VehicleTypeFactory.mapToSingle(record.vehicleType) : undefined,
};
} else if (record?.wearableTypeId) {
related = {
relatedId: record.wearableTypeId,
assigned: "wearable",
related: record.wearableType ? WearableTypeFactory.mapToSingle(record.wearableType) : undefined,
};
} else {
related = {
relatedId: undefined,
assigned: undefined,
related: undefined,
};
}
return {
id: record.id,
title: record.title,
inspectionInterval: record.inspectionInterval,
remindTime: record.remindTime,
version: record?.latestVersionedPlan?.version ?? 0,
created: record.createdAt,
inspectionPoints: record.latestVersionedPlan
? InspectionPointFactory.mapToBase(record.latestVersionedPlan.inspectionPoints)
: [],
...related,
};
}
/**
* @description map records to inspectionPlan
* @param {Array<inspectionPlan>} records
* @returns {Array<InspectionPlanViewModel>}
*/
public static mapToBase(records: Array<inspectionPlan>): Array<InspectionPlanViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,31 @@
import { inspectionPoint } from "../../../../entity/unit/inspection/inspectionPoint";
import { InspectionPointViewModel } from "../../../../viewmodel/admin/unit/inspection/inspectionPlan.models";
export default abstract class InspectionPointFactory {
/**
* @description map record to inspectionPoint
* @param {inspectionPoint} record
* @returns {InspectionPointViewModel}
*/
public static mapToSingle(record: inspectionPoint): InspectionPointViewModel {
return {
id: record.id,
title: record.title,
description: record.description,
type: record.type,
sort: record.sort,
min: record?.min,
max: record?.max,
others: record?.others,
};
}
/**
* @description map records to inspectionPoint
* @param {Array<inspectionPoint>} records
* @returns {Array<InspectionPointViewModel>}
*/
public static mapToBase(records: Array<inspectionPoint>): Array<InspectionPointViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,28 @@
import { inspectionPointResult } from "../../../../entity/unit/inspection/inspectionPointResult";
import { InspectionPointResultViewModel } from "../../../../viewmodel/admin/unit/inspection/inspection.models";
import InspectionPointFactory from "./inspectionPoint";
export default abstract class InspectionPointResultFactory {
/**
* @description map record to inspectionPointResult
* @param {inspectionPointResult} record
* @returns {InspectionPointResultViewModel}
*/
public static mapToSingle(record: inspectionPointResult): InspectionPointResultViewModel {
return {
inspectionId: record.inspectionId,
inspectionPointId: record.inspectionPointId,
inspectionPoint: InspectionPointFactory.mapToSingle(record.inspectionPoint),
value: record.value,
};
}
/**
* @description map records to inspectionPointResult
* @param {Array<inspectionPointResult>} records
* @returns {Array<InspectionPointResultViewModel>}
*/
public static mapToBase(records: Array<inspectionPointResult>): Array<InspectionPointResultViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,28 @@
import { inspectionVersionedPlan } from "../../../../entity/unit/inspection/inspectionVersionedPlan";
import { InspectionVersionedPlanViewModel } from "../../../../viewmodel/admin/unit/inspection/inspectionPlan.models";
import InspectionPointFactory from "./inspectionPoint";
export default abstract class InspectionVersionedPlanFactory {
/**
* @description map record to inspectionVersionedPlan
* @param {inspectionVersionedPlan} record
* @returns {InspectionVersionedPlanViewModel}
*/
public static mapToSingle(record: inspectionVersionedPlan): InspectionVersionedPlanViewModel {
return {
id: record.id,
version: record.version,
created: record.createdAt,
inspectionPoints: InspectionPointFactory.mapToBase(record.inspectionPoints),
};
}
/**
* @description map records to inspectionVersionedPlan
* @param {Array<inspectionVersionedPlan>} records
* @returns {Array<InspectionVersionedPlanViewModel>}
*/
public static mapToBase(records: Array<inspectionVersionedPlan>): Array<InspectionVersionedPlanViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,59 @@
import { maintenance } from "../../../entity/unit/maintenance";
import { MaintenanceAssigned, MaintenanceViewModel } from "../../../viewmodel/admin/unit/maintenance.models";
import DamageReportFactory from "./damageReport";
import EquipmentFactory from "./equipment/equipment";
import VehicleFactory from "./vehicle/vehicle";
import WearableFactory from "./wearable/wearable";
export default abstract class MaintenanceFactory {
/**
* @description map record to maintenance
* @param {maintenance} record
* @returns {MaintenanceViewModel}
*/
public static mapToSingle(record: maintenance): MaintenanceViewModel {
let assigned: MaintenanceAssigned;
if (record?.equipmentId) {
assigned = {
relatedId: record.equipmentId,
assigned: "equipment",
related: record.equipment ? EquipmentFactory.mapToSingle(record.equipment) : undefined,
};
} else if (record?.vehicleId) {
assigned = {
relatedId: record.vehicleId,
assigned: "vehicle",
related: record.vehicle ? VehicleFactory.mapToSingle(record.vehicle) : undefined,
};
} else if (record?.wearableId) {
assigned = {
relatedId: record.wearableId,
assigned: "wearable",
related: record.wearable ? WearableFactory.mapToSingle(record.wearable) : undefined,
};
} else {
assigned = {
relatedId: undefined,
assigned: undefined,
related: undefined,
};
}
return {
id: record.id,
createdAt: record.createdAt,
status: record.status,
description: record.description,
...assigned,
};
}
/**
* @description map records to maintenance
* @param {Array<maintenance>} records
* @returns {Array<MaintenanceViewModel>}
*/
public static mapToBase(records: Array<maintenance>): Array<MaintenanceViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,68 @@
import { repair } from "../../../entity/unit/repair";
import { RepairAssigned, RepairViewModel } from "../../../viewmodel/admin/unit/repair.models";
import DamageReportFactory from "./damageReport";
import EquipmentFactory from "./equipment/equipment";
import VehicleFactory from "./vehicle/vehicle";
import WearableFactory from "./wearable/wearable";
export default abstract class RepairFactory {
/**
* @description map record to repair
* @param {repair} record
* @returns {RepairViewModel}
*/
public static mapToSingle(record: repair): RepairViewModel {
let assigned: RepairAssigned;
if (record?.equipmentId) {
assigned = {
relatedId: record.equipmentId,
assigned: "equipment",
related: record.equipment ? EquipmentFactory.mapToSingle(record.equipment) : undefined,
};
} else if (record?.vehicleId) {
assigned = {
relatedId: record.vehicleId,
assigned: "vehicle",
related: record.vehicle ? VehicleFactory.mapToSingle(record.vehicle) : undefined,
};
} else if (record?.wearableId) {
assigned = {
relatedId: record.wearableId,
assigned: "wearable",
related: record.wearable ? WearableFactory.mapToSingle(record.wearable) : undefined,
};
} else {
assigned = {
relatedId: undefined,
assigned: undefined,
related: undefined,
};
}
return {
id: record.id,
createdAt: record.createdAt,
finishedAt: record.finishedAt,
finishedBy: record?.finishedBy
? record.finishedBy.firstname + " " + record.finishedBy.lastname
: record.finishedByString,
status: record.status,
responsible: record.responsible,
title: record.title,
description: record.description,
images: record.images,
reportDocument: record.reportDocument,
reports: record.reports ? DamageReportFactory.mapToBase(record.reports) : [],
...assigned,
};
}
/**
* @description map records to repair
* @param {Array<repair>} records
* @returns {Array<RepairViewModel>}
*/
public static mapToBase(records: Array<repair>): Array<RepairViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,56 @@
import { vehicle } from "../../../../entity/unit/vehicle/vehicle";
import { MinifiedVehicleViewModel, VehicleViewModel } from "../../../../viewmodel/admin/unit/vehicle/vehicle.models";
import VehicleTypeFactory from "./vehicleType";
export default abstract class VehicleFactory {
/**
* @description map record to vehicle
* @param {vehicle} record
* @returns {VehicleViewModel}
*/
public static mapToSingle(record: vehicle): VehicleViewModel {
return {
id: record.id,
code: record?.code,
name: record.name,
location: record.location,
commissioned: record.commissioned,
decommissioned: record?.decommissioned,
vehicleTypeId: record?.vehicleTypeId,
vehicleType: record?.vehicleType ? VehicleTypeFactory.mapToSingle(record.vehicleType) : null,
};
}
/**
* @description map records to vehicle
* @param {Array<vehicle>} records
* @returns {Array<VehicleViewModel>}
*/
public static mapToBase(records: Array<vehicle>): Array<VehicleViewModel> {
return records.map((r) => this.mapToSingle(r));
}
/**
* @description map record to minifed vehicle
* @param {vehicle} record
* @returns {MinifiedVehicleViewModel}
*/
public static mapToSingleMinified(record: vehicle): MinifiedVehicleViewModel {
return {
id: record.id,
code: record?.code,
name: record.name,
type: record?.vehicleType.type,
assigned: "vehicle",
};
}
/**
* @description map records to minified vehicle
* @param {Array<vehicle>} records
* @returns {Array<MinifiedVehicleViewModel>}
*/
public static mapToBaseMinifed(records: Array<vehicle>): Array<MinifiedVehicleViewModel> {
return records.map((r) => this.mapToSingleMinified(r));
}
}

View file

@ -0,0 +1,27 @@
import { vehicleType } from "../../../../entity/unit/vehicle/vehicleType";
import { VehicleTypeViewModel } from "../../../../viewmodel/admin/unit/vehicle/vehicleType.models";
export default abstract class VehicleTypeFactory {
/**
* @description map record to vehicleType
* @param {vehicleType} record
* @returns {VehicleTypeViewModel}
*/
public static mapToSingle(record: vehicleType): VehicleTypeViewModel {
return {
id: record.id,
type: record.type,
description: record.description,
vehicleCount: record.vehicleCount,
};
}
/**
* @description map records to vehicleType
* @param {Array<vehicleType>} records
* @returns {Array<VehicleTypeViewModel>}
*/
public static mapToBase(records: Array<vehicleType>): Array<VehicleTypeViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -0,0 +1,62 @@
import { wearable } from "../../../../entity/unit/wearable/wearable";
import {
MinifiedWearableViewModel,
WearableViewModel,
} from "../../../../viewmodel/admin/unit/wearable/wearable.models";
import MemberFactory from "../../club/member/member";
import WearableTypeFactory from "./wearableType";
export default abstract class WearableFactory {
/**
* @description map record to wearable
* @param {wearable} record
* @returns {WearableViewModel}
*/
public static mapToSingle(record: wearable): WearableViewModel {
return {
id: record.id,
code: record?.code,
name: record.name,
location: record.location,
commissioned: record.commissioned,
decommissioned: record?.decommissioned,
wearableTypeId: record?.wearableTypeId,
wearableType: record?.wearableType ? WearableTypeFactory.mapToSingle(record.wearableType) : null,
wearerId: record?.wearerId,
wearer: record?.wearer ? MemberFactory.mapToSingle(record.wearer) : null,
};
}
/**
* @description map records to wearable
* @param {Array<wearable>} records
* @returns {Array<WearableViewModel>}
*/
public static mapToBase(records: Array<wearable>): Array<WearableViewModel> {
return records.map((r) => this.mapToSingle(r));
}
/**
* @description map record to minifed wearable
* @param {wearable} record
* @returns {MinifiedWearableViewModel}
*/
public static mapToSingleMinified(record: wearable): MinifiedWearableViewModel {
return {
id: record.id,
code: record?.code,
name: record.name,
type: record?.wearableType.type,
assigned: "wearable",
};
}
/**
* @description map records to minified wearable
* @param {Array<wearable>} records
* @returns {Array<MinifiedWearableViewModel>}
*/
public static mapToBaseMinifed(records: Array<wearable>): Array<MinifiedWearableViewModel> {
return records.map((r) => this.mapToSingleMinified(r));
}
}

View file

@ -0,0 +1,27 @@
import { wearableType } from "../../../../entity/unit/wearable/wearableType";
import { WearableTypeViewModel } from "../../../../viewmodel/admin/unit/wearable/wearableType.models";
export default abstract class WearableTypeFactory {
/**
* @description map record to wearableType
* @param {wearableType} record
* @returns {WearableTypeViewModel}
*/
public static mapToSingle(record: wearableType): WearableTypeViewModel {
return {
id: record.id,
type: record.type,
description: record.description,
wearableCount: record.wearableCount,
};
}
/**
* @description map records to wearableType
* @param {Array<wearableType>} records
* @returns {Array<WearableTypeViewModel>}
*/
public static mapToBase(records: Array<wearableType>): Array<WearableTypeViewModel> {
return records.map((r) => this.mapToSingle(r));
}
}

View file

@ -59,3 +59,7 @@ Handlebars.registerHelper("longdatetimeWithWeekday", function (aString) {
Handlebars.registerHelper("json", function (context) { Handlebars.registerHelper("json", function (context) {
return JSON.stringify(context); return JSON.stringify(context);
}); });
Handlebars.registerHelper("eq", function (p, q, options) {
return p == q ? options.fn(this) : options.inverse(this);
});

View file

@ -20,7 +20,9 @@ export type BackupSection =
| "template" | "template"
| "user" | "user"
| "webapi" | "webapi"
| "settings"; | "settings"
| "unitBase"
| "unitInstances";
export type BackupSectionRefered = { export type BackupSectionRefered = {
[key in BackupSection]?: Array<string>; [key in BackupSection]?: Array<string>;
@ -34,7 +36,7 @@ export type BackupFileContentSection = Array<any> | { [key: string]: Array<any>
export default abstract class BackupHelper { export default abstract class BackupHelper {
// ! Order matters because of foreign keys // ! Order matters because of foreign keys
private static readonly backupSection: Array<{ type: BackupSection; orderOnInsert: number; orderOnClear: number }> = [ private static readonly backupSection: Array<{ type: BackupSection; orderOnInsert: number; orderOnClear: number }> = [
{ type: "member", orderOnInsert: 2, orderOnClear: 2 }, // CLEAR depends on protcol INSERT depends on Base { type: "member", orderOnInsert: 2, orderOnClear: 2 }, // CLEAR depends on protcol and wearables INSERT depends on Base
{ type: "memberBase", orderOnInsert: 1, orderOnClear: 3 }, // CLEAR depends on member { type: "memberBase", orderOnInsert: 1, orderOnClear: 3 }, // CLEAR depends on member
{ type: "protocol", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member { type: "protocol", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member
{ type: "newsletter", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member & query & calendar { type: "newsletter", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member & query & calendar
@ -45,6 +47,8 @@ export default abstract class BackupHelper {
{ type: "user", orderOnInsert: 1, orderOnClear: 1 }, { type: "user", orderOnInsert: 1, orderOnClear: 1 },
{ type: "webapi", orderOnInsert: 1, orderOnClear: 1 }, { type: "webapi", orderOnInsert: 1, orderOnClear: 1 },
{ type: "settings", orderOnInsert: 1, orderOnClear: 1 }, { type: "settings", orderOnInsert: 1, orderOnClear: 1 },
{ type: "unitBase", orderOnInsert: 1, orderOnClear: 2 },
{ type: "unitInstances", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member in wearable
]; ];
private static readonly backupSectionRefered: BackupSectionRefered = { private static readonly backupSectionRefered: BackupSectionRefered = {
@ -82,6 +86,8 @@ export default abstract class BackupHelper {
user: ["user", "user_permission", "role", "role_permission", "invite"], user: ["user", "user_permission", "role", "role_permission", "invite"],
webapi: ["webapi", "webapi_permission"], webapi: ["webapi", "webapi_permission"],
settings: ["setting"], settings: ["setting"],
unitBase: ["equipment_type", "vehicle_type", "wearable_type"],
unitInstances: ["equipment", "vehicle", "wearable"],
}; };
private static transactionManager: EntityManager; private static transactionManager: EntityManager;
@ -228,6 +234,10 @@ export default abstract class BackupHelper {
return await this.getWebapi(); return await this.getWebapi();
case "settings": case "settings":
return await this.getSettings(); return await this.getSettings();
case "unitBase":
return await this.getUnitBase();
case "unitInstances":
return await this.getUnitInstances();
default: default:
return []; return [];
} }
@ -489,6 +499,28 @@ export default abstract class BackupHelper {
.select(["setting.topic", "setting.key", "setting.value"]) .select(["setting.topic", "setting.key", "setting.value"])
.getMany(); .getMany();
} }
private static async getUnitBase(): Promise<{ [key: string]: Array<any> }> {
return {
equipment_type: await dataSource.getRepository("equipment_type").find(),
vehicle_type: await dataSource.getRepository("vehicle_type").find(),
wearable_type: await dataSource.getRepository("wearable_type").find(),
inspection_plan: await dataSource.getRepository("inspection_plan").find(),
inspection_versioned_plan: await dataSource.getRepository("inspection_versioned_plan").find(),
inspection_point: await dataSource.getRepository("inspection_point").find(),
};
}
private static async getUnitInstances(): Promise<{ [key: string]: Array<any> }> {
return {
equipment: await dataSource.getRepository("equipment").find(),
vehicle: await dataSource.getRepository("vehicle").find(),
wearable: await dataSource.getRepository("wearable").find(),
maintenance: await dataSource.getRepository("maintenance").find(),
damage_report: await dataSource.getRepository("damage_report").find(),
repair: await dataSource.getRepository("repair").find(),
inspection: await dataSource.getRepository("inspection").find(),
inspection_point_result: await dataSource.getRepository("inspection_point_result").find(),
};
}
private static async setSectionData( private static async setSectionData(
section: BackupSection, section: BackupSection,
@ -506,6 +538,8 @@ export default abstract class BackupHelper {
if (section == "user" && !Array.isArray(data)) await this.setUser(data); if (section == "user" && !Array.isArray(data)) await this.setUser(data);
if (section == "webapi" && Array.isArray(data)) await this.setWebapi(data); if (section == "webapi" && Array.isArray(data)) await this.setWebapi(data);
if (section == "settings" && Array.isArray(data)) await this.setSettings(data); if (section == "settings" && Array.isArray(data)) await this.setSettings(data);
if (section == "unitBase" && !Array.isArray(data)) await this.setUnitBase(data);
if (section == "unitInstances" && !Array.isArray(data)) await this.setUnitInstances(data);
} }
private static async setMemberData(data: Array<any>): Promise<void> { private static async setMemberData(data: Array<any>): Promise<void> {
@ -869,4 +903,27 @@ export default abstract class BackupHelper {
private static async setSettings(data: Array<any>): Promise<void> { private static async setSettings(data: Array<any>): Promise<void> {
await this.transactionManager.getRepository("setting").save(data); await this.transactionManager.getRepository("setting").save(data);
} }
private static async setUnitBase(data: { [key: string]: Array<any> }): Promise<void> {
await this.transactionManager.getRepository("equipment_type").save(data["equipment_type"] ?? []);
await this.transactionManager.getRepository("vehicle_type").save(data["vehicle_type"] ?? []);
await this.transactionManager.getRepository("wearable_type").save(data["wearable_type"] ?? []);
await this.transactionManager.getRepository("inspection_plan").save(data["inspection_plan"] ?? []);
await this.transactionManager
.getRepository("inspection_versioned_plan")
.save(data["inspection_versioned_plan"] ?? []);
await this.transactionManager.getRepository("inspection_point").save(data["inspection_point"] ?? []);
}
private static async setUnitInstances(data: { [key: string]: Array<any> }): Promise<void> {
await this.transactionManager.getRepository("equipment").save(data["equipment"] ?? []);
await this.transactionManager.getRepository("vehicle").save(data["vehicle"] ?? []);
await this.transactionManager.getRepository("wearable").save(data["wearable"] ?? []);
await this.transactionManager.getRepository("repair").save(data["repair"] ?? []);
await this.transactionManager.getRepository("damage_report").save(data["damage_report"] ?? []);
await this.transactionManager.getRepository("maintenance").save(data["maintenance"] ?? []);
await this.transactionManager.getRepository("inspection").save(data["inspection"] ?? []);
await this.transactionManager.getRepository("inspection_point_result").save(data["inspection_point_result"] ?? []);
}
} }

View file

@ -15,7 +15,7 @@ export abstract class FileSystemHelper {
return readFileSync(this.formatPath(...filePath), "utf8"); return readFileSync(this.formatPath(...filePath), "utf8");
} }
static readFileasBase64(...filePath: string[]) { static readFileAsBase64(...filePath: string[]) {
this.createFolder(...filePath); this.createFolder(...filePath);
return readFileSync(this.formatPath(...filePath), "base64"); return readFileSync(this.formatPath(...filePath), "base64");
} }

View file

@ -127,7 +127,7 @@ export abstract class PdfExport {
const mergedPdf = await PDFDocument.create(); const mergedPdf = await PDFDocument.create();
for (const pdfPath of pdfFilePaths) { for (const pdfPath of pdfFilePaths) {
const pdfBytes = FileSystemHelper.readFileasBase64(inputFolder, pdfPath); const pdfBytes = FileSystemHelper.readFileAsBase64(inputFolder, pdfPath);
const pdf = await PDFDocument.load(pdfBytes); const pdf = await PDFDocument.load(pdfBytes);
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices()); const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => mergedPdf.addPage(page)); copiedPages.forEach((page) => mergedPdf.addPage(page));

View file

@ -14,8 +14,6 @@ import {
UrlConverter, UrlConverter,
} from "./convertHelper"; } from "./convertHelper";
import cloneDeep from "lodash.clonedeep"; import cloneDeep from "lodash.clonedeep";
import { rejects } from "assert";
import InternalException from "../exceptions/internalException";
import MailHelper from "./mailHelper"; import MailHelper from "./mailHelper";
export default abstract class SettingHelper { export default abstract class SettingHelper {

22
src/helpers/typeTester.ts Normal file
View file

@ -0,0 +1,22 @@
import { PlanTimeDefinition } from "../viewmodel/admin/unit/inspection/inspectionPlan.models";
export default abstract class TypeTester {
static testPlanTimeDefinition(
val: string | null,
{ key = "", throwErr = false, allowNull = false }: { key?: string; throwErr?: boolean; allowNull?: boolean }
): PlanTimeDefinition | null {
if (val == null && allowNull) return null;
if (/^(\d+-(d|m|y)|\d+\/(\d+|\*))$/.test(val)) {
return val as PlanTimeDefinition;
} else if (throwErr) {
throw Error(
[
key,
"provided String does not match PlanTimeDefinition Format: ${number}-${'d'|'m'|'y'} or ${number}/${number|'*'}",
].join(": ")
);
} else {
return null;
}
}
}

View file

@ -1,6 +1,7 @@
import "dotenv/config"; import "dotenv/config";
import "./handlebars.config"; import "./handlebars.config";
import express from "express"; import express from "express";
import { createServer } from "http";
import { configCheck } from "./env.defaults"; import { configCheck } from "./env.defaults";
configCheck(); configCheck();
@ -11,6 +12,8 @@ declare global {
export interface Request { export interface Request {
userId: string; userId: string;
username: string; username: string;
firstname: string;
lastname: string;
isOwner: boolean; isOwner: boolean;
permissions: PermissionObject; permissions: PermissionObject;
isPWA: boolean; isPWA: boolean;
@ -35,7 +38,10 @@ dataSource.initialize().then(async () => {
const app = express(); const app = express();
import router from "./routes/index"; import router from "./routes/index";
router(app); router(app);
app.listen(process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000, () => { const httpServer = createServer(app);
import SocketServer from "./websocket";
SocketServer.init(httpServer);
httpServer.listen(process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000, () => {
console.log( console.log(
`${new Date().toISOString()}: listening on port ${process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000}` `${new Date().toISOString()}: listening on port ${process.env.NODE_ENV ? process.env.SERVER_PORT ?? 5000 : 5000}`
); );

View file

@ -35,6 +35,8 @@ export default async function authenticate(req: Request, res: Response, next: Ne
req.userId = decoded.userId; req.userId = decoded.userId;
req.username = decoded.username; req.username = decoded.username;
req.firstname = decoded.firstname;
req.lastname = decoded.lastname;
req.isOwner = decoded.isOwner; req.isOwner = decoded.isOwner;
req.permissions = decoded.permissions; req.permissions = decoded.permissions;
req.isWebApiRequest = decoded?.sub == "webapi_access_token"; req.isWebApiRequest = decoded?.sub == "webapi_access_token";

View file

@ -0,0 +1,53 @@
import jwt from "jsonwebtoken";
import BadRequestException from "../exceptions/badRequestException";
import InternalException from "../exceptions/internalException";
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
import { JWTHelper } from "../helpers/jwtHelper";
import { SocketMap } from "../storage/socketMap";
import { Socket } from "socket.io";
export default async function authenticateSocket(socket: Socket, next: Function) {
try {
const token = socket.handshake.auth.token;
if (!token) {
throw new BadRequestException("Provide valid Authorization Header");
}
let decoded: string | jwt.JwtPayload;
await JWTHelper.validate(token)
.then((result) => {
decoded = result;
})
.catch((err) => {
if (err == "jwt expired") {
throw new UnauthorizedRequestException("Token expired", err);
} else {
throw new BadRequestException("Failed Authorization Header decoding", err);
}
});
if (typeof decoded == "string" || !decoded) {
throw new InternalException("process failed");
}
if (decoded?.sub == "api_token_retrieve") {
throw new BadRequestException("This token is only authorized to get temporary access tokens via GET /api/webapi");
}
SocketMap.write(socket.id, {
socketId: socket.id,
userId: decoded.userId,
username: decoded.username,
firstname: decoded.firstname,
lastname: decoded.lastname,
isOwner: decoded.isOwner,
permissions: decoded.permissions,
isWebApiRequest: decoded?.sub == "webapi_access_token",
});
next();
} catch (err) {
next(err);
}
}

View file

@ -0,0 +1,11 @@
import { Event, Socket } from "socket.io";
import UnauthorizedRequestException from "../exceptions/unauthorizedRequestException";
import { SocketMap } from "../storage/socketMap";
export default async (socket: Socket, [event, ...args]: Event, next: any) => {
if (SocketMap.exists(socket.id)) {
next();
} else {
next(new UnauthorizedRequestException("not authorized for connection"));
}
};

View file

@ -2,7 +2,9 @@ import multer from "multer";
import { FileSystemHelper } from "../helpers/fileSystemHelper"; import { FileSystemHelper } from "../helpers/fileSystemHelper";
import path from "path"; import path from "path";
import BadRequestException from "../exceptions/badRequestException"; import BadRequestException from "../exceptions/badRequestException";
import { v4 as uuid } from "uuid";
/**Settings image upload */
export const clubImageStorage = multer.diskStorage({ export const clubImageStorage = multer.diskStorage({
destination: FileSystemHelper.formatPath("/app"), destination: FileSystemHelper.formatPath("/app"),
filename: function (req, file, cb) { filename: function (req, file, cb) {
@ -33,3 +35,52 @@ export const clubImageUpload = clubImageMulter.fields([
{ name: "icon", maxCount: 1 }, { name: "icon", maxCount: 1 },
{ name: "logo", maxCount: 1 }, { name: "logo", maxCount: 1 },
]); ]);
/**Inspection file upload */
export const inspectionFileStorage = multer.diskStorage({
destination: function (req, file, cb) {
FileSystemHelper.createFolder("inspection", req.params.id);
cb(null, FileSystemHelper.formatPath("inspection", req.params.id));
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
export const inspectionFileMulter = multer({
storage: inspectionFileStorage,
fileFilter(req, file, cb) {
if (file.mimetype.startsWith("image/") || file.mimetype === "application/pdf") {
cb(null, true);
} else {
cb(new BadRequestException("Wrong file format"));
}
},
});
export const inspectionFileUpload = inspectionFileMulter.array("files");
/**public damage report upload */
export const pDamageReportFileStorage = multer.diskStorage({
destination: function (req, file, cb) {
FileSystemHelper.createFolder("damageReport");
cb(null, FileSystemHelper.formatPath("damageReport"));
},
filename: function (req, file, cb) {
const fileExtension = path.extname(file.originalname).toLowerCase();
cb(null, uuid() + fileExtension);
},
});
export const pDamageReportFileMulter = multer({
storage: pDamageReportFileStorage,
fileFilter(req, file, cb) {
if (file.mimetype.startsWith("image/")) {
cb(null, true);
} else {
cb(new BadRequestException("Wrong file format"));
}
},
});
export const pDamageReportFileUpload = pDamageReportFileMulter.array("images");

View file

@ -0,0 +1,82 @@
import { MigrationInterface, QueryRunner } from "typeorm";
import {
inspection_plan_table,
inspection_versioned_plan_table,
inspection_point_table,
inspection_table,
inspection_point_result_table,
} from "./baseSchemaTables/inspection";
import {
equipment_type_table,
equipment_table,
vehicle_type_table,
vehicle_table,
wearable_type_table,
wearable_table,
} from "./baseSchemaTables/unit";
import { maintenance_table, damage_report_table, repair_table } from "./baseSchemaTables/unit_extend";
import { availableTemplates } from "../type/templateTypes";
import { template_usage_table } from "./baseSchemaTables/query_template";
export class UnitBase1752914551204 implements MigrationInterface {
name = "UnitBase1752914551204";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(equipment_type_table, true, true, true);
await queryRunner.createTable(equipment_table, true, true, true);
await queryRunner.createTable(vehicle_type_table, true, true, true);
await queryRunner.createTable(vehicle_table, true, true, true);
await queryRunner.createTable(wearable_type_table, true, true, true);
await queryRunner.createTable(wearable_table, true, true, true);
await queryRunner.createTable(maintenance_table, true, true, true);
await queryRunner.createTable(repair_table, true, true, true);
await queryRunner.createTable(damage_report_table, true, true, true);
await queryRunner.createTable(inspection_plan_table, true, true, true);
await queryRunner.createTable(inspection_versioned_plan_table, true, true, true);
await queryRunner.createTable(inspection_point_table, true, true, true);
await queryRunner.createTable(inspection_table, true, true, true);
await queryRunner.createTable(inspection_point_result_table, true, true, true);
await queryRunner.manager
.createQueryBuilder()
.insert()
.into(template_usage_table.name)
.values(
availableTemplates.map((at) => ({
scope: at,
}))
)
.orIgnore()
.execute();
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable(inspection_point_result_table, true, true, true);
await queryRunner.dropTable(inspection_table, true, true, true);
await queryRunner.dropTable(inspection_point_table, true, true, true);
await queryRunner.dropTable(inspection_versioned_plan_table, true, true, true);
await queryRunner.dropTable(inspection_plan_table, true, true, true);
await queryRunner.dropTable(damage_report_table, true, true, true);
await queryRunner.dropTable(repair_table, true, true, true);
await queryRunner.dropTable(maintenance_table, true, true, true);
await queryRunner.dropTable(wearable_table, true, true, true);
await queryRunner.dropTable(wearable_type_table, true, true, true);
await queryRunner.dropTable(vehicle_table, true, true, true);
await queryRunner.dropTable(vehicle_type_table, true, true, true);
await queryRunner.dropTable(equipment_table, true, true, true);
await queryRunner.dropTable(equipment_type_table, true, true, true);
await queryRunner.manager
.createQueryBuilder()
.delete()
.from(template_usage_table.name)
.where({ scope: "inspection" })
.execute();
}
}

View file

@ -0,0 +1,176 @@
import { Table, TableForeignKey, TableUnique } from "typeorm";
import { getTypeByORM, isUUIDPrimary, getDefaultByORM } from "../ormHelper";
export const inspection_plan_table = new Table({
name: "inspection_plan",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "title", ...getTypeByORM("varchar") },
{ name: "inspectionInterval", ...getTypeByORM("varchar", true) },
{ name: "remindTime", ...getTypeByORM("varchar", true) },
{ name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") },
{ name: "equipmentTypeId", ...getTypeByORM("uuid", true) },
{ name: "vehicleTypeId", ...getTypeByORM("uuid", true) },
{ name: "wearableTypeId", ...getTypeByORM("uuid", true) },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["equipmentTypeId"],
referencedColumnNames: ["id"],
referencedTableName: "equipment_type",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["vehicleTypeId"],
referencedColumnNames: ["id"],
referencedTableName: "vehicle_type",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["wearableTypeId"],
referencedColumnNames: ["id"],
referencedTableName: "wearable_type",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
],
});
export const inspection_versioned_plan_table = new Table({
name: "inspection_versioned_plan",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "version", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) },
{ name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") },
{ name: "inspectionPlanId", ...getTypeByORM("uuid") },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["inspectionPlanId"],
referencedColumnNames: ["id"],
referencedTableName: "inspection_plan",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
],
uniques: [
new TableUnique({
name: "unique_version",
columnNames: ["version", "inspectionPlanId"],
}),
],
});
export const inspection_point_table = new Table({
name: "inspection_point",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "title", ...getTypeByORM("varchar") },
{ name: "description", ...getTypeByORM("text") },
{ name: "type", ...getTypeByORM("varchar") },
{ name: "min", ...getTypeByORM("int", true) },
{ name: "max", ...getTypeByORM("int", true) },
{ name: "others", ...getTypeByORM("varchar", true) },
{ name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) },
{ name: "versionedPlanId", ...getTypeByORM("uuid") },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["versionedPlanId"],
referencedColumnNames: ["id"],
referencedTableName: "inspection_versioned_plan",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
],
});
export const inspection_table = new Table({
name: "inspection",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "context", ...getTypeByORM("text") },
{ name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") },
{ name: "finishedAt", ...getTypeByORM("datetime", true) },
{ name: "finishedById", ...getTypeByORM("uuid", true) },
{ name: "finishedByString", ...getTypeByORM("varchar", true) },
{ name: "nextInspection", ...getTypeByORM("date", true) },
{ name: "hasNewer", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) },
{ name: "inspectionPlanId", ...getTypeByORM("uuid") },
{ name: "inspectionVersionedPlanId", ...getTypeByORM("uuid") },
{ name: "equipmentId", ...getTypeByORM("uuid", true) },
{ name: "vehicleId", ...getTypeByORM("uuid", true) },
{ name: "wearableId", ...getTypeByORM("uuid", true) },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["finishedById"],
referencedColumnNames: ["id"],
referencedTableName: "user",
onDelete: "SET NULL",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["inspectionPlanId"],
referencedColumnNames: ["id"],
referencedTableName: "inspection_plan",
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["inspectionVersionedPlanId"],
referencedColumnNames: ["id"],
referencedTableName: "inspection_versioned_plan",
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["equipmentId"],
referencedColumnNames: ["id"],
referencedTableName: "equipment",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["vehicleId"],
referencedColumnNames: ["id"],
referencedTableName: "vehicle",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["wearableId"],
referencedColumnNames: ["id"],
referencedTableName: "wearable",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
],
});
export const inspection_point_result_table = new Table({
name: "inspection_point_result",
columns: [
{ name: "inspectionId", ...getTypeByORM("uuid"), isPrimary: true },
{ name: "inspectionPointId", ...getTypeByORM("uuid"), isPrimary: true },
{ name: "value", ...getTypeByORM("text") },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["inspectionId"],
referencedColumnNames: ["id"],
referencedTableName: "inspection",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["inspectionPointId"],
referencedColumnNames: ["id"],
referencedTableName: "inspection_point",
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
}),
],
});

View file

@ -0,0 +1,103 @@
import { Table, TableForeignKey } from "typeorm";
import { getTypeByORM, isUUIDPrimary, getDefaultByORM } from "../ormHelper";
export const equipment_table = new Table({
name: "equipment",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "code", ...getTypeByORM("varchar", true), isUnique: true },
{ name: "name", ...getTypeByORM("varchar") },
{ name: "location", ...getTypeByORM("varchar") },
{ name: "commissioned", ...getTypeByORM("date") },
{ name: "decommissioned", ...getTypeByORM("date", true) },
{ name: "equipmentTypeId", ...getTypeByORM("uuid") },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["equipmentTypeId"],
referencedColumnNames: ["id"],
referencedTableName: "equipment_type",
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
}),
],
});
export const equipment_type_table = new Table({
name: "equipment_type",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "type", ...getTypeByORM("varchar"), isUnique: true },
{ name: "description", ...getTypeByORM("text", true) },
],
});
export const vehicle_table = new Table({
name: "vehicle",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "code", ...getTypeByORM("varchar", true), isUnique: true },
{ name: "name", ...getTypeByORM("varchar") },
{ name: "location", ...getTypeByORM("varchar") },
{ name: "commissioned", ...getTypeByORM("date") },
{ name: "decommissioned", ...getTypeByORM("date", true) },
{ name: "vehicleTypeId", ...getTypeByORM("uuid") },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["vehicleTypeId"],
referencedColumnNames: ["id"],
referencedTableName: "vehicle_type",
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
}),
],
});
export const vehicle_type_table = new Table({
name: "vehicle_type",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "type", ...getTypeByORM("varchar"), isUnique: true },
{ name: "description", ...getTypeByORM("text", true) },
],
});
export const wearable_table = new Table({
name: "wearable",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "code", ...getTypeByORM("varchar", true), isUnique: true },
{ name: "name", ...getTypeByORM("varchar") },
{ name: "location", ...getTypeByORM("varchar") },
{ name: "commissioned", ...getTypeByORM("date") },
{ name: "decommissioned", ...getTypeByORM("date", true) },
{ name: "wearableTypeId", ...getTypeByORM("uuid") },
{ name: "wearerId", ...getTypeByORM("uuid", true) },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["wearableTypeId"],
referencedColumnNames: ["id"],
referencedTableName: "wearable_type",
onDelete: "RESTRICT",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["wearerId"],
referencedColumnNames: ["id"],
referencedTableName: "member",
onDelete: "SET NULL",
onUpdate: "RESTRICT",
}),
],
});
export const wearable_type_table = new Table({
name: "wearable_type",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "type", ...getTypeByORM("varchar"), isUnique: true },
{ name: "description", ...getTypeByORM("text", true) },
],
});

View file

@ -0,0 +1,162 @@
import { Table, TableForeignKey } from "typeorm";
import { getTypeByORM, isUUIDPrimary, getDefaultByORM } from "../ormHelper";
export const damage_report_table = new Table({
name: "damage_report",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "reportedAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") },
{ name: "closedAt", ...getTypeByORM("datetime", true) },
{ name: "closedById", ...getTypeByORM("uuid", true) },
{ name: "closedByString", ...getTypeByORM("varchar", true) },
{ name: "status", ...getTypeByORM("varchar") },
{ name: "title", ...getTypeByORM("varchar") },
{ name: "description", ...getTypeByORM("text") },
{ name: "location", ...getTypeByORM("text", true) },
{ name: "noteByReporter", ...getTypeByORM("text", true) },
{ name: "noteByWorker", ...getTypeByORM("text", true) },
{ name: "reportedBy", ...getTypeByORM("varchar", true) },
{ name: "images", ...getTypeByORM("text", true) },
{ name: "equipmentId", ...getTypeByORM("uuid", true) },
{ name: "vehicleId", ...getTypeByORM("uuid", true) },
{ name: "wearableId", ...getTypeByORM("uuid", true) },
{ name: "repairId", ...getTypeByORM("uuid", true) },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["closedById"],
referencedColumnNames: ["id"],
referencedTableName: "user",
onDelete: "SET NULL",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["equipmentId"],
referencedColumnNames: ["id"],
referencedTableName: "equipment",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["vehicleId"],
referencedColumnNames: ["id"],
referencedTableName: "vehicle",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["wearableId"],
referencedColumnNames: ["id"],
referencedTableName: "wearable",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["repairId"],
referencedColumnNames: ["id"],
referencedTableName: "repair",
onDelete: "SET NULL",
onUpdate: "RESTRICT",
}),
],
});
export const maintenance_table = new Table({
name: "maintenance",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") },
{ name: "finishedAt", ...getTypeByORM("datetime", true) },
{ name: "finishedById", ...getTypeByORM("uuid", true) },
{ name: "finishedByString", ...getTypeByORM("varchar", true) },
{ name: "status", ...getTypeByORM("varchar") },
{ name: "title", ...getTypeByORM("varchar") },
{ name: "description", ...getTypeByORM("text") },
{ name: "responsible", ...getTypeByORM("varchar", true) },
{ name: "images", ...getTypeByORM("text", true) },
{ name: "reportDocument", ...getTypeByORM("varchar", true) },
{ name: "equipmentId", ...getTypeByORM("uuid", true) },
{ name: "vehicleId", ...getTypeByORM("uuid", true) },
{ name: "wearableId", ...getTypeByORM("uuid", true) },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["finishedById"],
referencedColumnNames: ["id"],
referencedTableName: "user",
onDelete: "SET NULL",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["equipmentId"],
referencedColumnNames: ["id"],
referencedTableName: "equipment",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["vehicleId"],
referencedColumnNames: ["id"],
referencedTableName: "vehicle",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["wearableId"],
referencedColumnNames: ["id"],
referencedTableName: "wearable",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
],
});
export const repair_table = new Table({
name: "repair",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") },
{ name: "finishedAt", ...getTypeByORM("datetime", true) },
{ name: "finishedById", ...getTypeByORM("uuid", true) },
{ name: "finishedByString", ...getTypeByORM("varchar", true) },
{ name: "status", ...getTypeByORM("varchar") },
{ name: "title", ...getTypeByORM("varchar") },
{ name: "description", ...getTypeByORM("text") },
{ name: "responsible", ...getTypeByORM("varchar", true) },
{ name: "images", ...getTypeByORM("text", true) },
{ name: "reportDocument", ...getTypeByORM("varchar", true) },
{ name: "equipmentId", ...getTypeByORM("uuid", true) },
{ name: "vehicleId", ...getTypeByORM("uuid", true) },
{ name: "wearableId", ...getTypeByORM("uuid", true) },
],
foreignKeys: [
new TableForeignKey({
columnNames: ["finishedById"],
referencedColumnNames: ["id"],
referencedTableName: "user",
onDelete: "SET NULL",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["equipmentId"],
referencedColumnNames: ["id"],
referencedTableName: "equipment",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["vehicleId"],
referencedColumnNames: ["id"],
referencedTableName: "vehicle",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
new TableForeignKey({
columnNames: ["wearableId"],
referencedColumnNames: ["id"],
referencedTableName: "wearable",
onDelete: "CASCADE",
onUpdate: "RESTRICT",
}),
],
});

View file

@ -2,6 +2,7 @@ import express from "express";
import PermissionHelper from "../../helpers/permissionHelper"; import PermissionHelper from "../../helpers/permissionHelper";
import preventWebapiAccess from "../../middleware/preventWebApiAccess"; import preventWebapiAccess from "../../middleware/preventWebApiAccess";
/** configuration */
import award from "./configuration/award"; import award from "./configuration/award";
import communicationType from "./configuration/communicationType"; import communicationType from "./configuration/communicationType";
import executivePosition from "./configuration/executivePosition"; import executivePosition from "./configuration/executivePosition";
@ -15,6 +16,7 @@ import template from "./configuration/template";
import templateUsage from "./configuration/templateUsage"; import templateUsage from "./configuration/templateUsage";
import newsletterConfig from "./configuration/newsletterConfig"; import newsletterConfig from "./configuration/newsletterConfig";
/** club */
import member from "./club/member"; import member from "./club/member";
import protocol from "./club/protocol"; import protocol from "./club/protocol";
import calendar from "./club/calendar"; import calendar from "./club/calendar";
@ -22,6 +24,7 @@ import queryBuilder from "./club/queryBuilder";
import newsletter from "./club/newsletter"; import newsletter from "./club/newsletter";
import listprint from "./club/listprint"; import listprint from "./club/listprint";
/** management */
import role from "./management/role"; import role from "./management/role";
import user from "./management/user"; import user from "./management/user";
import invite from "./management/invite"; import invite from "./management/invite";
@ -29,8 +32,22 @@ import api from "./management/webapi";
import backup from "./management/backup"; import backup from "./management/backup";
import setting from "./management/setting"; import setting from "./management/setting";
/** unit */
import equipment from "./unit/equipment";
import equipmentType from "./unit/equipmentType";
import vehicle from "./unit/vehicle";
import vehicleType from "./unit/vehicleType";
import wearable from "./unit/wearable";
import wearableType from "./unit/wearableType";
import inspection from "./unit/inspection";
import inspectionPlan from "./unit/inspectionPlan";
import damageReport from "./unit/damageReport";
import maintenance from "./unit/maintenance";
import repair from "./unit/repair";
var router = express.Router({ mergeParams: true }); var router = express.Router({ mergeParams: true });
/** configuration */
router.use( router.use(
"/award", "/award",
PermissionHelper.passCheckSomeMiddleware([ PermissionHelper.passCheckSomeMiddleware([
@ -121,6 +138,7 @@ router.use(
newsletterConfig newsletterConfig
); );
/** club */
router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "member"), member); router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "member"), member);
router.use( router.use(
"/protocol", "/protocol",
@ -152,6 +170,7 @@ router.use(
); );
router.use("/listprint", PermissionHelper.passCheckMiddleware("read", "club", "listprint"), listprint); router.use("/listprint", PermissionHelper.passCheckMiddleware("read", "club", "listprint"), listprint);
/** management */
router.use("/role", PermissionHelper.passCheckMiddleware("read", "management", "role"), role); router.use("/role", PermissionHelper.passCheckMiddleware("read", "management", "role"), role);
router.use( router.use(
"/user", "/user",
@ -171,4 +190,109 @@ router.use(
); );
router.use("/setting", PermissionHelper.passCheckMiddleware("read", "management", "setting"), setting); router.use("/setting", PermissionHelper.passCheckMiddleware("read", "management", "setting"), setting);
/** unit */
router.use(
"/equipment",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "equipment" },
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
]),
equipment
);
router.use(
"/equipmenttype",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "equipment_type" },
{ requiredPermission: "read", section: "unit", module: "equipment" },
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
]),
equipmentType
);
router.use(
"/vehicle",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "vehicle" },
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
]),
vehicle
);
router.use(
"/vehicletype",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "vehicle_type" },
{ requiredPermission: "read", section: "unit", module: "vehicle" },
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
]),
vehicleType
);
router.use(
"/wearable",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "wearable" },
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
]),
wearable
);
router.use(
"/wearabletype",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "wearable_type" },
{ requiredPermission: "read", section: "unit", module: "wearable" },
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
]),
wearableType
);
router.use(
"/inspection",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "inspection" },
{ requiredPermission: "read", section: "unit", module: "equipment" },
{ requiredPermission: "read", section: "unit", module: "vehicle" },
{ requiredPermission: "read", section: "unit", module: "wearable" },
]),
inspection
);
router.use(
"/inspectionplan",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "inspection_plan" },
{ requiredPermission: "read", section: "unit", module: "inspection" },
{ requiredPermission: "read", section: "unit", module: "equipment_type" },
{ requiredPermission: "read", section: "unit", module: "vehicle_type" },
{ requiredPermission: "read", section: "unit", module: "wearable_type" },
]),
inspectionPlan
);
router.use(
"/damagereport",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "damage_report" },
{ requiredPermission: "read", section: "unit", module: "maintenance" },
{ requiredPermission: "read", section: "unit", module: "equipment" },
{ requiredPermission: "read", section: "unit", module: "vehicle" },
{ requiredPermission: "read", section: "unit", module: "wearable" },
]),
damageReport
);
router.use(
"/maintenance",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "maintenance" },
{ requiredPermission: "read", section: "unit", module: "equipment" },
{ requiredPermission: "read", section: "unit", module: "vehicle" },
{ requiredPermission: "read", section: "unit", module: "wearable" },
]),
maintenance
);
router.use(
"/repair",
PermissionHelper.passCheckSomeMiddleware([
{ requiredPermission: "read", section: "unit", module: "repair" },
{ requiredPermission: "read", section: "unit", module: "equipment" },
{ requiredPermission: "read", section: "unit", module: "vehicle" },
{ requiredPermission: "read", section: "unit", module: "wearable" },
]),
repair
);
export default router; export default router;

View file

@ -0,0 +1,62 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createInspection,
deleteInspectionById,
getAllInspectionsForRelated,
getInspectionById,
updateInspectionById,
} from "../../../controller/admin/unit/inspectionController";
import {
getAllDamageReportsByStatus,
getAllDamageReportsForRelated,
getDamageReportById,
getDamageReportsByIds,
provideDamageReportImageUpload,
updateDamageReportById,
} from "../../../controller/admin/unit/damageReportController";
import preventWebapiAccess from "../../../middleware/preventWebApiAccess";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllDamageReportsByStatus(req, res);
});
router.get(
["/vehicle/:relatedId", "/equipment/:relatedId", "/wearable/:relatedId"],
async (req: Request, res: Response) => {
if (req.path.startsWith("/vehicle")) {
req.params.related = "vehicle";
} else if (req.path.startsWith("/equipment")) {
req.params.related = "equipment";
} else {
req.params.related = "wearable";
}
await getAllDamageReportsForRelated(req, res);
}
);
router.get("/:id", async (req: Request, res: Response) => {
await getDamageReportById(req, res);
});
router.post("/ids", async (req: Request, res: Response) => {
await getDamageReportsByIds(req, res);
});
router.get("/:id/:filename", async (req: Request, res: Response) => {
await provideDamageReportImageUpload(req, res);
});
router.patch(
"/:id",
preventWebapiAccess,
PermissionHelper.passCheckMiddleware("update", "unit", "damage_report"),
async (req: Request, res: Response) => {
await updateDamageReportById(req, res);
}
);
export default router;

View file

@ -0,0 +1,50 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createEquipment,
deleteEquipmentById,
getAllEquipments,
getEquipmentById,
getEquipmentsByIds,
updateEquipmentById,
} from "../../../controller/admin/unit/equipmentController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllEquipments(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getEquipmentById(req, res);
});
router.post("/ids", async (req: Request, res: Response) => {
await getEquipmentsByIds(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "equipment"),
async (req: Request, res: Response) => {
await createEquipment(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "equipment"),
async (req: Request, res: Response) => {
await updateEquipmentById(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "equipment"),
async (req: Request, res: Response) => {
await deleteEquipmentById(req, res);
}
);
export default router;

View file

@ -0,0 +1,45 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createEquipmentType,
deleteEquipmentTypeById,
getAllEquipmentTypes,
getEquipmentTypeById,
updateEquipmentTypeById,
} from "../../../controller/admin/unit/equipmentTypeController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllEquipmentTypes(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getEquipmentTypeById(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "equipment_type"),
async (req: Request, res: Response) => {
await createEquipmentType(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "equipment_type"),
async (req: Request, res: Response) => {
await updateEquipmentTypeById(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "equipment_type"),
async (req: Request, res: Response) => {
await deleteEquipmentTypeById(req, res);
}
);
export default router;

View file

@ -0,0 +1,98 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createInspection,
deleteInspectionById,
getAllInspectionsSortedNotHavingNewer,
getAllInspectionsForRelated,
getInspectionById,
updateInspectionById,
getAllInspectionsRunning,
updateInspectionResults,
getInspectionPrintoutById,
finishInspection,
getInspectionPointUpload,
} from "../../../controller/admin/unit/inspectionController";
import { inspectionFileUpload } from "../../../middleware/multer";
import preventWebapiAccess from "../../../middleware/preventWebApiAccess";
var router = express.Router({ mergeParams: true });
router.get("/next", async (req: Request, res: Response) => {
await getAllInspectionsSortedNotHavingNewer(req, res);
});
router.get("/running", async (req: Request, res: Response) => {
await getAllInspectionsRunning(req, res);
});
router.get(
["/vehicle/:relatedId", "/equipment/:relatedId", "/wearable/:relatedId"],
async (req: Request, res: Response) => {
if (req.path.startsWith("/vehicle")) {
req.params.related = "vehicle";
} else if (req.path.startsWith("/equipment")) {
req.params.related = "equipment";
} else {
req.params.related = "wearable";
}
await getAllInspectionsForRelated(req, res);
}
);
router.get("/:id", async (req: Request, res: Response) => {
await getInspectionById(req, res);
});
router.get("/:id/printout", async (req: Request, res: Response) => {
await getInspectionPrintoutById(req, res);
});
router.get("/:id/:pointId/upload", async (req: Request, res: Response) => {
await getInspectionPointUpload(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "inspection"),
async (req: Request, res: Response) => {
await createInspection(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "inspection"),
async (req: Request, res: Response) => {
await updateInspectionById(req, res);
}
);
router.patch(
"/:id/results",
PermissionHelper.passCheckMiddleware("update", "unit", "inspection"),
inspectionFileUpload,
async (req: Request, res: Response) => {
await updateInspectionResults(req, res);
}
);
router.patch(
"/:id/finish",
preventWebapiAccess,
PermissionHelper.passCheckMiddleware("update", "unit", "inspection"),
async (req: Request, res: Response) => {
await finishInspection(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "inspection"),
async (req: Request, res: Response) => {
await deleteInspectionById(req, res);
}
);
export default router;

View file

@ -0,0 +1,75 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createInspectionPlan,
deleteInspectionPlanById,
getAllInspectionPlans,
getAllInspectionPlansForRelated,
getInspectionPlanById,
getInspectionPointsByPlanId,
updateInspectionPlanById,
updateInspectionPointsByPlanId,
} from "../../../controller/admin/unit/inspectionPlanController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllInspectionPlans(req, res);
});
router.get("/:id/points", async (req: Request, res: Response) => {
await getInspectionPointsByPlanId(req, res);
});
router.get(
["/vehicleType/:relatedTypeId", "/equipmentType/:relatedTypeId", "/wearableType/:relatedTypeId"],
async (req: Request, res: Response) => {
if (req.path.startsWith("/vehicleType")) {
req.params.related = "vehicleType";
} else if (req.path.startsWith("/equipmentType")) {
req.params.related = "equipmentType";
} else {
req.params.related = "wearableType";
}
await getAllInspectionPlansForRelated(req, res);
}
);
router.get("/:id", async (req: Request, res: Response) => {
await getInspectionPlanById(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "inspection_plan"),
async (req: Request, res: Response) => {
await createInspectionPlan(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "inspection_plan"),
async (req: Request, res: Response) => {
await updateInspectionPlanById(req, res);
}
);
router.patch(
"/:id/points",
PermissionHelper.passCheckMiddleware("update", "unit", "inspection_plan"),
async (req: Request, res: Response) => {
await updateInspectionPointsByPlanId(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "inspection_plan"),
async (req: Request, res: Response) => {
await deleteInspectionPlanById(req, res);
}
);
export default router;

View file

@ -0,0 +1,43 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
getAllMaintenancesByStatus,
getAllMaintenancesForRelated,
getMaintenanceById,
updateMaintenanceById,
} from "../../../controller/admin/unit/maintenanceController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllMaintenancesByStatus(req, res);
});
router.get(
["/vehicle/:relatedId", "/equipment/:relatedId", "/wearable/:relatedId"],
async (req: Request, res: Response) => {
if (req.path.startsWith("/vehicle")) {
req.params.related = "vehicle";
} else if (req.path.startsWith("/equipment")) {
req.params.related = "equipment";
} else {
req.params.related = "wearable";
}
await getAllMaintenancesForRelated(req, res);
}
);
router.get("/:id", async (req: Request, res: Response) => {
await getMaintenanceById(req, res);
});
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "maintenance"),
async (req: Request, res: Response) => {
await updateMaintenanceById(req, res);
}
);
export default router;

View file

@ -0,0 +1,72 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createRepair,
getAllRepairsByStatus,
getAllRepairsForRelated,
getRepairById,
updateRepairById,
updateRepairReportsById,
updateRepairStatusById,
} from "../../../controller/admin/unit/repairController";
import preventWebapiAccess from "../../../middleware/preventWebApiAccess";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllRepairsByStatus(req, res);
});
router.get(
["/vehicle/:relatedId", "/equipment/:relatedId", "/wearable/:relatedId"],
async (req: Request, res: Response) => {
if (req.path.startsWith("/vehicle")) {
req.params.related = "vehicle";
} else if (req.path.startsWith("/equipment")) {
req.params.related = "equipment";
} else {
req.params.related = "wearable";
}
await getAllRepairsForRelated(req, res);
}
);
router.get("/:id", async (req: Request, res: Response) => {
await getRepairById(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("update", "unit", "repair"),
async (req: Request, res: Response) => {
await createRepair(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "repair"),
async (req: Request, res: Response) => {
await updateRepairById(req, res);
}
);
router.patch(
"/:id/reports",
PermissionHelper.passCheckMiddleware("update", "unit", "repair"),
async (req: Request, res: Response) => {
await updateRepairReportsById(req, res);
}
);
router.patch(
"/:id/status",
preventWebapiAccess,
PermissionHelper.passCheckMiddleware("update", "unit", "repair"),
async (req: Request, res: Response) => {
await updateRepairStatusById(req, res);
}
);
export default router;

View file

@ -0,0 +1,50 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createVehicle,
deleteVehicleById,
getAllVehicles,
getVehicleById,
getVehiclesByIds,
updateVehicleById,
} from "../../../controller/admin/unit/vehicleController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllVehicles(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getVehicleById(req, res);
});
router.post("/ids", async (req: Request, res: Response) => {
await getVehiclesByIds(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "vehicle"),
async (req: Request, res: Response) => {
await createVehicle(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "vehicle"),
async (req: Request, res: Response) => {
await updateVehicleById(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "vehicle"),
async (req: Request, res: Response) => {
await deleteVehicleById(req, res);
}
);
export default router;

View file

@ -0,0 +1,45 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createVehicleType,
deleteVehicleTypeById,
getAllVehicleTypes,
getVehicleTypeById,
updateVehicleTypeById,
} from "../../../controller/admin/unit/vehicleTypeController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllVehicleTypes(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getVehicleTypeById(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "vehicle_type"),
async (req: Request, res: Response) => {
await createVehicleType(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "vehicle_type"),
async (req: Request, res: Response) => {
await updateVehicleTypeById(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "vehicle_type"),
async (req: Request, res: Response) => {
await deleteVehicleTypeById(req, res);
}
);
export default router;

View file

@ -0,0 +1,50 @@
import express, { Request, Response } from "express";
import PermissionHelper from "../../../helpers/permissionHelper";
import {
createWearable,
deleteWearableById,
getAllWearables,
getWearableById,
getWearablesByIds,
updateWearableById,
} from "../../../controller/admin/unit/wearableController";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllWearables(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getWearableById(req, res);
});
router.post("/ids", async (req: Request, res: Response) => {
await getWearablesByIds(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "unit", "wearable"),
async (req: Request, res: Response) => {
await createWearable(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "unit", "wearable"),
async (req: Request, res: Response) => {
await updateWearableById(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "unit", "wearable"),
async (req: Request, res: Response) => {
await deleteWearableById(req, res);
}
);
export default router;

Some files were not shown because too many files have changed in this diff Show more