From 15a511f942bbd846913ff7552c9a1c3ac2e266fd Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 24 May 2025 11:30:58 +0200 Subject: [PATCH 01/34] add viewmodels from frontend --- .../unit/damageReport/damageReport.models.ts | 27 ++++++++++++ .../admin/unit/equipment/equipment.models.ts | 31 ++++++++++++++ .../equipmentType/equipmentType.models.ts | 19 +++++++++ .../unit/inspection/inspection.models.ts | 37 +++++++++++++++++ .../inspectionPlan/inspectionPlan.models.ts | 41 +++++++++++++++++++ .../respiratoryGear/respiratoryGear.models.ts | 16 ++++++++ .../respiratoryMission.models.ts | 20 +++++++++ .../respiratoryWearer.models.ts | 16 ++++++++ .../admin/unit/vehicle/vehicle.models.ts | 31 ++++++++++++++ .../unit/vehicleType/vehicleType.models.ts | 19 +++++++++ .../admin/unit/wearable/wearable.models.ts | 34 +++++++++++++++ .../unit/wearableType/wearableType.models.ts | 16 ++++++++ 12 files changed, 307 insertions(+) create mode 100644 src/viewmodel/admin/unit/damageReport/damageReport.models.ts create mode 100644 src/viewmodel/admin/unit/equipment/equipment.models.ts create mode 100644 src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts create mode 100644 src/viewmodel/admin/unit/inspection/inspection.models.ts create mode 100644 src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts create mode 100644 src/viewmodel/admin/unit/respiratoryGear/respiratoryGear.models.ts create mode 100644 src/viewmodel/admin/unit/respiratoryMission/respiratoryMission.models.ts create mode 100644 src/viewmodel/admin/unit/respiratoryWearer/respiratoryWearer.models.ts create mode 100644 src/viewmodel/admin/unit/vehicle/vehicle.models.ts create mode 100644 src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts create mode 100644 src/viewmodel/admin/unit/wearable/wearable.models.ts create mode 100644 src/viewmodel/admin/unit/wearableType/wearableType.models.ts diff --git a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts b/src/viewmodel/admin/unit/damageReport/damageReport.models.ts new file mode 100644 index 0000000..b95ee33 --- /dev/null +++ b/src/viewmodel/admin/unit/damageReport/damageReport.models.ts @@ -0,0 +1,27 @@ +import type { EquipmentViewModel } from "../equipment/equipment.models"; +import type { VehicleViewModel } from "../vehicle/vehicle.models"; +import type { WearableViewModel } from "../wearable/wearable.models"; + +export interface DamageReportViewModel { + id: string; + reported: Date; + status: string; + done: boolean; + description: string; + providedImage: Array; + relatedId: string; + related: EquipmentViewModel | VehicleViewModel | WearableViewModel; + affected: "equipment" | "vehicle" | "wearable"; +} + +export interface CreateDamageReportViewModel { + description: string; + affectedId: string; + affected: "equipment" | "vehicle" | "wearable"; +} + +export interface UpdateDamageReportViewModel { + id: string; + status: string; + done: boolean; +} diff --git a/src/viewmodel/admin/unit/equipment/equipment.models.ts b/src/viewmodel/admin/unit/equipment/equipment.models.ts new file mode 100644 index 0000000..dcd4cea --- /dev/null +++ b/src/viewmodel/admin/unit/equipment/equipment.models.ts @@ -0,0 +1,31 @@ +import type { EquipmentTypeViewModel } from "../equipmentType/equipmentType.models"; +import type { InspectionViewModel } from "../inspection/inspection.models"; + +export interface EquipmentViewModel { + id: string; + code?: string; + name: string; + location: string; + commissioned: Date; + decommissioned?: Date; + equipmentTypeId: string; + equipmentType: EquipmentTypeViewModel; + inspections: Array; +} + +export interface CreateEquipmentViewModel { + code?: string; + name: string; + location: string; + commissioned: Date; + equipmentTypeId: string; +} + +export interface UpdateEquipmentViewModel { + id: string; + code?: string; + name: string; + location: string; + commissioned: Date; + decommissioned?: Date; +} diff --git a/src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts b/src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts new file mode 100644 index 0000000..e3116c9 --- /dev/null +++ b/src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts @@ -0,0 +1,19 @@ +import type { InspectionPlanViewModel } from "../inspectionPlan/inspectionPlan.models"; + +export interface EquipmentTypeViewModel { + id: string; + type: string; + description: string; + inspectionPlans: Array; +} + +export interface CreateEquipmentTypeViewModel { + type: string; + description: string; +} + +export interface UpdateEquipmentTypeViewModel { + id: string; + type: string; + description: string; +} diff --git a/src/viewmodel/admin/unit/inspection/inspection.models.ts b/src/viewmodel/admin/unit/inspection/inspection.models.ts new file mode 100644 index 0000000..a25c279 --- /dev/null +++ b/src/viewmodel/admin/unit/inspection/inspection.models.ts @@ -0,0 +1,37 @@ +import type { EquipmentViewModel } from "../equipment/equipment.models"; +import type { + InspectionPlanViewModel, + InspectionVersionedPlanViewModel, +} from "../inspectionPlan/inspectionPlan.models"; +import type { VehicleViewModel } from "../vehicle/vehicle.models"; + +export interface InspectionViewModel { + id: string; + inspectionPlanId: string; + inspectionPlan: InspectionPlanViewModel; + inspectionVersionedPlanId: string; + inspectionVersionedPlan: InspectionVersionedPlanViewModel; + context: string; + created: Date; + finished?: Date; + isOpen: boolean; + nextInspection?: Date; + checks: Array; + relatedId: string; + related: EquipmentViewModel | VehicleViewModel; +} + +export interface InspectionPointViewModel { + id: string; + title: string; + description: string; + type: "iO-niO" | "text" | "number"; + min?: number; +} + +export interface InspectionPointResultViewModel { + inspectionId: string; + inspectionVersionedPlanId: string; + inspectionPointId: string; + value: string; +} diff --git a/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts new file mode 100644 index 0000000..cdfb8b2 --- /dev/null +++ b/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts @@ -0,0 +1,41 @@ +import type { EquipmentViewModel } from "../equipment/equipment.models"; +import type { EquipmentTypeViewModel } from "../equipmentType/equipmentType.models"; +import type { InspectionPointViewModel } from "../inspection/inspection.models"; +import type { VehicleViewModel } from "../vehicle/vehicle.models"; +import type { VehicleTypeViewModel } from "../vehicleType/vehicleType.models"; + +export type PlanTimeDefinition = `${number}-${"d" | "m" | "y"}` | `${number}/${number | "*"}`; + +export interface InspectionPlanViewModel { + id: string; + title: string; + inspectionInterval: PlanTimeDefinition; + remindTime: PlanTimeDefinition; + version: number; + created: Date; + inspectionPoints: InspectionPointViewModel[]; + relatedId: string; + related: EquipmentTypeViewModel | VehicleTypeViewModel; +} + +export interface InspectionVersionedPlanViewModel { + id: string; + version: number; + created: Date; + inspectionPoints: InspectionPointViewModel[]; +} + +export interface CreateInspectionPlanViewModel { + title: string; + inspectionInterval: PlanTimeDefinition; + remindTime: PlanTimeDefinition; + relatedId: string; + assigned: "vehicle" | "equipment"; +} + +export interface UpdateInspectionPlanViewModel { + id: string; + title: string; + inspectionInterval: PlanTimeDefinition; + remindTime?: PlanTimeDefinition; +} diff --git a/src/viewmodel/admin/unit/respiratoryGear/respiratoryGear.models.ts b/src/viewmodel/admin/unit/respiratoryGear/respiratoryGear.models.ts new file mode 100644 index 0000000..07f4ec8 --- /dev/null +++ b/src/viewmodel/admin/unit/respiratoryGear/respiratoryGear.models.ts @@ -0,0 +1,16 @@ +import type { EquipmentViewModel } from "../equipment/equipment.models"; + +export interface RespiratoryGearViewModel { + id: string; + equipmentId: string; + equipment: EquipmentViewModel; +} + +export interface CreateRespiratoryGearViewModel { + equipmentId: string; +} + +export interface UpdateRespiratoryGearViewModel { + id: string; + equipmentId: string; +} diff --git a/src/viewmodel/admin/unit/respiratoryMission/respiratoryMission.models.ts b/src/viewmodel/admin/unit/respiratoryMission/respiratoryMission.models.ts new file mode 100644 index 0000000..49c6e7f --- /dev/null +++ b/src/viewmodel/admin/unit/respiratoryMission/respiratoryMission.models.ts @@ -0,0 +1,20 @@ +export interface RespiratoryMissionViewModel { + id: string; + date: Date; + title: string; + description: string; + // refs to used respiratory gear and wearers +} + +export interface CreateRespiratoryMissionViewModel { + date: Date; + title: string; + description: string; +} + +export interface UpdateRespiratoryMissionViewModel { + id: string; + date: Date; + title: string; + description: string; +} diff --git a/src/viewmodel/admin/unit/respiratoryWearer/respiratoryWearer.models.ts b/src/viewmodel/admin/unit/respiratoryWearer/respiratoryWearer.models.ts new file mode 100644 index 0000000..2957408 --- /dev/null +++ b/src/viewmodel/admin/unit/respiratoryWearer/respiratoryWearer.models.ts @@ -0,0 +1,16 @@ +import { MemberViewModel } from "../../club/member/member.models"; + +export interface RespiratoryWearerViewModel { + id: string; + memberId: string; + member: MemberViewModel; +} + +export interface CreateRespiratoryWearerViewModel { + memberId: string; +} + +export interface UpdateRespiratoryWearerViewModel { + id: string; + memberId: string; +} diff --git a/src/viewmodel/admin/unit/vehicle/vehicle.models.ts b/src/viewmodel/admin/unit/vehicle/vehicle.models.ts new file mode 100644 index 0000000..0bfccb6 --- /dev/null +++ b/src/viewmodel/admin/unit/vehicle/vehicle.models.ts @@ -0,0 +1,31 @@ +import type { InspectionViewModel } from "../inspection/inspection.models"; +import type { VehicleTypeViewModel } from "../vehicleType/vehicleType.models"; + +export interface VehicleViewModel { + id: string; + code?: string; + name: string; + location: string; + commissioned: Date; + decommissioned?: Date; + vehicleTypeId: string; + vehicleType: VehicleTypeViewModel; + inspections: Array; +} + +export interface CreateVehicleViewModel { + code?: string; + name: string; + location: string; + commissioned: Date; + vehicleTypeId: string; +} + +export interface UpdateVehicleViewModel { + id: string; + code?: string; + name: string; + location: string; + commissioned: Date; + decommissioned?: Date; +} diff --git a/src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts b/src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts new file mode 100644 index 0000000..2de497f --- /dev/null +++ b/src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts @@ -0,0 +1,19 @@ +import type { InspectionPlanViewModel } from "../inspectionPlan/inspectionPlan.models"; + +export interface VehicleTypeViewModel { + id: string; + type: string; + description: string; + inspectionPlans: Array; +} + +export interface CreateVehicleTypeViewModel { + type: string; + description: string; +} + +export interface UpdateVehicleTypeViewModel { + id: string; + type: string; + description: string; +} diff --git a/src/viewmodel/admin/unit/wearable/wearable.models.ts b/src/viewmodel/admin/unit/wearable/wearable.models.ts new file mode 100644 index 0000000..5e4fccc --- /dev/null +++ b/src/viewmodel/admin/unit/wearable/wearable.models.ts @@ -0,0 +1,34 @@ +import { MemberViewModel } from "../../club/member/member.models"; +import type { WearableTypeViewModel } from "../wearableType/wearableType.models"; + +export interface WearableViewModel { + id: string; + code?: string; + name: string; + location: string; + commissioned: Date; + decommissioned?: Date; + wearerId?: string; + wearer?: MemberViewModel; + wearableTypeId: string; + wearableType: WearableTypeViewModel; +} + +export interface CreateWearableViewModel { + code?: string; + name: string; + wearerId?: string; + location?: string; + commissioned: Date; + wearableTypeId: string; +} + +export interface UpdateWearableViewModel { + id: string; + code?: string; + name: string; + location?: string; + commissioned: Date; + decommissioned?: Date; + wearerId?: string; +} diff --git a/src/viewmodel/admin/unit/wearableType/wearableType.models.ts b/src/viewmodel/admin/unit/wearableType/wearableType.models.ts new file mode 100644 index 0000000..b3f49fc --- /dev/null +++ b/src/viewmodel/admin/unit/wearableType/wearableType.models.ts @@ -0,0 +1,16 @@ +export interface WearableTypeViewModel { + id: string; + type: string; + description: string; +} + +export interface CreateWearableTypeViewModel { + type: string; + description: string; +} + +export interface UpdateWearableTypeViewModel { + id: string; + type: string; + description: string; +} From 95d1113ff93002d51f4f203e3c52e6fe4d086329 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 24 May 2025 11:31:15 +0200 Subject: [PATCH 02/34] base unit data --- src/entity/unit/damageReport.ts | 52 ++++++++++++++++++++++ src/entity/unit/equipment/equipment.ts | 38 ++++++++++++++++ src/entity/unit/equipment/equipmentType.ts | 19 ++++++++ src/entity/unit/vehicle/vehicle.ts | 38 ++++++++++++++++ src/entity/unit/vehicle/vehicleType.ts | 19 ++++++++ src/entity/unit/wearable/wearable.ts | 49 ++++++++++++++++++++ src/entity/unit/wearable/wearableType.ts | 17 +++++++ 7 files changed, 232 insertions(+) create mode 100644 src/entity/unit/damageReport.ts create mode 100644 src/entity/unit/equipment/equipment.ts create mode 100644 src/entity/unit/equipment/equipmentType.ts create mode 100644 src/entity/unit/vehicle/vehicle.ts create mode 100644 src/entity/unit/vehicle/vehicleType.ts create mode 100644 src/entity/unit/wearable/wearable.ts create mode 100644 src/entity/unit/wearable/wearableType.ts diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts new file mode 100644 index 0000000..b8feefe --- /dev/null +++ b/src/entity/unit/damageReport.ts @@ -0,0 +1,52 @@ +import { Check, Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { Equipment } from "./equipment/equipment"; +import { Wearable } from "./wearable/wearable"; +import { Vehicle } from "./vehicle/vehicle"; + +@Entity() +export class DamageReport { + @PrimaryGeneratedColumn("uuid") + id: string; + + @CreateDateColumn() + reported: Date; + + @Column({ type: "varchar", length: 255 }) + status: string; + + @Column({ type: "boolean", default: false }) + done: boolean; + + @Column({ type: "text" }) + description: string; + + @Column({ nullable: true }) + equipmentId: string; + + @Column({ nullable: true }) + vehicleId: string; + + @Column({ nullable: true }) + wearableId: string; + + @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; +} diff --git a/src/entity/unit/equipment/equipment.ts b/src/entity/unit/equipment/equipment.ts new file mode 100644 index 0000000..9748cb1 --- /dev/null +++ b/src/entity/unit/equipment/equipment.ts @@ -0,0 +1,38 @@ +import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { getTypeByORM } from "../../../migrations/ormHelper"; +import { EquipmentType } from "./equipmentType"; +import { DamageReport } from "../damageReport"; + +@Entity() +export class Equipment { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255, nullable: true, unique: true }) + code?: string; + + @Column({ type: "varchar", length: 255 }) + name: string; + + @Column({ type: "varchar", length: 255 }) + location: string; + + @Column({ type: getTypeByORM("datetime").type as ColumnType }) + commissioned: Date; + + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) + decommissioned?: Date; + + @Column() + equipmentTypeId: string; + + @ManyToOne(() => EquipmentType, { + nullable: false, + onDelete: "RESTRICT", + onUpdate: "RESTRICT", + }) + equipmentType: EquipmentType; + + @OneToMany(() => DamageReport, (d) => d.equipment, { cascade: ["insert"] }) + reports: DamageReport[]; +} diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts new file mode 100644 index 0000000..1bd25bd --- /dev/null +++ b/src/entity/unit/equipment/equipmentType.ts @@ -0,0 +1,19 @@ +import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Equipment } from "./equipment"; + +@Entity() +export class EquipmentType { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255 }) + type: string; + + @Column({ type: "text", nullable: true }) + description: string; + + @OneToMany(() => Equipment, (e) => e.equipmentType, { cascade: ["insert"] }) + equipment: Equipment[]; + + inspectionPlans: Array; +} diff --git a/src/entity/unit/vehicle/vehicle.ts b/src/entity/unit/vehicle/vehicle.ts new file mode 100644 index 0000000..cff687e --- /dev/null +++ b/src/entity/unit/vehicle/vehicle.ts @@ -0,0 +1,38 @@ +import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { getTypeByORM } from "../../../migrations/ormHelper"; +import { VehicleType } from "./vehicleType"; +import { DamageReport } from "../damageReport"; + +@Entity() +export class Vehicle { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255, nullable: true, unique: true }) + code?: string; + + @Column({ type: "varchar", length: 255 }) + name: string; + + @Column({ type: "varchar", length: 255 }) + location: string; + + @Column({ type: getTypeByORM("datetime").type as ColumnType }) + commissioned: Date; + + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) + decommissioned?: Date; + + @Column() + vehicleTypeId: string; + + @ManyToOne(() => VehicleType, { + nullable: false, + onDelete: "RESTRICT", + onUpdate: "RESTRICT", + }) + vehicleType: VehicleType; + + @OneToMany(() => DamageReport, (d) => d.vehicle, { cascade: ["insert"] }) + reports: DamageReport[]; +} diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts new file mode 100644 index 0000000..7f43510 --- /dev/null +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -0,0 +1,19 @@ +import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Vehicle } from "./vehicle"; + +@Entity() +export class VehicleType { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255 }) + type: string; + + @Column({ type: "text", nullable: true }) + description: string; + + @OneToMany(() => Vehicle, (e) => e.vehicleType, { cascade: ["insert"] }) + equipment: Vehicle[]; + + inspectionPlans: Array; +} diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts new file mode 100644 index 0000000..439025b --- /dev/null +++ b/src/entity/unit/wearable/wearable.ts @@ -0,0 +1,49 @@ +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"; + +@Entity() +export class Wearable { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255, nullable: true, unique: true }) + code?: string; + + @Column({ type: "varchar", length: 255 }) + name: string; + + @Column({ type: "varchar", length: 255 }) + location: string; + + @Column({ type: getTypeByORM("datetime").type as ColumnType }) + commissioned: Date; + + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) + decommissioned?: Date; + + @Column() + equipmentTypeId: string; + + @Column() + wearerId: string; + + @ManyToOne(() => WearableType, { + nullable: false, + onDelete: "RESTRICT", + onUpdate: "RESTRICT", + }) + wearableType: WearableType; + + @ManyToOne(() => member, { + nullable: false, + onDelete: "SET NULL", + onUpdate: "RESTRICT", + }) + wearer: member; + + @OneToMany(() => DamageReport, (d) => d.wearable, { cascade: ["insert"] }) + reports: DamageReport[]; +} diff --git a/src/entity/unit/wearable/wearableType.ts b/src/entity/unit/wearable/wearableType.ts new file mode 100644 index 0000000..f900b84 --- /dev/null +++ b/src/entity/unit/wearable/wearableType.ts @@ -0,0 +1,17 @@ +import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Wearable } from "./wearable"; + +@Entity() +export class WearableType { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255 }) + type: string; + + @Column({ type: "text", nullable: true }) + description: string; + + @OneToMany(() => Wearable, (e) => e.wearableType, { cascade: ["insert"] }) + equipment: Wearable[]; +} From 3ff44f7370294a43fc6d1e3c6cef8f52552cf9ae Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 24 May 2025 13:51:38 +0200 Subject: [PATCH 03/34] inspection data model --- src/entity/unit/inspection/inspection.ts | 36 ++++++++++++++++ src/entity/unit/inspection/inspectionPlan.ts | 42 +++++++++++++++++++ src/entity/unit/inspection/inspectionPoint.ts | 39 +++++++++++++++++ .../unit/inspection/inspectionPointResult.ts | 19 +++++++++ .../inspection/inspectionVersionedPlan.ts | 35 ++++++++++++++++ src/enums/inspectionEnum.ts | 5 +++ .../unit/damageReport/damageReport.models.ts | 19 +++++++-- .../unit/inspection/inspection.models.ts | 22 +++++----- .../inspectionPlan/inspectionPlan.models.ts | 26 +++++++++--- 9 files changed, 222 insertions(+), 21 deletions(-) create mode 100644 src/entity/unit/inspection/inspection.ts create mode 100644 src/entity/unit/inspection/inspectionPlan.ts create mode 100644 src/entity/unit/inspection/inspectionPoint.ts create mode 100644 src/entity/unit/inspection/inspectionPointResult.ts create mode 100644 src/entity/unit/inspection/inspectionVersionedPlan.ts create mode 100644 src/enums/inspectionEnum.ts diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts new file mode 100644 index 0000000..1537492 --- /dev/null +++ b/src/entity/unit/inspection/inspection.ts @@ -0,0 +1,36 @@ +import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, 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"; + +@Entity() +export class inspection { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "text" }) + context: string; + + @CreateDateColumn() + createdAt: Date; + + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) + finished?: Date; + + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) + nextInspection?: Date; + + @ManyToOne(() => inspectionPlan) + inspectionPlan: inspectionPlan; + + @ManyToOne(() => inspectionVersionedPlan) + inspectionVersionedPlan: inspectionVersionedPlan; + + @ManyToOne(() => Equipment) + equipment: Equipment; + + @ManyToOne(() => Vehicle) + vehicle: Vehicle; +} diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts new file mode 100644 index 0000000..491a1a3 --- /dev/null +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -0,0 +1,42 @@ +import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Equipment } from "../equipment/equipment"; +import { Vehicle } from "../vehicle/vehicle"; +import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspectionPlan/inspectionPlan.models"; +import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; + +@Entity() +export class inspectionPlan { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "varchar", length: 255 }) + title: string; + + @Column({ type: "varchar", length: 255 }) + inspectionInterval: PlanTimeDefinition; + + @Column({ type: "varchar", length: 255 }) + remindTime: PlanTimeDefinition; + + @CreateDateColumn() + created: Date; + + @Column() + equipmentId: string; + + @Column() + vehicleId: string; + + @ManyToOne(() => Equipment) + equipment: Equipment; + + @ManyToOne(() => Vehicle) + vehicle: Vehicle; + + @OneToMany(() => inspectionVersionedPlan, (ivp) => ivp.inspectionPlan, { + cascade: ["insert"], + }) + versionedPlans: inspectionVersionedPlan[]; + + latestVersionedPlan?: inspectionVersionedPlan; +} diff --git a/src/entity/unit/inspection/inspectionPoint.ts b/src/entity/unit/inspection/inspectionPoint.ts new file mode 100644 index 0000000..28be6e0 --- /dev/null +++ b/src/entity/unit/inspection/inspectionPoint.ts @@ -0,0 +1,39 @@ +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } 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", default: 0 }) + min: number; + + @ManyToOne(() => inspectionVersionedPlan, { + nullable: false, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) + versionedPlan: inspectionVersionedPlan; +} diff --git a/src/entity/unit/inspection/inspectionPointResult.ts b/src/entity/unit/inspection/inspectionPointResult.ts new file mode 100644 index 0000000..2460516 --- /dev/null +++ b/src/entity/unit/inspection/inspectionPointResult.ts @@ -0,0 +1,19 @@ +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { inspection } from "./inspection"; +import { inspectionPoint } from "./inspectionPoint"; +import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; + +@Entity() +export class inspectionPointResult { + @PrimaryGeneratedColumn("uuid") + id: string; + + @Column({ type: "text" }) + value: string; + + @ManyToOne(() => inspection) + inspection: inspection; + + @ManyToOne(() => inspectionPoint) + inspectionPoint: inspectionPoint; +} diff --git a/src/entity/unit/inspection/inspectionVersionedPlan.ts b/src/entity/unit/inspection/inspectionVersionedPlan.ts new file mode 100644 index 0000000..2e8195f --- /dev/null +++ b/src/entity/unit/inspection/inspectionVersionedPlan.ts @@ -0,0 +1,35 @@ +import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique } from "typeorm"; +import { Equipment } from "../equipment/equipment"; +import { Vehicle } from "../vehicle/vehicle"; +import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspectionPlan/inspectionPlan.models"; +import { inspectionPlan } from "./inspectionPlan"; +import { getTypeByORM } from "../../../migrations/ormHelper"; +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() + created: Date; + + @Column() + inspectionPlanId: string; + + @ManyToOne(() => inspectionPlan, { + nullable: false, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) + inspectionPlan: inspectionPlan; + + @OneToMany(() => inspectionPoint, (ip) => ip.versionedPlan, { + cascade: ["insert"], + }) + inspectionPoints: inspectionPoint[]; +} diff --git a/src/enums/inspectionEnum.ts b/src/enums/inspectionEnum.ts new file mode 100644 index 0000000..5c87e55 --- /dev/null +++ b/src/enums/inspectionEnum.ts @@ -0,0 +1,5 @@ +export enum InspectionPointEnum { + oknok = "oknok", + text = "text", + number = "number", +} diff --git a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts b/src/viewmodel/admin/unit/damageReport/damageReport.models.ts index b95ee33..e1d7075 100644 --- a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts +++ b/src/viewmodel/admin/unit/damageReport/damageReport.models.ts @@ -2,7 +2,7 @@ import type { EquipmentViewModel } from "../equipment/equipment.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; import type { WearableViewModel } from "../wearable/wearable.models"; -export interface DamageReportViewModel { +export type DamageReportViewModel = { id: string; reported: Date; status: string; @@ -10,9 +10,20 @@ export interface DamageReportViewModel { description: string; providedImage: Array; relatedId: string; - related: EquipmentViewModel | VehicleViewModel | WearableViewModel; - affected: "equipment" | "vehicle" | "wearable"; -} +} & ( + | { + assigned: "equipment"; + related: EquipmentViewModel; + } + | { + assigned: "vehicle"; + related: VehicleViewModel; + } + | { + assigned: "wearable"; + related: WearableViewModel; + } +); export interface CreateDamageReportViewModel { description: string; diff --git a/src/viewmodel/admin/unit/inspection/inspection.models.ts b/src/viewmodel/admin/unit/inspection/inspection.models.ts index a25c279..8cd2e5f 100644 --- a/src/viewmodel/admin/unit/inspection/inspection.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspection.models.ts @@ -5,7 +5,7 @@ import type { } from "../inspectionPlan/inspectionPlan.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; -export interface InspectionViewModel { +export type InspectionViewModel = { id: string; inspectionPlanId: string; inspectionPlan: InspectionPlanViewModel; @@ -18,16 +18,16 @@ export interface InspectionViewModel { nextInspection?: Date; checks: Array; relatedId: string; - related: EquipmentViewModel | VehicleViewModel; -} - -export interface InspectionPointViewModel { - id: string; - title: string; - description: string; - type: "iO-niO" | "text" | "number"; - min?: number; -} +} & ( + | { + assigned: "equipment"; + related: EquipmentViewModel; + } + | { + assigned: "vehicle"; + related: VehicleViewModel; + } +); export interface InspectionPointResultViewModel { inspectionId: string; diff --git a/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts index cdfb8b2..31384d7 100644 --- a/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts +++ b/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts @@ -1,12 +1,10 @@ +import { InspectionPointEnum } from "../../../../enums/inspectionEnum"; import type { EquipmentViewModel } from "../equipment/equipment.models"; -import type { EquipmentTypeViewModel } from "../equipmentType/equipmentType.models"; -import type { InspectionPointViewModel } from "../inspection/inspection.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; -import type { VehicleTypeViewModel } from "../vehicleType/vehicleType.models"; export type PlanTimeDefinition = `${number}-${"d" | "m" | "y"}` | `${number}/${number | "*"}`; -export interface InspectionPlanViewModel { +export type InspectionPlanViewModel = { id: string; title: string; inspectionInterval: PlanTimeDefinition; @@ -15,8 +13,16 @@ export interface InspectionPlanViewModel { created: Date; inspectionPoints: InspectionPointViewModel[]; relatedId: string; - related: EquipmentTypeViewModel | VehicleTypeViewModel; -} +} & ( + | { + assigned: "equipment"; + related: EquipmentViewModel; + } + | { + assigned: "vehicle"; + related: VehicleViewModel; + } +); export interface InspectionVersionedPlanViewModel { id: string; @@ -25,6 +31,14 @@ export interface InspectionVersionedPlanViewModel { inspectionPoints: InspectionPointViewModel[]; } +export interface InspectionPointViewModel { + id: string; + title: string; + description: string; + type: InspectionPointEnum; + min?: number; +} + export interface CreateInspectionPlanViewModel { title: string; inspectionInterval: PlanTimeDefinition; From 0d8499b8281bded19eb8a5ab0b90e403815d773c Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 25 May 2025 07:01:13 +0200 Subject: [PATCH 04/34] model clean and consistent naming --- src/entity/unit/damageReport.ts | 22 +++++++++---------- src/entity/unit/equipment/equipment.ts | 14 ++++++------ src/entity/unit/equipment/equipmentType.ts | 8 +++---- src/entity/unit/inspection/inspection.ts | 14 ++++++------ src/entity/unit/inspection/inspectionPlan.ts | 12 +++++----- .../unit/inspection/inspectionPointResult.ts | 1 - .../inspection/inspectionVersionedPlan.ts | 6 +---- src/entity/unit/vehicle/vehicle.ts | 14 ++++++------ src/entity/unit/vehicle/vehicleType.ts | 8 +++---- src/entity/unit/wearable/wearable.ts | 16 +++++++------- src/entity/unit/wearable/wearableType.ts | 8 +++---- 11 files changed, 59 insertions(+), 64 deletions(-) diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index b8feefe..746a25f 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -1,15 +1,15 @@ import { Check, Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; -import { Equipment } from "./equipment/equipment"; -import { Wearable } from "./wearable/wearable"; -import { Vehicle } from "./vehicle/vehicle"; +import { equipment } from "./equipment/equipment"; +import { wearable } from "./wearable/wearable"; +import { vehicle } from "./vehicle/vehicle"; @Entity() -export class DamageReport { +export class damageReport { @PrimaryGeneratedColumn("uuid") id: string; @CreateDateColumn() - reported: Date; + reportedAt: Date; @Column({ type: "varchar", length: 255 }) status: string; @@ -29,24 +29,24 @@ export class DamageReport { @Column({ nullable: true }) wearableId: string; - @ManyToOne(() => Equipment, { + @ManyToOne(() => equipment, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - equipment: Equipment; + equipment: equipment; - @ManyToOne(() => Vehicle, { + @ManyToOne(() => vehicle, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - vehicle: Vehicle; + vehicle: vehicle; - @ManyToOne(() => Wearable, { + @ManyToOne(() => wearable, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - wearable: Wearable; + wearable: wearable; } diff --git a/src/entity/unit/equipment/equipment.ts b/src/entity/unit/equipment/equipment.ts index 9748cb1..252c035 100644 --- a/src/entity/unit/equipment/equipment.ts +++ b/src/entity/unit/equipment/equipment.ts @@ -1,10 +1,10 @@ import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { getTypeByORM } from "../../../migrations/ormHelper"; -import { EquipmentType } from "./equipmentType"; -import { DamageReport } from "../damageReport"; +import { equipmentType } from "./equipmentType"; +import { damageReport } from "../damageReport"; @Entity() -export class Equipment { +export class equipment { @PrimaryGeneratedColumn("uuid") id: string; @@ -26,13 +26,13 @@ export class Equipment { @Column() equipmentTypeId: string; - @ManyToOne(() => EquipmentType, { + @ManyToOne(() => equipmentType, { nullable: false, onDelete: "RESTRICT", onUpdate: "RESTRICT", }) - equipmentType: EquipmentType; + equipmentType: equipmentType; - @OneToMany(() => DamageReport, (d) => d.equipment, { cascade: ["insert"] }) - reports: DamageReport[]; + @OneToMany(() => damageReport, (d) => d.equipment, { cascade: ["insert"] }) + reports: damageReport[]; } diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts index 1bd25bd..9aa6366 100644 --- a/src/entity/unit/equipment/equipmentType.ts +++ b/src/entity/unit/equipment/equipmentType.ts @@ -1,8 +1,8 @@ import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; -import { Equipment } from "./equipment"; +import { equipment } from "./equipment"; @Entity() -export class EquipmentType { +export class equipmentType { @PrimaryGeneratedColumn("uuid") id: string; @@ -12,8 +12,8 @@ export class EquipmentType { @Column({ type: "text", nullable: true }) description: string; - @OneToMany(() => Equipment, (e) => e.equipmentType, { cascade: ["insert"] }) - equipment: Equipment[]; + @OneToMany(() => equipment, (e) => e.equipmentType, { cascade: ["insert"] }) + equipment: equipment[]; inspectionPlans: Array; } diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 1537492..825caee 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -2,8 +2,8 @@ import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, PrimaryGenerat import { inspectionPlan } from "./inspectionPlan"; import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; import { getTypeByORM } from "../../../migrations/ormHelper"; -import { Vehicle } from "../vehicle/vehicle"; -import { Equipment } from "../equipment/equipment"; +import { vehicle } from "../vehicle/vehicle"; +import { equipment } from "../equipment/equipment"; @Entity() export class inspection { @@ -17,7 +17,7 @@ export class inspection { createdAt: Date; @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) - finished?: Date; + finishedAt?: Date; @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) nextInspection?: Date; @@ -28,9 +28,9 @@ export class inspection { @ManyToOne(() => inspectionVersionedPlan) inspectionVersionedPlan: inspectionVersionedPlan; - @ManyToOne(() => Equipment) - equipment: Equipment; + @ManyToOne(() => equipment) + equipment: equipment; - @ManyToOne(() => Vehicle) - vehicle: Vehicle; + @ManyToOne(() => vehicle) + vehicle: vehicle; } diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts index 491a1a3..b2c4358 100644 --- a/src/entity/unit/inspection/inspectionPlan.ts +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -1,6 +1,6 @@ import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; -import { Equipment } from "../equipment/equipment"; -import { Vehicle } from "../vehicle/vehicle"; +import { equipment } from "../equipment/equipment"; +import { vehicle } from "../vehicle/vehicle"; import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspectionPlan/inspectionPlan.models"; import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; @@ -27,11 +27,11 @@ export class inspectionPlan { @Column() vehicleId: string; - @ManyToOne(() => Equipment) - equipment: Equipment; + @ManyToOne(() => equipment) + equipment: equipment; - @ManyToOne(() => Vehicle) - vehicle: Vehicle; + @ManyToOne(() => vehicle) + vehicle: vehicle; @OneToMany(() => inspectionVersionedPlan, (ivp) => ivp.inspectionPlan, { cascade: ["insert"], diff --git a/src/entity/unit/inspection/inspectionPointResult.ts b/src/entity/unit/inspection/inspectionPointResult.ts index 2460516..018649b 100644 --- a/src/entity/unit/inspection/inspectionPointResult.ts +++ b/src/entity/unit/inspection/inspectionPointResult.ts @@ -1,7 +1,6 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; import { inspection } from "./inspection"; import { inspectionPoint } from "./inspectionPoint"; -import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; @Entity() export class inspectionPointResult { diff --git a/src/entity/unit/inspection/inspectionVersionedPlan.ts b/src/entity/unit/inspection/inspectionVersionedPlan.ts index 2e8195f..59d8d4a 100644 --- a/src/entity/unit/inspection/inspectionVersionedPlan.ts +++ b/src/entity/unit/inspection/inspectionVersionedPlan.ts @@ -1,9 +1,5 @@ import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique } from "typeorm"; -import { Equipment } from "../equipment/equipment"; -import { Vehicle } from "../vehicle/vehicle"; -import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspectionPlan/inspectionPlan.models"; import { inspectionPlan } from "./inspectionPlan"; -import { getTypeByORM } from "../../../migrations/ormHelper"; import { inspectionPoint } from "./inspectionPoint"; @Entity() @@ -16,7 +12,7 @@ export class inspectionVersionedPlan { version: number; @CreateDateColumn() - created: Date; + createdAt: Date; @Column() inspectionPlanId: string; diff --git a/src/entity/unit/vehicle/vehicle.ts b/src/entity/unit/vehicle/vehicle.ts index cff687e..a2cd129 100644 --- a/src/entity/unit/vehicle/vehicle.ts +++ b/src/entity/unit/vehicle/vehicle.ts @@ -1,10 +1,10 @@ import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { getTypeByORM } from "../../../migrations/ormHelper"; -import { VehicleType } from "./vehicleType"; -import { DamageReport } from "../damageReport"; +import { vehicleType } from "./vehicleType"; +import { damageReport } from "../damageReport"; @Entity() -export class Vehicle { +export class vehicle { @PrimaryGeneratedColumn("uuid") id: string; @@ -26,13 +26,13 @@ export class Vehicle { @Column() vehicleTypeId: string; - @ManyToOne(() => VehicleType, { + @ManyToOne(() => vehicleType, { nullable: false, onDelete: "RESTRICT", onUpdate: "RESTRICT", }) - vehicleType: VehicleType; + vehicleType: vehicleType; - @OneToMany(() => DamageReport, (d) => d.vehicle, { cascade: ["insert"] }) - reports: DamageReport[]; + @OneToMany(() => damageReport, (d) => d.vehicle, { cascade: ["insert"] }) + reports: damageReport[]; } diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts index 7f43510..fba4177 100644 --- a/src/entity/unit/vehicle/vehicleType.ts +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -1,8 +1,8 @@ import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; -import { Vehicle } from "./vehicle"; +import { vehicle } from "./vehicle"; @Entity() -export class VehicleType { +export class vehicleType { @PrimaryGeneratedColumn("uuid") id: string; @@ -12,8 +12,8 @@ export class VehicleType { @Column({ type: "text", nullable: true }) description: string; - @OneToMany(() => Vehicle, (e) => e.vehicleType, { cascade: ["insert"] }) - equipment: Vehicle[]; + @OneToMany(() => vehicle, (e) => e.vehicleType, { cascade: ["insert"] }) + vehicle: vehicle[]; inspectionPlans: Array; } diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index 439025b..509732d 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -1,11 +1,11 @@ import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { getTypeByORM } from "../../../migrations/ormHelper"; -import { WearableType } from "./wearableType"; -import { DamageReport } from "../damageReport"; +import { wearableType } from "./wearableType"; +import { damageReport } from "../damageReport"; import { member } from "../../club/member/member"; @Entity() -export class Wearable { +export class wearable { @PrimaryGeneratedColumn("uuid") id: string; @@ -25,17 +25,17 @@ export class Wearable { decommissioned?: Date; @Column() - equipmentTypeId: string; + wearableTypeId: string; @Column() wearerId: string; - @ManyToOne(() => WearableType, { + @ManyToOne(() => wearableType, { nullable: false, onDelete: "RESTRICT", onUpdate: "RESTRICT", }) - wearableType: WearableType; + wearableType: wearableType; @ManyToOne(() => member, { nullable: false, @@ -44,6 +44,6 @@ export class Wearable { }) wearer: member; - @OneToMany(() => DamageReport, (d) => d.wearable, { cascade: ["insert"] }) - reports: DamageReport[]; + @OneToMany(() => damageReport, (d) => d.wearable, { cascade: ["insert"] }) + reports: damageReport[]; } diff --git a/src/entity/unit/wearable/wearableType.ts b/src/entity/unit/wearable/wearableType.ts index f900b84..71e553e 100644 --- a/src/entity/unit/wearable/wearableType.ts +++ b/src/entity/unit/wearable/wearableType.ts @@ -1,8 +1,8 @@ import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; -import { Wearable } from "./wearable"; +import { wearable as wearable } from "./wearable"; @Entity() -export class WearableType { +export class wearableType { @PrimaryGeneratedColumn("uuid") id: string; @@ -12,6 +12,6 @@ export class WearableType { @Column({ type: "text", nullable: true }) description: string; - @OneToMany(() => Wearable, (e) => e.wearableType, { cascade: ["insert"] }) - equipment: Wearable[]; + @OneToMany(() => wearable, (e) => e.wearableType, { cascade: ["insert"] }) + wearable: wearable[]; } From d156cc6ad6f2aa6992a91be7de907dd644f24fdb Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 26 May 2025 14:53:25 +0200 Subject: [PATCH 05/34] base migration and schema optimization --- src/data-source.ts | 26 +++ src/entity/unit/damageReport.ts | 6 +- src/entity/unit/equipment/equipment.ts | 4 +- src/entity/unit/equipment/equipmentType.ts | 2 +- src/entity/unit/inspection/inspection.ts | 28 +++- src/entity/unit/inspection/inspectionPlan.ts | 2 +- src/entity/unit/inspection/inspectionPoint.ts | 8 +- .../unit/inspection/inspectionPointResult.ts | 12 +- src/entity/unit/vehicle/vehicle.ts | 4 +- src/entity/unit/vehicle/vehicleType.ts | 2 +- src/entity/unit/wearable/wearable.ts | 4 +- src/entity/unit/wearable/wearableType.ts | 2 +- src/migrations/1748261477410-unitBase.ts | 57 +++++++ src/migrations/baseSchemaTables/inspection.ts | 149 ++++++++++++++++++ src/migrations/baseSchemaTables/unit.ts | 103 ++++++++++++ .../baseSchemaTables/unit_extend.ts | 39 +++++ 16 files changed, 426 insertions(+), 22 deletions(-) create mode 100644 src/migrations/1748261477410-unitBase.ts create mode 100644 src/migrations/baseSchemaTables/inspection.ts create mode 100644 src/migrations/baseSchemaTables/unit.ts create mode 100644 src/migrations/baseSchemaTables/unit_extend.ts diff --git a/src/data-source.ts b/src/data-source.ts index 63de0f8..85fe595 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -56,6 +56,19 @@ import { SettingsFromEnv1745059495807 } from "./migrations/1745059495807-setting import { MemberCreatedAt1746006549262 } from "./migrations/1746006549262-memberCreatedAt"; import { UserLoginRoutine1746252454922 } from "./migrations/1746252454922-UserLoginRoutine"; import { SettingsFromEnv_SET1745059495808 } from "./migrations/1745059495808-settingsFromEnv_set"; +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 { UnitBase1748261477410 } from "./migrations/1748261477410-unitBase"; configCheck(); @@ -111,6 +124,18 @@ const dataSource = new DataSource({ webapi, webapiPermission, setting, + equipmentType, + equipment, + vehicleType, + vehicle, + wearableType, + wearable, + damageReport, + inspectionPlan, + inspectionVersionedPlan, + inspectionPoint, + inspection, + inspectionPointResult, ], migrations: [ BackupAndResetDatabase1738166124200, @@ -123,6 +148,7 @@ const dataSource = new DataSource({ SettingsFromEnv_SET1745059495808, MemberCreatedAt1746006549262, UserLoginRoutine1746252454922, + UnitBase1748261477410, ], migrationsRun: true, migrationsTransactionMode: "each", diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index 746a25f..54bd219 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -20,13 +20,13 @@ export class damageReport { @Column({ type: "text" }) description: string; - @Column({ nullable: true }) + @Column({ nullable: true, default: null }) equipmentId: string; - @Column({ nullable: true }) + @Column({ nullable: true, default: null }) vehicleId: string; - @Column({ nullable: true }) + @Column({ nullable: true, default: null }) wearableId: string; @ManyToOne(() => equipment, { diff --git a/src/entity/unit/equipment/equipment.ts b/src/entity/unit/equipment/equipment.ts index 252c035..22df384 100644 --- a/src/entity/unit/equipment/equipment.ts +++ b/src/entity/unit/equipment/equipment.ts @@ -8,7 +8,7 @@ export class equipment { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "varchar", length: 255, nullable: true, unique: true }) + @Column({ type: "varchar", length: 255, nullable: true, default: null, unique: true }) code?: string; @Column({ type: "varchar", length: 255 }) @@ -20,7 +20,7 @@ export class equipment { @Column({ type: getTypeByORM("datetime").type as ColumnType }) commissioned: Date; - @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null }) decommissioned?: Date; @Column() diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts index 9aa6366..d28fb72 100644 --- a/src/entity/unit/equipment/equipmentType.ts +++ b/src/entity/unit/equipment/equipmentType.ts @@ -6,7 +6,7 @@ export class equipmentType { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, unique: true }) type: string; @Column({ type: "text", nullable: true }) diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 825caee..23460f6 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -16,21 +16,37 @@ export class inspection { @CreateDateColumn() createdAt: Date; - @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) finishedAt?: Date; - @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) nextInspection?: Date; - @ManyToOne(() => inspectionPlan) + @ManyToOne(() => inspectionPlan, { + nullable: false, + onDelete: "RESTRICT", + onUpdate: "RESTRICT", + }) inspectionPlan: inspectionPlan; - @ManyToOne(() => inspectionVersionedPlan) + @ManyToOne(() => inspectionVersionedPlan, { + nullable: false, + onDelete: "RESTRICT", + onUpdate: "RESTRICT", + }) inspectionVersionedPlan: inspectionVersionedPlan; - @ManyToOne(() => equipment) + @ManyToOne(() => equipment, { + nullable: true, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) equipment: equipment; - @ManyToOne(() => vehicle) + @ManyToOne(() => vehicle, { + nullable: true, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) vehicle: vehicle; } diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts index b2c4358..9be6406 100644 --- a/src/entity/unit/inspection/inspectionPlan.ts +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -19,7 +19,7 @@ export class inspectionPlan { remindTime: PlanTimeDefinition; @CreateDateColumn() - created: Date; + createdAt: Date; @Column() equipmentId: string; diff --git a/src/entity/unit/inspection/inspectionPoint.ts b/src/entity/unit/inspection/inspectionPoint.ts index 28be6e0..5185355 100644 --- a/src/entity/unit/inspection/inspectionPoint.ts +++ b/src/entity/unit/inspection/inspectionPoint.ts @@ -27,9 +27,15 @@ export class inspectionPoint { }) type: InspectionPointEnum; - @Column({ type: "int", default: 0 }) + @Column({ type: "int", nullable: true, default: null }) min: number; + @Column({ type: "int", nullable: true, default: null }) + max: number; + + @Column() + versionedPlanId: string; + @ManyToOne(() => inspectionVersionedPlan, { nullable: false, onDelete: "CASCADE", diff --git a/src/entity/unit/inspection/inspectionPointResult.ts b/src/entity/unit/inspection/inspectionPointResult.ts index 018649b..4b44146 100644 --- a/src/entity/unit/inspection/inspectionPointResult.ts +++ b/src/entity/unit/inspection/inspectionPointResult.ts @@ -10,9 +10,17 @@ export class inspectionPointResult { @Column({ type: "text" }) value: string; - @ManyToOne(() => inspection) + @ManyToOne(() => inspection, { + nullable: false, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) inspection: inspection; - @ManyToOne(() => inspectionPoint) + @ManyToOne(() => inspectionPoint, { + nullable: false, + onDelete: "RESTRICT", + onUpdate: "RESTRICT", + }) inspectionPoint: inspectionPoint; } diff --git a/src/entity/unit/vehicle/vehicle.ts b/src/entity/unit/vehicle/vehicle.ts index a2cd129..0c30847 100644 --- a/src/entity/unit/vehicle/vehicle.ts +++ b/src/entity/unit/vehicle/vehicle.ts @@ -8,7 +8,7 @@ export class vehicle { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "varchar", length: 255, nullable: true, unique: true }) + @Column({ type: "varchar", length: 255, nullable: true, default: null, unique: true }) code?: string; @Column({ type: "varchar", length: 255 }) @@ -20,7 +20,7 @@ export class vehicle { @Column({ type: getTypeByORM("datetime").type as ColumnType }) commissioned: Date; - @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null }) decommissioned?: Date; @Column() diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts index fba4177..5773709 100644 --- a/src/entity/unit/vehicle/vehicleType.ts +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -6,7 +6,7 @@ export class vehicleType { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, unique: true }) type: string; @Column({ type: "text", nullable: true }) diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index 509732d..75a64b7 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -9,7 +9,7 @@ export class wearable { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "varchar", length: 255, nullable: true, unique: true }) + @Column({ type: "varchar", length: 255, nullable: true, default: null, unique: true }) code?: string; @Column({ type: "varchar", length: 255 }) @@ -21,7 +21,7 @@ export class wearable { @Column({ type: getTypeByORM("datetime").type as ColumnType }) commissioned: Date; - @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true }) + @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null }) decommissioned?: Date; @Column() diff --git a/src/entity/unit/wearable/wearableType.ts b/src/entity/unit/wearable/wearableType.ts index 71e553e..0905a33 100644 --- a/src/entity/unit/wearable/wearableType.ts +++ b/src/entity/unit/wearable/wearableType.ts @@ -6,7 +6,7 @@ export class wearableType { @PrimaryGeneratedColumn("uuid") id: string; - @Column({ type: "varchar", length: 255 }) + @Column({ type: "varchar", length: 255, unique: true }) type: string; @Column({ type: "text", nullable: true }) diff --git a/src/migrations/1748261477410-unitBase.ts b/src/migrations/1748261477410-unitBase.ts new file mode 100644 index 0000000..d4951c6 --- /dev/null +++ b/src/migrations/1748261477410-unitBase.ts @@ -0,0 +1,57 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; +import { + equipment_table, + equipment_type_table, + vehicle_table, + vehicle_type_table, + wearable_table, + wearable_type_table, +} from "./baseSchemaTables/unit"; +import { damage_report_table } from "./baseSchemaTables/unit_extend"; +import { + inspection_plan_table, + inspection_point_result_table, + inspection_point_table, + inspection_table, + inspection_versioned_plan_table, +} from "./baseSchemaTables/inspection"; + +export class UnitBase1748261477410 implements MigrationInterface { + name = "UnitBase1748261477410"; + + public async up(queryRunner: QueryRunner): Promise { + 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(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); + } + + public async down(queryRunner: QueryRunner): Promise { + 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(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); + } +} diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts new file mode 100644 index 0000000..9048e95 --- /dev/null +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -0,0 +1,149 @@ +import { Table, TableForeignKey, TableUnique, Unique } 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") }, + { name: "remindTime", ...getTypeByORM("varchar") }, + { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + ], + foreignKeys: [ + new TableForeignKey({ + columnNames: ["equipmentId"], + referencedColumnNames: ["id"], + referencedTableName: "equipment", + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }), + new TableForeignKey({ + columnNames: ["vehicleId"], + referencedColumnNames: ["id"], + referencedTableName: "vehicle", + 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("date"), 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), default: getDefaultByORM("null") }, + { name: "max", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { 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("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "finishedAt", ...getTypeByORM("date", true) }, + { name: "nextInspection", ...getTypeByORM("date", true) }, + { name: "inspectionPlanId", ...getTypeByORM("uuid") }, + { name: "inspectionVersionedPlanId", ...getTypeByORM("uuid") }, + { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + ], + foreignKeys: [ + 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", + }), + ], +}); + +export const inspection_point_result_table = new Table({ + name: "inspection_point_result", + columns: [ + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "value", ...getTypeByORM("text") }, + { name: "inspectionId", ...getTypeByORM("uuid") }, + { name: "inspectionPointId", ...getTypeByORM("uuid") }, + ], + 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", + }), + ], +}); diff --git a/src/migrations/baseSchemaTables/unit.ts b/src/migrations/baseSchemaTables/unit.ts new file mode 100644 index 0000000..aec48b3 --- /dev/null +++ b/src/migrations/baseSchemaTables/unit.ts @@ -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), default: getDefaultByORM("null"), isUnique: true }, + { name: "name", ...getTypeByORM("varchar") }, + { name: "location", ...getTypeByORM("varchar") }, + { name: "commissioned", ...getTypeByORM("date") }, + { name: "decommissioned", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { 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") }, + ], +}); + +export const vehicle_table = new Table({ + name: "vehicle", + columns: [ + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "code", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "name", ...getTypeByORM("varchar") }, + { name: "location", ...getTypeByORM("varchar") }, + { name: "commissioned", ...getTypeByORM("date") }, + { name: "decommissioned", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { 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") }, + ], +}); + +export const wearable_table = new Table({ + name: "wearable", + columns: [ + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "code", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "name", ...getTypeByORM("varchar") }, + { name: "location", ...getTypeByORM("varchar") }, + { name: "commissioned", ...getTypeByORM("date") }, + { name: "decommissioned", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { name: "wearableTypeId", ...getTypeByORM("uuid") }, + { name: "wearerId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + ], + 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") }, + ], +}); diff --git a/src/migrations/baseSchemaTables/unit_extend.ts b/src/migrations/baseSchemaTables/unit_extend.ts new file mode 100644 index 0000000..49ce9e9 --- /dev/null +++ b/src/migrations/baseSchemaTables/unit_extend.ts @@ -0,0 +1,39 @@ +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("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "status", ...getTypeByORM("varchar") }, + { name: "done", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "description", ...getTypeByORM("text") }, + { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + ], + foreignKeys: [ + 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", + }), + ], +}); From baa3b2cc8cf20605a3c715d732ba9ff35d6acc8c Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Tue, 27 May 2025 16:01:00 +0200 Subject: [PATCH 06/34] add reporter to damage report --- src/entity/unit/damageReport.ts | 3 +++ src/migrations/baseSchemaTables/unit_extend.ts | 1 + 2 files changed, 4 insertions(+) diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index 54bd219..a59c9e2 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -20,6 +20,9 @@ export class damageReport { @Column({ type: "text" }) description: string; + @Column({ type: "varchar", length: 255 }) + reportedBy: string; + @Column({ nullable: true, default: null }) equipmentId: string; diff --git a/src/migrations/baseSchemaTables/unit_extend.ts b/src/migrations/baseSchemaTables/unit_extend.ts index 49ce9e9..a81f8ac 100644 --- a/src/migrations/baseSchemaTables/unit_extend.ts +++ b/src/migrations/baseSchemaTables/unit_extend.ts @@ -9,6 +9,7 @@ export const damage_report_table = new Table({ { name: "status", ...getTypeByORM("varchar") }, { name: "done", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, { name: "description", ...getTypeByORM("text") }, + { name: "reportedBy", ...getTypeByORM("varchar") }, { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, From 8c81c8f336f22e7f97f9624fab14c38ba437230e Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 17:06:45 +0200 Subject: [PATCH 07/34] db schema connects --- src/entity/unit/equipment/equipment.ts | 4 ++++ src/entity/unit/equipment/equipmentType.ts | 4 +++- src/entity/unit/inspection/inspection.ts | 12 ++++++++++++ src/entity/unit/inspection/inspectionPointResult.ts | 6 ++++++ src/entity/unit/vehicle/vehicle.ts | 4 ++++ src/entity/unit/vehicle/vehicleType.ts | 4 +++- src/entity/unit/wearable/wearable.ts | 1 + 7 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/entity/unit/equipment/equipment.ts b/src/entity/unit/equipment/equipment.ts index 22df384..d55ea0d 100644 --- a/src/entity/unit/equipment/equipment.ts +++ b/src/entity/unit/equipment/equipment.ts @@ -2,6 +2,7 @@ import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColum import { getTypeByORM } from "../../../migrations/ormHelper"; import { equipmentType } from "./equipmentType"; import { damageReport } from "../damageReport"; +import { inspection } from "../inspection/inspection"; @Entity() export class equipment { @@ -35,4 +36,7 @@ export class equipment { @OneToMany(() => damageReport, (d) => d.equipment, { cascade: ["insert"] }) reports: damageReport[]; + + @OneToMany(() => inspection, (i) => i.equipment) + inspections: inspection[]; } diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts index d28fb72..3888ebe 100644 --- a/src/entity/unit/equipment/equipmentType.ts +++ b/src/entity/unit/equipment/equipmentType.ts @@ -1,5 +1,6 @@ import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { equipment } from "./equipment"; +import { inspectionPlan } from "../inspection/inspectionPlan"; @Entity() export class equipmentType { @@ -15,5 +16,6 @@ export class equipmentType { @OneToMany(() => equipment, (e) => e.equipmentType, { cascade: ["insert"] }) equipment: equipment[]; - inspectionPlans: Array; + @OneToMany(() => inspectionPlan, (ip) => ip.equipment) + inspectionPlans: inspectionPlan[]; } diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 23460f6..27b85c1 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -22,6 +22,18 @@ export class inspection { @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) nextInspection?: Date; + @Column() + inspectionPlanId: string; + + @Column() + inspectionVersionedPlanId: string; + + @Column() + equipmentId: string; + + @Column() + vehicleId: string; + @ManyToOne(() => inspectionPlan, { nullable: false, onDelete: "RESTRICT", diff --git a/src/entity/unit/inspection/inspectionPointResult.ts b/src/entity/unit/inspection/inspectionPointResult.ts index 4b44146..5b3501d 100644 --- a/src/entity/unit/inspection/inspectionPointResult.ts +++ b/src/entity/unit/inspection/inspectionPointResult.ts @@ -10,6 +10,12 @@ export class inspectionPointResult { @Column({ type: "text" }) value: string; + @Column() + inspectionId: string; + + @Column() + inspectionPointId: string; + @ManyToOne(() => inspection, { nullable: false, onDelete: "CASCADE", diff --git a/src/entity/unit/vehicle/vehicle.ts b/src/entity/unit/vehicle/vehicle.ts index 0c30847..dc4a8d6 100644 --- a/src/entity/unit/vehicle/vehicle.ts +++ b/src/entity/unit/vehicle/vehicle.ts @@ -2,6 +2,7 @@ import { Column, ColumnType, Entity, ManyToOne, OneToMany, PrimaryGeneratedColum import { getTypeByORM } from "../../../migrations/ormHelper"; import { vehicleType } from "./vehicleType"; import { damageReport } from "../damageReport"; +import { inspection } from "../inspection/inspection"; @Entity() export class vehicle { @@ -35,4 +36,7 @@ export class vehicle { @OneToMany(() => damageReport, (d) => d.vehicle, { cascade: ["insert"] }) reports: damageReport[]; + + @OneToMany(() => inspection, (i) => i.vehicle) + inspections: inspection[]; } diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts index 5773709..d58b478 100644 --- a/src/entity/unit/vehicle/vehicleType.ts +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -1,5 +1,6 @@ import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { vehicle } from "./vehicle"; +import { inspectionPlan } from "../inspection/inspectionPlan"; @Entity() export class vehicleType { @@ -15,5 +16,6 @@ export class vehicleType { @OneToMany(() => vehicle, (e) => e.vehicleType, { cascade: ["insert"] }) vehicle: vehicle[]; - inspectionPlans: Array; + @OneToMany(() => inspectionPlan, (ip) => ip.vehicle) + inspectionPlans: inspectionPlan[]; } diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index 75a64b7..f532cb0 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -3,6 +3,7 @@ import { getTypeByORM } from "../../../migrations/ormHelper"; import { wearableType } from "./wearableType"; import { damageReport } from "../damageReport"; import { member } from "../../club/member/member"; +import { inspection } from "../inspection/inspection"; @Entity() export class wearable { From 2433120e26704f98e17a3deb6f7e9a572eed1a29 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 17:06:56 +0200 Subject: [PATCH 08/34] service base --- src/service/unit/damageReport.ts | 41 +++++++++++++++++++ .../unit/equipment/equipmentService.ts | 41 +++++++++++++++++++ .../unit/equipment/equipmentTypeService.ts | 41 +++++++++++++++++++ .../unit/inspection/inspectionPlanService.ts | 41 +++++++++++++++++++ .../inspectionPointResultService.ts | 41 +++++++++++++++++++ .../unit/inspection/inspectionPointService.ts | 41 +++++++++++++++++++ .../unit/inspection/inspectionService.ts | 41 +++++++++++++++++++ .../inspectionVersionedPlanService.ts | 41 +++++++++++++++++++ src/service/unit/vehicle/vehicleService.ts | 41 +++++++++++++++++++ .../unit/vehicle/vehicleTypeService.ts | 41 +++++++++++++++++++ src/service/unit/wearable/wearableService.ts | 41 +++++++++++++++++++ .../unit/wearable/wearableTypeService.ts | 41 +++++++++++++++++++ .../unit/damageReport/damageReport.models.ts | 2 + 13 files changed, 494 insertions(+) create mode 100644 src/service/unit/damageReport.ts create mode 100644 src/service/unit/equipment/equipmentService.ts create mode 100644 src/service/unit/equipment/equipmentTypeService.ts create mode 100644 src/service/unit/inspection/inspectionPlanService.ts create mode 100644 src/service/unit/inspection/inspectionPointResultService.ts create mode 100644 src/service/unit/inspection/inspectionPointService.ts create mode 100644 src/service/unit/inspection/inspectionService.ts create mode 100644 src/service/unit/inspection/inspectionVersionedPlanService.ts create mode 100644 src/service/unit/vehicle/vehicleService.ts create mode 100644 src/service/unit/vehicle/vehicleTypeService.ts create mode 100644 src/service/unit/wearable/wearableService.ts create mode 100644 src/service/unit/wearable/wearableTypeService.ts diff --git a/src/service/unit/damageReport.ts b/src/service/unit/damageReport.ts new file mode 100644 index 0000000..0832766 --- /dev/null +++ b/src/service/unit/damageReport.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../data-source"; +import { damageReport } from "../../entity/unit/damageReport"; +import DatabaseActionException from "../../exceptions/databaseActionException"; + +export default abstract class DamageReportService { + /** + * @description get all damageReport types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(damageReport) + .createQueryBuilder("damageReport") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "damageReport", err); + }); + } + + /** + * @description get damageReport by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(damageReport) + .createQueryBuilder("damageReport") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "damageReport", err); + }); + } +} diff --git a/src/service/unit/equipment/equipmentService.ts b/src/service/unit/equipment/equipmentService.ts new file mode 100644 index 0000000..8c28427 --- /dev/null +++ b/src/service/unit/equipment/equipmentService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { equipment } from "../../../entity/unit/equipment/equipment"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class EquipmentService { + /** + * @description get all equipment types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(equipment) + .createQueryBuilder("equipment") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "equipment", err); + }); + } + + /** + * @description get equipment by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(equipment) + .createQueryBuilder("equipment") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "equipment", err); + }); + } +} diff --git a/src/service/unit/equipment/equipmentTypeService.ts b/src/service/unit/equipment/equipmentTypeService.ts new file mode 100644 index 0000000..4617544 --- /dev/null +++ b/src/service/unit/equipment/equipmentTypeService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { equipmentType } from "../../../entity/unit/equipment/equipmentType"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class EquipmentTypeService { + /** + * @description get all equipment types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(equipmentType) + .createQueryBuilder("equipmentType") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "equipmentType", err); + }); + } + + /** + * @description get equipmentType by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(equipmentType) + .createQueryBuilder("equipmentType") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "equipmentType", err); + }); + } +} diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts new file mode 100644 index 0000000..96fbab9 --- /dev/null +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { inspectionPlan } from "../../../entity/unit/inspection/inspectionPlan"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class InspectionPlanService { + /** + * @description get all inspectionPlan types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(inspectionPlan) + .createQueryBuilder("inspectionPlan") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPlan", err); + }); + } + + /** + * @description get inspectionPlan by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(inspectionPlan) + .createQueryBuilder("inspectionPlan") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPlan", err); + }); + } +} diff --git a/src/service/unit/inspection/inspectionPointResultService.ts b/src/service/unit/inspection/inspectionPointResultService.ts new file mode 100644 index 0000000..4ac3450 --- /dev/null +++ b/src/service/unit/inspection/inspectionPointResultService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { inspectionPointResult } from "../../../entity/unit/inspection/inspectionPointResult"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class InspectionPointResultService { + /** + * @description get all inspectionPointResult types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(inspectionPointResult) + .createQueryBuilder("inspectionPointResult") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPointResult", err); + }); + } + + /** + * @description get inspectionPointResult by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(inspectionPointResult) + .createQueryBuilder("inspectionPointResult") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPointResult", err); + }); + } +} diff --git a/src/service/unit/inspection/inspectionPointService.ts b/src/service/unit/inspection/inspectionPointService.ts new file mode 100644 index 0000000..4203550 --- /dev/null +++ b/src/service/unit/inspection/inspectionPointService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { inspectionPoint } from "../../../entity/unit/inspection/inspectionPoint"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class InspectionPointService { + /** + * @description get all inspectionPoint types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(inspectionPoint) + .createQueryBuilder("inspectionPoint") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPoint", err); + }); + } + + /** + * @description get inspectionPoint by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(inspectionPoint) + .createQueryBuilder("inspectionPoint") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPoint", err); + }); + } +} diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts new file mode 100644 index 0000000..cd8ba7d --- /dev/null +++ b/src/service/unit/inspection/inspectionService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { inspection } from "../../../entity/unit/inspection/inspection"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class InspectionService { + /** + * @description get all inspection types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(inspection) + .createQueryBuilder("inspection") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspection", err); + }); + } + + /** + * @description get inspection by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(inspection) + .createQueryBuilder("inspection") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspection", err); + }); + } +} diff --git a/src/service/unit/inspection/inspectionVersionedPlanService.ts b/src/service/unit/inspection/inspectionVersionedPlanService.ts new file mode 100644 index 0000000..ebaa296 --- /dev/null +++ b/src/service/unit/inspection/inspectionVersionedPlanService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { inspectionVersionedPlan } from "../../../entity/unit/inspection/inspectionVersionedPlan"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class InspectionVersionedPlanService { + /** + * @description get all inspectionVersionedPlan types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(inspectionVersionedPlan) + .createQueryBuilder("inspectionVersionedPlan") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionVersionedPlan", err); + }); + } + + /** + * @description get inspectionVersionedPlan by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(inspectionVersionedPlan) + .createQueryBuilder("inspectionVersionedPlan") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionVersionedPlan", err); + }); + } +} diff --git a/src/service/unit/vehicle/vehicleService.ts b/src/service/unit/vehicle/vehicleService.ts new file mode 100644 index 0000000..898911f --- /dev/null +++ b/src/service/unit/vehicle/vehicleService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { vehicle } from "../../../entity/unit/vehicle/vehicle"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class VehicleService { + /** + * @description get all vehicle types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(vehicle) + .createQueryBuilder("vehicle") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "vehicle", err); + }); + } + + /** + * @description get vehicle by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(vehicle) + .createQueryBuilder("vehicle") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "vehicle", err); + }); + } +} diff --git a/src/service/unit/vehicle/vehicleTypeService.ts b/src/service/unit/vehicle/vehicleTypeService.ts new file mode 100644 index 0000000..2af3acc --- /dev/null +++ b/src/service/unit/vehicle/vehicleTypeService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { vehicleType } from "../../../entity/unit/vehicle/vehicleType"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class VehicleTypeService { + /** + * @description get all vehicleType types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(vehicleType) + .createQueryBuilder("vehicleType") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "vehicleType", err); + }); + } + + /** + * @description get vehicleType by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(vehicleType) + .createQueryBuilder("vehicleType") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "vehicleType", err); + }); + } +} diff --git a/src/service/unit/wearable/wearableService.ts b/src/service/unit/wearable/wearableService.ts new file mode 100644 index 0000000..77c120a --- /dev/null +++ b/src/service/unit/wearable/wearableService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { wearable } from "../../../entity/unit/wearable/wearable"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class WearableService { + /** + * @description get all wearable types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(wearable) + .createQueryBuilder("wearable") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "wearable", err); + }); + } + + /** + * @description get wearable by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(wearable) + .createQueryBuilder("wearable") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "wearable", err); + }); + } +} diff --git a/src/service/unit/wearable/wearableTypeService.ts b/src/service/unit/wearable/wearableTypeService.ts new file mode 100644 index 0000000..77f7a90 --- /dev/null +++ b/src/service/unit/wearable/wearableTypeService.ts @@ -0,0 +1,41 @@ +import { dataSource } from "../../../data-source"; +import { wearableType } from "../../../entity/unit/wearable/wearableType"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; + +export default abstract class WearableTypeService { + /** + * @description get all wearableType types + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(wearableType) + .createQueryBuilder("wearableType") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "wearableType", err); + }); + } + + /** + * @description get wearableType by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(wearableType) + .createQueryBuilder("wearableType") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "wearableType", err); + }); + } +} diff --git a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts b/src/viewmodel/admin/unit/damageReport/damageReport.models.ts index e1d7075..a144114 100644 --- a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts +++ b/src/viewmodel/admin/unit/damageReport/damageReport.models.ts @@ -9,6 +9,7 @@ export type DamageReportViewModel = { done: boolean; description: string; providedImage: Array; + reportedBy: string; relatedId: string; } & ( | { @@ -27,6 +28,7 @@ export type DamageReportViewModel = { export interface CreateDamageReportViewModel { description: string; + reportedBy: string; affectedId: string; affected: "equipment" | "vehicle" | "wearable"; } From e404989a2858866a8dad97c5bd3c5e17a525aedc Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 17:13:39 +0200 Subject: [PATCH 09/34] add sort to inspection point --- src/entity/unit/inspection/inspectionPoint.ts | 5 ++++- src/migrations/baseSchemaTables/inspection.ts | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/entity/unit/inspection/inspectionPoint.ts b/src/entity/unit/inspection/inspectionPoint.ts index 5185355..2ff25b1 100644 --- a/src/entity/unit/inspection/inspectionPoint.ts +++ b/src/entity/unit/inspection/inspectionPoint.ts @@ -1,4 +1,4 @@ -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, Unique } from "typeorm"; import { InspectionPointEnum } from "../../../enums/inspectionEnum"; import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; @@ -33,6 +33,9 @@ export class inspectionPoint { @Column({ type: "int", nullable: true, default: null }) max: number; + @Column({ type: "int", default: 0 }) + sort: number; + @Column() versionedPlanId: string; diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index 9048e95..83e856f 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -64,6 +64,7 @@ export const inspection_point_table = new Table({ { name: "type", ...getTypeByORM("varchar") }, { name: "min", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, { name: "max", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "versionedPlanId", ...getTypeByORM("uuid") }, ], foreignKeys: [ From fcbfe560c3a347fd978f731be2414e01f9d2dcf1 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 17:32:07 +0200 Subject: [PATCH 10/34] basic services joins --- src/entity/unit/inspection/inspection.ts | 6 +++- src/service/unit/damageReport.ts | 2 +- .../unit/equipment/equipmentService.ts | 6 ++-- .../unit/equipment/equipmentTypeService.ts | 2 +- .../unit/inspection/inspectionPlanService.ts | 28 +++++++++++++++++-- .../inspectionPointResultService.ts | 8 ++++-- .../unit/inspection/inspectionPointService.ts | 7 +++-- .../unit/inspection/inspectionService.ts | 17 +++++++++-- .../inspectionVersionedPlanService.ts | 9 ++++-- src/service/unit/vehicle/vehicleService.ts | 6 ++-- .../unit/vehicle/vehicleTypeService.ts | 2 +- src/service/unit/wearable/wearableService.ts | 6 ++-- .../unit/wearable/wearableTypeService.ts | 2 +- 13 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 27b85c1..77e32d0 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -1,9 +1,10 @@ -import { Column, ColumnType, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +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"; @Entity() export class inspection { @@ -61,4 +62,7 @@ export class inspection { onUpdate: "RESTRICT", }) vehicle: vehicle; + + @OneToMany(() => inspectionPointResult, (ipr) => ipr.inspection) + pointResults: inspectionPointResult[]; } diff --git a/src/service/unit/damageReport.ts b/src/service/unit/damageReport.ts index 0832766..b6134d6 100644 --- a/src/service/unit/damageReport.ts +++ b/src/service/unit/damageReport.ts @@ -4,7 +4,7 @@ import DatabaseActionException from "../../exceptions/databaseActionException"; export default abstract class DamageReportService { /** - * @description get all damageReport types + * @description get all damageReports * @returns {Promise>} */ static async getAll(): Promise> { diff --git a/src/service/unit/equipment/equipmentService.ts b/src/service/unit/equipment/equipmentService.ts index 8c28427..a2e1823 100644 --- a/src/service/unit/equipment/equipmentService.ts +++ b/src/service/unit/equipment/equipmentService.ts @@ -4,14 +4,15 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class EquipmentService { /** - * @description get all equipment types + * @description get all equipment * @returns {Promise>} */ static async getAll(): Promise> { return await dataSource .getRepository(equipment) .createQueryBuilder("equipment") - .orderBy("type", "ASC") + .leftJoinAndSelect("equipment.equipmentType", "equipmenttype") + .orderBy("name", "ASC") .getMany() .then((res) => { return res; @@ -29,6 +30,7 @@ export default abstract class EquipmentService { return await dataSource .getRepository(equipment) .createQueryBuilder("equipment") + .leftJoinAndSelect("equipment.equipmentType", "equipmenttype") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/equipment/equipmentTypeService.ts b/src/service/unit/equipment/equipmentTypeService.ts index 4617544..237b0cd 100644 --- a/src/service/unit/equipment/equipmentTypeService.ts +++ b/src/service/unit/equipment/equipmentTypeService.ts @@ -4,7 +4,7 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class EquipmentTypeService { /** - * @description get all equipment types + * @description get all equipmentTypes * @returns {Promise>} */ static async getAll(): Promise> { diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index 96fbab9..0e2cc47 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -1,17 +1,30 @@ import { dataSource } from "../../../data-source"; import { inspectionPlan } from "../../../entity/unit/inspection/inspectionPlan"; +import { DB_TYPE } from "../../../env.defaults"; import DatabaseActionException from "../../../exceptions/databaseActionException"; export default abstract class InspectionPlanService { /** - * @description get all inspectionPlan types + * @description get all inspectionPlans for related * @returns {Promise>} */ - static async getAll(): Promise> { + static async getAllForRelated( + where: { equipmentId: string } | { vehicleId: string } + ): Promise> { return await dataSource .getRepository(inspectionPlan) .createQueryBuilder("inspectionPlan") - .orderBy("type", "ASC") + .leftJoinAndMapOne( + "inspectionPlan.latestVersionedPlan", + "inspectionPlan.versionedPlans", + "latestVersionedPlan", + DB_TYPE == "postgres" + ? 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."start") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' + : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.start) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" + ) + .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") + .where(where) + .orderBy("title", "ASC") .getMany() .then((res) => { return res; @@ -29,6 +42,15 @@ export default abstract class InspectionPlanService { return await dataSource .getRepository(inspectionPlan) .createQueryBuilder("inspectionPlan") + .leftJoinAndMapOne( + "inspectionPlan.latestVersionedPlan", + "inspectionPlan.versionedPlans", + "latestVersionedPlan", + DB_TYPE == "postgres" + ? 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."start") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' + : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.start) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" + ) + .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/inspection/inspectionPointResultService.ts b/src/service/unit/inspection/inspectionPointResultService.ts index 4ac3450..d538a63 100644 --- a/src/service/unit/inspection/inspectionPointResultService.ts +++ b/src/service/unit/inspection/inspectionPointResultService.ts @@ -4,14 +4,15 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class InspectionPointResultService { /** - * @description get all inspectionPointResult types + * @description get all inspectionPointResults * @returns {Promise>} */ - static async getAll(): Promise> { + static async getAllForInspection(inspectionId: string): Promise> { return await dataSource .getRepository(inspectionPointResult) .createQueryBuilder("inspectionPointResult") - .orderBy("type", "ASC") + .leftJoinAndSelect("inspectionPointResult.inspectionPoint", "inspectionPoint") + .where({ inspectionId }) .getMany() .then((res) => { return res; @@ -29,6 +30,7 @@ export default abstract class InspectionPointResultService { return await dataSource .getRepository(inspectionPointResult) .createQueryBuilder("inspectionPointResult") + .leftJoinAndSelect("inspectionPointResult.inspectionPoint", "inspectionPoint") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/inspection/inspectionPointService.ts b/src/service/unit/inspection/inspectionPointService.ts index 4203550..0285c9f 100644 --- a/src/service/unit/inspection/inspectionPointService.ts +++ b/src/service/unit/inspection/inspectionPointService.ts @@ -4,14 +4,15 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class InspectionPointService { /** - * @description get all inspectionPoint types + * @description get all inspectionPoints * @returns {Promise>} */ - static async getAll(): Promise> { + static async getAllForVersionedPlan(versionedPlanId: string): Promise> { return await dataSource .getRepository(inspectionPoint) .createQueryBuilder("inspectionPoint") - .orderBy("type", "ASC") + .where({ versionedPlanId }) + .orderBy("sort", "ASC") .getMany() .then((res) => { return res; diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index cd8ba7d..8262dd9 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -4,14 +4,20 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class InspectionService { /** - * @description get all inspection types + * @description get all inspections for related * @returns {Promise>} */ - static async getAll(): Promise> { + static async getAllForRelated(where: { equipmentId: string } | { vehicleId: string }): Promise> { return await dataSource .getRepository(inspection) .createQueryBuilder("inspection") - .orderBy("type", "ASC") + .leftJoinAndSelect("inspection.inspectionPlan", "inspectionPlan") + .leftJoinAndSelect("inspection.inspectionVersionedPlan", "inspectionVersionedPlan") + .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") + .leftJoinAndSelect("inspection.pointResults", "pointResults") + .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") + .where(where) + .orderBy("createdAt", "DESC") .getMany() .then((res) => { return res; @@ -29,6 +35,11 @@ export default abstract class InspectionService { return await dataSource .getRepository(inspection) .createQueryBuilder("inspection") + .leftJoinAndSelect("inspection.inspectionPlan", "inspectionPlan") + .leftJoinAndSelect("inspection.inspectionVersionedPlan", "inspectionVersionedPlan") + .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") + .leftJoinAndSelect("inspection.pointResults", "pointResults") + .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/inspection/inspectionVersionedPlanService.ts b/src/service/unit/inspection/inspectionVersionedPlanService.ts index ebaa296..9313979 100644 --- a/src/service/unit/inspection/inspectionVersionedPlanService.ts +++ b/src/service/unit/inspection/inspectionVersionedPlanService.ts @@ -4,14 +4,16 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class InspectionVersionedPlanService { /** - * @description get all inspectionVersionedPlan types + * @description get all inspectionVersionedPlans * @returns {Promise>} */ - static async getAll(): Promise> { + static async getAllForInspectionPlan(inspectionPlanId: string): Promise> { return await dataSource .getRepository(inspectionVersionedPlan) .createQueryBuilder("inspectionVersionedPlan") - .orderBy("type", "ASC") + .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") + .where({ inspectionPlanId }) + .orderBy("version", "ASC") .getMany() .then((res) => { return res; @@ -29,6 +31,7 @@ export default abstract class InspectionVersionedPlanService { return await dataSource .getRepository(inspectionVersionedPlan) .createQueryBuilder("inspectionVersionedPlan") + .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/vehicle/vehicleService.ts b/src/service/unit/vehicle/vehicleService.ts index 898911f..39d7b06 100644 --- a/src/service/unit/vehicle/vehicleService.ts +++ b/src/service/unit/vehicle/vehicleService.ts @@ -4,14 +4,15 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class VehicleService { /** - * @description get all vehicle types + * @description get all vehicles * @returns {Promise>} */ static async getAll(): Promise> { return await dataSource .getRepository(vehicle) .createQueryBuilder("vehicle") - .orderBy("type", "ASC") + .leftJoinAndSelect("vehicle.vehicleType", "vehicletype") + .orderBy("name", "ASC") .getMany() .then((res) => { return res; @@ -29,6 +30,7 @@ export default abstract class VehicleService { return await dataSource .getRepository(vehicle) .createQueryBuilder("vehicle") + .leftJoinAndSelect("vehicle.vehicleType", "vehicletype") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/vehicle/vehicleTypeService.ts b/src/service/unit/vehicle/vehicleTypeService.ts index 2af3acc..8ba8104 100644 --- a/src/service/unit/vehicle/vehicleTypeService.ts +++ b/src/service/unit/vehicle/vehicleTypeService.ts @@ -4,7 +4,7 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class VehicleTypeService { /** - * @description get all vehicleType types + * @description get all vehicleTypes * @returns {Promise>} */ static async getAll(): Promise> { diff --git a/src/service/unit/wearable/wearableService.ts b/src/service/unit/wearable/wearableService.ts index 77c120a..9fc7325 100644 --- a/src/service/unit/wearable/wearableService.ts +++ b/src/service/unit/wearable/wearableService.ts @@ -4,14 +4,15 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class WearableService { /** - * @description get all wearable types + * @description get all wearables * @returns {Promise>} */ static async getAll(): Promise> { return await dataSource .getRepository(wearable) .createQueryBuilder("wearable") - .orderBy("type", "ASC") + .leftJoinAndSelect("wearable.wearableType", "wearabletype") + .orderBy("name", "ASC") .getMany() .then((res) => { return res; @@ -29,6 +30,7 @@ export default abstract class WearableService { return await dataSource .getRepository(wearable) .createQueryBuilder("wearable") + .leftJoinAndSelect("wearable.wearableType", "wearabletype") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/wearable/wearableTypeService.ts b/src/service/unit/wearable/wearableTypeService.ts index 77f7a90..63a696b 100644 --- a/src/service/unit/wearable/wearableTypeService.ts +++ b/src/service/unit/wearable/wearableTypeService.ts @@ -4,7 +4,7 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class WearableTypeService { /** - * @description get all wearableType types + * @description get all wearableTypes * @returns {Promise>} */ static async getAll(): Promise> { From 117ced38ab297d0b53b8775223f1d2c5722445c7 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 18:30:00 +0200 Subject: [PATCH 11/34] factory and restructure view models --- src/entity/unit/damageReport.ts | 17 +++--- src/entity/unit/inspection/inspection.ts | 4 +- src/entity/unit/inspection/inspectionPlan.ts | 22 +++++--- src/entity/unit/inspection/inspectionPoint.ts | 4 +- src/entity/unit/wearable/wearable.ts | 6 +- src/factory/admin/unit/damageReport.ts | 55 +++++++++++++++++++ src/factory/admin/unit/equipment/equipment.ts | 32 +++++++++++ .../admin/unit/equipment/equipmentType.ts | 26 +++++++++ .../admin/unit/inspection/inspection.ts | 50 +++++++++++++++++ .../admin/unit/inspection/inspectionPlan.ts | 44 +++++++++++++++ .../admin/unit/inspection/inspectionPoint.ts | 30 ++++++++++ .../unit/inspection/inspectionPointResult.ts | 29 ++++++++++ .../inspection/inspectionVersionedPlan.ts | 28 ++++++++++ src/factory/admin/unit/vehicle/vehicle.ts | 32 +++++++++++ src/factory/admin/unit/vehicle/vehicleType.ts | 26 +++++++++ src/factory/admin/unit/wearable/wearable.ts | 35 ++++++++++++ .../admin/unit/wearable/wearableType.ts | 26 +++++++++ src/service/unit/damageReport.ts | 3 + .../unit/inspection/inspectionPlanService.ts | 4 ++ .../unit/inspection/inspectionService.ts | 4 ++ src/service/unit/wearable/wearableService.ts | 1 + .../{damageReport => }/damageReport.models.ts | 25 +++++---- .../admin/unit/equipment/equipment.models.ts | 4 +- .../equipmentType.models.ts | 3 - .../unit/inspection/inspection.models.ts | 4 +- .../inspectionPlan.models.ts | 2 + .../respiratoryGear.models.ts | 0 .../respiratoryMission.models.ts | 0 .../respiratoryWearer.models.ts | 0 .../admin/unit/vehicle/vehicle.models.ts | 4 +- .../vehicleType.models.ts | 3 - .../admin/unit/wearable/wearable.models.ts | 2 +- .../wearableType.models.ts | 0 33 files changed, 479 insertions(+), 46 deletions(-) create mode 100644 src/factory/admin/unit/damageReport.ts create mode 100644 src/factory/admin/unit/equipment/equipment.ts create mode 100644 src/factory/admin/unit/equipment/equipmentType.ts create mode 100644 src/factory/admin/unit/inspection/inspection.ts create mode 100644 src/factory/admin/unit/inspection/inspectionPlan.ts create mode 100644 src/factory/admin/unit/inspection/inspectionPoint.ts create mode 100644 src/factory/admin/unit/inspection/inspectionPointResult.ts create mode 100644 src/factory/admin/unit/inspection/inspectionVersionedPlan.ts create mode 100644 src/factory/admin/unit/vehicle/vehicle.ts create mode 100644 src/factory/admin/unit/vehicle/vehicleType.ts create mode 100644 src/factory/admin/unit/wearable/wearable.ts create mode 100644 src/factory/admin/unit/wearable/wearableType.ts rename src/viewmodel/admin/unit/{damageReport => }/damageReport.models.ts (70%) rename src/viewmodel/admin/unit/{equipmentType => equipment}/equipmentType.models.ts (67%) rename src/viewmodel/admin/unit/{inspectionPlan => inspection}/inspectionPlan.models.ts (97%) rename src/viewmodel/admin/unit/{respiratoryGear => respiratory}/respiratoryGear.models.ts (100%) rename src/viewmodel/admin/unit/{respiratoryMission => respiratory}/respiratoryMission.models.ts (100%) rename src/viewmodel/admin/unit/{respiratoryWearer => respiratory}/respiratoryWearer.models.ts (100%) rename src/viewmodel/admin/unit/{vehicleType => vehicle}/vehicleType.models.ts (67%) rename src/viewmodel/admin/unit/{wearableType => wearable}/wearableType.models.ts (100%) diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index a59c9e2..dd0955e 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -23,33 +23,36 @@ export class damageReport { @Column({ type: "varchar", length: 255 }) reportedBy: string; - @Column({ nullable: true, default: null }) - equipmentId: string; + @Column({ type: "int", default: 0 }) + imageCount: number; @Column({ nullable: true, default: null }) - vehicleId: string; + equipmentId?: string; @Column({ nullable: true, default: null }) - wearableId: string; + vehicleId?: string; + + @Column({ nullable: true, default: null }) + wearableId?: string; @ManyToOne(() => equipment, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - equipment: equipment; + equipment?: equipment; @ManyToOne(() => vehicle, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - vehicle: vehicle; + vehicle?: vehicle; @ManyToOne(() => wearable, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - wearable: wearable; + wearable?: wearable; } diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 77e32d0..00faf98 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -30,10 +30,10 @@ export class inspection { inspectionVersionedPlanId: string; @Column() - equipmentId: string; + equipmentId?: string; @Column() - vehicleId: string; + vehicleId?: string; @ManyToOne(() => inspectionPlan, { nullable: false, diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts index 9be6406..f94bf5a 100644 --- a/src/entity/unit/inspection/inspectionPlan.ts +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -1,7 +1,7 @@ import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { equipment } from "../equipment/equipment"; import { vehicle } from "../vehicle/vehicle"; -import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspectionPlan/inspectionPlan.models"; +import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspection/inspectionPlan.models"; import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; @Entity() @@ -22,16 +22,24 @@ export class inspectionPlan { createdAt: Date; @Column() - equipmentId: string; + equipmentId?: string; @Column() - vehicleId: string; + vehicleId?: string; - @ManyToOne(() => equipment) - equipment: equipment; + @ManyToOne(() => equipment, { + nullable: true, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) + equipment?: equipment; - @ManyToOne(() => vehicle) - vehicle: vehicle; + @ManyToOne(() => vehicle, { + nullable: true, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) + vehicle?: vehicle; @OneToMany(() => inspectionVersionedPlan, (ivp) => ivp.inspectionPlan, { cascade: ["insert"], diff --git a/src/entity/unit/inspection/inspectionPoint.ts b/src/entity/unit/inspection/inspectionPoint.ts index 2ff25b1..4995bc8 100644 --- a/src/entity/unit/inspection/inspectionPoint.ts +++ b/src/entity/unit/inspection/inspectionPoint.ts @@ -28,10 +28,10 @@ export class inspectionPoint { type: InspectionPointEnum; @Column({ type: "int", nullable: true, default: null }) - min: number; + min?: number; @Column({ type: "int", nullable: true, default: null }) - max: number; + max?: number; @Column({ type: "int", default: 0 }) sort: number; diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index f532cb0..3b1ea39 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -29,7 +29,7 @@ export class wearable { wearableTypeId: string; @Column() - wearerId: string; + wearerId?: string; @ManyToOne(() => wearableType, { nullable: false, @@ -39,11 +39,11 @@ export class wearable { wearableType: wearableType; @ManyToOne(() => member, { - nullable: false, + nullable: true, onDelete: "SET NULL", onUpdate: "RESTRICT", }) - wearer: member; + wearer?: member; @OneToMany(() => damageReport, (d) => d.wearable, { cascade: ["insert"] }) reports: damageReport[]; diff --git a/src/factory/admin/unit/damageReport.ts b/src/factory/admin/unit/damageReport.ts new file mode 100644 index 0000000..908c0fe --- /dev/null +++ b/src/factory/admin/unit/damageReport.ts @@ -0,0 +1,55 @@ +import { damageReport } from "../../../entity/unit/damageReport"; +import { DamageReportAssigned, DamageReportViewModel } from "../../../viewmodel/admin/unit/damageReport.models"; +import EquipmentFactory from "./equipment/equipment"; +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: EquipmentFactory.mapToSingle(record.equipment), + }; + } else if (record?.vehicleId) { + assigned = { + relatedId: record.vehicleId, + assigned: "vehicle", + related: VehicleFactory.mapToSingle(record.vehicle), + }; + } else { + assigned = { + relatedId: record.wearableId, + assigned: "wearable", + related: WearableFactory.mapToSingle(record.wearable), + }; + } + + return { + id: record.id, + reported: record.reportedAt, + status: record.status, + done: record.done, + description: record.description, + imageCount: record.imageCount, + reportedBy: record?.reportedBy, + ...assigned, + }; + } + + /** + * @description map records to damageReport + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/equipment/equipment.ts b/src/factory/admin/unit/equipment/equipment.ts new file mode 100644 index 0000000..8f0b520 --- /dev/null +++ b/src/factory/admin/unit/equipment/equipment.ts @@ -0,0 +1,32 @@ +import { equipment } from "../../../../entity/unit/equipment/equipment"; +import { EquipmentViewModel } 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} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/equipment/equipmentType.ts b/src/factory/admin/unit/equipment/equipmentType.ts new file mode 100644 index 0000000..6e84107 --- /dev/null +++ b/src/factory/admin/unit/equipment/equipmentType.ts @@ -0,0 +1,26 @@ +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, + }; + } + + /** + * @description map records to equipmentType + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/inspection/inspection.ts b/src/factory/admin/unit/inspection/inspection.ts new file mode 100644 index 0000000..3505e11 --- /dev/null +++ b/src/factory/admin/unit/inspection/inspection.ts @@ -0,0 +1,50 @@ +import { inspection } from "../../../../entity/unit/inspection/inspection"; +import { InspectionViewModel } from "../../../../viewmodel/admin/unit/inspection/inspection.models"; +import EquipmentFactory from "../equipment/equipment"; +import VehicleFactory from "../vehicle/vehicle"; +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 mapToSingle(record: inspection): InspectionViewModel { + 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, + finished: record?.finishedAt, + isOpen: record?.finishedAt == undefined, + nextInspection: record?.nextInspection, + checks: InspectionPointResultFactory.mapToBase(record.pointResults), + ...(record.equipmentId + ? { + relatedId: record.equipmentId, + assigned: "equipment", + related: EquipmentFactory.mapToSingle(record.equipment), + } + : { + relatedId: record.vehicleId, + assigned: "vehicle", + related: VehicleFactory.mapToSingle(record.vehicle), + }), + }; + } + + /** + * @description map records to inspection + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/inspection/inspectionPlan.ts b/src/factory/admin/unit/inspection/inspectionPlan.ts new file mode 100644 index 0000000..2e8fe5b --- /dev/null +++ b/src/factory/admin/unit/inspection/inspectionPlan.ts @@ -0,0 +1,44 @@ +import { inspectionPlan } from "../../../../entity/unit/inspection/inspectionPlan"; +import { InspectionPlanViewModel } from "../../../../viewmodel/admin/unit/inspection/inspectionPlan.models"; +import EquipmentFactory from "../equipment/equipment"; +import VehicleFactory from "../vehicle/vehicle"; +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 { + return { + id: record.id, + title: record.title, + inspectionInterval: record.inspectionInterval, + remindTime: record.remindTime, + version: record.latestVersionedPlan.version, + created: record.createdAt, + inspectionPoints: InspectionPointFactory.mapToBase(record.latestVersionedPlan.inspectionPoints), + ...(record.equipmentId + ? { + relatedId: record.equipmentId, + assigned: "equipment", + related: EquipmentFactory.mapToSingle(record.equipment), + } + : { + relatedId: record.vehicleId, + assigned: "vehicle", + related: VehicleFactory.mapToSingle(record.vehicle), + }), + }; + } + + /** + * @description map records to inspectionPlan + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/inspection/inspectionPoint.ts b/src/factory/admin/unit/inspection/inspectionPoint.ts new file mode 100644 index 0000000..1f6150c --- /dev/null +++ b/src/factory/admin/unit/inspection/inspectionPoint.ts @@ -0,0 +1,30 @@ +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, + }; + } + + /** + * @description map records to inspectionPoint + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/inspection/inspectionPointResult.ts b/src/factory/admin/unit/inspection/inspectionPointResult.ts new file mode 100644 index 0000000..b258a6a --- /dev/null +++ b/src/factory/admin/unit/inspection/inspectionPointResult.ts @@ -0,0 +1,29 @@ +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, + inspectionVersionedPlanId: record.inspection.inspectionVersionedPlanId, + inspectionPointId: record.inspectionPointId, + inspectionPoint: InspectionPointFactory.mapToSingle(record.inspectionPoint), + value: record.value, + }; + } + + /** + * @description map records to inspectionPointResult + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/inspection/inspectionVersionedPlan.ts b/src/factory/admin/unit/inspection/inspectionVersionedPlan.ts new file mode 100644 index 0000000..c655342 --- /dev/null +++ b/src/factory/admin/unit/inspection/inspectionVersionedPlan.ts @@ -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} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/vehicle/vehicle.ts b/src/factory/admin/unit/vehicle/vehicle.ts new file mode 100644 index 0000000..fd7a86d --- /dev/null +++ b/src/factory/admin/unit/vehicle/vehicle.ts @@ -0,0 +1,32 @@ +import { vehicle } from "../../../../entity/unit/vehicle/vehicle"; +import { 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} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/vehicle/vehicleType.ts b/src/factory/admin/unit/vehicle/vehicleType.ts new file mode 100644 index 0000000..6155ca1 --- /dev/null +++ b/src/factory/admin/unit/vehicle/vehicleType.ts @@ -0,0 +1,26 @@ +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, + }; + } + + /** + * @description map records to vehicleType + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/wearable/wearable.ts b/src/factory/admin/unit/wearable/wearable.ts new file mode 100644 index 0000000..d3b39af --- /dev/null +++ b/src/factory/admin/unit/wearable/wearable.ts @@ -0,0 +1,35 @@ +import { wearable } from "../../../../entity/unit/wearable/wearable"; +import { 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} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/factory/admin/unit/wearable/wearableType.ts b/src/factory/admin/unit/wearable/wearableType.ts new file mode 100644 index 0000000..b574bae --- /dev/null +++ b/src/factory/admin/unit/wearable/wearableType.ts @@ -0,0 +1,26 @@ +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, + }; + } + + /** + * @description map records to wearableType + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/service/unit/damageReport.ts b/src/service/unit/damageReport.ts index b6134d6..ef8b999 100644 --- a/src/service/unit/damageReport.ts +++ b/src/service/unit/damageReport.ts @@ -11,6 +11,9 @@ export default abstract class DamageReportService { return await dataSource .getRepository(damageReport) .createQueryBuilder("damageReport") + .leftJoinAndSelect("damageReport.equipment", "equipment") + .leftJoinAndSelect("damageReport.vehicle", "vehicle") + .leftJoinAndSelect("damageReport.wearable", "wearable") .orderBy("type", "ASC") .getMany() .then((res) => { diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index 0e2cc47..e9495fe 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -23,6 +23,8 @@ export default abstract class InspectionPlanService { : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.start) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") + .leftJoinAndSelect("inspectionPlan.equipment", "equipment") + .leftJoinAndSelect("inspectionPlan.vehicle", "vehicle") .where(where) .orderBy("title", "ASC") .getMany() @@ -51,6 +53,8 @@ export default abstract class InspectionPlanService { : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.start) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") + .leftJoinAndSelect("inspectionPlan.equipment", "equipment") + .leftJoinAndSelect("inspectionPlan.vehicle", "vehicle") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index 8262dd9..0fdf490 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -16,6 +16,8 @@ export default abstract class InspectionService { .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspection.pointResults", "pointResults") .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") + .leftJoinAndSelect("inspection.equipment", "equipment") + .leftJoinAndSelect("inspection.vehicle", "vehicle") .where(where) .orderBy("createdAt", "DESC") .getMany() @@ -40,6 +42,8 @@ export default abstract class InspectionService { .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspection.pointResults", "pointResults") .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") + .leftJoinAndSelect("inspection.equipment", "equipment") + .leftJoinAndSelect("inspection.vehicle", "vehicle") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/wearable/wearableService.ts b/src/service/unit/wearable/wearableService.ts index 9fc7325..7733d4a 100644 --- a/src/service/unit/wearable/wearableService.ts +++ b/src/service/unit/wearable/wearableService.ts @@ -12,6 +12,7 @@ export default abstract class WearableService { .getRepository(wearable) .createQueryBuilder("wearable") .leftJoinAndSelect("wearable.wearableType", "wearabletype") + .leftJoinAndSelect("wearable.wearer", "wearer") .orderBy("name", "ASC") .getMany() .then((res) => { diff --git a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts b/src/viewmodel/admin/unit/damageReport.models.ts similarity index 70% rename from src/viewmodel/admin/unit/damageReport/damageReport.models.ts rename to src/viewmodel/admin/unit/damageReport.models.ts index a144114..b0f5c20 100644 --- a/src/viewmodel/admin/unit/damageReport/damageReport.models.ts +++ b/src/viewmodel/admin/unit/damageReport.models.ts @@ -1,15 +1,8 @@ -import type { EquipmentViewModel } from "../equipment/equipment.models"; -import type { VehicleViewModel } from "../vehicle/vehicle.models"; -import type { WearableViewModel } from "../wearable/wearable.models"; +import { EquipmentViewModel } from "./equipment/equipment.models"; +import { VehicleViewModel } from "./vehicle/vehicle.models"; +import { WearableViewModel } from "./wearable/wearable.models"; -export type DamageReportViewModel = { - id: string; - reported: Date; - status: string; - done: boolean; - description: string; - providedImage: Array; - reportedBy: string; +export type DamageReportAssigned = { relatedId: string; } & ( | { @@ -26,6 +19,16 @@ export type DamageReportViewModel = { } ); +export type DamageReportViewModel = { + id: string; + reported: Date; + status: string; + done: boolean; + description: string; + imageCount: number; + reportedBy: string; +} & DamageReportAssigned; + export interface CreateDamageReportViewModel { description: string; reportedBy: string; diff --git a/src/viewmodel/admin/unit/equipment/equipment.models.ts b/src/viewmodel/admin/unit/equipment/equipment.models.ts index dcd4cea..abbdee7 100644 --- a/src/viewmodel/admin/unit/equipment/equipment.models.ts +++ b/src/viewmodel/admin/unit/equipment/equipment.models.ts @@ -1,5 +1,4 @@ -import type { EquipmentTypeViewModel } from "../equipmentType/equipmentType.models"; -import type { InspectionViewModel } from "../inspection/inspection.models"; +import type { EquipmentTypeViewModel } from "./equipmentType.models"; export interface EquipmentViewModel { id: string; @@ -10,7 +9,6 @@ export interface EquipmentViewModel { decommissioned?: Date; equipmentTypeId: string; equipmentType: EquipmentTypeViewModel; - inspections: Array; } export interface CreateEquipmentViewModel { diff --git a/src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts b/src/viewmodel/admin/unit/equipment/equipmentType.models.ts similarity index 67% rename from src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts rename to src/viewmodel/admin/unit/equipment/equipmentType.models.ts index e3116c9..fcf47ee 100644 --- a/src/viewmodel/admin/unit/equipmentType/equipmentType.models.ts +++ b/src/viewmodel/admin/unit/equipment/equipmentType.models.ts @@ -1,10 +1,7 @@ -import type { InspectionPlanViewModel } from "../inspectionPlan/inspectionPlan.models"; - export interface EquipmentTypeViewModel { id: string; type: string; description: string; - inspectionPlans: Array; } export interface CreateEquipmentTypeViewModel { diff --git a/src/viewmodel/admin/unit/inspection/inspection.models.ts b/src/viewmodel/admin/unit/inspection/inspection.models.ts index 8cd2e5f..6565377 100644 --- a/src/viewmodel/admin/unit/inspection/inspection.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspection.models.ts @@ -1,8 +1,9 @@ import type { EquipmentViewModel } from "../equipment/equipment.models"; import type { InspectionPlanViewModel, + InspectionPointViewModel, InspectionVersionedPlanViewModel, -} from "../inspectionPlan/inspectionPlan.models"; +} from "./inspectionPlan.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; export type InspectionViewModel = { @@ -33,5 +34,6 @@ export interface InspectionPointResultViewModel { inspectionId: string; inspectionVersionedPlanId: string; inspectionPointId: string; + inspectionPoint: InspectionPointViewModel; value: string; } diff --git a/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts similarity index 97% rename from src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts rename to src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts index 31384d7..b2aecc0 100644 --- a/src/viewmodel/admin/unit/inspectionPlan/inspectionPlan.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts @@ -37,6 +37,8 @@ export interface InspectionPointViewModel { description: string; type: InspectionPointEnum; min?: number; + max?: number; + sort: number; } export interface CreateInspectionPlanViewModel { diff --git a/src/viewmodel/admin/unit/respiratoryGear/respiratoryGear.models.ts b/src/viewmodel/admin/unit/respiratory/respiratoryGear.models.ts similarity index 100% rename from src/viewmodel/admin/unit/respiratoryGear/respiratoryGear.models.ts rename to src/viewmodel/admin/unit/respiratory/respiratoryGear.models.ts diff --git a/src/viewmodel/admin/unit/respiratoryMission/respiratoryMission.models.ts b/src/viewmodel/admin/unit/respiratory/respiratoryMission.models.ts similarity index 100% rename from src/viewmodel/admin/unit/respiratoryMission/respiratoryMission.models.ts rename to src/viewmodel/admin/unit/respiratory/respiratoryMission.models.ts diff --git a/src/viewmodel/admin/unit/respiratoryWearer/respiratoryWearer.models.ts b/src/viewmodel/admin/unit/respiratory/respiratoryWearer.models.ts similarity index 100% rename from src/viewmodel/admin/unit/respiratoryWearer/respiratoryWearer.models.ts rename to src/viewmodel/admin/unit/respiratory/respiratoryWearer.models.ts diff --git a/src/viewmodel/admin/unit/vehicle/vehicle.models.ts b/src/viewmodel/admin/unit/vehicle/vehicle.models.ts index 0bfccb6..4e273f6 100644 --- a/src/viewmodel/admin/unit/vehicle/vehicle.models.ts +++ b/src/viewmodel/admin/unit/vehicle/vehicle.models.ts @@ -1,5 +1,4 @@ -import type { InspectionViewModel } from "../inspection/inspection.models"; -import type { VehicleTypeViewModel } from "../vehicleType/vehicleType.models"; +import type { VehicleTypeViewModel } from "./vehicleType.models"; export interface VehicleViewModel { id: string; @@ -10,7 +9,6 @@ export interface VehicleViewModel { decommissioned?: Date; vehicleTypeId: string; vehicleType: VehicleTypeViewModel; - inspections: Array; } export interface CreateVehicleViewModel { diff --git a/src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts b/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts similarity index 67% rename from src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts rename to src/viewmodel/admin/unit/vehicle/vehicleType.models.ts index 2de497f..ea6c7cf 100644 --- a/src/viewmodel/admin/unit/vehicleType/vehicleType.models.ts +++ b/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts @@ -1,10 +1,7 @@ -import type { InspectionPlanViewModel } from "../inspectionPlan/inspectionPlan.models"; - export interface VehicleTypeViewModel { id: string; type: string; description: string; - inspectionPlans: Array; } export interface CreateVehicleTypeViewModel { diff --git a/src/viewmodel/admin/unit/wearable/wearable.models.ts b/src/viewmodel/admin/unit/wearable/wearable.models.ts index 5e4fccc..e2c5bbc 100644 --- a/src/viewmodel/admin/unit/wearable/wearable.models.ts +++ b/src/viewmodel/admin/unit/wearable/wearable.models.ts @@ -1,5 +1,5 @@ import { MemberViewModel } from "../../club/member/member.models"; -import type { WearableTypeViewModel } from "../wearableType/wearableType.models"; +import type { WearableTypeViewModel } from "./wearableType.models"; export interface WearableViewModel { id: string; diff --git a/src/viewmodel/admin/unit/wearableType/wearableType.models.ts b/src/viewmodel/admin/unit/wearable/wearableType.models.ts similarity index 100% rename from src/viewmodel/admin/unit/wearableType/wearableType.models.ts rename to src/viewmodel/admin/unit/wearable/wearableType.models.ts From cb60d617735e7747ee4b7a2bd1c81e8b54dab9e7 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 18:30:24 +0200 Subject: [PATCH 12/34] update migration to image count on damageReport --- src/migrations/baseSchemaTables/unit_extend.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/migrations/baseSchemaTables/unit_extend.ts b/src/migrations/baseSchemaTables/unit_extend.ts index a81f8ac..9115540 100644 --- a/src/migrations/baseSchemaTables/unit_extend.ts +++ b/src/migrations/baseSchemaTables/unit_extend.ts @@ -10,6 +10,7 @@ export const damage_report_table = new Table({ { name: "done", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, { name: "description", ...getTypeByORM("text") }, { name: "reportedBy", ...getTypeByORM("varchar") }, + { name: "imageCount", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, From 0f6401953f1d4ea60d8500fe265c06a01859bb95 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 28 May 2025 22:51:17 +0200 Subject: [PATCH 13/34] add maintenance model, factory and service --- src/data-source.ts | 2 + src/entity/unit/damageReport.ts | 13 ++++- src/entity/unit/maintenance.ts | 56 +++++++++++++++++++ src/factory/admin/unit/damageReport.ts | 4 +- src/factory/admin/unit/maintenance.ts | 55 ++++++++++++++++++ src/migrations/1748261477410-unitBase.ts | 4 +- .../baseSchemaTables/unit_extend.ts | 45 +++++++++++++++ src/service/unit/damageReport.ts | 5 ++ src/service/unit/maintenance.ts | 49 ++++++++++++++++ .../admin/unit/damageReport.models.ts | 4 +- .../admin/unit/maintenance.models.ts | 43 ++++++++++++++ 11 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 src/entity/unit/maintenance.ts create mode 100644 src/factory/admin/unit/maintenance.ts create mode 100644 src/service/unit/maintenance.ts create mode 100644 src/viewmodel/admin/unit/maintenance.models.ts diff --git a/src/data-source.ts b/src/data-source.ts index 85fe595..42e035a 100644 --- a/src/data-source.ts +++ b/src/data-source.ts @@ -69,6 +69,7 @@ import { inspectionPoint } from "./entity/unit/inspection/inspectionPoint"; import { inspection } from "./entity/unit/inspection/inspection"; import { inspectionPointResult } from "./entity/unit/inspection/inspectionPointResult"; import { UnitBase1748261477410 } from "./migrations/1748261477410-unitBase"; +import { maintenance } from "./entity/unit/maintenance"; configCheck(); @@ -131,6 +132,7 @@ const dataSource = new DataSource({ wearableType, wearable, damageReport, + maintenance, inspectionPlan, inspectionVersionedPlan, inspectionPoint, diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index dd0955e..20a78c2 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -1,7 +1,8 @@ -import { Check, Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; import { equipment } from "./equipment/equipment"; import { wearable } from "./wearable/wearable"; import { vehicle } from "./vehicle/vehicle"; +import { maintenance } from "./maintenance"; @Entity() export class damageReport { @@ -29,6 +30,9 @@ export class damageReport { @Column({ nullable: true, default: null }) equipmentId?: string; + @Column({ nullable: true, default: null }) + maintenanceId: string; + @Column({ nullable: true, default: null }) vehicleId?: string; @@ -55,4 +59,11 @@ export class damageReport { onUpdate: "RESTRICT", }) wearable?: wearable; + + @ManyToOne(() => maintenance, { + nullable: true, + onDelete: "SET NULL", + onUpdate: "RESTRICT", + }) + maintenance?: maintenance; } diff --git a/src/entity/unit/maintenance.ts b/src/entity/unit/maintenance.ts new file mode 100644 index 0000000..f3c9669 --- /dev/null +++ b/src/entity/unit/maintenance.ts @@ -0,0 +1,56 @@ +import { Column, 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"; + +@Entity() +export class maintenance { + @PrimaryGeneratedColumn("uuid") + id: string; + + @CreateDateColumn() + createdAt: Date; + + @Column({ type: "varchar", length: 255 }) + status: string; + + @Column({ type: "boolean", default: false }) + done: boolean; + + @Column({ type: "text" }) + description: string; + + @Column({ nullable: true, default: null }) + equipmentId?: string; + + @Column({ nullable: true, default: null }) + vehicleId?: string; + + @Column({ nullable: true, default: null }) + wearableId?: string; + + @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(() => damageReport, (dr) => dr.maintenance) + reports: damageReport[]; +} diff --git a/src/factory/admin/unit/damageReport.ts b/src/factory/admin/unit/damageReport.ts index 908c0fe..fb9115e 100644 --- a/src/factory/admin/unit/damageReport.ts +++ b/src/factory/admin/unit/damageReport.ts @@ -1,6 +1,7 @@ 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 VehicleFactory from "./vehicle/vehicle"; import WearableFactory from "./wearable/wearable"; @@ -34,13 +35,14 @@ export default abstract class DamageReportFactory { return { id: record.id, - reported: record.reportedAt, + reportedAt: record.reportedAt, status: record.status, done: record.done, description: record.description, imageCount: record.imageCount, reportedBy: record?.reportedBy, ...assigned, + maintenance: record.maintenance ? MaintenanceFactory.mapToSingle(record.maintenance) : null, }; } diff --git a/src/factory/admin/unit/maintenance.ts b/src/factory/admin/unit/maintenance.ts new file mode 100644 index 0000000..69f4c78 --- /dev/null +++ b/src/factory/admin/unit/maintenance.ts @@ -0,0 +1,55 @@ +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: EquipmentFactory.mapToSingle(record.equipment), + }; + } else if (record?.vehicleId) { + assigned = { + relatedId: record.vehicleId, + assigned: "vehicle", + related: VehicleFactory.mapToSingle(record.vehicle), + }; + } else { + assigned = { + relatedId: record.wearableId, + assigned: "wearable", + related: WearableFactory.mapToSingle(record.wearable), + }; + } + + return { + id: record.id, + createdAt: record.createdAt, + status: record.status, + done: record.done, + description: record.description, + ...assigned, + reports: record.reports ? DamageReportFactory.mapToBase(record.reports) : [], + }; + } + + /** + * @description map records to maintenance + * @param {Array} records + * @returns {Array} + */ + public static mapToBase(records: Array): Array { + return records.map((r) => this.mapToSingle(r)); + } +} diff --git a/src/migrations/1748261477410-unitBase.ts b/src/migrations/1748261477410-unitBase.ts index d4951c6..cc6e201 100644 --- a/src/migrations/1748261477410-unitBase.ts +++ b/src/migrations/1748261477410-unitBase.ts @@ -7,7 +7,7 @@ import { wearable_table, wearable_type_table, } from "./baseSchemaTables/unit"; -import { damage_report_table } from "./baseSchemaTables/unit_extend"; +import { damage_report_table, maintenance_table } from "./baseSchemaTables/unit_extend"; import { inspection_plan_table, inspection_point_result_table, @@ -27,6 +27,7 @@ export class UnitBase1748261477410 implements MigrationInterface { 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(damage_report_table, true, true, true); await queryRunner.createTable(inspection_plan_table, true, true, true); @@ -46,6 +47,7 @@ export class UnitBase1748261477410 implements MigrationInterface { await queryRunner.dropTable(inspection_plan_table, true, true, true); await queryRunner.dropTable(damage_report_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); diff --git a/src/migrations/baseSchemaTables/unit_extend.ts b/src/migrations/baseSchemaTables/unit_extend.ts index 9115540..3f78910 100644 --- a/src/migrations/baseSchemaTables/unit_extend.ts +++ b/src/migrations/baseSchemaTables/unit_extend.ts @@ -14,6 +14,51 @@ export const damage_report_table = new Table({ { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "maintenanceId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + ], + foreignKeys: [ + 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: ["maintenanceId"], + referencedColumnNames: ["id"], + referencedTableName: "maintenance", + onDelete: "SET NULL", + onUpdate: "RESTRICT", + }), + ], +}); + +export const maintenance_table = new Table({ + name: "maintenance", + columns: [ + { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "status", ...getTypeByORM("varchar") }, + { name: "done", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, + { name: "description", ...getTypeByORM("text") }, + { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/service/unit/damageReport.ts b/src/service/unit/damageReport.ts index ef8b999..7821ea1 100644 --- a/src/service/unit/damageReport.ts +++ b/src/service/unit/damageReport.ts @@ -14,6 +14,7 @@ export default abstract class DamageReportService { .leftJoinAndSelect("damageReport.equipment", "equipment") .leftJoinAndSelect("damageReport.vehicle", "vehicle") .leftJoinAndSelect("damageReport.wearable", "wearable") + .leftJoinAndSelect("damageReport.maintenance", "maintenance") .orderBy("type", "ASC") .getMany() .then((res) => { @@ -32,6 +33,10 @@ export default abstract class DamageReportService { return await dataSource .getRepository(damageReport) .createQueryBuilder("damageReport") + .leftJoinAndSelect("damageReport.equipment", "equipment") + .leftJoinAndSelect("damageReport.vehicle", "vehicle") + .leftJoinAndSelect("damageReport.wearable", "wearable") + .leftJoinAndSelect("damageReport.maintenance", "maintenance") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/maintenance.ts b/src/service/unit/maintenance.ts new file mode 100644 index 0000000..d9e8519 --- /dev/null +++ b/src/service/unit/maintenance.ts @@ -0,0 +1,49 @@ +import { dataSource } from "../../data-source"; +import { maintenance } from "../../entity/unit/maintenance"; +import DatabaseActionException from "../../exceptions/databaseActionException"; + +export default abstract class MaintenanceService { + /** + * @description get all maintenances + * @returns {Promise>} + */ + static async getAll(): Promise> { + return await dataSource + .getRepository(maintenance) + .createQueryBuilder("maintenance") + .leftJoinAndSelect("maintenance.equipment", "equipment") + .leftJoinAndSelect("maintenance.vehicle", "vehicle") + .leftJoinAndSelect("maintenance.wearable", "wearable") + .leftJoinAndSelect("maintenance.reports", "reports") + .orderBy("type", "ASC") + .getMany() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "maintenance", err); + }); + } + + /** + * @description get maintenance by id + * @returns {Promise} + */ + static async getById(id: string): Promise { + return await dataSource + .getRepository(maintenance) + .createQueryBuilder("maintenance") + .leftJoinAndSelect("maintenance.equipment", "equipment") + .leftJoinAndSelect("maintenance.vehicle", "vehicle") + .leftJoinAndSelect("maintenance.wearable", "wearable") + .leftJoinAndSelect("maintenance.reports", "reports") + .where({ id }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "maintenance", err); + }); + } +} diff --git a/src/viewmodel/admin/unit/damageReport.models.ts b/src/viewmodel/admin/unit/damageReport.models.ts index b0f5c20..e675c9c 100644 --- a/src/viewmodel/admin/unit/damageReport.models.ts +++ b/src/viewmodel/admin/unit/damageReport.models.ts @@ -1,4 +1,5 @@ import { EquipmentViewModel } from "./equipment/equipment.models"; +import { MaintenanceViewModel } from "./maintenance.models"; import { VehicleViewModel } from "./vehicle/vehicle.models"; import { WearableViewModel } from "./wearable/wearable.models"; @@ -21,12 +22,13 @@ export type DamageReportAssigned = { export type DamageReportViewModel = { id: string; - reported: Date; + reportedAt: Date; status: string; done: boolean; description: string; imageCount: number; reportedBy: string; + maintenance?: MaintenanceViewModel; } & DamageReportAssigned; export interface CreateDamageReportViewModel { diff --git a/src/viewmodel/admin/unit/maintenance.models.ts b/src/viewmodel/admin/unit/maintenance.models.ts new file mode 100644 index 0000000..ce5c0b9 --- /dev/null +++ b/src/viewmodel/admin/unit/maintenance.models.ts @@ -0,0 +1,43 @@ +import { DamageReportViewModel } from "./damageReport.models"; +import { EquipmentViewModel } from "./equipment/equipment.models"; +import { VehicleViewModel } from "./vehicle/vehicle.models"; +import { WearableViewModel } from "./wearable/wearable.models"; + +export type MaintenanceAssigned = { + relatedId: string; +} & ( + | { + assigned: "equipment"; + related: EquipmentViewModel; + } + | { + assigned: "vehicle"; + related: VehicleViewModel; + } + | { + assigned: "wearable"; + related: WearableViewModel; + } +); + +export type MaintenanceViewModel = { + id: string; + createdAt: Date; + status: string; + done: boolean; + description: string; + reports: DamageReportViewModel[]; +} & MaintenanceAssigned; + +export interface CreateMaintenanceViewModel { + description: string; + reportedBy: string; + affectedId: string; + affected: "equipment" | "vehicle" | "wearable"; +} + +export interface UpdateMaintenanceViewModel { + id: string; + status: string; + done: boolean; +} From 7883bb7d7f25ab6d74e632fc9d51afa77c5b7330 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Thu, 29 May 2025 10:31:40 +0200 Subject: [PATCH 14/34] command Handlers and schema update --- src/command/unit/damageReportCommand.ts | 22 ++++ .../unit/damageReportCommandHandler.ts | 100 ++++++++++++++++++ .../unit/equipment/equipmentCommand.ts | 20 ++++ .../unit/equipment/equipmentCommandHandler.ts | 74 +++++++++++++ .../unit/equipment/equipmentTypeCommand.ts | 14 +++ .../equipment/equipmentTypeCommandHandler.ts | 72 +++++++++++++ .../unit/inspection/inspectionCommand.ts | 17 +++ .../inspection/inspectionCommandHandler.ts | 76 +++++++++++++ .../unit/inspection/inspectionPlanCommand.ts | 20 ++++ .../inspectionPlanCommandHandler.ts | 76 +++++++++++++ .../unit/inspection/inspectionPointCommand.ts | 11 ++ .../inspectionPointCommandHandler.ts | 34 ++++++ .../inspectionPointResultCommand.ts | 5 + .../inspectionPointResultCommandHandler.ts | 31 ++++++ .../inspectionVersionedPlanCommand.ts | 3 + .../inspectionVersionedPlanCommandHandler.ts | 28 +++++ src/command/unit/maintenanceCommand.ts | 16 +++ src/command/unit/maintenanceCommandHandler.ts | 72 +++++++++++++ src/command/unit/vehicle/vehicleCommand.ts | 20 ++++ .../unit/vehicle/vehicleCommandHandler.ts | 73 +++++++++++++ .../unit/vehicle/vehicleTypeCommand.ts | 14 +++ .../unit/vehicle/vehicleTypeCommandHandler.ts | 68 ++++++++++++ src/command/unit/wearable/wearableCommand.ts | 22 ++++ .../unit/wearable/wearableCommandHandler.ts | 76 +++++++++++++ .../unit/wearable/wearableTypeCommand.ts | 14 +++ .../wearable/wearableTypeCommandHandler.ts | 68 ++++++++++++ src/entity/unit/damageReport.ts | 2 +- .../unit/inspection/inspectionPointResult.ts | 15 ++- src/migrations/baseSchemaTables/inspection.ts | 5 +- ...damageReport.ts => damageReportService.ts} | 0 .../inspectionPointResultService.ts | 19 ---- .../inspectionVersionedPlanService.ts | 21 ++++ .../{maintenance.ts => maintenanceService.ts} | 0 .../admin/unit/damageReport.models.ts | 13 --- .../admin/unit/equipment/equipment.models.ts | 17 --- .../unit/equipment/equipmentType.models.ts | 11 -- .../unit/inspection/inspectionPlan.models.ts | 15 --- .../admin/unit/maintenance.models.ts | 13 --- .../admin/unit/vehicle/vehicle.models.ts | 17 --- .../admin/unit/vehicle/vehicleType.models.ts | 11 -- .../admin/unit/wearable/wearable.models.ts | 19 ---- .../unit/wearable/wearableType.models.ts | 11 -- 42 files changed, 1076 insertions(+), 159 deletions(-) create mode 100644 src/command/unit/damageReportCommand.ts create mode 100644 src/command/unit/damageReportCommandHandler.ts create mode 100644 src/command/unit/equipment/equipmentCommand.ts create mode 100644 src/command/unit/equipment/equipmentCommandHandler.ts create mode 100644 src/command/unit/equipment/equipmentTypeCommand.ts create mode 100644 src/command/unit/equipment/equipmentTypeCommandHandler.ts create mode 100644 src/command/unit/inspection/inspectionCommand.ts create mode 100644 src/command/unit/inspection/inspectionCommandHandler.ts create mode 100644 src/command/unit/inspection/inspectionPlanCommand.ts create mode 100644 src/command/unit/inspection/inspectionPlanCommandHandler.ts create mode 100644 src/command/unit/inspection/inspectionPointCommand.ts create mode 100644 src/command/unit/inspection/inspectionPointCommandHandler.ts create mode 100644 src/command/unit/inspection/inspectionPointResultCommand.ts create mode 100644 src/command/unit/inspection/inspectionPointResultCommandHandler.ts create mode 100644 src/command/unit/inspection/inspectionVersionedPlanCommand.ts create mode 100644 src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts create mode 100644 src/command/unit/maintenanceCommand.ts create mode 100644 src/command/unit/maintenanceCommandHandler.ts create mode 100644 src/command/unit/vehicle/vehicleCommand.ts create mode 100644 src/command/unit/vehicle/vehicleCommandHandler.ts create mode 100644 src/command/unit/vehicle/vehicleTypeCommand.ts create mode 100644 src/command/unit/vehicle/vehicleTypeCommandHandler.ts create mode 100644 src/command/unit/wearable/wearableCommand.ts create mode 100644 src/command/unit/wearable/wearableCommandHandler.ts create mode 100644 src/command/unit/wearable/wearableTypeCommand.ts create mode 100644 src/command/unit/wearable/wearableTypeCommandHandler.ts rename src/service/unit/{damageReport.ts => damageReportService.ts} (100%) rename src/service/unit/{maintenance.ts => maintenanceService.ts} (100%) diff --git a/src/command/unit/damageReportCommand.ts b/src/command/unit/damageReportCommand.ts new file mode 100644 index 0000000..62a4773 --- /dev/null +++ b/src/command/unit/damageReportCommand.ts @@ -0,0 +1,22 @@ +export interface CreateDamageReportCommand { + description: string; + reportedBy: string; + imageCount: number; + affectedId: string; + affected: "equipment" | "vehicle" | "wearable"; +} + +export interface UpdateDamageReportCommand { + id: string; + status: string; + done: boolean; +} + +export interface UpdateDamageReportRelatedMaintenanceCommand { + id: string; + maintenanceId: string; +} + +export interface DeleteDamageReportCommand { + id: string; +} diff --git a/src/command/unit/damageReportCommandHandler.ts b/src/command/unit/damageReportCommandHandler.ts new file mode 100644 index 0000000..71a72fa --- /dev/null +++ b/src/command/unit/damageReportCommandHandler.ts @@ -0,0 +1,100 @@ +import { dataSource } from "../../data-source"; +import { damageReport } from "../../entity/unit/damageReport"; +import DatabaseActionException from "../../exceptions/databaseActionException"; +import { + CreateDamageReportCommand, + UpdateDamageReportCommand, + DeleteDamageReportCommand, + UpdateDamageReportRelatedMaintenanceCommand, +} from "./damageReportCommand"; + +export default abstract class DamageReportCommandHandler { + /** + * @description create damageReport + * @param {CreateDamageReportCommand} createDamageReport + * @returns {Promise} + */ + static async create(createDamageReport: CreateDamageReportCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(damageReport) + .values({ + status: "eingereicht", + description: createDamageReport.description, + reportedBy: createDamageReport.reportedBy, + imageCount: createDamageReport.imageCount, + 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} + */ + static async update(updateDamageReport: UpdateDamageReportCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(damageReport) + .set({ + status: updateDamageReport.status, + done: updateDamageReport.done, + }) + .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} + */ + static async updateRelatedMaintenance( + updateDamageReport: UpdateDamageReportRelatedMaintenanceCommand + ): Promise { + return await dataSource + .createQueryBuilder() + .update(damageReport) + .set({ + maintenanceId: updateDamageReport.maintenanceId, + }) + .where("id = :id", { id: updateDamageReport.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("UPDATE", "damageReport->maintenance", err); + }); + } + + /** + * @description delete damageReport + * @param {DeleteDamageReportCommand} deleteDamageReport + * @returns {Promise} + */ + static async delete(deleteDamageReport: DeleteDamageReportCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(damageReport) + .where("id = :id", { id: deleteDamageReport.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "damageReport", err); + }); + } +} diff --git a/src/command/unit/equipment/equipmentCommand.ts b/src/command/unit/equipment/equipmentCommand.ts new file mode 100644 index 0000000..500d4c2 --- /dev/null +++ b/src/command/unit/equipment/equipmentCommand.ts @@ -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; +} diff --git a/src/command/unit/equipment/equipmentCommandHandler.ts b/src/command/unit/equipment/equipmentCommandHandler.ts new file mode 100644 index 0000000..0aef534 --- /dev/null +++ b/src/command/unit/equipment/equipmentCommandHandler.ts @@ -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} + */ + static async create(createEquipment: CreateEquipmentCommand): Promise { + 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} + */ + static async update(updateEquipment: UpdateEquipmentCommand): Promise { + 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} + */ + static async delete(deleteEquipment: DeleteEquipmentCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(equipment) + .where("id = :id", { id: deleteEquipment.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "equipment", err); + }); + } +} diff --git a/src/command/unit/equipment/equipmentTypeCommand.ts b/src/command/unit/equipment/equipmentTypeCommand.ts new file mode 100644 index 0000000..7d5c2f7 --- /dev/null +++ b/src/command/unit/equipment/equipmentTypeCommand.ts @@ -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; +} diff --git a/src/command/unit/equipment/equipmentTypeCommandHandler.ts b/src/command/unit/equipment/equipmentTypeCommandHandler.ts new file mode 100644 index 0000000..47caec3 --- /dev/null +++ b/src/command/unit/equipment/equipmentTypeCommandHandler.ts @@ -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} + */ + static async create(createEquipmentType: CreateEquipmentTypeCommand): Promise { + 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} + */ + static async update(updateEquipmentType: UpdateEquipmentTypeCommand): Promise { + 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} + */ + static async delete(deleteEquipmentType: DeleteEquipmentTypeCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(equipmentType) + .where("id = :id", { id: deleteEquipmentType.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "equipmentType", err); + }); + } +} diff --git a/src/command/unit/inspection/inspectionCommand.ts b/src/command/unit/inspection/inspectionCommand.ts new file mode 100644 index 0000000..1c020fb --- /dev/null +++ b/src/command/unit/inspection/inspectionCommand.ts @@ -0,0 +1,17 @@ +export interface CreateInspectionCommand { + context: string; + nextInspection?: Date; + inspectionPlanId: string; + relatedId: string; + assigned: "vehicle" | "equipment"; +} + +export interface UpdateInspectionCommand { + id: string; + context: string; + nextInspection?: Date; +} + +export interface DeleteInspectionCommand { + id: string; +} diff --git a/src/command/unit/inspection/inspectionCommandHandler.ts b/src/command/unit/inspection/inspectionCommandHandler.ts new file mode 100644 index 0000000..5f4a61d --- /dev/null +++ b/src/command/unit/inspection/inspectionCommandHandler.ts @@ -0,0 +1,76 @@ +import { dataSource } from "../../../data-source"; +import { inspection } from "../../../entity/unit/inspection/inspection"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; +import InspectionVersionedPlanService from "../../../service/unit/inspection/inspectionVersionedPlanService"; +import { CreateInspectionCommand, UpdateInspectionCommand, DeleteInspectionCommand } from "./inspectionCommand"; + +export default abstract class InspectionCommandHandler { + /** + * @description create inspection + * @param {CreateInspectionCommand} createInspection + * @returns {Promise} + */ + static async create(createInspection: CreateInspectionCommand): Promise { + let latestVersionedPlan = await InspectionVersionedPlanService.getLatestForInspectionPlan( + createInspection.inspectionPlanId + ); + return await dataSource + .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, + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new DatabaseActionException("CREATE", "inspection", err); + }); + } + + /** + * @description update inspection + * @param {UpdateInspectionCommand} updateInspection + * @returns {Promise} + */ + static async update(updateInspection: UpdateInspectionCommand): Promise { + 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 delete inspection + * @param {DeleteInspectionCommand} deleteInspection + * @returns {Promise} + */ + static async delete(deleteInspection: DeleteInspectionCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(inspection) + .where("id = :id", { id: deleteInspection.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "inspection", err); + }); + } +} diff --git a/src/command/unit/inspection/inspectionPlanCommand.ts b/src/command/unit/inspection/inspectionPlanCommand.ts new file mode 100644 index 0000000..0daac13 --- /dev/null +++ b/src/command/unit/inspection/inspectionPlanCommand.ts @@ -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"; +} + +export interface UpdateInspectionPlanCommand { + id: string; + title: string; + inspectionInterval: PlanTimeDefinition; + remindTime?: PlanTimeDefinition; +} + +export interface DeleteInspectionPlanCommand { + id: string; +} diff --git a/src/command/unit/inspection/inspectionPlanCommandHandler.ts b/src/command/unit/inspection/inspectionPlanCommandHandler.ts new file mode 100644 index 0000000..cf48ef7 --- /dev/null +++ b/src/command/unit/inspection/inspectionPlanCommandHandler.ts @@ -0,0 +1,76 @@ +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} + */ + static async create(createInspectionPlan: CreateInspectionPlanCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(inspectionPlan) + .values({ + title: createInspectionPlan.title, + inspectionInterval: createInspectionPlan.inspectionInterval, + remindTime: createInspectionPlan.remindTime, + equipmentId: createInspectionPlan.assigned == "equipment" ? createInspectionPlan.relatedId : null, + vehicleId: createInspectionPlan.assigned == "vehicle" ? 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} + */ + static async update(updateInspectionPlan: UpdateInspectionPlanCommand): Promise { + 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} + */ + static async delete(deleteInspectionPlan: DeleteInspectionPlanCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(inspectionPlan) + .where("id = :id", { id: deleteInspectionPlan.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "inspectionPlan", err); + }); + } +} diff --git a/src/command/unit/inspection/inspectionPointCommand.ts b/src/command/unit/inspection/inspectionPointCommand.ts new file mode 100644 index 0000000..5aa45a6 --- /dev/null +++ b/src/command/unit/inspection/inspectionPointCommand.ts @@ -0,0 +1,11 @@ +import { InspectionPointEnum } from "../../../enums/inspectionEnum"; + +export interface CreateInspectionPointCommand { + title: string; + description: string; + type: InspectionPointEnum; + min?: number; + max?: number; + sort: number; + versionedPointId: string; +} diff --git a/src/command/unit/inspection/inspectionPointCommandHandler.ts b/src/command/unit/inspection/inspectionPointCommandHandler.ts new file mode 100644 index 0000000..749f325 --- /dev/null +++ b/src/command/unit/inspection/inspectionPointCommandHandler.ts @@ -0,0 +1,34 @@ +import { dataSource } from "../../../data-source"; +import { inspectionPoint } from "../../../entity/unit/inspection/inspectionPoint"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; +import { CreateInspectionPointCommand } from "./inspectionPointCommand"; + +export default abstract class InspectionPointCommandHandler { + /** + * @description create inspectionPoint + * @param {CreateInspectionPointCommand} createInspectionPoint + * @returns {Promise} + */ + static async create(createInspectionPoint: CreateInspectionPointCommand): Promise { + 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); + }); + } +} diff --git a/src/command/unit/inspection/inspectionPointResultCommand.ts b/src/command/unit/inspection/inspectionPointResultCommand.ts new file mode 100644 index 0000000..9fb36d6 --- /dev/null +++ b/src/command/unit/inspection/inspectionPointResultCommand.ts @@ -0,0 +1,5 @@ +export interface CreateInspectionPointResultCommand { + inspectionId: string; + inspectionPointId: string; + value: string; +} diff --git a/src/command/unit/inspection/inspectionPointResultCommandHandler.ts b/src/command/unit/inspection/inspectionPointResultCommandHandler.ts new file mode 100644 index 0000000..23916dc --- /dev/null +++ b/src/command/unit/inspection/inspectionPointResultCommandHandler.ts @@ -0,0 +1,31 @@ +import { dataSource } from "../../../data-source"; +import { inspectionPointResult } from "../../../entity/unit/inspection/inspectionPointResult"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; +import { CreateInspectionPointResultCommand } from "./inspectionPointResultCommand"; + +export default abstract class InspectionPointResultCommandHandler { + /** + * @description create inspectionPointResult + * @param {CreateInspectionPointResultCommand} createInspectionPointResult + * @returns {Promise} + */ + static async createOrUpdate(createInspectionPointResult: CreateInspectionPointResultCommand): Promise { + 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", "inspectionPointResult", err); + }); + } +} diff --git a/src/command/unit/inspection/inspectionVersionedPlanCommand.ts b/src/command/unit/inspection/inspectionVersionedPlanCommand.ts new file mode 100644 index 0000000..825de12 --- /dev/null +++ b/src/command/unit/inspection/inspectionVersionedPlanCommand.ts @@ -0,0 +1,3 @@ +export interface CreateInspectionVersionedPlanCommand { + inspectionPlanId: string; +} diff --git a/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts b/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts new file mode 100644 index 0000000..9c9710b --- /dev/null +++ b/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts @@ -0,0 +1,28 @@ +import { dataSource } from "../../../data-source"; +import { inspectionVersionedPlan } from "../../../entity/unit/inspection/inspectionVersionedPlan"; +import DatabaseActionException from "../../../exceptions/databaseActionException"; +import { CreateInspectionVersionedPlanCommand } from "./inspectionVersionedPlanCommand"; + +export default abstract class InspectionVersionedPlanCommandHandler { + /** + * @description create inspectionVersionedPlan + * @param {CreateInspectionVersionedPlanCommand} createInspectionVersionedPlan + * @returns {Promise} + */ + static async create(createInspectionVersionedPlan: CreateInspectionVersionedPlanCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(inspectionVersionedPlan) + .values({ + inspectionPlanId: createInspectionVersionedPlan.inspectionPlanId, + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new DatabaseActionException("CREATE", "inspectionVersionedPlan", err); + }); + } +} diff --git a/src/command/unit/maintenanceCommand.ts b/src/command/unit/maintenanceCommand.ts new file mode 100644 index 0000000..637ed3b --- /dev/null +++ b/src/command/unit/maintenanceCommand.ts @@ -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; +} diff --git a/src/command/unit/maintenanceCommandHandler.ts b/src/command/unit/maintenanceCommandHandler.ts new file mode 100644 index 0000000..96819dd --- /dev/null +++ b/src/command/unit/maintenanceCommandHandler.ts @@ -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} + */ + static async create(createMaintenance: CreateMaintenanceCommand): Promise { + 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} + */ + static async update(updateMaintenance: UpdateMaintenanceCommand): Promise { + 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} + */ + static async delete(deleteMaintenance: DeleteMaintenanceCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(maintenance) + .where("id = :id", { id: deleteMaintenance.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "maintenance", err); + }); + } +} diff --git a/src/command/unit/vehicle/vehicleCommand.ts b/src/command/unit/vehicle/vehicleCommand.ts new file mode 100644 index 0000000..1310c0b --- /dev/null +++ b/src/command/unit/vehicle/vehicleCommand.ts @@ -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; +} diff --git a/src/command/unit/vehicle/vehicleCommandHandler.ts b/src/command/unit/vehicle/vehicleCommandHandler.ts new file mode 100644 index 0000000..db493f6 --- /dev/null +++ b/src/command/unit/vehicle/vehicleCommandHandler.ts @@ -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} + */ + static async create(createVehicle: CreateVehicleCommand): Promise { + 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} + */ + static async update(updateVehicle: UpdateVehicleCommand): Promise { + 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} + */ + static async delete(deleteVehicle: DeleteVehicleCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(vehicle) + .where("id = :id", { id: deleteVehicle.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "vehicle", err); + }); + } +} diff --git a/src/command/unit/vehicle/vehicleTypeCommand.ts b/src/command/unit/vehicle/vehicleTypeCommand.ts new file mode 100644 index 0000000..d155fe8 --- /dev/null +++ b/src/command/unit/vehicle/vehicleTypeCommand.ts @@ -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; +} diff --git a/src/command/unit/vehicle/vehicleTypeCommandHandler.ts b/src/command/unit/vehicle/vehicleTypeCommandHandler.ts new file mode 100644 index 0000000..de25fd1 --- /dev/null +++ b/src/command/unit/vehicle/vehicleTypeCommandHandler.ts @@ -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} + */ + static async create(createVehicleType: CreateVehicleTypeCommand): Promise { + 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} + */ + static async update(updateVehicleType: UpdateVehicleTypeCommand): Promise { + 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} + */ + static async delete(deleteVehicleType: DeleteVehicleTypeCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(vehicleType) + .where("id = :id", { id: deleteVehicleType.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "vehicleType", err); + }); + } +} diff --git a/src/command/unit/wearable/wearableCommand.ts b/src/command/unit/wearable/wearableCommand.ts new file mode 100644 index 0000000..c58eeb7 --- /dev/null +++ b/src/command/unit/wearable/wearableCommand.ts @@ -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; +} diff --git a/src/command/unit/wearable/wearableCommandHandler.ts b/src/command/unit/wearable/wearableCommandHandler.ts new file mode 100644 index 0000000..a13b773 --- /dev/null +++ b/src/command/unit/wearable/wearableCommandHandler.ts @@ -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} + */ + static async create(createWearable: CreateWearableCommand): Promise { + 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} + */ + static async update(updateWearable: UpdateWearableCommand): Promise { + 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} + */ + static async delete(deleteWearable: DeleteWearableCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(wearable) + .where("id = :id", { id: deleteWearable.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "wearable", err); + }); + } +} diff --git a/src/command/unit/wearable/wearableTypeCommand.ts b/src/command/unit/wearable/wearableTypeCommand.ts new file mode 100644 index 0000000..45cbc41 --- /dev/null +++ b/src/command/unit/wearable/wearableTypeCommand.ts @@ -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; +} diff --git a/src/command/unit/wearable/wearableTypeCommandHandler.ts b/src/command/unit/wearable/wearableTypeCommandHandler.ts new file mode 100644 index 0000000..b8f0f6f --- /dev/null +++ b/src/command/unit/wearable/wearableTypeCommandHandler.ts @@ -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} + */ + static async create(createWearableType: CreateWearableTypeCommand): Promise { + 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} + */ + static async update(updateWearableType: UpdateWearableTypeCommand): Promise { + 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} + */ + static async delete(deleteWearableType: DeleteWearableTypeCommand): Promise { + return await dataSource + .createQueryBuilder() + .delete() + .from(wearableType) + .where("id = :id", { id: deleteWearableType.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("DELETE", "wearableType", err); + }); + } +} diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index 20a78c2..f080e38 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -31,7 +31,7 @@ export class damageReport { equipmentId?: string; @Column({ nullable: true, default: null }) - maintenanceId: string; + maintenanceId?: string; @Column({ nullable: true, default: null }) vehicleId?: string; diff --git a/src/entity/unit/inspection/inspectionPointResult.ts b/src/entity/unit/inspection/inspectionPointResult.ts index 5b3501d..4f98e74 100644 --- a/src/entity/unit/inspection/inspectionPointResult.ts +++ b/src/entity/unit/inspection/inspectionPointResult.ts @@ -1,21 +1,18 @@ -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { Column, Entity, ManyToOne, PrimaryColumn } from "typeorm"; import { inspection } from "./inspection"; import { inspectionPoint } from "./inspectionPoint"; @Entity() export class inspectionPointResult { - @PrimaryGeneratedColumn("uuid") - id: string; + @PrimaryColumn() + inspectionId: string; + + @PrimaryColumn() + inspectionPointId: string; @Column({ type: "text" }) value: string; - @Column() - inspectionId: string; - - @Column() - inspectionPointId: string; - @ManyToOne(() => inspection, { nullable: false, onDelete: "CASCADE", diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index 83e856f..b064cb6 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -126,10 +126,9 @@ export const inspection_table = new Table({ export const inspection_point_result_table = new Table({ name: "inspection_point_result", columns: [ - { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, + { name: "inspectionId", ...getTypeByORM("uuid"), isPrimary: true }, + { name: "inspectionPointId", ...getTypeByORM("uuid"), isPrimary: true }, { name: "value", ...getTypeByORM("text") }, - { name: "inspectionId", ...getTypeByORM("uuid") }, - { name: "inspectionPointId", ...getTypeByORM("uuid") }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/service/unit/damageReport.ts b/src/service/unit/damageReportService.ts similarity index 100% rename from src/service/unit/damageReport.ts rename to src/service/unit/damageReportService.ts diff --git a/src/service/unit/inspection/inspectionPointResultService.ts b/src/service/unit/inspection/inspectionPointResultService.ts index d538a63..d294139 100644 --- a/src/service/unit/inspection/inspectionPointResultService.ts +++ b/src/service/unit/inspection/inspectionPointResultService.ts @@ -21,23 +21,4 @@ export default abstract class InspectionPointResultService { throw new DatabaseActionException("SELECT", "inspectionPointResult", err); }); } - - /** - * @description get inspectionPointResult by id - * @returns {Promise} - */ - static async getById(id: string): Promise { - return await dataSource - .getRepository(inspectionPointResult) - .createQueryBuilder("inspectionPointResult") - .leftJoinAndSelect("inspectionPointResult.inspectionPoint", "inspectionPoint") - .where({ id }) - .getOneOrFail() - .then((res) => { - return res; - }) - .catch((err) => { - throw new DatabaseActionException("SELECT", "inspectionPointResult", err); - }); - } } diff --git a/src/service/unit/inspection/inspectionVersionedPlanService.ts b/src/service/unit/inspection/inspectionVersionedPlanService.ts index 9313979..55eab31 100644 --- a/src/service/unit/inspection/inspectionVersionedPlanService.ts +++ b/src/service/unit/inspection/inspectionVersionedPlanService.ts @@ -23,6 +23,27 @@ export default abstract class InspectionVersionedPlanService { }); } + /** + * @description get latest inspectionVersionedPlan for plan + * @returns {Promise>} + */ + static async getLatestForInspectionPlan(inspectionPlanId: string): Promise { + return await dataSource + .getRepository(inspectionVersionedPlan) + .createQueryBuilder("inspectionVersionedPlan") + .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") + .where({ inspectionPlanId }) + .orderBy("inspectionVersionedPlan.version", "DESC") + .limit(1) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionVersionedPlan", err); + }); + } + /** * @description get inspectionVersionedPlan by id * @returns {Promise} diff --git a/src/service/unit/maintenance.ts b/src/service/unit/maintenanceService.ts similarity index 100% rename from src/service/unit/maintenance.ts rename to src/service/unit/maintenanceService.ts diff --git a/src/viewmodel/admin/unit/damageReport.models.ts b/src/viewmodel/admin/unit/damageReport.models.ts index e675c9c..9427d8a 100644 --- a/src/viewmodel/admin/unit/damageReport.models.ts +++ b/src/viewmodel/admin/unit/damageReport.models.ts @@ -30,16 +30,3 @@ export type DamageReportViewModel = { reportedBy: string; maintenance?: MaintenanceViewModel; } & DamageReportAssigned; - -export interface CreateDamageReportViewModel { - description: string; - reportedBy: string; - affectedId: string; - affected: "equipment" | "vehicle" | "wearable"; -} - -export interface UpdateDamageReportViewModel { - id: string; - status: string; - done: boolean; -} diff --git a/src/viewmodel/admin/unit/equipment/equipment.models.ts b/src/viewmodel/admin/unit/equipment/equipment.models.ts index abbdee7..2990c1d 100644 --- a/src/viewmodel/admin/unit/equipment/equipment.models.ts +++ b/src/viewmodel/admin/unit/equipment/equipment.models.ts @@ -10,20 +10,3 @@ export interface EquipmentViewModel { equipmentTypeId: string; equipmentType: EquipmentTypeViewModel; } - -export interface CreateEquipmentViewModel { - code?: string; - name: string; - location: string; - commissioned: Date; - equipmentTypeId: string; -} - -export interface UpdateEquipmentViewModel { - id: string; - code?: string; - name: string; - location: string; - commissioned: Date; - decommissioned?: Date; -} diff --git a/src/viewmodel/admin/unit/equipment/equipmentType.models.ts b/src/viewmodel/admin/unit/equipment/equipmentType.models.ts index fcf47ee..05ad905 100644 --- a/src/viewmodel/admin/unit/equipment/equipmentType.models.ts +++ b/src/viewmodel/admin/unit/equipment/equipmentType.models.ts @@ -3,14 +3,3 @@ export interface EquipmentTypeViewModel { type: string; description: string; } - -export interface CreateEquipmentTypeViewModel { - type: string; - description: string; -} - -export interface UpdateEquipmentTypeViewModel { - id: string; - type: string; - description: string; -} diff --git a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts index b2aecc0..cbbea41 100644 --- a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts @@ -40,18 +40,3 @@ export interface InspectionPointViewModel { max?: number; sort: number; } - -export interface CreateInspectionPlanViewModel { - title: string; - inspectionInterval: PlanTimeDefinition; - remindTime: PlanTimeDefinition; - relatedId: string; - assigned: "vehicle" | "equipment"; -} - -export interface UpdateInspectionPlanViewModel { - id: string; - title: string; - inspectionInterval: PlanTimeDefinition; - remindTime?: PlanTimeDefinition; -} diff --git a/src/viewmodel/admin/unit/maintenance.models.ts b/src/viewmodel/admin/unit/maintenance.models.ts index ce5c0b9..98f22f2 100644 --- a/src/viewmodel/admin/unit/maintenance.models.ts +++ b/src/viewmodel/admin/unit/maintenance.models.ts @@ -28,16 +28,3 @@ export type MaintenanceViewModel = { description: string; reports: DamageReportViewModel[]; } & MaintenanceAssigned; - -export interface CreateMaintenanceViewModel { - description: string; - reportedBy: string; - affectedId: string; - affected: "equipment" | "vehicle" | "wearable"; -} - -export interface UpdateMaintenanceViewModel { - id: string; - status: string; - done: boolean; -} diff --git a/src/viewmodel/admin/unit/vehicle/vehicle.models.ts b/src/viewmodel/admin/unit/vehicle/vehicle.models.ts index 4e273f6..b25ab0c 100644 --- a/src/viewmodel/admin/unit/vehicle/vehicle.models.ts +++ b/src/viewmodel/admin/unit/vehicle/vehicle.models.ts @@ -10,20 +10,3 @@ export interface VehicleViewModel { vehicleTypeId: string; vehicleType: VehicleTypeViewModel; } - -export interface CreateVehicleViewModel { - code?: string; - name: string; - location: string; - commissioned: Date; - vehicleTypeId: string; -} - -export interface UpdateVehicleViewModel { - id: string; - code?: string; - name: string; - location: string; - commissioned: Date; - decommissioned?: Date; -} diff --git a/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts b/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts index ea6c7cf..726311e 100644 --- a/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts +++ b/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts @@ -3,14 +3,3 @@ export interface VehicleTypeViewModel { type: string; description: string; } - -export interface CreateVehicleTypeViewModel { - type: string; - description: string; -} - -export interface UpdateVehicleTypeViewModel { - id: string; - type: string; - description: string; -} diff --git a/src/viewmodel/admin/unit/wearable/wearable.models.ts b/src/viewmodel/admin/unit/wearable/wearable.models.ts index e2c5bbc..e3bacac 100644 --- a/src/viewmodel/admin/unit/wearable/wearable.models.ts +++ b/src/viewmodel/admin/unit/wearable/wearable.models.ts @@ -13,22 +13,3 @@ export interface WearableViewModel { wearableTypeId: string; wearableType: WearableTypeViewModel; } - -export interface CreateWearableViewModel { - code?: string; - name: string; - wearerId?: string; - location?: string; - commissioned: Date; - wearableTypeId: string; -} - -export interface UpdateWearableViewModel { - id: string; - code?: string; - name: string; - location?: string; - commissioned: Date; - decommissioned?: Date; - wearerId?: string; -} diff --git a/src/viewmodel/admin/unit/wearable/wearableType.models.ts b/src/viewmodel/admin/unit/wearable/wearableType.models.ts index b3f49fc..73fd7c5 100644 --- a/src/viewmodel/admin/unit/wearable/wearableType.models.ts +++ b/src/viewmodel/admin/unit/wearable/wearableType.models.ts @@ -3,14 +3,3 @@ export interface WearableTypeViewModel { type: string; description: string; } - -export interface CreateWearableTypeViewModel { - type: string; - description: string; -} - -export interface UpdateWearableTypeViewModel { - id: string; - type: string; - description: string; -} From 0684605093deee62b07fd8beb9fde4e1d590cd8d Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Thu, 29 May 2025 10:52:05 +0200 Subject: [PATCH 15/34] base router and permissions --- src/routes/admin/index.ts | 54 +++++++++++++++++++ src/routes/admin/unit/equipment.ts | 10 ++++ src/routes/admin/unit/equipmentType.ts | 10 ++++ src/routes/admin/unit/inspection.ts | 10 ++++ src/routes/admin/unit/inspectionPlan.ts | 10 ++++ src/routes/admin/unit/vehicle.ts | 10 ++++ src/routes/admin/unit/vehicleType.ts | 10 ++++ src/routes/admin/unit/wearable.ts | 10 ++++ src/routes/admin/unit/wearableType.ts | 10 ++++ src/routes/public.ts | 4 ++ src/type/permissionTypes.ts | 70 ++++++++++++++++++++----- 11 files changed, 196 insertions(+), 12 deletions(-) create mode 100644 src/routes/admin/unit/equipment.ts create mode 100644 src/routes/admin/unit/equipmentType.ts create mode 100644 src/routes/admin/unit/inspection.ts create mode 100644 src/routes/admin/unit/inspectionPlan.ts create mode 100644 src/routes/admin/unit/vehicle.ts create mode 100644 src/routes/admin/unit/vehicleType.ts create mode 100644 src/routes/admin/unit/wearable.ts create mode 100644 src/routes/admin/unit/wearableType.ts diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index 4e74012..13e48f5 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -2,6 +2,7 @@ import express from "express"; import PermissionHelper from "../../helpers/permissionHelper"; import preventWebapiAccess from "../../middleware/preventWebApiAccess"; +/** configuration */ import award from "./configuration/award"; import communicationType from "./configuration/communicationType"; import executivePosition from "./configuration/executivePosition"; @@ -14,6 +15,7 @@ import template from "./configuration/template"; import templateUsage from "./configuration/templateUsage"; import newsletterConfig from "./configuration/newsletterConfig"; +/** club */ import member from "./club/member"; import protocol from "./club/protocol"; import calendar from "./club/calendar"; @@ -21,6 +23,7 @@ import queryBuilder from "./club/queryBuilder"; import newsletter from "./club/newsletter"; import listprint from "./club/listprint"; +/** management */ import role from "./management/role"; import user from "./management/user"; import invite from "./management/invite"; @@ -28,8 +31,19 @@ import api from "./management/webapi"; import backup from "./management/backup"; 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"; + var router = express.Router({ mergeParams: true }); +/** configuration */ router.use( "/award", PermissionHelper.passCheckSomeMiddleware([ @@ -112,6 +126,7 @@ router.use( newsletterConfig ); +/** club */ router.use("/member", PermissionHelper.passCheckMiddleware("read", "club", "member"), member); router.use( "/protocol", @@ -143,6 +158,7 @@ router.use( ); router.use("/listprint", PermissionHelper.passCheckMiddleware("read", "club", "listprint"), listprint); +/** management */ router.use("/role", PermissionHelper.passCheckMiddleware("read", "management", "role"), role); router.use( "/user", @@ -162,4 +178,42 @@ router.use( ); router.use("/setting", PermissionHelper.passCheckMiddleware("read", "management", "setting"), setting); +/** unit */ +router.use("/equipment", PermissionHelper.passCheckMiddleware("read", "unit", "equipment"), equipment); +router.use( + "/equipmenttype", + PermissionHelper.passCheckSomeMiddleware([ + { requiredPermission: "read", section: "unit", module: "equipment_type" }, + { requiredPermission: "read", section: "unit", module: "equipment" }, + ]), + equipmentType +); +router.use("/vehicle", PermissionHelper.passCheckMiddleware("read", "unit", "vehicle"), vehicle); +router.use( + "/vehicletype", + PermissionHelper.passCheckSomeMiddleware([ + { requiredPermission: "read", section: "unit", module: "vehicle_type" }, + { requiredPermission: "read", section: "unit", module: "vehicle" }, + ]), + vehicleType +); +router.use("/wearable", PermissionHelper.passCheckMiddleware("read", "unit", "wearable"), wearable); +router.use( + "/wearabletype", + PermissionHelper.passCheckSomeMiddleware([ + { requiredPermission: "read", section: "unit", module: "wearable_type" }, + { requiredPermission: "read", section: "unit", module: "wearable" }, + ]), + wearableType +); +router.use("/inspection", PermissionHelper.passCheckMiddleware("read", "unit", "inspection"), inspection); +router.use( + "/inspectionplan", + PermissionHelper.passCheckSomeMiddleware([ + { requiredPermission: "read", section: "unit", module: "inspection_plan" }, + { requiredPermission: "read", section: "unit", module: "inspection" }, + ]), + inspectionPlan +); + export default router; diff --git a/src/routes/admin/unit/equipment.ts b/src/routes/admin/unit/equipment.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/equipment.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/equipmentType.ts b/src/routes/admin/unit/equipmentType.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/equipmentType.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/inspection.ts b/src/routes/admin/unit/inspection.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/inspection.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/inspectionPlan.ts b/src/routes/admin/unit/inspectionPlan.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/inspectionPlan.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/vehicle.ts b/src/routes/admin/unit/vehicle.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/vehicle.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/vehicleType.ts b/src/routes/admin/unit/vehicleType.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/vehicleType.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/wearable.ts b/src/routes/admin/unit/wearable.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/wearable.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/admin/unit/wearableType.ts b/src/routes/admin/unit/wearableType.ts new file mode 100644 index 0000000..e13bc7d --- /dev/null +++ b/src/routes/admin/unit/wearableType.ts @@ -0,0 +1,10 @@ +import express, { Request, Response } from "express"; +import PermissionHelper from "../../../helpers/permissionHelper"; + +var router = express.Router({ mergeParams: true }); + +router.get("/", async (req: Request, res: Response) => { + res.send("TODO"); +}); + +export default router; diff --git a/src/routes/public.ts b/src/routes/public.ts index d557dd7..360f962 100644 --- a/src/routes/public.ts +++ b/src/routes/public.ts @@ -14,6 +14,10 @@ router.get("/calendar", async (req, res) => { await getCalendarItemsByTypes(req, res); }); +router.post("/reportdamage", async (req, res) => { + res.send("TODO"); +}); + router.get("/configuration", async (req, res) => { await getApplicationConfig(req, res); }); diff --git a/src/type/permissionTypes.ts b/src/type/permissionTypes.ts index eff7fd1..d6ec391 100644 --- a/src/type/permissionTypes.ts +++ b/src/type/permissionTypes.ts @@ -1,27 +1,43 @@ -export type PermissionSection = "club" | "configuration" | "management"; +export type PermissionSection = "club" | "unit" | "configuration" | "management"; export type PermissionModule = + // club | "member" | "calendar" | "newsletter" - | "newsletter_config" | "protocol" + | "query" | "listprint" + // unit + | "equipment" + | "equipment_type" + | "vehicle" + | "vehicle_type" + | "wearable" + | "wearable_type" + | "inspection" + | "inspection_plan" + | "respiratory_gear" + | "respiratory_wearer" + | "respiratory_mission" + | "damage_report" + // configuration | "qualification" | "award" | "executive_position" | "communication_type" | "membership_status" + | "newsletter_config" | "salutation" | "calendar_type" - | "user" - | "role" - | "webapi" - | "query" | "query_store" | "template" | "template_usage" | "backup" + // management + | "user" + | "role" + | "webapi" | "setting"; export type PermissionType = "read" | "create" | "update" | "delete"; @@ -56,34 +72,64 @@ export type SectionsAndModulesObject = { }>; }; -export const permissionSections: Array = ["club", "configuration", "management"]; +export const permissionSections: Array = ["club", "unit", "configuration", "management"]; export const permissionModules: Array = [ + // club "member", "calendar", "newsletter", - "newsletter_config", "protocol", + "query", "listprint", + // unit + "equipment", + "equipment_type", + "vehicle", + "vehicle_type", + "wearable", + "wearable_type", + "inspection", + "inspection_plan", + "respiratory_gear", + "respiratory_wearer", + "respiratory_mission", + "damage_report", + // configuration "qualification", "award", "executive_position", "communication_type", "membership_status", + "newsletter_config", "salutation", "calendar_type", - "user", - "role", - "webapi", - "query", "query_store", "template", "template_usage", "backup", + // management + "user", + "role", + "webapi", "setting", ]; export const permissionTypes: Array = ["read", "create", "update", "delete"]; export const sectionsAndModules: SectionsAndModulesObject = { club: ["member", "calendar", "newsletter", "protocol", "query", "listprint"], + unit: [ + "equipment", + "equipment_type", + "vehicle", + "vehicle_type", + "wearable", + "wearable_type", + "inspection", + "inspection_plan", + "respiratory_gear", + "respiratory_wearer", + "respiratory_mission", + "damage_report", + ], configuration: [ "qualification", "award", From 9a1e7e74ca57f935379c20deeca1ffe51ce95088 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Thu, 29 May 2025 11:00:23 +0200 Subject: [PATCH 16/34] base controller files --- src/controller/admin/unit/equipmentController.ts | 0 src/controller/admin/unit/equipmentTypeController.ts | 0 src/controller/admin/unit/inspectionController.ts | 0 src/controller/admin/unit/inspectionPlanController.ts | 0 src/controller/admin/unit/vehicleController.ts | 0 src/controller/admin/unit/vehicleTypeController.ts | 0 src/controller/admin/unit/wearableController.ts | 0 src/controller/admin/unit/wearableTypeController.ts | 0 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/controller/admin/unit/equipmentController.ts create mode 100644 src/controller/admin/unit/equipmentTypeController.ts create mode 100644 src/controller/admin/unit/inspectionController.ts create mode 100644 src/controller/admin/unit/inspectionPlanController.ts create mode 100644 src/controller/admin/unit/vehicleController.ts create mode 100644 src/controller/admin/unit/vehicleTypeController.ts create mode 100644 src/controller/admin/unit/wearableController.ts create mode 100644 src/controller/admin/unit/wearableTypeController.ts diff --git a/src/controller/admin/unit/equipmentController.ts b/src/controller/admin/unit/equipmentController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/equipmentTypeController.ts b/src/controller/admin/unit/equipmentTypeController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/inspectionPlanController.ts b/src/controller/admin/unit/inspectionPlanController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/vehicleController.ts b/src/controller/admin/unit/vehicleController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/vehicleTypeController.ts b/src/controller/admin/unit/vehicleTypeController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/wearableController.ts b/src/controller/admin/unit/wearableController.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/controller/admin/unit/wearableTypeController.ts b/src/controller/admin/unit/wearableTypeController.ts new file mode 100644 index 0000000..e69de29 From 9f2a08ccc974f919f8526f955f4b867878c1c812 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 31 May 2025 15:12:16 +0200 Subject: [PATCH 17/34] define routes --- .../admin/unit/equipmentController.ts | 104 +++++++++++++++++ .../admin/unit/equipmentTypeController.ts | 101 +++++++++++++++++ .../admin/unit/inspectionController.ts | 106 ++++++++++++++++++ .../admin/unit/inspectionPlanController.ts | 106 ++++++++++++++++++ .../admin/unit/vehicleController.ts | 104 +++++++++++++++++ .../admin/unit/vehicleTypeController.ts | 101 +++++++++++++++++ .../admin/unit/wearableController.ts | 104 +++++++++++++++++ .../admin/unit/wearableTypeController.ts | 101 +++++++++++++++++ src/routes/admin/unit/equipment.ts | 37 +++++- src/routes/admin/unit/equipmentType.ts | 37 +++++- src/routes/admin/unit/inspection.ts | 45 +++++++- src/routes/admin/unit/inspectionPlan.ts | 45 +++++++- src/routes/admin/unit/vehicle.ts | 37 +++++- src/routes/admin/unit/vehicleType.ts | 37 +++++- src/routes/admin/unit/wearable.ts | 37 +++++- src/routes/admin/unit/wearableType.ts | 37 +++++- 16 files changed, 1129 insertions(+), 10 deletions(-) diff --git a/src/controller/admin/unit/equipmentController.ts b/src/controller/admin/unit/equipmentController.ts index e69de29..8546df7 100644 --- a/src/controller/admin/unit/equipmentController.ts +++ b/src/controller/admin/unit/equipmentController.ts @@ -0,0 +1,104 @@ +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 { + 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); + + //{ offset, count, search, noLimit, ids } + let [equipments, total] = await EquipmentService.getAll(); + + res.json({ + equipments: 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 { + const equipmentId = req.params.id; + let equipment = await EquipmentService.getById(equipmentId); + + res.json(EquipmentFactory.mapToSingle(equipment)); +} + +/** + * @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 { + const salutationId = parseInt(req.body.salutationId); + + let createEquipment: CreateEquipmentCommand = { + name: "", + location: "", + commissioned: undefined, + 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 { + const equipmentId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + let updateEquipment: UpdateEquipmentCommand = { + id: equipmentId, + name: "", + location: "", + commissioned: undefined, + }; + 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 { + const equipmentId = req.params.id; + + let deleteEquipment: DeleteEquipmentCommand = { + id: equipmentId, + }; + await EquipmentCommandHandler.delete(deleteEquipment); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/equipmentTypeController.ts b/src/controller/admin/unit/equipmentTypeController.ts index e69de29..27e387f 100644 --- a/src/controller/admin/unit/equipmentTypeController.ts +++ b/src/controller/admin/unit/equipmentTypeController.ts @@ -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 { + 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); + + //{ offset, count, search, noLimit, ids } + let [equipmentTypes, total] = await EquipmentTypeService.getAll(); + + res.json({ + equipmentTypes: 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 { + 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 { + const salutationId = parseInt(req.body.salutationId); + + 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 { + const equipmentTypeId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + 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 { + const equipmentTypeId = req.params.id; + + let deleteEquipmentType: DeleteEquipmentTypeCommand = { + id: equipmentTypeId, + }; + await EquipmentTypeCommandHandler.delete(deleteEquipmentType); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index e69de29..c1f183b 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -0,0 +1,106 @@ +import { Request, Response } from "express"; +import InspectionService from "../../../service/unit/inspection/inspectionService"; +import InspectionFactory from "../../../factory/admin/unit/inspection/inspection"; +import { + CreateInspectionCommand, + DeleteInspectionCommand, + UpdateInspectionCommand, +} from "../../../command/unit/inspection/inspectionCommand"; +import InspectionCommandHandler from "../../../command/unit/inspection/inspectionCommandHandler"; + +/** + * @description get all inspections for related id + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getAllInspectionsForRelated(req: Request, res: Response): Promise { + let relation = req.params.related as "vehicle" | "equipment"; + 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 search = (req.query.search as string) ?? ""; + let noLimit = req.query.noLimit === "true"; + let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); + + //{ offset, count, search, noLimit, ids } + let [inspections, total] = await InspectionService.getAllForRelated({ equipmentId: relationId }); + + res.json({ + inspections: 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 getInspectionById(req: Request, res: Response): Promise { + const inspectionId = req.params.id; + let inspection = await InspectionService.getById(inspectionId); + + res.json(InspectionFactory.mapToSingle(inspection)); +} + +/** + * @description create inspection + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function createInspection(req: Request, res: Response): Promise { + const salutationId = parseInt(req.body.salutationId); + + let createInspection: CreateInspectionCommand = { + context: "", + inspectionPlanId: "", + relatedId: "", + assigned: "equipment", + }; + let inspectionId = await InspectionCommandHandler.create(createInspection); + + res.status(200).send(inspectionId); +} + +/** + * @description update inspection by id + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function updateInspectionById(req: Request, res: Response): Promise { + const inspectionId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + let updateInspection: UpdateInspectionCommand = { + id: inspectionId, + context: "", + }; + await InspectionCommandHandler.update(updateInspection); + + res.sendStatus(204); +} + +/** + * @description delete inspection by id + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function deleteInspectionById(req: Request, res: Response): Promise { + const inspectionId = req.params.id; + + // TODO finished inspection cannot be deleted + + let deleteInspection: DeleteInspectionCommand = { + id: inspectionId, + }; + await InspectionCommandHandler.delete(deleteInspection); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/inspectionPlanController.ts b/src/controller/admin/unit/inspectionPlanController.ts index e69de29..4b60588 100644 --- a/src/controller/admin/unit/inspectionPlanController.ts +++ b/src/controller/admin/unit/inspectionPlanController.ts @@ -0,0 +1,106 @@ +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"; + +/** + * @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 { + let relation = req.params.related as "vehicle" | "equipment"; + 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 search = (req.query.search as string) ?? ""; + let noLimit = req.query.noLimit === "true"; + let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); + + //{ offset, count, search, noLimit, ids } + let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated({ equipmentId: relationId }); + + res.json({ + inspectionPlans: inspectionPlans, + total: total, + offset: offset, + count: count, + }); +} + +/** + * @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 { + 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 { + const salutationId = parseInt(req.body.salutationId); + + let createInspectionPlan: CreateInspectionPlanCommand = { + title: "", + inspectionInterval: "1-m", + remindTime: "1-m", + relatedId: "", + assigned: "equipment", + }; + 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 { + const inspectionPlanId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + let updateInspectionPlan: UpdateInspectionPlanCommand = { + id: inspectionPlanId, + title: "", + inspectionInterval: "1-m", + }; + await InspectionPlanCommandHandler.update(updateInspectionPlan); + + 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 { + const inspectionPlanId = req.params.id; + + let deleteInspectionPlan: DeleteInspectionPlanCommand = { + id: inspectionPlanId, + }; + await InspectionPlanCommandHandler.delete(deleteInspectionPlan); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/vehicleController.ts b/src/controller/admin/unit/vehicleController.ts index e69de29..55c1902 100644 --- a/src/controller/admin/unit/vehicleController.ts +++ b/src/controller/admin/unit/vehicleController.ts @@ -0,0 +1,104 @@ +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 { + 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); + + //{ offset, count, search, noLimit, ids } + let [vehicles, total] = await VehicleService.getAll(); + + res.json({ + vehicles: 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 { + const vehicleId = req.params.id; + let vehicle = await VehicleService.getById(vehicleId); + + res.json(VehicleFactory.mapToSingle(vehicle)); +} + +/** + * @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 { + const salutationId = parseInt(req.body.salutationId); + + let createVehicle: CreateVehicleCommand = { + name: "", + location: "", + commissioned: undefined, + 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 { + const vehicleId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + let updateVehicle: UpdateVehicleCommand = { + id: vehicleId, + name: "", + location: "", + commissioned: undefined, + }; + 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 { + const vehicleId = req.params.id; + + let deleteVehicle: DeleteVehicleCommand = { + id: vehicleId, + }; + await VehicleCommandHandler.delete(deleteVehicle); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/vehicleTypeController.ts b/src/controller/admin/unit/vehicleTypeController.ts index e69de29..c11d1f1 100644 --- a/src/controller/admin/unit/vehicleTypeController.ts +++ b/src/controller/admin/unit/vehicleTypeController.ts @@ -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 { + 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); + + //{ offset, count, search, noLimit, ids } + let [vehicleTypes, total] = await VehicleTypeService.getAll(); + + res.json({ + vehicleTypes: 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 { + 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 { + const salutationId = parseInt(req.body.salutationId); + + 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 { + const vehicleTypeId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + 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 { + const vehicleTypeId = req.params.id; + + let deleteVehicleType: DeleteVehicleTypeCommand = { + id: vehicleTypeId, + }; + await VehicleTypeCommandHandler.delete(deleteVehicleType); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/wearableController.ts b/src/controller/admin/unit/wearableController.ts index e69de29..209eaa5 100644 --- a/src/controller/admin/unit/wearableController.ts +++ b/src/controller/admin/unit/wearableController.ts @@ -0,0 +1,104 @@ +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 { + 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); + + //{ offset, count, search, noLimit, ids } + let [wearables, total] = await WearableService.getAll(); + + res.json({ + wearables: 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 { + const wearableId = req.params.id; + let wearable = await WearableService.getById(wearableId); + + res.json(WearableFactory.mapToSingle(wearable)); +} + +/** + * @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 { + const salutationId = parseInt(req.body.salutationId); + + let createWearable: CreateWearableCommand = { + name: "", + location: "", + commissioned: undefined, + wearableTypeId: "", + }; + 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 { + const wearableId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + let updateWearable: UpdateWearableCommand = { + id: wearableId, + name: "", + location: "", + commissioned: undefined, + }; + 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 { + const wearableId = req.params.id; + + let deleteWearable: DeleteWearableCommand = { + id: wearableId, + }; + await WearableCommandHandler.delete(deleteWearable); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/wearableTypeController.ts b/src/controller/admin/unit/wearableTypeController.ts index e69de29..fffc969 100644 --- a/src/controller/admin/unit/wearableTypeController.ts +++ b/src/controller/admin/unit/wearableTypeController.ts @@ -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 { + 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); + + //{ offset, count, search, noLimit, ids } + let [wearableTypes, total] = await WearableTypeService.getAll(); + + res.json({ + wearableTypes: 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 { + 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 { + const salutationId = parseInt(req.body.salutationId); + + 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 { + const wearableTypeId = req.params.id; + const salutationId = parseInt(req.body.salutationId); + + 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 { + const wearableTypeId = req.params.id; + + let deleteWearableType: DeleteWearableTypeCommand = { + id: wearableTypeId, + }; + await WearableTypeCommandHandler.delete(deleteWearableType); + + res.sendStatus(204); +} diff --git a/src/routes/admin/unit/equipment.ts b/src/routes/admin/unit/equipment.ts index e13bc7d..96f432c 100644 --- a/src/routes/admin/unit/equipment.ts +++ b/src/routes/admin/unit/equipment.ts @@ -1,10 +1,45 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createEquipment, + deleteEquipmentById, + getAllEquipments, + getEquipmentById, + updateEquipmentById, +} from "../../../controller/admin/unit/equipmentController"; var router = express.Router({ mergeParams: true }); router.get("/", async (req: Request, res: Response) => { - res.send("TODO"); + await getAllEquipments(req, res); }); +router.get("/:id", async (req: Request, res: Response) => { + await getEquipmentById(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; diff --git a/src/routes/admin/unit/equipmentType.ts b/src/routes/admin/unit/equipmentType.ts index e13bc7d..e197e34 100644 --- a/src/routes/admin/unit/equipmentType.ts +++ b/src/routes/admin/unit/equipmentType.ts @@ -1,10 +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) => { - res.send("TODO"); + 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; diff --git a/src/routes/admin/unit/inspection.ts b/src/routes/admin/unit/inspection.ts index e13bc7d..8c7a63d 100644 --- a/src/routes/admin/unit/inspection.ts +++ b/src/routes/admin/unit/inspection.ts @@ -1,10 +1,51 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createInspection, + deleteInspectionById, + getAllInspectionsForRelated, + getInspectionById, + updateInspectionById, +} from "../../../controller/admin/unit/inspectionController"; var router = express.Router({ mergeParams: true }); -router.get("/", async (req: Request, res: Response) => { - res.send("TODO"); +router.get(["/vehicle/:relatedId", "/equipment/:relatedId"], async (req: Request, res: Response) => { + if (req.path.startsWith("/vehicle")) { + req.params.related = "vehicle"; + } else { + req.params.related = "equipment"; + } + + await getAllInspectionsForRelated(req, res); }); +router.get("/:id", async (req: Request, res: Response) => { + await getInspectionById(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.delete( + "/:id", + PermissionHelper.passCheckMiddleware("delete", "unit", "inspection"), + async (req: Request, res: Response) => { + await deleteInspectionById(req, res); + } +); + export default router; diff --git a/src/routes/admin/unit/inspectionPlan.ts b/src/routes/admin/unit/inspectionPlan.ts index e13bc7d..0e33d5c 100644 --- a/src/routes/admin/unit/inspectionPlan.ts +++ b/src/routes/admin/unit/inspectionPlan.ts @@ -1,10 +1,51 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createInspectionPlan, + deleteInspectionPlanById, + getAllInspectionPlansForRelated, + getInspectionPlanById, + updateInspectionPlanById, +} from "../../../controller/admin/unit/inspectionPlanController"; var router = express.Router({ mergeParams: true }); -router.get("/", async (req: Request, res: Response) => { - res.send("TODO"); +router.get(["/vehicle/:relatedId", "/equipment/:relatedId"], async (req: Request, res: Response) => { + if (req.path.startsWith("/vehicle")) { + req.params.related = "vehicle"; + } else { + req.params.related = "equipment"; + } + + 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.delete( + "/:id", + PermissionHelper.passCheckMiddleware("delete", "unit", "inspection_plan"), + async (req: Request, res: Response) => { + await deleteInspectionPlanById(req, res); + } +); + export default router; diff --git a/src/routes/admin/unit/vehicle.ts b/src/routes/admin/unit/vehicle.ts index e13bc7d..832e248 100644 --- a/src/routes/admin/unit/vehicle.ts +++ b/src/routes/admin/unit/vehicle.ts @@ -1,10 +1,45 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createVehicle, + deleteVehicleById, + getAllVehicles, + getVehicleById, + updateVehicleById, +} from "../../../controller/admin/unit/vehicleController"; var router = express.Router({ mergeParams: true }); router.get("/", async (req: Request, res: Response) => { - res.send("TODO"); + await getAllVehicles(req, res); }); +router.get("/:id", async (req: Request, res: Response) => { + await getVehicleById(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; diff --git a/src/routes/admin/unit/vehicleType.ts b/src/routes/admin/unit/vehicleType.ts index e13bc7d..03f2989 100644 --- a/src/routes/admin/unit/vehicleType.ts +++ b/src/routes/admin/unit/vehicleType.ts @@ -1,10 +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) => { - res.send("TODO"); + 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; diff --git a/src/routes/admin/unit/wearable.ts b/src/routes/admin/unit/wearable.ts index e13bc7d..c25226a 100644 --- a/src/routes/admin/unit/wearable.ts +++ b/src/routes/admin/unit/wearable.ts @@ -1,10 +1,45 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createWearable, + deleteWearableById, + getAllWearables, + getWearableById, + updateWearableById, +} from "../../../controller/admin/unit/wearableController"; var router = express.Router({ mergeParams: true }); router.get("/", async (req: Request, res: Response) => { - res.send("TODO"); + await getAllWearables(req, res); }); +router.get("/:id", async (req: Request, res: Response) => { + await getWearableById(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; diff --git a/src/routes/admin/unit/wearableType.ts b/src/routes/admin/unit/wearableType.ts index e13bc7d..b61584f 100644 --- a/src/routes/admin/unit/wearableType.ts +++ b/src/routes/admin/unit/wearableType.ts @@ -1,10 +1,45 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; +import { + createWearableType, + getAllWearableTypes, + getWearableTypeById, + updateWearableTypeById, +} from "../../../controller/admin/unit/wearableTypeController"; +import { deleteWearableById } from "../../../controller/admin/unit/wearableController"; var router = express.Router({ mergeParams: true }); router.get("/", async (req: Request, res: Response) => { - res.send("TODO"); + await getAllWearableTypes(req, res); }); +router.get("/:id", async (req: Request, res: Response) => { + await getWearableTypeById(req, res); +}); + +router.post( + "/", + PermissionHelper.passCheckMiddleware("create", "unit", "wearable_type"), + async (req: Request, res: Response) => { + await createWearableType(req, res); + } +); + +router.patch( + "/:id", + PermissionHelper.passCheckMiddleware("update", "unit", "wearable_type"), + async (req: Request, res: Response) => { + await updateWearableTypeById(req, res); + } +); + +router.delete( + "/:id", + PermissionHelper.passCheckMiddleware("delete", "unit", "wearable_type"), + async (req: Request, res: Response) => { + await deleteWearableById(req, res); + } +); + export default router; From 2609ecc1bf3f38ef5375ec38ab7349d6ff4bb573 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 2 Jun 2025 13:14:09 +0200 Subject: [PATCH 18/34] controller --- .../admin/unit/equipmentController.ts | 22 +++++- .../admin/unit/equipmentTypeController.ts | 3 +- .../admin/unit/inspectionController.ts | 6 +- .../admin/unit/inspectionPlanController.ts | 10 ++- .../admin/unit/vehicleController.ts | 3 +- .../admin/unit/vehicleTypeController.ts | 3 +- .../admin/unit/wearableController.ts | 3 +- .../admin/unit/wearableTypeController.ts | 3 +- src/routes/admin/unit/equipment.ts | 5 ++ .../unit/equipment/equipmentService.ts | 41 +++++++++-- .../unit/equipment/equipmentTypeService.ts | 39 +++++++++-- .../unit/inspection/inspectionPlanService.ts | 69 ++++++++++++------- .../unit/inspection/inspectionService.ts | 48 ++++++++----- src/service/unit/vehicle/vehicleService.ts | 41 +++++++++-- .../unit/vehicle/vehicleTypeService.ts | 39 +++++++++-- src/service/unit/wearable/wearableService.ts | 41 +++++++++-- .../unit/wearable/wearableTypeService.ts | 39 +++++++++-- 17 files changed, 320 insertions(+), 95 deletions(-) diff --git a/src/controller/admin/unit/equipmentController.ts b/src/controller/admin/unit/equipmentController.ts index 8546df7..8d7e200 100644 --- a/src/controller/admin/unit/equipmentController.ts +++ b/src/controller/admin/unit/equipmentController.ts @@ -21,8 +21,7 @@ export async function getAllEquipments(req: Request, res: Response): Promise i); - //{ offset, count, search, noLimit, ids } - let [equipments, total] = await EquipmentService.getAll(); + let [equipments, total] = await EquipmentService.getAll({ offset, count, search, noLimit, ids }); res.json({ equipments: equipments, @@ -45,6 +44,25 @@ export async function getEquipmentById(req: Request, res: Response): Promise} + */ +export async function getEquipmentsByIds(req: Request, res: Response): Promise { + let ids = req.body.ids as Array; + + 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 diff --git a/src/controller/admin/unit/equipmentTypeController.ts b/src/controller/admin/unit/equipmentTypeController.ts index 27e387f..dce7b77 100644 --- a/src/controller/admin/unit/equipmentTypeController.ts +++ b/src/controller/admin/unit/equipmentTypeController.ts @@ -21,8 +21,7 @@ export async function getAllEquipmentTypes(req: Request, res: Response): Promise let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - //{ offset, count, search, noLimit, ids } - let [equipmentTypes, total] = await EquipmentTypeService.getAll(); + let [equipmentTypes, total] = await EquipmentTypeService.getAll({ offset, count, search, noLimit, ids }); res.json({ equipmentTypes: equipmentTypes, diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index c1f183b..8c4b782 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -19,12 +19,10 @@ export async function getAllInspectionsForRelated(req: Request, res: Response): 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 search = (req.query.search as string) ?? ""; let noLimit = req.query.noLimit === "true"; - let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - //{ offset, count, search, noLimit, ids } - let [inspections, total] = await InspectionService.getAllForRelated({ equipmentId: relationId }); + let where = relation === "equipment" ? { equipmentId: relationId } : { vehicleId: relationId }; + let [inspections, total] = await InspectionService.getAllForRelated(where, { offset, count, noLimit }); res.json({ inspections: inspections, diff --git a/src/controller/admin/unit/inspectionPlanController.ts b/src/controller/admin/unit/inspectionPlanController.ts index 4b60588..358ac66 100644 --- a/src/controller/admin/unit/inspectionPlanController.ts +++ b/src/controller/admin/unit/inspectionPlanController.ts @@ -23,8 +23,14 @@ export async function getAllInspectionPlansForRelated(req: Request, res: Respons let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - //{ offset, count, search, noLimit, ids } - let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated({ equipmentId: relationId }); + let where = relation === "equipment" ? { equipmentId: relationId } : { vehicleId: relationId }; + let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated(where, { + offset, + count, + search, + noLimit, + ids, + }); res.json({ inspectionPlans: inspectionPlans, diff --git a/src/controller/admin/unit/vehicleController.ts b/src/controller/admin/unit/vehicleController.ts index 55c1902..02b3606 100644 --- a/src/controller/admin/unit/vehicleController.ts +++ b/src/controller/admin/unit/vehicleController.ts @@ -21,8 +21,7 @@ export async function getAllVehicles(req: Request, res: Response): Promise let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - //{ offset, count, search, noLimit, ids } - let [vehicles, total] = await VehicleService.getAll(); + let [vehicles, total] = await VehicleService.getAll({ offset, count, search, noLimit, ids }); res.json({ vehicles: vehicles, diff --git a/src/controller/admin/unit/vehicleTypeController.ts b/src/controller/admin/unit/vehicleTypeController.ts index c11d1f1..7cf5552 100644 --- a/src/controller/admin/unit/vehicleTypeController.ts +++ b/src/controller/admin/unit/vehicleTypeController.ts @@ -21,8 +21,7 @@ export async function getAllVehicleTypes(req: Request, res: Response): Promise i); - //{ offset, count, search, noLimit, ids } - let [vehicleTypes, total] = await VehicleTypeService.getAll(); + let [vehicleTypes, total] = await VehicleTypeService.getAll({ offset, count, search, noLimit, ids }); res.json({ vehicleTypes: vehicleTypes, diff --git a/src/controller/admin/unit/wearableController.ts b/src/controller/admin/unit/wearableController.ts index 209eaa5..7775c36 100644 --- a/src/controller/admin/unit/wearableController.ts +++ b/src/controller/admin/unit/wearableController.ts @@ -21,8 +21,7 @@ export async function getAllWearables(req: Request, res: Response): Promise let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - //{ offset, count, search, noLimit, ids } - let [wearables, total] = await WearableService.getAll(); + let [wearables, total] = await WearableService.getAll({ offset, count, search, noLimit, ids }); res.json({ wearables: wearables, diff --git a/src/controller/admin/unit/wearableTypeController.ts b/src/controller/admin/unit/wearableTypeController.ts index fffc969..40def8b 100644 --- a/src/controller/admin/unit/wearableTypeController.ts +++ b/src/controller/admin/unit/wearableTypeController.ts @@ -21,8 +21,7 @@ export async function getAllWearableTypes(req: Request, res: Response): Promise< let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - //{ offset, count, search, noLimit, ids } - let [wearableTypes, total] = await WearableTypeService.getAll(); + let [wearableTypes, total] = await WearableTypeService.getAll({ offset, count, search, noLimit, ids }); res.json({ wearableTypes: wearableTypes, diff --git a/src/routes/admin/unit/equipment.ts b/src/routes/admin/unit/equipment.ts index 96f432c..4e45a52 100644 --- a/src/routes/admin/unit/equipment.ts +++ b/src/routes/admin/unit/equipment.ts @@ -5,6 +5,7 @@ import { deleteEquipmentById, getAllEquipments, getEquipmentById, + getEquipmentsByIds, updateEquipmentById, } from "../../../controller/admin/unit/equipmentController"; @@ -18,6 +19,10 @@ 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"), diff --git a/src/service/unit/equipment/equipmentService.ts b/src/service/unit/equipment/equipmentService.ts index a2e1823..7e2267b 100644 --- a/src/service/unit/equipment/equipmentService.ts +++ b/src/service/unit/equipment/equipmentService.ts @@ -1,3 +1,4 @@ +import { In, Like } from "typeorm"; import { dataSource } from "../../../data-source"; import { equipment } from "../../../entity/unit/equipment/equipment"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -5,15 +6,45 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class EquipmentService { /** * @description get all equipment - * @returns {Promise>} + * @returns {Promise<[Array, number]>} */ - static async getAll(): Promise> { - return await dataSource + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = dataSource .getRepository(equipment) .createQueryBuilder("equipment") - .leftJoinAndSelect("equipment.equipmentType", "equipmenttype") + .leftJoinAndSelect("equipment.equipmentType", "equipmenttype"); + + if (search != "") { + query = query.where({ + code: Like(search), + name: Like(search), + location: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("name", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) diff --git a/src/service/unit/equipment/equipmentTypeService.ts b/src/service/unit/equipment/equipmentTypeService.ts index 237b0cd..8789fe7 100644 --- a/src/service/unit/equipment/equipmentTypeService.ts +++ b/src/service/unit/equipment/equipmentTypeService.ts @@ -1,3 +1,4 @@ +import { Like, In } from "typeorm"; import { dataSource } from "../../../data-source"; import { equipmentType } from "../../../entity/unit/equipment/equipmentType"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -5,14 +6,40 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class EquipmentTypeService { /** * @description get all equipmentTypes - * @returns {Promise>} + * @returns {Promise<[Array, number]>} */ - static async getAll(): Promise> { - return await dataSource - .getRepository(equipmentType) - .createQueryBuilder("equipmentType") + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = dataSource.getRepository(equipmentType).createQueryBuilder("equipmentType"); + + if (search != "") { + query = query.where({ + type: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("type", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index e9495fe..2514ad1 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -1,17 +1,12 @@ +import { Like, In } from "typeorm"; import { dataSource } from "../../../data-source"; import { inspectionPlan } from "../../../entity/unit/inspection/inspectionPlan"; import { DB_TYPE } from "../../../env.defaults"; import DatabaseActionException from "../../../exceptions/databaseActionException"; export default abstract class InspectionPlanService { - /** - * @description get all inspectionPlans for related - * @returns {Promise>} - */ - static async getAllForRelated( - where: { equipmentId: string } | { vehicleId: string } - ): Promise> { - return await dataSource + private static query = () => + dataSource .getRepository(inspectionPlan) .createQueryBuilder("inspectionPlan") .leftJoinAndMapOne( @@ -24,10 +19,47 @@ export default abstract class InspectionPlanService { ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspectionPlan.equipment", "equipment") - .leftJoinAndSelect("inspectionPlan.vehicle", "vehicle") - .where(where) + .leftJoinAndSelect("inspectionPlan.vehicle", "vehicle"); + + /** + * @description get all inspectionPlans for related + * @returns {Promise<[Array, number]>} + */ + static async getAllForRelated( + where: { equipmentId: string } | { vehicleId: string }, + { + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + } + ): Promise<[Array, number]> { + let query = this.query().where(where); + + if (search != "") { + query = query.where({ + title: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("title", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) @@ -41,20 +73,7 @@ export default abstract class InspectionPlanService { * @returns {Promise} */ static async getById(id: string): Promise { - return await dataSource - .getRepository(inspectionPlan) - .createQueryBuilder("inspectionPlan") - .leftJoinAndMapOne( - "inspectionPlan.latestVersionedPlan", - "inspectionPlan.versionedPlans", - "latestVersionedPlan", - DB_TYPE == "postgres" - ? 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."start") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' - : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.start) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" - ) - .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") - .leftJoinAndSelect("inspectionPlan.equipment", "equipment") - .leftJoinAndSelect("inspectionPlan.vehicle", "vehicle") + return await this.query() .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index 0fdf490..709b335 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -3,12 +3,8 @@ import { inspection } from "../../../entity/unit/inspection/inspection"; import DatabaseActionException from "../../../exceptions/databaseActionException"; export default abstract class InspectionService { - /** - * @description get all inspections for related - * @returns {Promise>} - */ - static async getAllForRelated(where: { equipmentId: string } | { vehicleId: string }): Promise> { - return await dataSource + private static query = () => + dataSource .getRepository(inspection) .createQueryBuilder("inspection") .leftJoinAndSelect("inspection.inspectionPlan", "inspectionPlan") @@ -17,10 +13,33 @@ export default abstract class InspectionService { .leftJoinAndSelect("inspection.pointResults", "pointResults") .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") .leftJoinAndSelect("inspection.equipment", "equipment") - .leftJoinAndSelect("inspection.vehicle", "vehicle") - .where(where) + .leftJoinAndSelect("inspection.vehicle", "vehicle"); + + /** + * @description get all inspections for related + * @returns {Promise>} + */ + static async getAllForRelated( + where: { equipmentId: string } | { vehicleId: string }, + { + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + } + ): Promise<[Array, number]> { + let query = this.query().where(where); + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("createdAt", "DESC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) @@ -34,16 +53,7 @@ export default abstract class InspectionService { * @returns {Promise} */ static async getById(id: string): Promise { - return await dataSource - .getRepository(inspection) - .createQueryBuilder("inspection") - .leftJoinAndSelect("inspection.inspectionPlan", "inspectionPlan") - .leftJoinAndSelect("inspection.inspectionVersionedPlan", "inspectionVersionedPlan") - .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") - .leftJoinAndSelect("inspection.pointResults", "pointResults") - .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") - .leftJoinAndSelect("inspection.equipment", "equipment") - .leftJoinAndSelect("inspection.vehicle", "vehicle") + return await this.query() .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/vehicle/vehicleService.ts b/src/service/unit/vehicle/vehicleService.ts index 39d7b06..921a981 100644 --- a/src/service/unit/vehicle/vehicleService.ts +++ b/src/service/unit/vehicle/vehicleService.ts @@ -1,3 +1,4 @@ +import { Like, In } from "typeorm"; import { dataSource } from "../../../data-source"; import { vehicle } from "../../../entity/unit/vehicle/vehicle"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -5,15 +6,45 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class VehicleService { /** * @description get all vehicles - * @returns {Promise>} + * @returns {Promise<[Array, number]>} */ - static async getAll(): Promise> { - return await dataSource + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = dataSource .getRepository(vehicle) .createQueryBuilder("vehicle") - .leftJoinAndSelect("vehicle.vehicleType", "vehicletype") + .leftJoinAndSelect("vehicle.vehicleType", "vehicletype"); + + if (search != "") { + query = query.where({ + code: Like(search), + name: Like(search), + location: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("name", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) diff --git a/src/service/unit/vehicle/vehicleTypeService.ts b/src/service/unit/vehicle/vehicleTypeService.ts index 8ba8104..6ecb703 100644 --- a/src/service/unit/vehicle/vehicleTypeService.ts +++ b/src/service/unit/vehicle/vehicleTypeService.ts @@ -1,3 +1,4 @@ +import { Like, In } from "typeorm"; import { dataSource } from "../../../data-source"; import { vehicleType } from "../../../entity/unit/vehicle/vehicleType"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -5,14 +6,40 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class VehicleTypeService { /** * @description get all vehicleTypes - * @returns {Promise>} + * @returns {Promise<[Array, number]>} */ - static async getAll(): Promise> { - return await dataSource - .getRepository(vehicleType) - .createQueryBuilder("vehicleType") + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = dataSource.getRepository(vehicleType).createQueryBuilder("vehicleType"); + + if (search != "") { + query = query.where({ + type: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("type", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) diff --git a/src/service/unit/wearable/wearableService.ts b/src/service/unit/wearable/wearableService.ts index 7733d4a..b369f47 100644 --- a/src/service/unit/wearable/wearableService.ts +++ b/src/service/unit/wearable/wearableService.ts @@ -1,3 +1,4 @@ +import { Like, In } from "typeorm"; import { dataSource } from "../../../data-source"; import { wearable } from "../../../entity/unit/wearable/wearable"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -5,16 +6,46 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class WearableService { /** * @description get all wearables - * @returns {Promise>} + * @returns {Promise<[Array, number]>} */ - static async getAll(): Promise> { - return await dataSource + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = dataSource .getRepository(wearable) .createQueryBuilder("wearable") .leftJoinAndSelect("wearable.wearableType", "wearabletype") - .leftJoinAndSelect("wearable.wearer", "wearer") + .leftJoinAndSelect("wearable.wearer", "wearer"); + + if (search != "") { + query = query.where({ + code: Like(search), + name: Like(search), + location: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("name", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) diff --git a/src/service/unit/wearable/wearableTypeService.ts b/src/service/unit/wearable/wearableTypeService.ts index 63a696b..d6f167f 100644 --- a/src/service/unit/wearable/wearableTypeService.ts +++ b/src/service/unit/wearable/wearableTypeService.ts @@ -1,3 +1,4 @@ +import { In, Like } from "typeorm"; import { dataSource } from "../../../data-source"; import { wearableType } from "../../../entity/unit/wearable/wearableType"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -5,14 +6,40 @@ import DatabaseActionException from "../../../exceptions/databaseActionException export default abstract class WearableTypeService { /** * @description get all wearableTypes - * @returns {Promise>} + * @returns {Promise<[Array, number]>} */ - static async getAll(): Promise> { - return await dataSource - .getRepository(wearableType) - .createQueryBuilder("wearableType") + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = dataSource.getRepository(wearableType).createQueryBuilder("wearableType"); + + if (search != "") { + query = query.where({ + type: Like(search), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query .orderBy("type", "ASC") - .getMany() + .getManyAndCount() .then((res) => { return res; }) From e3db523a0e314a90a3832a045ead8a3d30cf7221 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 4 Jun 2025 14:30:57 +0200 Subject: [PATCH 19/34] change according to connection from frontend --- .../inspectionPlanCommandHandler.ts | 4 +- .../admin/unit/damageReportController.ts | 113 ++++++++++++++++++ .../admin/unit/equipmentController.ts | 31 +++-- .../admin/unit/equipmentTypeController.ts | 19 +-- .../admin/unit/inspectionController.ts | 27 +++-- .../admin/unit/inspectionPlanController.ts | 67 +++++++++-- .../admin/unit/vehicleController.ts | 50 ++++++-- .../admin/unit/vehicleTypeController.ts | 19 +-- .../admin/unit/wearableController.ts | 54 +++++++-- .../admin/unit/wearableTypeController.ts | 19 +-- src/entity/unit/equipment/equipment.ts | 4 +- src/entity/unit/equipment/equipmentType.ts | 2 +- src/entity/unit/inspection/inspectionPlan.ts | 16 +-- src/entity/unit/vehicle/vehicle.ts | 4 +- src/entity/unit/vehicle/vehicleType.ts | 2 +- src/entity/unit/wearable/wearable.ts | 4 +- src/factory/admin/club/member/member.ts | 2 +- .../admin/unit/inspection/inspectionPlan.ts | 18 +-- src/helpers/typeTester.ts | 18 +++ src/migrations/baseSchemaTables/inspection.ts | 12 +- src/routes/admin/index.ts | 11 ++ src/routes/admin/unit/damageReport.ts | 50 ++++++++ src/routes/admin/unit/inspectionPlan.ts | 5 + src/routes/admin/unit/vehicle.ts | 5 + src/routes/admin/unit/wearable.ts | 5 + src/routes/admin/unit/wearableType.ts | 4 +- src/service/unit/damageReportService.ts | 79 +++++++++--- .../unit/equipment/equipmentService.ts | 15 ++- .../unit/equipment/equipmentTypeService.ts | 8 +- .../unit/inspection/inspectionPlanService.ts | 62 ++++++++-- .../unit/inspection/inspectionService.ts | 2 +- src/service/unit/vehicle/vehicleService.ts | 15 ++- .../unit/vehicle/vehicleTypeService.ts | 8 +- src/service/unit/wearable/wearableService.ts | 16 ++- .../unit/wearable/wearableTypeService.ts | 8 +- .../unit/inspection/inspectionPlan.models.ts | 6 +- 36 files changed, 611 insertions(+), 173 deletions(-) create mode 100644 src/controller/admin/unit/damageReportController.ts create mode 100644 src/helpers/typeTester.ts create mode 100644 src/routes/admin/unit/damageReport.ts diff --git a/src/command/unit/inspection/inspectionPlanCommandHandler.ts b/src/command/unit/inspection/inspectionPlanCommandHandler.ts index cf48ef7..179f8a7 100644 --- a/src/command/unit/inspection/inspectionPlanCommandHandler.ts +++ b/src/command/unit/inspection/inspectionPlanCommandHandler.ts @@ -22,8 +22,8 @@ export default abstract class InspectionPlanCommandHandler { title: createInspectionPlan.title, inspectionInterval: createInspectionPlan.inspectionInterval, remindTime: createInspectionPlan.remindTime, - equipmentId: createInspectionPlan.assigned == "equipment" ? createInspectionPlan.relatedId : null, - vehicleId: createInspectionPlan.assigned == "vehicle" ? createInspectionPlan.relatedId : null, + equipmentTypeId: createInspectionPlan.assigned == "equipment" ? createInspectionPlan.relatedId : null, + vehicleTypeId: createInspectionPlan.assigned == "vehicle" ? createInspectionPlan.relatedId : null, }) .execute() .then((result) => { diff --git a/src/controller/admin/unit/damageReportController.ts b/src/controller/admin/unit/damageReportController.ts new file mode 100644 index 0000000..9576ec9 --- /dev/null +++ b/src/controller/admin/unit/damageReportController.ts @@ -0,0 +1,113 @@ +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"; + +/** + * @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 { + 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.getAll(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 { + let relation = req.params.related as "vehicle" | "equipment"; + 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 = relation === "equipment" ? { equipmentId: relationId } : { vehicleId: 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 { + const damageReportId = req.params.id; + let damageReport = await DamageReportService.getById(damageReportId); + + res.json(DamageReportFactory.mapToSingle(damageReport)); +} + +/** + * @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 { + const description = req.body.description; + const reportedBy = req.body.reportedBy; + 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 = { + description, + reportedBy, + imageCount: 0, + 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 { + const damageReportId = req.params.id; + const status = req.body.status; + const done = req.body.done; + + let updateDamageReport: UpdateDamageReportCommand = { + id: damageReportId, + status, + done, + }; + await DamageReportCommandHandler.update(updateDamageReport); + + res.sendStatus(204); +} diff --git a/src/controller/admin/unit/equipmentController.ts b/src/controller/admin/unit/equipmentController.ts index 8d7e200..caee218 100644 --- a/src/controller/admin/unit/equipmentController.ts +++ b/src/controller/admin/unit/equipmentController.ts @@ -24,7 +24,7 @@ export async function getAllEquipments(req: Request, res: Response): Promise} */ export async function createEquipment(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + 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 = { - name: "", - location: "", - commissioned: undefined, - equipmentTypeId: "", + code, + name, + location, + commissioned, + equipmentTypeId, }; let equipmentId = await EquipmentCommandHandler.create(createEquipment); @@ -91,13 +96,19 @@ export async function createEquipment(req: Request, res: Response): Promise */ export async function updateEquipmentById(req: Request, res: Response): Promise { const equipmentId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + 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: "", - location: "", - commissioned: undefined, + name, + code, + location, + commissioned, + decommissioned, }; await EquipmentCommandHandler.update(updateEquipment); diff --git a/src/controller/admin/unit/equipmentTypeController.ts b/src/controller/admin/unit/equipmentTypeController.ts index dce7b77..cfae069 100644 --- a/src/controller/admin/unit/equipmentTypeController.ts +++ b/src/controller/admin/unit/equipmentTypeController.ts @@ -19,12 +19,11 @@ export async function getAllEquipmentTypes(req: Request, res: Response): Promise 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 [equipmentTypes, total] = await EquipmentTypeService.getAll({ offset, count, search, noLimit, ids }); + let [equipmentTypes, total] = await EquipmentTypeService.getAll({ offset, count, search, noLimit }); res.json({ - equipmentTypes: equipmentTypes, + equipmentTypes: EquipmentTypeFactory.mapToBase(equipmentTypes), total: total, offset: offset, count: count, @@ -51,11 +50,12 @@ export async function getEquipmentTypeById(req: Request, res: Response): Promise * @returns {Promise<*>} */ export async function createEquipmentType(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + const type = req.body.type; + const description = req.body.description; let createEquipmentType: CreateEquipmentTypeCommand = { - type: "", - description: "", + type, + description, }; let equipmentTypeId = await EquipmentTypeCommandHandler.create(createEquipmentType); @@ -70,12 +70,13 @@ export async function createEquipmentType(req: Request, res: Response): Promise< */ export async function updateEquipmentTypeById(req: Request, res: Response): Promise { const equipmentTypeId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + const type = req.body.type; + const description = req.body.description; let updateEquipmentType: UpdateEquipmentTypeCommand = { id: equipmentTypeId, - type: "", - description: "", + type, + description, }; await EquipmentTypeCommandHandler.update(updateEquipmentType); diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index 8c4b782..2380bdf 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -7,6 +7,7 @@ import { UpdateInspectionCommand, } from "../../../command/unit/inspection/inspectionCommand"; import InspectionCommandHandler from "../../../command/unit/inspection/inspectionCommandHandler"; +import BadRequestException from "../../../exceptions/badRequestException"; /** * @description get all inspections for related id @@ -25,7 +26,7 @@ export async function getAllInspectionsForRelated(req: Request, res: Response): let [inspections, total] = await InspectionService.getAllForRelated(where, { offset, count, noLimit }); res.json({ - inspections: inspections, + inspections: InspectionFactory.mapToBase(inspections), total: total, offset: offset, count: count, @@ -52,13 +53,21 @@ export async function getInspectionById(req: Request, res: Response): Promise} */ export async function createInspection(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + const context = req.body.context; + const inspectionPlanId = req.body.inspectionPlanId; + const relatedId = req.body.relatedId; + const assigned = req.body.assigned; + const nextInspection = req.body.nextInspection || null; + + if (assigned != "equipment" && assigned != "vehicle") + throw new BadRequestException("set assigned to equipment or vehicle"); let createInspection: CreateInspectionCommand = { - context: "", - inspectionPlanId: "", - relatedId: "", - assigned: "equipment", + context, + nextInspection, + inspectionPlanId, + relatedId, + assigned, }; let inspectionId = await InspectionCommandHandler.create(createInspection); @@ -73,11 +82,13 @@ export async function createInspection(req: Request, res: Response): Promise { const inspectionId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + const context = req.body.context; + const nextInspection = req.body.nextInspection || null; let updateInspection: UpdateInspectionCommand = { id: inspectionId, - context: "", + context, + nextInspection, }; await InspectionCommandHandler.update(updateInspection); diff --git a/src/controller/admin/unit/inspectionPlanController.ts b/src/controller/admin/unit/inspectionPlanController.ts index 358ac66..5089c82 100644 --- a/src/controller/admin/unit/inspectionPlanController.ts +++ b/src/controller/admin/unit/inspectionPlanController.ts @@ -7,6 +7,37 @@ import { UpdateInspectionPlanCommand, } from "../../../command/unit/inspection/inspectionPlanCommand"; import InspectionPlanCommandHandler from "../../../command/unit/inspection/inspectionPlanCommandHandler"; +import BadRequestException from "../../../exceptions/badRequestException"; +import TypeTester from "../../../helpers/typeTester"; + +/** + * @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 { + 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 @@ -23,7 +54,7 @@ export async function getAllInspectionPlansForRelated(req: Request, res: Respons let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - let where = relation === "equipment" ? { equipmentId: relationId } : { vehicleId: relationId }; + let where = relation === "equipment" ? { equipmentTypeId: relationId } : { vehicleTypeId: relationId }; let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated(where, { offset, count, @@ -60,14 +91,24 @@ export async function getInspectionPlanById(req: Request, res: Response): Promis * @returns {Promise<*>} */ export async function createInspectionPlan(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + const title = req.body.title; + const inspectionInterval = req.body.inspectionInterval; + const remindTime = req.body.remindTime; + const relatedId = req.body.relatedId; + const assigned = req.body.assigned; + + TypeTester.testPlanTimeDefinition(inspectionInterval, "inspectionInterval", true); + TypeTester.testPlanTimeDefinition(remindTime, "remindTime", true); + + if (assigned != "equipment" && assigned != "vehicle") + throw new BadRequestException("set assigned to equipment or vehicle"); let createInspectionPlan: CreateInspectionPlanCommand = { - title: "", - inspectionInterval: "1-m", - remindTime: "1-m", - relatedId: "", - assigned: "equipment", + title, + inspectionInterval, + remindTime, + relatedId, + assigned, }; let inspectionPlanId = await InspectionPlanCommandHandler.create(createInspectionPlan); @@ -82,12 +123,18 @@ export async function createInspectionPlan(req: Request, res: Response): Promise */ export async function updateInspectionPlanById(req: Request, res: Response): Promise { const inspectionPlanId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + const title = req.body.title; + const inspectionInterval = req.body.inspectionInterval; + const remindTime = req.body.remindTime; + + TypeTester.testPlanTimeDefinition(inspectionInterval, "inspectionInterval", true); + TypeTester.testPlanTimeDefinition(remindTime, "remindTime", true); let updateInspectionPlan: UpdateInspectionPlanCommand = { id: inspectionPlanId, - title: "", - inspectionInterval: "1-m", + title, + inspectionInterval, + remindTime, }; await InspectionPlanCommandHandler.update(updateInspectionPlan); diff --git a/src/controller/admin/unit/vehicleController.ts b/src/controller/admin/unit/vehicleController.ts index 02b3606..a54d2c1 100644 --- a/src/controller/admin/unit/vehicleController.ts +++ b/src/controller/admin/unit/vehicleController.ts @@ -24,7 +24,7 @@ export async function getAllVehicles(req: Request, res: Response): Promise let [vehicles, total] = await VehicleService.getAll({ offset, count, search, noLimit, ids }); res.json({ - vehicles: vehicles, + vehicles: VehicleFactory.mapToBase(vehicles), total: total, offset: offset, count: count, @@ -44,6 +44,25 @@ export async function getVehicleById(req: Request, res: Response): Promise 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 { + let ids = req.body.ids as Array; + + 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 @@ -51,13 +70,18 @@ export async function getVehicleById(req: Request, res: Response): Promise * @returns {Promise<*>} */ export async function createVehicle(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + 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 = { - name: "", - location: "", - commissioned: undefined, - vehicleTypeId: "", + code, + name, + location, + commissioned, + vehicleTypeId, }; let vehicleId = await VehicleCommandHandler.create(createVehicle); @@ -72,13 +96,19 @@ export async function createVehicle(req: Request, res: Response): Promise { */ export async function updateVehicleById(req: Request, res: Response): Promise { const vehicleId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + 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, - name: "", - location: "", - commissioned: undefined, + code, + name, + location, + commissioned, + decommissioned, }; await VehicleCommandHandler.update(updateVehicle); diff --git a/src/controller/admin/unit/vehicleTypeController.ts b/src/controller/admin/unit/vehicleTypeController.ts index 7cf5552..b105ea1 100644 --- a/src/controller/admin/unit/vehicleTypeController.ts +++ b/src/controller/admin/unit/vehicleTypeController.ts @@ -19,12 +19,11 @@ export async function getAllVehicleTypes(req: Request, res: Response): Promise i); - let [vehicleTypes, total] = await VehicleTypeService.getAll({ offset, count, search, noLimit, ids }); + let [vehicleTypes, total] = await VehicleTypeService.getAll({ offset, count, search, noLimit }); res.json({ - vehicleTypes: vehicleTypes, + vehicleTypes: VehicleTypeFactory.mapToBase(vehicleTypes), total: total, offset: offset, count: count, @@ -51,11 +50,12 @@ export async function getVehicleTypeById(req: Request, res: Response): Promise} */ export async function createVehicleType(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + const type = req.body.type; + const description = req.body.description; let createVehicleType: CreateVehicleTypeCommand = { - type: "", - description: "", + type, + description, }; let vehicleTypeId = await VehicleTypeCommandHandler.create(createVehicleType); @@ -70,12 +70,13 @@ export async function createVehicleType(req: Request, res: Response): Promise { const vehicleTypeId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + const type = req.body.type; + const description = req.body.description; let updateVehicleType: UpdateVehicleTypeCommand = { id: vehicleTypeId, - type: "", - description: "", + type, + description, }; await VehicleTypeCommandHandler.update(updateVehicleType); diff --git a/src/controller/admin/unit/wearableController.ts b/src/controller/admin/unit/wearableController.ts index 7775c36..b28fb46 100644 --- a/src/controller/admin/unit/wearableController.ts +++ b/src/controller/admin/unit/wearableController.ts @@ -24,7 +24,7 @@ export async function getAllWearables(req: Request, res: Response): Promise let [wearables, total] = await WearableService.getAll({ offset, count, search, noLimit, ids }); res.json({ - wearables: wearables, + wearables: WearableFactory.mapToBase(wearables), total: total, offset: offset, count: count, @@ -44,6 +44,25 @@ export async function getWearableById(req: Request, res: Response): Promise 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 { + let ids = req.body.ids as Array; + + 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 @@ -51,13 +70,20 @@ export async function getWearableById(req: Request, res: Response): Promise * @returns {Promise<*>} */ export async function createWearable(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + 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 = { - name: "", - location: "", - commissioned: undefined, - wearableTypeId: "", + code, + name, + location, + commissioned, + wearableTypeId, + wearerId, }; let wearableId = await WearableCommandHandler.create(createWearable); @@ -72,13 +98,21 @@ export async function createWearable(req: Request, res: Response): Promise */ export async function updateWearableById(req: Request, res: Response): Promise { const wearableId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + 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, - name: "", - location: "", - commissioned: undefined, + code, + name, + location, + commissioned, + decommissioned, + wearerId, }; await WearableCommandHandler.update(updateWearable); diff --git a/src/controller/admin/unit/wearableTypeController.ts b/src/controller/admin/unit/wearableTypeController.ts index 40def8b..8597916 100644 --- a/src/controller/admin/unit/wearableTypeController.ts +++ b/src/controller/admin/unit/wearableTypeController.ts @@ -19,12 +19,11 @@ export async function getAllWearableTypes(req: Request, res: Response): Promise< 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 [wearableTypes, total] = await WearableTypeService.getAll({ offset, count, search, noLimit, ids }); + let [wearableTypes, total] = await WearableTypeService.getAll({ offset, count, search, noLimit }); res.json({ - wearableTypes: wearableTypes, + wearableTypes: WearableTypeFactory.mapToBase(wearableTypes), total: total, offset: offset, count: count, @@ -51,11 +50,12 @@ export async function getWearableTypeById(req: Request, res: Response): Promise< * @returns {Promise<*>} */ export async function createWearableType(req: Request, res: Response): Promise { - const salutationId = parseInt(req.body.salutationId); + const type = req.body.type; + const description = req.body.description; let createWearableType: CreateWearableTypeCommand = { - type: "", - description: "", + type, + description, }; let wearableTypeId = await WearableTypeCommandHandler.create(createWearableType); @@ -70,12 +70,13 @@ export async function createWearableType(req: Request, res: Response): Promise { const wearableTypeId = req.params.id; - const salutationId = parseInt(req.body.salutationId); + const type = req.body.type; + const description = req.body.description; let updateWearableType: UpdateWearableTypeCommand = { id: wearableTypeId, - type: "", - description: "", + type, + description, }; await WearableTypeCommandHandler.update(updateWearableType); diff --git a/src/entity/unit/equipment/equipment.ts b/src/entity/unit/equipment/equipment.ts index d55ea0d..bbd12a0 100644 --- a/src/entity/unit/equipment/equipment.ts +++ b/src/entity/unit/equipment/equipment.ts @@ -18,10 +18,10 @@ export class equipment { @Column({ type: "varchar", length: 255 }) location: string; - @Column({ type: getTypeByORM("datetime").type as ColumnType }) + @Column({ type: getTypeByORM("date").type as ColumnType }) commissioned: Date; - @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) decommissioned?: Date; @Column() diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts index 3888ebe..3d0b134 100644 --- a/src/entity/unit/equipment/equipmentType.ts +++ b/src/entity/unit/equipment/equipmentType.ts @@ -16,6 +16,6 @@ export class equipmentType { @OneToMany(() => equipment, (e) => e.equipmentType, { cascade: ["insert"] }) equipment: equipment[]; - @OneToMany(() => inspectionPlan, (ip) => ip.equipment) + @OneToMany(() => inspectionPlan, (ip) => ip.equipmentType) inspectionPlans: inspectionPlan[]; } diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts index f94bf5a..b2a43eb 100644 --- a/src/entity/unit/inspection/inspectionPlan.ts +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -1,8 +1,8 @@ import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; -import { equipment } from "../equipment/equipment"; -import { vehicle } from "../vehicle/vehicle"; import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspection/inspectionPlan.models"; import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; +import { equipmentType } from "../equipment/equipmentType"; +import { vehicleType } from "../vehicle/vehicleType"; @Entity() export class inspectionPlan { @@ -22,24 +22,24 @@ export class inspectionPlan { createdAt: Date; @Column() - equipmentId?: string; + equipmentTypeId?: string; @Column() - vehicleId?: string; + vehicleTypeId?: string; - @ManyToOne(() => equipment, { + @ManyToOne(() => equipmentType, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - equipment?: equipment; + equipmentType?: equipmentType; - @ManyToOne(() => vehicle, { + @ManyToOne(() => vehicleType, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) - vehicle?: vehicle; + vehicleType?: vehicleType; @OneToMany(() => inspectionVersionedPlan, (ivp) => ivp.inspectionPlan, { cascade: ["insert"], diff --git a/src/entity/unit/vehicle/vehicle.ts b/src/entity/unit/vehicle/vehicle.ts index dc4a8d6..c09a28d 100644 --- a/src/entity/unit/vehicle/vehicle.ts +++ b/src/entity/unit/vehicle/vehicle.ts @@ -18,10 +18,10 @@ export class vehicle { @Column({ type: "varchar", length: 255 }) location: string; - @Column({ type: getTypeByORM("datetime").type as ColumnType }) + @Column({ type: getTypeByORM("date").type as ColumnType }) commissioned: Date; - @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) decommissioned?: Date; @Column() diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts index d58b478..a3e3403 100644 --- a/src/entity/unit/vehicle/vehicleType.ts +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -16,6 +16,6 @@ export class vehicleType { @OneToMany(() => vehicle, (e) => e.vehicleType, { cascade: ["insert"] }) vehicle: vehicle[]; - @OneToMany(() => inspectionPlan, (ip) => ip.vehicle) + @OneToMany(() => inspectionPlan, (ip) => ip.vehicleType) inspectionPlans: inspectionPlan[]; } diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index 3b1ea39..0313997 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -19,10 +19,10 @@ export class wearable { @Column({ type: "varchar", length: 255 }) location: string; - @Column({ type: getTypeByORM("datetime").type as ColumnType }) + @Column({ type: getTypeByORM("date").type as ColumnType }) commissioned: Date; - @Column({ type: getTypeByORM("datetime").type as ColumnType, nullable: true, default: null }) + @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) decommissioned?: Date; @Column() diff --git a/src/factory/admin/club/member/member.ts b/src/factory/admin/club/member/member.ts index 246c0ae..4e953cb 100644 --- a/src/factory/admin/club/member/member.ts +++ b/src/factory/admin/club/member/member.ts @@ -15,7 +15,7 @@ export default abstract class MemberFactory { public static mapToSingle(record: member): MemberViewModel { return { id: record?.id, - salutation: SalutationFactory.mapToSingle(record?.salutation), + salutation: record?.salutation ? SalutationFactory.mapToSingle(record?.salutation) : null, firstname: record?.firstname, lastname: record?.lastname, nameaffix: record?.nameaffix, diff --git a/src/factory/admin/unit/inspection/inspectionPlan.ts b/src/factory/admin/unit/inspection/inspectionPlan.ts index 2e8fe5b..1a0439d 100644 --- a/src/factory/admin/unit/inspection/inspectionPlan.ts +++ b/src/factory/admin/unit/inspection/inspectionPlan.ts @@ -1,7 +1,9 @@ import { inspectionPlan } from "../../../../entity/unit/inspection/inspectionPlan"; import { 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 InspectionPointFactory from "./inspectionPoint"; export default abstract class InspectionPlanFactory { @@ -16,19 +18,21 @@ export default abstract class InspectionPlanFactory { title: record.title, inspectionInterval: record.inspectionInterval, remindTime: record.remindTime, - version: record.latestVersionedPlan.version, + version: record?.latestVersionedPlan?.version ?? 0, created: record.createdAt, - inspectionPoints: InspectionPointFactory.mapToBase(record.latestVersionedPlan.inspectionPoints), - ...(record.equipmentId + inspectionPoints: record.latestVersionedPlan + ? InspectionPointFactory.mapToBase(record.latestVersionedPlan.inspectionPoints) + : [], + ...(record.equipmentTypeId ? { - relatedId: record.equipmentId, + relatedId: record.equipmentTypeId, assigned: "equipment", - related: EquipmentFactory.mapToSingle(record.equipment), + related: EquipmentTypeFactory.mapToSingle(record.equipmentType), } : { - relatedId: record.vehicleId, + relatedId: record.vehicleTypeId, assigned: "vehicle", - related: VehicleFactory.mapToSingle(record.vehicle), + related: VehicleTypeFactory.mapToSingle(record.vehicleType), }), }; } diff --git a/src/helpers/typeTester.ts b/src/helpers/typeTester.ts new file mode 100644 index 0000000..ab37808 --- /dev/null +++ b/src/helpers/typeTester.ts @@ -0,0 +1,18 @@ +import { PlanTimeDefinition } from "../viewmodel/admin/unit/inspection/inspectionPlan.models"; + +export default abstract class TypeTester { + static testPlanTimeDefinition(val: string, key: string = "", throwErr: boolean = false): PlanTimeDefinition | 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; + } + } +} diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index b064cb6..bfa480a 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -9,21 +9,21 @@ export const inspection_plan_table = new Table({ { name: "inspectionInterval", ...getTypeByORM("varchar") }, { name: "remindTime", ...getTypeByORM("varchar") }, { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, - { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "equipmentTypeId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "vehicleTypeId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, ], foreignKeys: [ new TableForeignKey({ - columnNames: ["equipmentId"], + columnNames: ["equipmentTypeId"], referencedColumnNames: ["id"], - referencedTableName: "equipment", + referencedTableName: "equipment_type", onDelete: "CASCADE", onUpdate: "RESTRICT", }), new TableForeignKey({ - columnNames: ["vehicleId"], + columnNames: ["vehicleTypeId"], referencedColumnNames: ["id"], - referencedTableName: "vehicle", + referencedTableName: "vehicle_type", onDelete: "CASCADE", onUpdate: "RESTRICT", }), diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index 13e48f5..782f89b 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -40,6 +40,7 @@ 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"; var router = express.Router({ mergeParams: true }); @@ -215,5 +216,15 @@ router.use( ]), inspectionPlan ); +router.use( + "/damagereport", + PermissionHelper.passCheckSomeMiddleware([ + { requiredPermission: "read", section: "unit", module: "damage_report" }, + { requiredPermission: "read", section: "unit", module: "equipment" }, + { requiredPermission: "read", section: "unit", module: "vehicle" }, + { requiredPermission: "read", section: "unit", module: "wearable" }, + ]), + damageReport +); export default router; diff --git a/src/routes/admin/unit/damageReport.ts b/src/routes/admin/unit/damageReport.ts new file mode 100644 index 0000000..aee6261 --- /dev/null +++ b/src/routes/admin/unit/damageReport.ts @@ -0,0 +1,50 @@ +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, + updateDamageReportById, +} from "../../../controller/admin/unit/damageReportController"; + +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.patch( + "/:id", + PermissionHelper.passCheckMiddleware("update", "unit", "inspection"), + async (req: Request, res: Response) => { + await updateDamageReportById(req, res); + } +); + +export default router; diff --git a/src/routes/admin/unit/inspectionPlan.ts b/src/routes/admin/unit/inspectionPlan.ts index 0e33d5c..632c130 100644 --- a/src/routes/admin/unit/inspectionPlan.ts +++ b/src/routes/admin/unit/inspectionPlan.ts @@ -3,6 +3,7 @@ import PermissionHelper from "../../../helpers/permissionHelper"; import { createInspectionPlan, deleteInspectionPlanById, + getAllInspectionPlans, getAllInspectionPlansForRelated, getInspectionPlanById, updateInspectionPlanById, @@ -10,6 +11,10 @@ import { var router = express.Router({ mergeParams: true }); +router.get("/", async (req: Request, res: Response) => { + await getAllInspectionPlans(req, res); +}); + router.get(["/vehicle/:relatedId", "/equipment/:relatedId"], async (req: Request, res: Response) => { if (req.path.startsWith("/vehicle")) { req.params.related = "vehicle"; diff --git a/src/routes/admin/unit/vehicle.ts b/src/routes/admin/unit/vehicle.ts index 832e248..7ca588c 100644 --- a/src/routes/admin/unit/vehicle.ts +++ b/src/routes/admin/unit/vehicle.ts @@ -5,6 +5,7 @@ import { deleteVehicleById, getAllVehicles, getVehicleById, + getVehiclesByIds, updateVehicleById, } from "../../../controller/admin/unit/vehicleController"; @@ -18,6 +19,10 @@ 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"), diff --git a/src/routes/admin/unit/wearable.ts b/src/routes/admin/unit/wearable.ts index c25226a..e1c1730 100644 --- a/src/routes/admin/unit/wearable.ts +++ b/src/routes/admin/unit/wearable.ts @@ -5,6 +5,7 @@ import { deleteWearableById, getAllWearables, getWearableById, + getWearablesByIds, updateWearableById, } from "../../../controller/admin/unit/wearableController"; @@ -18,6 +19,10 @@ 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"), diff --git a/src/routes/admin/unit/wearableType.ts b/src/routes/admin/unit/wearableType.ts index b61584f..983e401 100644 --- a/src/routes/admin/unit/wearableType.ts +++ b/src/routes/admin/unit/wearableType.ts @@ -2,11 +2,11 @@ import express, { Request, Response } from "express"; import PermissionHelper from "../../../helpers/permissionHelper"; import { createWearableType, + deleteWearableTypeById, getAllWearableTypes, getWearableTypeById, updateWearableTypeById, } from "../../../controller/admin/unit/wearableTypeController"; -import { deleteWearableById } from "../../../controller/admin/unit/wearableController"; var router = express.Router({ mergeParams: true }); @@ -38,7 +38,7 @@ router.delete( "/:id", PermissionHelper.passCheckMiddleware("delete", "unit", "wearable_type"), async (req: Request, res: Response) => { - await deleteWearableById(req, res); + await deleteWearableTypeById(req, res); } ); diff --git a/src/service/unit/damageReportService.ts b/src/service/unit/damageReportService.ts index 7821ea1..622b377 100644 --- a/src/service/unit/damageReportService.ts +++ b/src/service/unit/damageReportService.ts @@ -3,20 +3,73 @@ import { damageReport } from "../../entity/unit/damageReport"; import DatabaseActionException from "../../exceptions/databaseActionException"; export default abstract class DamageReportService { - /** - * @description get all damageReports - * @returns {Promise>} - */ - static async getAll(): Promise> { - return await dataSource + private static query = () => + dataSource .getRepository(damageReport) .createQueryBuilder("damageReport") .leftJoinAndSelect("damageReport.equipment", "equipment") .leftJoinAndSelect("damageReport.vehicle", "vehicle") .leftJoinAndSelect("damageReport.wearable", "wearable") - .leftJoinAndSelect("damageReport.maintenance", "maintenance") - .orderBy("type", "ASC") - .getMany() + .leftJoinAndSelect("damageReport.maintenance", "maintenance"); + + /** + * @description get all damageReports By done + * @returns {Promise<[Array, number]>} + */ + static async getAll( + done = false, + { + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + } + ): Promise<[Array, number]> { + let query = this.query().where({ done }); + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("damageReport.reportedAt", "ASC") + .getManyAndCount() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "damageReport", err); + }); + } + + /** + * @description get all damageReports By related + * @returns {Promise<[Array, number]>} + */ + static async getAllForRelated( + where: { equipmentId: string } | { vehicleId: string } | { wearableId: string }, + { + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + } + ): Promise<[Array, number]> { + let query = this.query().where(where); + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("reportedAt", "ASC") + .getManyAndCount() .then((res) => { return res; }) @@ -30,13 +83,7 @@ export default abstract class DamageReportService { * @returns {Promise} */ static async getById(id: string): Promise { - return await dataSource - .getRepository(damageReport) - .createQueryBuilder("damageReport") - .leftJoinAndSelect("damageReport.equipment", "equipment") - .leftJoinAndSelect("damageReport.vehicle", "vehicle") - .leftJoinAndSelect("damageReport.wearable", "wearable") - .leftJoinAndSelect("damageReport.maintenance", "maintenance") + return await this.query() .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/equipment/equipmentService.ts b/src/service/unit/equipment/equipmentService.ts index 7e2267b..921f574 100644 --- a/src/service/unit/equipment/equipmentService.ts +++ b/src/service/unit/equipment/equipmentService.ts @@ -27,11 +27,16 @@ export default abstract class EquipmentService { .leftJoinAndSelect("equipment.equipmentType", "equipmenttype"); if (search != "") { - query = query.where({ - code: Like(search), - name: Like(search), - location: Like(search), - }); + query = query + .where({ + code: Like(`%${search}%`), + }) + .orWhere({ + name: Like(`%${search}%`), + }) + .orWhere({ + location: Like(`%${search}%`), + }); } if (ids.length != 0) { diff --git a/src/service/unit/equipment/equipmentTypeService.ts b/src/service/unit/equipment/equipmentTypeService.ts index 8789fe7..b85b9f1 100644 --- a/src/service/unit/equipment/equipmentTypeService.ts +++ b/src/service/unit/equipment/equipmentTypeService.ts @@ -13,26 +13,20 @@ export default abstract class EquipmentTypeService { count = 25, search = "", noLimit = false, - ids = [], }: { offset?: number; count?: number; search?: string; noLimit?: boolean; - ids?: Array; }): Promise<[Array, number]> { let query = dataSource.getRepository(equipmentType).createQueryBuilder("equipmentType"); if (search != "") { query = query.where({ - type: Like(search), + type: Like(`%${search}%`), }); } - if (ids.length != 0) { - query = query.where({ id: In(ids) }); - } - if (!noLimit) { query = query.offset(offset).limit(count); } diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index 2514ad1..197912d 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -14,19 +14,63 @@ export default abstract class InspectionPlanService { "inspectionPlan.versionedPlans", "latestVersionedPlan", DB_TYPE == "postgres" - ? 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."start") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' - : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.start) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" + ? 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."createdAt") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' + : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.createdAt) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") - .leftJoinAndSelect("inspectionPlan.equipment", "equipment") - .leftJoinAndSelect("inspectionPlan.vehicle", "vehicle"); + .leftJoinAndSelect("inspectionPlan.equipmentType", "equipmentType") + .leftJoinAndSelect("inspectionPlan.vehicleType", "vehicleType"); + + /** + * @description get all inspectionPlans for related + * @returns {Promise<[Array, number]>} + */ + static async getAll({ + offset = 0, + count = 25, + search = "", + noLimit = false, + ids = [], + }: { + offset?: number; + count?: number; + search?: string; + noLimit?: boolean; + ids?: Array; + }): Promise<[Array, number]> { + let query = this.query(); + + if (search != "") { + query = query.where({ + title: Like(`%${search}%`), + }); + } + + if (ids.length != 0) { + query = query.where({ id: In(ids) }); + } + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("inspectionPlan.title", "ASC") + .getManyAndCount() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPlan", err); + }); + } /** * @description get all inspectionPlans for related * @returns {Promise<[Array, number]>} */ static async getAllForRelated( - where: { equipmentId: string } | { vehicleId: string }, + where: { equipmentTypeId: string } | { vehicleTypeId: string }, { offset = 0, count = 25, @@ -44,13 +88,13 @@ export default abstract class InspectionPlanService { let query = this.query().where(where); if (search != "") { - query = query.where({ - title: Like(search), + query = query.andWhere({ + title: Like(`%${search}%`), }); } if (ids.length != 0) { - query = query.where({ id: In(ids) }); + query = query.andWhere({ id: In(ids) }); } if (!noLimit) { @@ -58,7 +102,7 @@ export default abstract class InspectionPlanService { } return await query - .orderBy("title", "ASC") + .orderBy("inspectionPlan.title", "ASC") .getManyAndCount() .then((res) => { return res; diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index 709b335..08ec621 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -38,7 +38,7 @@ export default abstract class InspectionService { } return await query - .orderBy("createdAt", "DESC") + .orderBy("inspection.createdAt", "DESC") .getManyAndCount() .then((res) => { return res; diff --git a/src/service/unit/vehicle/vehicleService.ts b/src/service/unit/vehicle/vehicleService.ts index 921a981..61c2b73 100644 --- a/src/service/unit/vehicle/vehicleService.ts +++ b/src/service/unit/vehicle/vehicleService.ts @@ -27,11 +27,16 @@ export default abstract class VehicleService { .leftJoinAndSelect("vehicle.vehicleType", "vehicletype"); if (search != "") { - query = query.where({ - code: Like(search), - name: Like(search), - location: Like(search), - }); + query = query + .where({ + code: Like(`%${search}%`), + }) + .orWhere({ + name: Like(`%${search}%`), + }) + .orWhere({ + location: Like(`%${search}%`), + }); } if (ids.length != 0) { diff --git a/src/service/unit/vehicle/vehicleTypeService.ts b/src/service/unit/vehicle/vehicleTypeService.ts index 6ecb703..c1dbdf2 100644 --- a/src/service/unit/vehicle/vehicleTypeService.ts +++ b/src/service/unit/vehicle/vehicleTypeService.ts @@ -13,26 +13,20 @@ export default abstract class VehicleTypeService { count = 25, search = "", noLimit = false, - ids = [], }: { offset?: number; count?: number; search?: string; noLimit?: boolean; - ids?: Array; }): Promise<[Array, number]> { let query = dataSource.getRepository(vehicleType).createQueryBuilder("vehicleType"); if (search != "") { query = query.where({ - type: Like(search), + type: Like(`%${search}%`), }); } - if (ids.length != 0) { - query = query.where({ id: In(ids) }); - } - if (!noLimit) { query = query.offset(offset).limit(count); } diff --git a/src/service/unit/wearable/wearableService.ts b/src/service/unit/wearable/wearableService.ts index b369f47..d016b0f 100644 --- a/src/service/unit/wearable/wearableService.ts +++ b/src/service/unit/wearable/wearableService.ts @@ -28,11 +28,16 @@ export default abstract class WearableService { .leftJoinAndSelect("wearable.wearer", "wearer"); if (search != "") { - query = query.where({ - code: Like(search), - name: Like(search), - location: Like(search), - }); + query = query + .where({ + code: Like(`%${search}%`), + }) + .orWhere({ + name: Like(`%${search}%`), + }) + .orWhere({ + location: Like(`%${search}%`), + }); } if (ids.length != 0) { @@ -63,6 +68,7 @@ export default abstract class WearableService { .getRepository(wearable) .createQueryBuilder("wearable") .leftJoinAndSelect("wearable.wearableType", "wearabletype") + .leftJoinAndSelect("wearable.wearer", "wearer") .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/service/unit/wearable/wearableTypeService.ts b/src/service/unit/wearable/wearableTypeService.ts index d6f167f..cd91a26 100644 --- a/src/service/unit/wearable/wearableTypeService.ts +++ b/src/service/unit/wearable/wearableTypeService.ts @@ -13,26 +13,20 @@ export default abstract class WearableTypeService { count = 25, search = "", noLimit = false, - ids = [], }: { offset?: number; count?: number; search?: string; noLimit?: boolean; - ids?: Array; }): Promise<[Array, number]> { let query = dataSource.getRepository(wearableType).createQueryBuilder("wearableType"); if (search != "") { query = query.where({ - type: Like(search), + type: Like(`%${search}%`), }); } - if (ids.length != 0) { - query = query.where({ id: In(ids) }); - } - if (!noLimit) { query = query.offset(offset).limit(count); } diff --git a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts index cbbea41..fe215d5 100644 --- a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts @@ -1,6 +1,8 @@ import { InspectionPointEnum } from "../../../../enums/inspectionEnum"; import type { EquipmentViewModel } from "../equipment/equipment.models"; +import { EquipmentTypeViewModel } from "../equipment/equipmentType.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; +import { VehicleTypeViewModel } from "../vehicle/vehicleType.models"; export type PlanTimeDefinition = `${number}-${"d" | "m" | "y"}` | `${number}/${number | "*"}`; @@ -16,11 +18,11 @@ export type InspectionPlanViewModel = { } & ( | { assigned: "equipment"; - related: EquipmentViewModel; + related: EquipmentTypeViewModel; } | { assigned: "vehicle"; - related: VehicleViewModel; + related: VehicleTypeViewModel; } ); From f11ed83afc10beb95c8d8223a29bce420bdc9b7d Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 8 Jun 2025 07:55:40 +0200 Subject: [PATCH 20/34] change schema according to migration --- src/entity/unit/inspection/inspection.ts | 4 ++-- src/entity/unit/inspection/inspectionPlan.ts | 4 ++-- src/entity/unit/wearable/wearable.ts | 2 +- src/migrations/baseSchemaTables/inspection.ts | 20 +++++++++---------- src/migrations/baseSchemaTables/unit.ts | 20 +++++++++---------- .../baseSchemaTables/unit_extend.ts | 18 ++++++++--------- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 00faf98..1bcbde4 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -29,10 +29,10 @@ export class inspection { @Column() inspectionVersionedPlanId: string; - @Column() + @Column({ nullable: true, default: null }) equipmentId?: string; - @Column() + @Column({ nullable: true, default: null }) vehicleId?: string; @ManyToOne(() => inspectionPlan, { diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts index b2a43eb..1e9b2e3 100644 --- a/src/entity/unit/inspection/inspectionPlan.ts +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -21,10 +21,10 @@ export class inspectionPlan { @CreateDateColumn() createdAt: Date; - @Column() + @Column({ nullable: true, default: null }) equipmentTypeId?: string; - @Column() + @Column({ nullable: true, default: null }) vehicleTypeId?: string; @ManyToOne(() => equipmentType, { diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index 0313997..d1168d6 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -28,7 +28,7 @@ export class wearable { @Column() wearableTypeId: string; - @Column() + @Column({ nullable: true, default: null }) wearerId?: string; @ManyToOne(() => wearableType, { diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index bfa480a..fbca0ab 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -1,4 +1,4 @@ -import { Table, TableForeignKey, TableUnique, Unique } from "typeorm"; +import { Table, TableForeignKey, TableUnique } from "typeorm"; import { getTypeByORM, isUUIDPrimary, getDefaultByORM } from "../ormHelper"; export const inspection_plan_table = new Table({ @@ -8,9 +8,9 @@ export const inspection_plan_table = new Table({ { name: "title", ...getTypeByORM("varchar") }, { name: "inspectionInterval", ...getTypeByORM("varchar") }, { name: "remindTime", ...getTypeByORM("varchar") }, - { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, - { name: "equipmentTypeId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "vehicleTypeId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") }, + { name: "equipmentTypeId", ...getTypeByORM("uuid", true) }, + { name: "vehicleTypeId", ...getTypeByORM("uuid", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -35,7 +35,7 @@ export const inspection_versioned_plan_table = new Table({ columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "version", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, - { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") }, { name: "inspectionPlanId", ...getTypeByORM("uuid") }, ], foreignKeys: [ @@ -62,8 +62,8 @@ export const inspection_point_table = new Table({ { name: "title", ...getTypeByORM("varchar") }, { name: "description", ...getTypeByORM("text") }, { name: "type", ...getTypeByORM("varchar") }, - { name: "min", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, - { name: "max", ...getTypeByORM("int", true), default: getDefaultByORM("null") }, + { name: "min", ...getTypeByORM("int", true) }, + { name: "max", ...getTypeByORM("int", true) }, { name: "sort", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, { name: "versionedPlanId", ...getTypeByORM("uuid") }, ], @@ -83,13 +83,13 @@ export const inspection_table = new Table({ columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "context", ...getTypeByORM("text") }, - { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") }, { name: "finishedAt", ...getTypeByORM("date", true) }, { name: "nextInspection", ...getTypeByORM("date", true) }, { name: "inspectionPlanId", ...getTypeByORM("uuid") }, { name: "inspectionVersionedPlanId", ...getTypeByORM("uuid") }, - { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "equipmentId", ...getTypeByORM("uuid", true) }, + { name: "vehicleId", ...getTypeByORM("uuid", true) }, ], foreignKeys: [ new TableForeignKey({ diff --git a/src/migrations/baseSchemaTables/unit.ts b/src/migrations/baseSchemaTables/unit.ts index aec48b3..4d18e11 100644 --- a/src/migrations/baseSchemaTables/unit.ts +++ b/src/migrations/baseSchemaTables/unit.ts @@ -5,11 +5,11 @@ export const equipment_table = new Table({ name: "equipment", columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, - { name: "code", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "code", ...getTypeByORM("varchar", true), isUnique: true }, { name: "name", ...getTypeByORM("varchar") }, { name: "location", ...getTypeByORM("varchar") }, { name: "commissioned", ...getTypeByORM("date") }, - { name: "decommissioned", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { name: "decommissioned", ...getTypeByORM("date", true) }, { name: "equipmentTypeId", ...getTypeByORM("uuid") }, ], foreignKeys: [ @@ -28,7 +28,7 @@ export const equipment_type_table = new Table({ columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "type", ...getTypeByORM("varchar"), isUnique: true }, - { name: "description", ...getTypeByORM("text") }, + { name: "description", ...getTypeByORM("text", true) }, ], }); @@ -36,11 +36,11 @@ export const vehicle_table = new Table({ name: "vehicle", columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, - { name: "code", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "code", ...getTypeByORM("varchar", true), isUnique: true }, { name: "name", ...getTypeByORM("varchar") }, { name: "location", ...getTypeByORM("varchar") }, { name: "commissioned", ...getTypeByORM("date") }, - { name: "decommissioned", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { name: "decommissioned", ...getTypeByORM("date", true) }, { name: "vehicleTypeId", ...getTypeByORM("uuid") }, ], foreignKeys: [ @@ -59,7 +59,7 @@ export const vehicle_type_table = new Table({ columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "type", ...getTypeByORM("varchar"), isUnique: true }, - { name: "description", ...getTypeByORM("text") }, + { name: "description", ...getTypeByORM("text", true) }, ], }); @@ -67,13 +67,13 @@ export const wearable_table = new Table({ name: "wearable", columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, - { name: "code", ...getTypeByORM("varchar", true), default: getDefaultByORM("null"), isUnique: true }, + { name: "code", ...getTypeByORM("varchar", true), isUnique: true }, { name: "name", ...getTypeByORM("varchar") }, { name: "location", ...getTypeByORM("varchar") }, { name: "commissioned", ...getTypeByORM("date") }, - { name: "decommissioned", ...getTypeByORM("date", true), default: getDefaultByORM("null") }, + { name: "decommissioned", ...getTypeByORM("date", true) }, { name: "wearableTypeId", ...getTypeByORM("uuid") }, - { name: "wearerId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "wearerId", ...getTypeByORM("uuid", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -98,6 +98,6 @@ export const wearable_type_table = new Table({ columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, { name: "type", ...getTypeByORM("varchar"), isUnique: true }, - { name: "description", ...getTypeByORM("text") }, + { name: "description", ...getTypeByORM("text", true) }, ], }); diff --git a/src/migrations/baseSchemaTables/unit_extend.ts b/src/migrations/baseSchemaTables/unit_extend.ts index 3f78910..43bece7 100644 --- a/src/migrations/baseSchemaTables/unit_extend.ts +++ b/src/migrations/baseSchemaTables/unit_extend.ts @@ -5,16 +5,16 @@ export const damage_report_table = new Table({ name: "damage_report", columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, - { name: "reportedAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "reportedAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") }, { name: "status", ...getTypeByORM("varchar") }, { name: "done", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, { name: "description", ...getTypeByORM("text") }, { name: "reportedBy", ...getTypeByORM("varchar") }, { name: "imageCount", ...getTypeByORM("int"), default: getDefaultByORM("number", 0) }, - { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "maintenanceId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "equipmentId", ...getTypeByORM("uuid", true) }, + { name: "vehicleId", ...getTypeByORM("uuid", true) }, + { name: "wearableId", ...getTypeByORM("uuid", true) }, + { name: "maintenanceId", ...getTypeByORM("uuid", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -52,13 +52,13 @@ export const maintenance_table = new Table({ name: "maintenance", columns: [ { name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary }, - { name: "createdAt", ...getTypeByORM("date"), default: getDefaultByORM("currentTimestamp") }, + { name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") }, { name: "status", ...getTypeByORM("varchar") }, { name: "done", ...getTypeByORM("boolean"), default: getDefaultByORM("boolean", false) }, { name: "description", ...getTypeByORM("text") }, - { name: "equipmentId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "vehicleId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, - { name: "wearableId", ...getTypeByORM("uuid", true), default: getDefaultByORM("null") }, + { name: "equipmentId", ...getTypeByORM("uuid", true) }, + { name: "vehicleId", ...getTypeByORM("uuid", true) }, + { name: "wearableId", ...getTypeByORM("uuid", true) }, ], foreignKeys: [ new TableForeignKey({ From aeb1ccbc42087ad19fab3da5da3d6eed0255f8f6 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 8 Jun 2025 08:02:07 +0200 Subject: [PATCH 21/34] fix according to move to postgres --- src/service/unit/inspection/inspectionPlanService.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index 197912d..62f851a 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -1,7 +1,6 @@ import { Like, In } from "typeorm"; import { dataSource } from "../../../data-source"; import { inspectionPlan } from "../../../entity/unit/inspection/inspectionPlan"; -import { DB_TYPE } from "../../../env.defaults"; import DatabaseActionException from "../../../exceptions/databaseActionException"; export default abstract class InspectionPlanService { @@ -13,9 +12,7 @@ export default abstract class InspectionPlanService { "inspectionPlan.latestVersionedPlan", "inspectionPlan.versionedPlans", "latestVersionedPlan", - DB_TYPE == "postgres" - ? 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."createdAt") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' - : "latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX(ivp.createdAt) FROM inspection_versioned_plan ivp WHERE ivp.inspectionPlanId = inspectionPlan.id)" + 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."createdAt") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspectionPlan.equipmentType", "equipmentType") From b8b2186c5861fdf986bdd9b8e465be4d79a9e86d Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 13 Jun 2025 11:31:34 +0200 Subject: [PATCH 22/34] extend wearable and enable maintenance --- .../admin/unit/damageReportController.ts | 11 +- .../admin/unit/inspectionController.ts | 15 ++- .../admin/unit/inspectionPlanController.ts | 15 ++- .../admin/unit/maintenanceController.ts | 119 ++++++++++++++++++ src/entity/unit/inspection/inspection.ts | 11 ++ src/entity/unit/inspection/inspectionPlan.ts | 11 ++ src/entity/unit/wearable/wearable.ts | 3 + src/entity/unit/wearable/wearableType.ts | 4 + .../admin/unit/inspection/inspection.ts | 36 ++++-- .../admin/unit/inspection/inspectionPlan.ts | 39 ++++-- src/routes/admin/index.ts | 56 ++++++++- src/routes/admin/unit/inspection.ts | 21 ++-- src/routes/admin/unit/inspectionPlan.ts | 21 ++-- src/routes/admin/unit/maintenance.ts | 43 +++++++ .../unit/inspection/inspectionPlanService.ts | 5 +- .../unit/inspection/inspectionService.ts | 5 +- src/service/unit/maintenanceService.ts | 78 +++++++++--- src/type/permissionTypes.ts | 3 + .../unit/inspection/inspection.models.ts | 30 +++-- .../unit/inspection/inspectionPlan.models.ts | 24 ++-- 20 files changed, 457 insertions(+), 93 deletions(-) create mode 100644 src/controller/admin/unit/maintenanceController.ts create mode 100644 src/routes/admin/unit/maintenance.ts diff --git a/src/controller/admin/unit/damageReportController.ts b/src/controller/admin/unit/damageReportController.ts index 9576ec9..443a6cc 100644 --- a/src/controller/admin/unit/damageReportController.ts +++ b/src/controller/admin/unit/damageReportController.ts @@ -34,13 +34,20 @@ export async function getAllDamageReportsByStatus(req: Request, res: Response): * @returns {Promise<*>} */ export async function getAllDamageReportsForRelated(req: Request, res: Response): Promise { - let relation = req.params.related as "vehicle" | "equipment"; + 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 = relation === "equipment" ? { equipmentId: relationId } : { vehicleId: relationId }; + 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({ diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index 2380bdf..e7d3dce 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -16,13 +16,20 @@ import BadRequestException from "../../../exceptions/badRequestException"; * @returns {Promise<*>} */ export async function getAllInspectionsForRelated(req: Request, res: Response): Promise { - let relation = req.params.related as "vehicle" | "equipment"; + 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 = relation === "equipment" ? { equipmentId: relationId } : { vehicleId: relationId }; + 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({ @@ -59,8 +66,8 @@ export async function createInspection(req: Request, res: Response): Promise} */ export async function getAllInspectionPlansForRelated(req: Request, res: Response): Promise { - let relation = req.params.related as "vehicle" | "equipment"; + 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"); @@ -54,7 +54,14 @@ export async function getAllInspectionPlansForRelated(req: Request, res: Respons let noLimit = req.query.noLimit === "true"; let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); - let where = relation === "equipment" ? { equipmentTypeId: relationId } : { vehicleTypeId: relationId }; + let where; + if (relation == "equipment") { + where = { equipmentTypeId: relationId }; + } else if (relation == "vehicle") { + where = { vehicleTypeId: relationId }; + } else { + where = { wearableTypeId: relationId }; + } let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated(where, { offset, count, @@ -100,8 +107,8 @@ export async function createInspectionPlan(req: Request, res: Response): Promise TypeTester.testPlanTimeDefinition(inspectionInterval, "inspectionInterval", true); TypeTester.testPlanTimeDefinition(remindTime, "remindTime", true); - if (assigned != "equipment" && assigned != "vehicle") - throw new BadRequestException("set assigned to equipment or vehicle"); + if (assigned != "equipment" && assigned != "vehicle" && assigned != "wearable") + throw new BadRequestException("set assigned to equipment or vehicle or wearable"); let createInspectionPlan: CreateInspectionPlanCommand = { title, diff --git a/src/controller/admin/unit/maintenanceController.ts b/src/controller/admin/unit/maintenanceController.ts new file mode 100644 index 0000000..78c6a7b --- /dev/null +++ b/src/controller/admin/unit/maintenanceController.ts @@ -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 { + 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.getAll(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 { + 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 { + 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 { + 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 { + 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); +} diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 1bcbde4..16aae27 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -5,6 +5,7 @@ import { getTypeByORM } from "../../../migrations/ormHelper"; import { vehicle } from "../vehicle/vehicle"; import { equipment } from "../equipment/equipment"; import { inspectionPointResult } from "./inspectionPointResult"; +import { wearable } from "../wearable/wearable"; @Entity() export class inspection { @@ -35,6 +36,9 @@ export class inspection { @Column({ nullable: true, default: null }) vehicleId?: string; + @Column({ nullable: true, default: null }) + wearableId?: string; + @ManyToOne(() => inspectionPlan, { nullable: false, onDelete: "RESTRICT", @@ -63,6 +67,13 @@ export class inspection { }) vehicle: vehicle; + @ManyToOne(() => wearable, { + nullable: true, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) + wearable: wearable; + @OneToMany(() => inspectionPointResult, (ipr) => ipr.inspection) pointResults: inspectionPointResult[]; } diff --git a/src/entity/unit/inspection/inspectionPlan.ts b/src/entity/unit/inspection/inspectionPlan.ts index 1e9b2e3..9fa6fad 100644 --- a/src/entity/unit/inspection/inspectionPlan.ts +++ b/src/entity/unit/inspection/inspectionPlan.ts @@ -3,6 +3,7 @@ import { PlanTimeDefinition } from "../../../viewmodel/admin/unit/inspection/ins import { inspectionVersionedPlan } from "./inspectionVersionedPlan"; import { equipmentType } from "../equipment/equipmentType"; import { vehicleType } from "../vehicle/vehicleType"; +import { wearableType } from "../wearable/wearableType"; @Entity() export class inspectionPlan { @@ -27,6 +28,9 @@ export class inspectionPlan { @Column({ nullable: true, default: null }) vehicleTypeId?: string; + @Column({ nullable: true, default: null }) + wearableTypeId?: string; + @ManyToOne(() => equipmentType, { nullable: true, onDelete: "CASCADE", @@ -41,6 +45,13 @@ export class inspectionPlan { }) vehicleType?: vehicleType; + @ManyToOne(() => wearableType, { + nullable: true, + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }) + wearableType?: wearableType; + @OneToMany(() => inspectionVersionedPlan, (ivp) => ivp.inspectionPlan, { cascade: ["insert"], }) diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index d1168d6..902d23a 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -47,4 +47,7 @@ export class wearable { @OneToMany(() => damageReport, (d) => d.wearable, { cascade: ["insert"] }) reports: damageReport[]; + + @OneToMany(() => inspection, (i) => i.wearable) + inspections: inspection[]; } diff --git a/src/entity/unit/wearable/wearableType.ts b/src/entity/unit/wearable/wearableType.ts index 0905a33..15ae351 100644 --- a/src/entity/unit/wearable/wearableType.ts +++ b/src/entity/unit/wearable/wearableType.ts @@ -1,5 +1,6 @@ import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { wearable as wearable } from "./wearable"; +import { inspectionPlan } from "../inspection/inspectionPlan"; @Entity() export class wearableType { @@ -14,4 +15,7 @@ export class wearableType { @OneToMany(() => wearable, (e) => e.wearableType, { cascade: ["insert"] }) wearable: wearable[]; + + @OneToMany(() => inspectionPlan, (ip) => ip.wearableType) + inspectionPlans: inspectionPlan[]; } diff --git a/src/factory/admin/unit/inspection/inspection.ts b/src/factory/admin/unit/inspection/inspection.ts index 3505e11..52a10f8 100644 --- a/src/factory/admin/unit/inspection/inspection.ts +++ b/src/factory/admin/unit/inspection/inspection.ts @@ -1,7 +1,8 @@ import { inspection } from "../../../../entity/unit/inspection/inspection"; -import { InspectionViewModel } from "../../../../viewmodel/admin/unit/inspection/inspection.models"; +import { InspectionRelated, InspectionViewModel } 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"; @@ -13,6 +14,27 @@ export default abstract class InspectionFactory { * @returns {InspectionViewModel} */ public static mapToSingle(record: inspection): InspectionViewModel { + let related: InspectionRelated; + if (record?.equipmentId) { + related = { + relatedId: record.equipmentId, + assigned: "equipment", + related: EquipmentFactory.mapToSingle(record.equipment), + }; + } else if (record?.vehicleId) { + related = { + relatedId: record.vehicleId, + assigned: "vehicle", + related: VehicleFactory.mapToSingle(record.vehicle), + }; + } else { + related = { + relatedId: record.wearableId, + assigned: "wearable", + related: WearableFactory.mapToSingle(record.wearable), + }; + } + return { id: record.id, inspectionPlanId: record.inspectionPlanId, @@ -25,17 +47,7 @@ export default abstract class InspectionFactory { isOpen: record?.finishedAt == undefined, nextInspection: record?.nextInspection, checks: InspectionPointResultFactory.mapToBase(record.pointResults), - ...(record.equipmentId - ? { - relatedId: record.equipmentId, - assigned: "equipment", - related: EquipmentFactory.mapToSingle(record.equipment), - } - : { - relatedId: record.vehicleId, - assigned: "vehicle", - related: VehicleFactory.mapToSingle(record.vehicle), - }), + ...related, }; } diff --git a/src/factory/admin/unit/inspection/inspectionPlan.ts b/src/factory/admin/unit/inspection/inspectionPlan.ts index 1a0439d..6e48ed5 100644 --- a/src/factory/admin/unit/inspection/inspectionPlan.ts +++ b/src/factory/admin/unit/inspection/inspectionPlan.ts @@ -1,9 +1,13 @@ import { inspectionPlan } from "../../../../entity/unit/inspection/inspectionPlan"; -import { InspectionPlanViewModel } from "../../../../viewmodel/admin/unit/inspection/inspectionPlan.models"; +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 { @@ -13,6 +17,27 @@ export default abstract class InspectionPlanFactory { * @returns {InspectionPlanViewModel} */ public static mapToSingle(record: inspectionPlan): InspectionPlanViewModel { + let related: InspectionPlanRelated; + if (record?.equipmentTypeId) { + related = { + relatedId: record.equipmentTypeId, + assigned: "equipment", + related: EquipmentTypeFactory.mapToSingle(record.equipmentType), + }; + } else if (record?.vehicleTypeId) { + related = { + relatedId: record.vehicleTypeId, + assigned: "vehicle", + related: VehicleTypeFactory.mapToSingle(record.vehicleType), + }; + } else { + related = { + relatedId: record.wearableTypeId, + assigned: "wearable", + related: WearableTypeFactory.mapToSingle(record.wearableType), + }; + } + return { id: record.id, title: record.title, @@ -23,17 +48,7 @@ export default abstract class InspectionPlanFactory { inspectionPoints: record.latestVersionedPlan ? InspectionPointFactory.mapToBase(record.latestVersionedPlan.inspectionPoints) : [], - ...(record.equipmentTypeId - ? { - relatedId: record.equipmentTypeId, - assigned: "equipment", - related: EquipmentTypeFactory.mapToSingle(record.equipmentType), - } - : { - relatedId: record.vehicleTypeId, - assigned: "vehicle", - related: VehicleTypeFactory.mapToSingle(record.vehicleType), - }), + ...related, }; } diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index 6f7e187..f6f1f3d 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -42,6 +42,7 @@ 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"; var router = express.Router({ mergeParams: true }); @@ -189,39 +190,75 @@ router.use( router.use("/setting", PermissionHelper.passCheckMiddleware("read", "management", "setting"), setting); /** unit */ -router.use("/equipment", PermissionHelper.passCheckMiddleware("read", "unit", "equipment"), equipment); +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.passCheckMiddleware("read", "unit", "vehicle"), vehicle); +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.passCheckMiddleware("read", "unit", "wearable"), wearable); +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.passCheckMiddleware("read", "unit", "inspection"), inspection); +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 ); @@ -229,11 +266,22 @@ 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( + "/mainenance", + 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 +); export default router; diff --git a/src/routes/admin/unit/inspection.ts b/src/routes/admin/unit/inspection.ts index 8c7a63d..41694ea 100644 --- a/src/routes/admin/unit/inspection.ts +++ b/src/routes/admin/unit/inspection.ts @@ -10,15 +10,20 @@ import { var router = express.Router({ mergeParams: true }); -router.get(["/vehicle/:relatedId", "/equipment/:relatedId"], async (req: Request, res: Response) => { - if (req.path.startsWith("/vehicle")) { - req.params.related = "vehicle"; - } else { - req.params.related = "equipment"; - } +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); -}); + await getAllInspectionsForRelated(req, res); + } +); router.get("/:id", async (req: Request, res: Response) => { await getInspectionById(req, res); diff --git a/src/routes/admin/unit/inspectionPlan.ts b/src/routes/admin/unit/inspectionPlan.ts index 632c130..0aaf46a 100644 --- a/src/routes/admin/unit/inspectionPlan.ts +++ b/src/routes/admin/unit/inspectionPlan.ts @@ -15,15 +15,20 @@ router.get("/", async (req: Request, res: Response) => { await getAllInspectionPlans(req, res); }); -router.get(["/vehicle/:relatedId", "/equipment/:relatedId"], async (req: Request, res: Response) => { - if (req.path.startsWith("/vehicle")) { - req.params.related = "vehicle"; - } else { - req.params.related = "equipment"; - } +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 getAllInspectionPlansForRelated(req, res); -}); + await getAllInspectionPlansForRelated(req, res); + } +); router.get("/:id", async (req: Request, res: Response) => { await getInspectionPlanById(req, res); diff --git a/src/routes/admin/unit/maintenance.ts b/src/routes/admin/unit/maintenance.ts new file mode 100644 index 0000000..76c80b1 --- /dev/null +++ b/src/routes/admin/unit/maintenance.ts @@ -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", "inspection"), + async (req: Request, res: Response) => { + await updateMaintenanceById(req, res); + } +); + +export default router; diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index 62f851a..f422798 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -16,7 +16,8 @@ export default abstract class InspectionPlanService { ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspectionPlan.equipmentType", "equipmentType") - .leftJoinAndSelect("inspectionPlan.vehicleType", "vehicleType"); + .leftJoinAndSelect("inspectionPlan.vehicleType", "vehicleType") + .leftJoinAndSelect("inspectionPlan.wearableType", "wearableType"); /** * @description get all inspectionPlans for related @@ -67,7 +68,7 @@ export default abstract class InspectionPlanService { * @returns {Promise<[Array, number]>} */ static async getAllForRelated( - where: { equipmentTypeId: string } | { vehicleTypeId: string }, + where: { equipmentTypeId: string } | { vehicleTypeId: string } | { wearableTypeId: string }, { offset = 0, count = 25, diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index 08ec621..c4c8b1d 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -13,14 +13,15 @@ export default abstract class InspectionService { .leftJoinAndSelect("inspection.pointResults", "pointResults") .leftJoinAndSelect("pointResults.inspectionPoint", "inspectionPoint") .leftJoinAndSelect("inspection.equipment", "equipment") - .leftJoinAndSelect("inspection.vehicle", "vehicle"); + .leftJoinAndSelect("inspection.vehicle", "vehicle") + .leftJoinAndSelect("inspection.wearable", "wearable"); /** * @description get all inspections for related * @returns {Promise>} */ static async getAllForRelated( - where: { equipmentId: string } | { vehicleId: string }, + where: { equipmentId: string } | { vehicleId: string } | { wearableId: string }, { offset = 0, count = 25, diff --git a/src/service/unit/maintenanceService.ts b/src/service/unit/maintenanceService.ts index d9e8519..73a8a39 100644 --- a/src/service/unit/maintenanceService.ts +++ b/src/service/unit/maintenanceService.ts @@ -3,20 +3,72 @@ import { maintenance } from "../../entity/unit/maintenance"; import DatabaseActionException from "../../exceptions/databaseActionException"; export default abstract class MaintenanceService { - /** - * @description get all maintenances - * @returns {Promise>} - */ - static async getAll(): Promise> { - return await dataSource + private static query = () => + dataSource .getRepository(maintenance) .createQueryBuilder("maintenance") .leftJoinAndSelect("maintenance.equipment", "equipment") .leftJoinAndSelect("maintenance.vehicle", "vehicle") .leftJoinAndSelect("maintenance.wearable", "wearable") - .leftJoinAndSelect("maintenance.reports", "reports") - .orderBy("type", "ASC") - .getMany() + .leftJoinAndSelect("maintenance.reports", "reports"); + + /** + * @description get all maintenances + * @returns {Promise<[Array, number]>} + */ + static async getAll( + done = false, + { + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + } + ): Promise<[Array, number]> { + let query = this.query().where({ done }); + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("maintenance.type", "ASC") + .getManyAndCount() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "maintenance", err); + }); + } + + /** + * @description get all maintenances By related + * @returns {Promise<[Array, number]>} + */ + static async getAllForRelated( + where: { equipmentId: string } | { vehicleId: string } | { wearableId: string }, + { + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + } + ): Promise<[Array, number]> { + let query = this.query().where(where); + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("maintenance.createdAt", "ASC") + .getManyAndCount() .then((res) => { return res; }) @@ -30,13 +82,7 @@ export default abstract class MaintenanceService { * @returns {Promise} */ static async getById(id: string): Promise { - return await dataSource - .getRepository(maintenance) - .createQueryBuilder("maintenance") - .leftJoinAndSelect("maintenance.equipment", "equipment") - .leftJoinAndSelect("maintenance.vehicle", "vehicle") - .leftJoinAndSelect("maintenance.wearable", "wearable") - .leftJoinAndSelect("maintenance.reports", "reports") + return await this.query() .where({ id }) .getOneOrFail() .then((res) => { diff --git a/src/type/permissionTypes.ts b/src/type/permissionTypes.ts index f85a54f..2442d9f 100644 --- a/src/type/permissionTypes.ts +++ b/src/type/permissionTypes.ts @@ -21,6 +21,7 @@ export type PermissionModule = | "respiratory_wearer" | "respiratory_mission" | "damage_report" + | "maintenance" // configuration | "qualification" | "award" @@ -95,6 +96,7 @@ export const permissionModules: Array = [ "respiratory_wearer", "respiratory_mission", "damage_report", + "maintenance", // configuration "qualification", "award", @@ -131,6 +133,7 @@ export const sectionsAndModules: SectionsAndModulesObject = { "respiratory_wearer", "respiratory_mission", "damage_report", + "maintenance", ], configuration: [ "qualification", diff --git a/src/viewmodel/admin/unit/inspection/inspection.models.ts b/src/viewmodel/admin/unit/inspection/inspection.models.ts index 6565377..4d18e7c 100644 --- a/src/viewmodel/admin/unit/inspection/inspection.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspection.models.ts @@ -5,6 +5,24 @@ import type { InspectionVersionedPlanViewModel, } from "./inspectionPlan.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; +import { WearableViewModel } from "../wearable/wearable.models"; + +export type InspectionRelated = { + relatedId: string; +} & ( + | { + assigned: "equipment"; + related: EquipmentViewModel; + } + | { + assigned: "vehicle"; + related: VehicleViewModel; + } + | { + assigned: "wearable"; + related: WearableViewModel; + } +); export type InspectionViewModel = { id: string; @@ -18,17 +36,7 @@ export type InspectionViewModel = { isOpen: boolean; nextInspection?: Date; checks: Array; - relatedId: string; -} & ( - | { - assigned: "equipment"; - related: EquipmentViewModel; - } - | { - assigned: "vehicle"; - related: VehicleViewModel; - } -); +} & InspectionRelated; export interface InspectionPointResultViewModel { inspectionId: string; diff --git a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts index fe215d5..30706a7 100644 --- a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts @@ -3,17 +3,11 @@ import type { EquipmentViewModel } from "../equipment/equipment.models"; import { EquipmentTypeViewModel } from "../equipment/equipmentType.models"; import type { VehicleViewModel } from "../vehicle/vehicle.models"; import { VehicleTypeViewModel } from "../vehicle/vehicleType.models"; +import { WearableTypeViewModel } from "../wearable/wearableType.models"; export type PlanTimeDefinition = `${number}-${"d" | "m" | "y"}` | `${number}/${number | "*"}`; -export type InspectionPlanViewModel = { - id: string; - title: string; - inspectionInterval: PlanTimeDefinition; - remindTime: PlanTimeDefinition; - version: number; - created: Date; - inspectionPoints: InspectionPointViewModel[]; +export type InspectionPlanRelated = { relatedId: string; } & ( | { @@ -24,8 +18,22 @@ export type InspectionPlanViewModel = { assigned: "vehicle"; related: VehicleTypeViewModel; } + | { + assigned: "wearable"; + related: WearableTypeViewModel; + } ); +export type InspectionPlanViewModel = { + id: string; + title: string; + inspectionInterval: PlanTimeDefinition; + remindTime: PlanTimeDefinition; + version: number; + created: Date; + inspectionPoints: InspectionPointViewModel[]; +} & InspectionPlanRelated; + export interface InspectionVersionedPlanViewModel { id: string; version: number; From d5646753f1d47675b29d1b4ba02ad0515eac67f7 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 13 Jun 2025 18:05:55 +0200 Subject: [PATCH 23/34] inspection extend fixes --- src/migrations/baseSchemaTables/inspection.ts | 16 ++++++++++++++++ src/routes/admin/index.ts | 2 +- src/service/unit/damageReportService.ts | 2 +- src/service/unit/maintenanceService.ts | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index fbca0ab..2b827fc 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -11,6 +11,7 @@ export const inspection_plan_table = new Table({ { 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({ @@ -27,6 +28,13 @@ export const inspection_plan_table = new Table({ onDelete: "CASCADE", onUpdate: "RESTRICT", }), + new TableForeignKey({ + columnNames: ["wearableTypeId"], + referencedColumnNames: ["id"], + referencedTableName: "wearable_type", + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }), ], }); @@ -90,6 +98,7 @@ export const inspection_table = new Table({ { name: "inspectionVersionedPlanId", ...getTypeByORM("uuid") }, { name: "equipmentId", ...getTypeByORM("uuid", true) }, { name: "vehicleId", ...getTypeByORM("uuid", true) }, + { name: "wearableId", ...getTypeByORM("uuid", true) }, ], foreignKeys: [ new TableForeignKey({ @@ -120,6 +129,13 @@ export const inspection_table = new Table({ onDelete: "CASCADE", onUpdate: "RESTRICT", }), + new TableForeignKey({ + columnNames: ["wearableId"], + referencedColumnNames: ["id"], + referencedTableName: "wearable", + onDelete: "CASCADE", + onUpdate: "RESTRICT", + }), ], }); diff --git a/src/routes/admin/index.ts b/src/routes/admin/index.ts index f6f1f3d..3a6edf2 100644 --- a/src/routes/admin/index.ts +++ b/src/routes/admin/index.ts @@ -274,7 +274,7 @@ router.use( damageReport ); router.use( - "/mainenance", + "/maintenance", PermissionHelper.passCheckSomeMiddleware([ { requiredPermission: "read", section: "unit", module: "maintenance" }, { requiredPermission: "read", section: "unit", module: "equipment" }, diff --git a/src/service/unit/damageReportService.ts b/src/service/unit/damageReportService.ts index 622b377..21072c7 100644 --- a/src/service/unit/damageReportService.ts +++ b/src/service/unit/damageReportService.ts @@ -68,7 +68,7 @@ export default abstract class DamageReportService { } return await query - .orderBy("reportedAt", "ASC") + .orderBy("damageReport.reportedAt", "ASC") .getManyAndCount() .then((res) => { return res; diff --git a/src/service/unit/maintenanceService.ts b/src/service/unit/maintenanceService.ts index 73a8a39..d9d997d 100644 --- a/src/service/unit/maintenanceService.ts +++ b/src/service/unit/maintenanceService.ts @@ -34,7 +34,7 @@ export default abstract class MaintenanceService { } return await query - .orderBy("maintenance.type", "ASC") + .orderBy("maintenance.createdAt", "ASC") .getManyAndCount() .then((res) => { return res; From a0a8edf7afd4af861c673e9a496996dd24744007 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 4 Jul 2025 11:57:13 +0200 Subject: [PATCH 24/34] fix get latest inspection plan --- src/service/unit/inspection/inspectionPlanService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service/unit/inspection/inspectionPlanService.ts b/src/service/unit/inspection/inspectionPlanService.ts index f422798..0ee2e89 100644 --- a/src/service/unit/inspection/inspectionPlanService.ts +++ b/src/service/unit/inspection/inspectionPlanService.ts @@ -12,7 +12,7 @@ export default abstract class InspectionPlanService { "inspectionPlan.latestVersionedPlan", "inspectionPlan.versionedPlans", "latestVersionedPlan", - 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."createdAt") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' + 'latestVersionedPlan.inspectionPlanId = inspectionPlan.id AND latestVersionedPlan.version = (SELECT MAX("ivp"."version") FROM "inspection_versioned_plan" "ivp" WHERE "ivp"."inspectionPlanId" = "inspectionPlan"."id")' ) .leftJoinAndSelect("latestVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspectionPlan.equipmentType", "equipmentType") From 95b6cec66d48999ac46195a76baadd481bc72d26 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 9 Jul 2025 12:57:37 +0200 Subject: [PATCH 25/34] inspection fetch --- .../inspection/inspectionCommandHandler.ts | 87 ++++++++++++++----- .../admin/unit/inspectionController.ts | 48 +++++++++- src/entity/unit/inspection/inspection.ts | 3 + src/migrations/baseSchemaTables/inspection.ts | 1 + src/routes/admin/unit/inspection.ts | 10 +++ .../unit/inspection/inspectionService.ts | 61 +++++++++++++ 6 files changed, 189 insertions(+), 21 deletions(-) diff --git a/src/command/unit/inspection/inspectionCommandHandler.ts b/src/command/unit/inspection/inspectionCommandHandler.ts index 5f4a61d..34b7bf5 100644 --- a/src/command/unit/inspection/inspectionCommandHandler.ts +++ b/src/command/unit/inspection/inspectionCommandHandler.ts @@ -1,6 +1,8 @@ +import { 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 } from "./inspectionCommand"; @@ -8,27 +10,42 @@ export default abstract class InspectionCommandHandler { /** * @description create inspection * @param {CreateInspectionCommand} createInspection - * @returns {Promise} + * @returns {Promise} */ - static async create(createInspection: CreateInspectionCommand): Promise { + static async create(createInspection: CreateInspectionCommand): Promise { let latestVersionedPlan = await InspectionVersionedPlanService.getLatestForInspectionPlan( createInspection.inspectionPlanId ); + let insertId = ""; return await dataSource - .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, + .transaction(async (manager) => { + await manager + .createQueryBuilder() + .update(inspection) + .set({ + hasNewer: true, + }) + .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, + }) + .execute() + .then((result) => { + insertId = result.identifiers[0].id; + }); }) - .execute() - .then((result) => { - return result.identifiers[0].id; + .then(() => { + return insertId; }) .catch((err) => { throw new DatabaseActionException("CREATE", "inspection", err); @@ -62,12 +79,42 @@ export default abstract class InspectionCommandHandler { * @returns {Promise} */ static async delete(deleteInspection: DeleteInspectionCommand): Promise { + let deleteInspectionData = await InspectionService.getById(deleteInspection.id); return await dataSource - .createQueryBuilder() - .delete() - .from(inspection) - .where("id = :id", { id: deleteInspection.id }) - .execute() + .transaction(async (manager) => { + await manager + .createQueryBuilder() + .update(inspection) + .set({ + hasNewer: false, + }) + .where((qb) => { + const subQuery = qb + .createQueryBuilder() + .select("id") + .from(inspection, "sub") + .where({ + inspectionPlanId: deleteInspectionData.inspectionPlanId, + inspectionVersionedPlanId: deleteInspectionData.inspectionVersionedPlanId, + equipmentId: deleteInspectionData.equipmentId, + vehicleId: deleteInspectionData.vehicleId, + wearableId: deleteInspectionData.wearableId, + }) + .andWhere({ id: Not(deleteInspection.id) }) + .orderBy("sub.createdAt", "DESC") + .limit(1) + .getQuery(); + return "id = " + subQuery; + }) + .execute(); + + await manager + .createQueryBuilder() + .delete() + .from(inspection) + .where("id = :id", { id: deleteInspection.id }) + .execute(); + }) .then(() => {}) .catch((err) => { throw new DatabaseActionException("DELETE", "inspection", err); diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index e7d3dce..f98f4c5 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -8,6 +8,49 @@ import { } from "../../../command/unit/inspection/inspectionCommand"; import InspectionCommandHandler from "../../../command/unit/inspection/inspectionCommandHandler"; import BadRequestException from "../../../exceptions/badRequestException"; +import ForbiddenRequestException from "../../../exceptions/forbiddenRequestException"; + +/** + * @description get all inspections sorted by id not having newer inspection + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getAllInspectionsSortedNotHavingNewer(req: Request, res: Response): Promise { + let offset = parseInt((req.query.offset as string) ?? "0"); + let count = parseInt((req.query.count as string) ?? "25"); + let noLimit = req.query.noLimit === "true"; + + let [inspections, total] = await InspectionService.getAllSortedNotHavingNewer({ offset, count, noLimit }); + + res.json({ + inspections: InspectionFactory.mapToBase(inspections), + total: total, + offset: offset, + count: count, + }); +} + +/** + * @description get all inspections running + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getAllInspectionsRunning(req: Request, res: Response): Promise { + let offset = parseInt((req.query.offset as string) ?? "0"); + let count = parseInt((req.query.count as string) ?? "25"); + let noLimit = req.query.noLimit === "true"; + + let [inspections, total] = await InspectionService.getAllRunning({ offset, count, noLimit }); + + res.json({ + inspections: InspectionFactory.mapToBase(inspections), + total: total, + offset: offset, + count: count, + }); +} /** * @description get all inspections for related id @@ -111,7 +154,10 @@ export async function updateInspectionById(req: Request, res: Response): Promise export async function deleteInspectionById(req: Request, res: Response): Promise { const inspectionId = req.params.id; - // TODO finished inspection cannot be deleted + 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, diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index 16aae27..f49b92d 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -24,6 +24,9 @@ export class inspection { @Column({ type: getTypeByORM("date").type as ColumnType, nullable: true, default: null }) nextInspection?: Date; + @Column({ type: "boolean", default: false }) + hasNewer: boolean; + @Column() inspectionPlanId: string; diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index 2b827fc..87af919 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -94,6 +94,7 @@ export const inspection_table = new Table({ { name: "createdAt", ...getTypeByORM("datetime"), default: getDefaultByORM("currentTimestamp") }, { name: "finishedAt", ...getTypeByORM("date", 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) }, diff --git a/src/routes/admin/unit/inspection.ts b/src/routes/admin/unit/inspection.ts index 41694ea..57f6883 100644 --- a/src/routes/admin/unit/inspection.ts +++ b/src/routes/admin/unit/inspection.ts @@ -3,13 +3,23 @@ import PermissionHelper from "../../../helpers/permissionHelper"; import { createInspection, deleteInspectionById, + getAllInspectionsSortedNotHavingNewer, getAllInspectionsForRelated, getInspectionById, updateInspectionById, + getAllInspectionsRunning, } from "../../../controller/admin/unit/inspectionController"; 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) => { diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index c4c8b1d..7de9af8 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -1,3 +1,4 @@ +import { IsNull } from "typeorm"; import { dataSource } from "../../../data-source"; import { inspection } from "../../../entity/unit/inspection/inspection"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -16,6 +17,66 @@ export default abstract class InspectionService { .leftJoinAndSelect("inspection.vehicle", "vehicle") .leftJoinAndSelect("inspection.wearable", "wearable"); + /** + * @description get all inspections sorted by next inspection not having newer + * @returns {Promise>} + */ + static async getAllSortedNotHavingNewer({ + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + }): Promise<[Array, number]> { + let query = this.query().where({ hasNewer: false }); + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("inspection.nextInspection", "ASC", "NULLS LAST") + .getManyAndCount() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspection", err); + }); + } + + /** + * @description get all inspections running + * @returns {Promise>} + */ + static async getAllRunning({ + offset = 0, + count = 25, + noLimit = false, + }: { + offset?: number; + count?: number; + noLimit?: boolean; + }): Promise<[Array, number]> { + let query = this.query().where({ finishedAt: IsNull() }); + + if (!noLimit) { + query = query.offset(offset).limit(count); + } + + return await query + .orderBy("inspection.createdAt", "ASC") + .getManyAndCount() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspection", err); + }); + } + /** * @description get all inspections for related * @returns {Promise>} From db3004fa04449a8fc77c857b5b3e0292041a6fcf Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 9 Jul 2025 16:01:44 +0200 Subject: [PATCH 26/34] update or create inspection versioned plan --- .../unit/inspection/inspectionPointCommand.ts | 4 +- .../inspectionPointCommandHandler.ts | 39 +++++++++++++++ .../inspectionVersionedPlanCommandHandler.ts | 48 +++++++++++++++---- .../admin/unit/inspectionPlanController.ts | 48 +++++++++++++++++++ src/entity/unit/inspection/inspectionPoint.ts | 3 ++ src/enums/inspectionEnum.ts | 1 + .../admin/unit/inspection/inspectionPoint.ts | 1 + src/migrations/1752063536385-test.ts | 44 +++++++++++++++++ src/migrations/baseSchemaTables/inspection.ts | 1 + src/routes/admin/unit/inspectionPlan.ts | 14 ++++++ .../unit/inspection/inspectionService.ts | 18 +++++++ .../inspectionVersionedPlanService.ts | 18 +++++++ .../unit/inspection/inspectionPlan.models.ts | 1 + 13 files changed, 229 insertions(+), 11 deletions(-) create mode 100644 src/migrations/1752063536385-test.ts diff --git a/src/command/unit/inspection/inspectionPointCommand.ts b/src/command/unit/inspection/inspectionPointCommand.ts index 5aa45a6..8163bae 100644 --- a/src/command/unit/inspection/inspectionPointCommand.ts +++ b/src/command/unit/inspection/inspectionPointCommand.ts @@ -1,11 +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; + versionedPointId?: string; } diff --git a/src/command/unit/inspection/inspectionPointCommandHandler.ts b/src/command/unit/inspection/inspectionPointCommandHandler.ts index 749f325..2a46ae1 100644 --- a/src/command/unit/inspection/inspectionPointCommandHandler.ts +++ b/src/command/unit/inspection/inspectionPointCommandHandler.ts @@ -1,6 +1,7 @@ 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 { @@ -31,4 +32,42 @@ export default abstract class InspectionPointCommandHandler { throw new DatabaseActionException("CREATE", "inspectionPoint", err); }); } + + /** + * @description sync points + * @param {string} versionedPlanId + * @param {Array} sync + * @returns {Promise} + */ + static async sync(versionedPlanId: string, sync: Array): Promise { + 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, + 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); + }); + } } diff --git a/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts b/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts index 9c9710b..decbba2 100644 --- a/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts +++ b/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts @@ -1,25 +1,53 @@ 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} + * @returns {Promise} */ - static async create(createInspectionVersionedPlan: CreateInspectionVersionedPlanCommand): Promise { + static async create( + createInspectionVersionedPlan: CreateInspectionVersionedPlanCommand, + inspectionPoints: Array + ): Promise { + let count = await InspectionVersionedPlanService.countForPlanId(createInspectionVersionedPlan.inspectionPlanId); + let returnId = ""; + return await dataSource - .createQueryBuilder() - .insert() - .into(inspectionVersionedPlan) - .values({ - inspectionPlanId: createInspectionVersionedPlan.inspectionPlanId, + .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) => ({ + ...ip, + versionedPlanId: returnId, + })) + ) + .execute(); }) - .execute() - .then((result) => { - return result.identifiers[0].id; + .then(() => { + return returnId; }) .catch((err) => { throw new DatabaseActionException("CREATE", "inspectionVersionedPlan", err); diff --git a/src/controller/admin/unit/inspectionPlanController.ts b/src/controller/admin/unit/inspectionPlanController.ts index a913e2b..69e3e1e 100644 --- a/src/controller/admin/unit/inspectionPlanController.ts +++ b/src/controller/admin/unit/inspectionPlanController.ts @@ -9,6 +9,11 @@ import { 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 @@ -78,6 +83,25 @@ export async function getAllInspectionPlansForRelated(req: Request, res: Respons }); } +/** + * @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 { + 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 @@ -148,6 +172,30 @@ export async function updateInspectionPlanById(req: Request, res: Response): Pro 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 { + 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 diff --git a/src/entity/unit/inspection/inspectionPoint.ts b/src/entity/unit/inspection/inspectionPoint.ts index 4995bc8..84c0a80 100644 --- a/src/entity/unit/inspection/inspectionPoint.ts +++ b/src/entity/unit/inspection/inspectionPoint.ts @@ -33,6 +33,9 @@ export class inspectionPoint { @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; diff --git a/src/enums/inspectionEnum.ts b/src/enums/inspectionEnum.ts index 5c87e55..58143e6 100644 --- a/src/enums/inspectionEnum.ts +++ b/src/enums/inspectionEnum.ts @@ -2,4 +2,5 @@ export enum InspectionPointEnum { oknok = "oknok", text = "text", number = "number", + file = "file", } diff --git a/src/factory/admin/unit/inspection/inspectionPoint.ts b/src/factory/admin/unit/inspection/inspectionPoint.ts index 1f6150c..b494542 100644 --- a/src/factory/admin/unit/inspection/inspectionPoint.ts +++ b/src/factory/admin/unit/inspection/inspectionPoint.ts @@ -16,6 +16,7 @@ export default abstract class InspectionPointFactory { sort: record.sort, min: record?.min, max: record?.max, + others: record?.others, }; } diff --git a/src/migrations/1752063536385-test.ts b/src/migrations/1752063536385-test.ts new file mode 100644 index 0000000..2760925 --- /dev/null +++ b/src/migrations/1752063536385-test.ts @@ -0,0 +1,44 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Test1752063536385 implements MigrationInterface { + name = 'Test1752063536385' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_view","public"]); + await queryRunner.query(`DROP VIEW "membership_view"`); + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_total_view","public"]); + await queryRunner.query(`DROP VIEW "membership_total_view"`); + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_qualifications_view","public"]); + await queryRunner.query(`DROP VIEW "member_qualifications_view"`); + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_executive_positions_view","public"]); + await queryRunner.query(`DROP VIEW "member_executive_positions_view"`); + await queryRunner.query(`CREATE VIEW "member_executive_positions_view" AS SELECT "executivePosition"."id" AS "positionId", "executivePosition"."position" AS "position", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")) AS "exactDuration" FROM "member_executive_positions" "memberExecutivePositions" LEFT JOIN "executive_position" "executivePosition" ON "executivePosition"."id"="memberExecutivePositions"."executivePositionId" LEFT JOIN "member" "member" ON "member"."id"="memberExecutivePositions"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "executivePosition"."id", "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_executive_positions_view","SELECT \"executivePosition\".\"id\" AS \"positionId\", \"executivePosition\".\"position\" AS \"position\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE) - \"memberExecutivePositions\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\")) AS \"exactDuration\" FROM \"member_executive_positions\" \"memberExecutivePositions\" LEFT JOIN \"executive_position\" \"executivePosition\" ON \"executivePosition\".\"id\"=\"memberExecutivePositions\".\"executivePositionId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberExecutivePositions\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"executivePosition\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); + await queryRunner.query(`CREATE VIEW "member_qualifications_view" AS SELECT "qualification"."id" AS "qualificationId", "qualification"."qualification" AS "qualification", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")) AS "exactDuration" FROM "member_qualifications" "memberQualifications" LEFT JOIN "qualification" "qualification" ON "qualification"."id"="memberQualifications"."qualificationId" LEFT JOIN "member" "member" ON "member"."id"="memberQualifications"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "qualification"."id", "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_qualifications_view","SELECT \"qualification\".\"id\" AS \"qualificationId\", \"qualification\".\"qualification\" AS \"qualification\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE) - \"memberQualifications\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\")) AS \"exactDuration\" FROM \"member_qualifications\" \"memberQualifications\" LEFT JOIN \"qualification\" \"qualification\" ON \"qualification\".\"id\"=\"memberQualifications\".\"qualificationId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberQualifications\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"qualification\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); + await queryRunner.query(`CREATE VIEW "membership_view" AS SELECT "status"."id" AS "statusId", "status"."status" AS "status", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "status"."id", "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_view","SELECT \"status\".\"id\" AS \"statusId\", \"status\".\"status\" AS \"status\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"status\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); + await queryRunner.query(`CREATE VIEW "membership_total_view" AS SELECT "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_total_view","SELECT \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"member\".\"id\", \"salutation\".\"id\""]); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_total_view","public"]); + await queryRunner.query(`DROP VIEW "membership_total_view"`); + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_view","public"]); + await queryRunner.query(`DROP VIEW "membership_view"`); + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_qualifications_view","public"]); + await queryRunner.query(`DROP VIEW "member_qualifications_view"`); + await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_executive_positions_view","public"]); + await queryRunner.query(`DROP VIEW "member_executive_positions_view"`); + await queryRunner.query(`CREATE VIEW "member_executive_positions_view" AS SELECT "executivePosition"."id" AS "positionId", "executivePosition"."position" AS "position", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")) AS "exactDuration" FROM "member_executive_positions" "memberExecutivePositions" LEFT JOIN "executive_position" "executivePosition" ON "executivePosition"."id"="memberExecutivePositions"."executivePositionId" LEFT JOIN "member" "member" ON "member"."id"="memberExecutivePositions"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "executivePosition"."id", "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_executive_positions_view","SELECT \"executivePosition\".\"id\" AS \"positionId\", \"executivePosition\".\"position\" AS \"position\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE) - \"memberExecutivePositions\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\")) AS \"exactDuration\" FROM \"member_executive_positions\" \"memberExecutivePositions\" LEFT JOIN \"executive_position\" \"executivePosition\" ON \"executivePosition\".\"id\"=\"memberExecutivePositions\".\"executivePositionId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberExecutivePositions\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"executivePosition\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); + await queryRunner.query(`CREATE VIEW "member_qualifications_view" AS SELECT "qualification"."id" AS "qualificationId", "qualification"."qualification" AS "qualification", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")) AS "exactDuration" FROM "member_qualifications" "memberQualifications" LEFT JOIN "qualification" "qualification" ON "qualification"."id"="memberQualifications"."qualificationId" LEFT JOIN "member" "member" ON "member"."id"="memberQualifications"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "qualification"."id", "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_qualifications_view","SELECT \"qualification\".\"id\" AS \"qualificationId\", \"qualification\".\"qualification\" AS \"qualification\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE) - \"memberQualifications\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\")) AS \"exactDuration\" FROM \"member_qualifications\" \"memberQualifications\" LEFT JOIN \"qualification\" \"qualification\" ON \"qualification\".\"id\"=\"memberQualifications\".\"qualificationId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberQualifications\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"qualification\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); + await queryRunner.query(`CREATE VIEW "membership_total_view" AS SELECT "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_total_view","SELECT \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"member\".\"id\", \"salutation\".\"id\""]); + await queryRunner.query(`CREATE VIEW "membership_view" AS SELECT "status"."id" AS "statusId", "status"."status" AS "status", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "status"."id", "member"."id", "salutation"."id"`); + await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_view","SELECT \"status\".\"id\" AS \"statusId\", \"status\".\"status\" AS \"status\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"status\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); + } + +} diff --git a/src/migrations/baseSchemaTables/inspection.ts b/src/migrations/baseSchemaTables/inspection.ts index 87af919..fad995f 100644 --- a/src/migrations/baseSchemaTables/inspection.ts +++ b/src/migrations/baseSchemaTables/inspection.ts @@ -72,6 +72,7 @@ export const inspection_point_table = new Table({ { 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") }, ], diff --git a/src/routes/admin/unit/inspectionPlan.ts b/src/routes/admin/unit/inspectionPlan.ts index 0aaf46a..4fbab19 100644 --- a/src/routes/admin/unit/inspectionPlan.ts +++ b/src/routes/admin/unit/inspectionPlan.ts @@ -6,7 +6,9 @@ import { getAllInspectionPlans, getAllInspectionPlansForRelated, getInspectionPlanById, + getInspectionPointsByPlanId, updateInspectionPlanById, + updateInspectionPointsByPlanId, } from "../../../controller/admin/unit/inspectionPlanController"; var router = express.Router({ mergeParams: true }); @@ -15,6 +17,10 @@ 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( ["/vehicle/:relatedId", "/equipment/:relatedId", "/wearable/:relatedId"], async (req: Request, res: Response) => { @@ -50,6 +56,14 @@ router.patch( } ); +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"), diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index 7de9af8..e31ad0e 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -125,4 +125,22 @@ export default abstract class InspectionService { throw new DatabaseActionException("SELECT", "inspection", err); }); } + + /** + * @description uses versionedPlan + * @returns {Promise} + */ + static async usesVersionedInspectionPlan(inspectionVersionedPlanId: string): Promise { + return await dataSource + .getRepository(inspection) + .createQueryBuilder("inspection") + .where({ inspectionVersionedPlanId }) + .getExists() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "used inspection", err); + }); + } } diff --git a/src/service/unit/inspection/inspectionVersionedPlanService.ts b/src/service/unit/inspection/inspectionVersionedPlanService.ts index 55eab31..00f7500 100644 --- a/src/service/unit/inspection/inspectionVersionedPlanService.ts +++ b/src/service/unit/inspection/inspectionVersionedPlanService.ts @@ -62,4 +62,22 @@ export default abstract class InspectionVersionedPlanService { throw new DatabaseActionException("SELECT", "inspectionVersionedPlan", err); }); } + + /** + * @description count for plan id + * @returns {Promise} + */ + static async countForPlanId(planId: string): Promise { + return await dataSource + .getRepository(inspectionVersionedPlan) + .createQueryBuilder("inspectionVersionedPlan") + .where({ inspectionPlanId: planId }) + .getCount() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionVersionedPlan", err); + }); + } } diff --git a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts index 30706a7..67d7957 100644 --- a/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspectionPlan.models.ts @@ -48,5 +48,6 @@ export interface InspectionPointViewModel { type: InspectionPointEnum; min?: number; max?: number; + others?: string; sort: number; } From 8747baaf2e98240c46d638bf5d95b4535fe81dd9 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Thu, 10 Jul 2025 10:49:30 +0200 Subject: [PATCH 27/34] corrections in plan update and fetch --- .../unit/inspection/inspectionPointCommandHandler.ts | 1 + .../inspection/inspectionVersionedPlanCommandHandler.ts | 8 +++++++- .../admin/unit/inspection/inspectionPointResult.ts | 1 - src/service/unit/inspection/inspectionService.ts | 3 +++ src/viewmodel/admin/unit/inspection/inspection.models.ts | 1 - 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/command/unit/inspection/inspectionPointCommandHandler.ts b/src/command/unit/inspection/inspectionPointCommandHandler.ts index 2a46ae1..a704f04 100644 --- a/src/command/unit/inspection/inspectionPointCommandHandler.ts +++ b/src/command/unit/inspection/inspectionPointCommandHandler.ts @@ -51,6 +51,7 @@ export default abstract class InspectionPointCommandHandler { .values( sync.map((s) => ({ ...s, + id: points.some((p) => p.id == s.id) ? s.id : undefined, versionedPlanId, })) ) diff --git a/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts b/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts index decbba2..151aa16 100644 --- a/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts +++ b/src/command/unit/inspection/inspectionVersionedPlanCommandHandler.ts @@ -40,7 +40,13 @@ export default abstract class InspectionVersionedPlanCommandHandler { .into(inspectionPoint) .values( inspectionPoints.map((ip) => ({ - ...ip, + title: ip.title, + description: ip.description, + type: ip.type, + min: ip.min, + max: ip.max, + others: ip.others, + sort: ip.sort, versionedPlanId: returnId, })) ) diff --git a/src/factory/admin/unit/inspection/inspectionPointResult.ts b/src/factory/admin/unit/inspection/inspectionPointResult.ts index b258a6a..e210e57 100644 --- a/src/factory/admin/unit/inspection/inspectionPointResult.ts +++ b/src/factory/admin/unit/inspection/inspectionPointResult.ts @@ -11,7 +11,6 @@ export default abstract class InspectionPointResultFactory { public static mapToSingle(record: inspectionPointResult): InspectionPointResultViewModel { return { inspectionId: record.inspectionId, - inspectionVersionedPlanId: record.inspection.inspectionVersionedPlanId, inspectionPointId: record.inspectionPointId, inspectionPoint: InspectionPointFactory.mapToSingle(record.inspectionPoint), value: record.value, diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index e31ad0e..fbbe081 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -9,6 +9,9 @@ export default abstract class InspectionService { .getRepository(inspection) .createQueryBuilder("inspection") .leftJoinAndSelect("inspection.inspectionPlan", "inspectionPlan") + .leftJoinAndSelect("inspectionPlan.equipmentType", "equipmentType") + .leftJoinAndSelect("inspectionPlan.vehicleType", "vehicleType") + .leftJoinAndSelect("inspectionPlan.wearableType", "wearableType") .leftJoinAndSelect("inspection.inspectionVersionedPlan", "inspectionVersionedPlan") .leftJoinAndSelect("inspectionVersionedPlan.inspectionPoints", "inspectionPoints") .leftJoinAndSelect("inspection.pointResults", "pointResults") diff --git a/src/viewmodel/admin/unit/inspection/inspection.models.ts b/src/viewmodel/admin/unit/inspection/inspection.models.ts index 4d18e7c..7efdede 100644 --- a/src/viewmodel/admin/unit/inspection/inspection.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspection.models.ts @@ -40,7 +40,6 @@ export type InspectionViewModel = { export interface InspectionPointResultViewModel { inspectionId: string; - inspectionVersionedPlanId: string; inspectionPointId: string; inspectionPoint: InspectionPointViewModel; value: string; From 705297ba5013b17a204cf5078fdd027ba49fbf18 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Thu, 10 Jul 2025 13:22:29 +0200 Subject: [PATCH 28/34] next and running inspections --- .../unit/inspection/inspectionCommand.ts | 2 +- .../inspection/inspectionCommandHandler.ts | 9 ++- .../admin/unit/inspectionController.ts | 11 ++- .../admin/unit/inspection/inspection.ts | 75 ++++++++++++++++++- .../unit/inspection/inspectionService.ts | 32 +++++++- .../unit/inspection/inspection.models.ts | 20 +++++ 6 files changed, 142 insertions(+), 7 deletions(-) diff --git a/src/command/unit/inspection/inspectionCommand.ts b/src/command/unit/inspection/inspectionCommand.ts index 1c020fb..e3a7b9d 100644 --- a/src/command/unit/inspection/inspectionCommand.ts +++ b/src/command/unit/inspection/inspectionCommand.ts @@ -3,7 +3,7 @@ export interface CreateInspectionCommand { nextInspection?: Date; inspectionPlanId: string; relatedId: string; - assigned: "vehicle" | "equipment"; + assigned: "vehicle" | "equipment" | "wearable"; } export interface UpdateInspectionCommand { diff --git a/src/command/unit/inspection/inspectionCommandHandler.ts b/src/command/unit/inspection/inspectionCommandHandler.ts index 34b7bf5..f287625 100644 --- a/src/command/unit/inspection/inspectionCommandHandler.ts +++ b/src/command/unit/inspection/inspectionCommandHandler.ts @@ -1,4 +1,4 @@ -import { Not } from "typeorm"; +import { IsNull, Not } from "typeorm"; import { dataSource } from "../../../data-source"; import { inspection } from "../../../entity/unit/inspection/inspection"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -25,6 +25,12 @@ export default abstract class InspectionCommandHandler { .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 @@ -38,6 +44,7 @@ export default abstract class InspectionCommandHandler { 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) => { diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index f98f4c5..fc126cd 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -24,7 +24,7 @@ export async function getAllInspectionsSortedNotHavingNewer(req: Request, res: R let [inspections, total] = await InspectionService.getAllSortedNotHavingNewer({ offset, count, noLimit }); res.json({ - inspections: InspectionFactory.mapToBase(inspections), + inspections: InspectionFactory.mapToBaseNext(inspections), total: total, offset: offset, count: count, @@ -45,7 +45,7 @@ export async function getAllInspectionsRunning(req: Request, res: Response): Pro let [inspections, total] = await InspectionService.getAllRunning({ offset, count, noLimit }); res.json({ - inspections: InspectionFactory.mapToBase(inspections), + inspections: InspectionFactory.mapToBaseMinified(inspections), total: total, offset: offset, count: count, @@ -112,6 +112,13 @@ export async function createInspection(req: Request, res: Response): Promise): Array { 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, + finished: record?.finishedAt, + isOpen: record?.finishedAt == undefined, + nextInspection: record?.nextInspection, + ...related, + }; + } + + /** + * @description map records to minified inspection + * @param {Array} records + * @returns {Array} + */ + public static mapToBaseMinified(records: Array): Array { + 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} records + * @returns {Array} + */ + public static mapToBaseNext(records: Array): Array { + return records.map((r) => this.mapToSingleNext(r)); + } } diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index fbbe081..6e4e79b 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -1,4 +1,4 @@ -import { IsNull } from "typeorm"; +import { IsNull, Not } from "typeorm"; import { dataSource } from "../../../data-source"; import { inspection } from "../../../entity/unit/inspection/inspection"; import DatabaseActionException from "../../../exceptions/databaseActionException"; @@ -129,6 +129,36 @@ export default abstract class InspectionService { }); } + /** + * @description uses versionedPlan + * @returns {Promise} + */ + static async existsUnfinishedInspectionToPlan( + inspectionPlanId: string, + relation: "vehicle" | "equipment" | "wearable", + relationId: string + ): Promise { + let where: { equipmentId: string } | { vehicleId: string } | { wearableId: string }; + if (relation == "equipment") { + where = { equipmentId: relationId }; + } else if (relation == "vehicle") { + where = { vehicleId: relationId }; + } else { + where = { wearableId: relationId }; + } + return await dataSource + .getRepository(inspection) + .createQueryBuilder("inspection") + .where({ inspectionPlanId, finishedAt: IsNull(), ...where }) + .getExists() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "used inspection", err); + }); + } + /** * @description uses versionedPlan * @returns {Promise} diff --git a/src/viewmodel/admin/unit/inspection/inspection.models.ts b/src/viewmodel/admin/unit/inspection/inspection.models.ts index 7efdede..87af590 100644 --- a/src/viewmodel/admin/unit/inspection/inspection.models.ts +++ b/src/viewmodel/admin/unit/inspection/inspection.models.ts @@ -38,6 +38,26 @@ export type InspectionViewModel = { checks: Array; } & InspectionRelated; +export type MinifiedInspectionViewModel = { + id: string; + inspectionPlanId: string; + inspectionPlan: InspectionPlanViewModel; + context: string; + created: Date; + finished?: Date; + isOpen: boolean; + nextInspection?: Date; + relatedId: string; +} & InspectionRelated; + +export type InspectionNextViewModel = { + id: string; + inspectionPlanId: string; + inspectionPlan: InspectionPlanViewModel; + dueDate: Date; + relatedId: string; +} & InspectionRelated; + export interface InspectionPointResultViewModel { inspectionId: string; inspectionPointId: string; From c42a41d89565872c735e94ba5a214481ea5d12a7 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 11 Jul 2025 09:33:37 +0200 Subject: [PATCH 29/34] count instances to type --- src/entity/unit/equipment/equipmentType.ts | 2 ++ src/entity/unit/vehicle/vehicleType.ts | 2 ++ src/entity/unit/wearable/wearableType.ts | 2 ++ src/factory/admin/unit/equipment/equipmentType.ts | 1 + src/factory/admin/unit/vehicle/vehicleType.ts | 1 + src/factory/admin/unit/wearable/wearableType.ts | 1 + src/service/unit/equipment/equipmentTypeService.ts | 5 ++++- src/service/unit/vehicle/vehicleTypeService.ts | 5 ++++- src/service/unit/wearable/wearableTypeService.ts | 5 ++++- src/viewmodel/admin/unit/equipment/equipmentType.models.ts | 1 + src/viewmodel/admin/unit/vehicle/vehicleType.models.ts | 1 + src/viewmodel/admin/unit/wearable/wearableType.models.ts | 1 + 12 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts index 3d0b134..1739cfa 100644 --- a/src/entity/unit/equipment/equipmentType.ts +++ b/src/entity/unit/equipment/equipmentType.ts @@ -18,4 +18,6 @@ export class equipmentType { @OneToMany(() => inspectionPlan, (ip) => ip.equipmentType) inspectionPlans: inspectionPlan[]; + + equipmentCount: number; } diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts index a3e3403..2e83b23 100644 --- a/src/entity/unit/vehicle/vehicleType.ts +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -18,4 +18,6 @@ export class vehicleType { @OneToMany(() => inspectionPlan, (ip) => ip.vehicleType) inspectionPlans: inspectionPlan[]; + + vehicleCount: number; } diff --git a/src/entity/unit/wearable/wearableType.ts b/src/entity/unit/wearable/wearableType.ts index 15ae351..099ed26 100644 --- a/src/entity/unit/wearable/wearableType.ts +++ b/src/entity/unit/wearable/wearableType.ts @@ -18,4 +18,6 @@ export class wearableType { @OneToMany(() => inspectionPlan, (ip) => ip.wearableType) inspectionPlans: inspectionPlan[]; + + wearableCount: number; } diff --git a/src/factory/admin/unit/equipment/equipmentType.ts b/src/factory/admin/unit/equipment/equipmentType.ts index 6e84107..6906215 100644 --- a/src/factory/admin/unit/equipment/equipmentType.ts +++ b/src/factory/admin/unit/equipment/equipmentType.ts @@ -12,6 +12,7 @@ export default abstract class EquipmentTypeFactory { id: record.id, type: record.type, description: record.description, + equipmentCount: record.equipmentCount, }; } diff --git a/src/factory/admin/unit/vehicle/vehicleType.ts b/src/factory/admin/unit/vehicle/vehicleType.ts index 6155ca1..b282b79 100644 --- a/src/factory/admin/unit/vehicle/vehicleType.ts +++ b/src/factory/admin/unit/vehicle/vehicleType.ts @@ -12,6 +12,7 @@ export default abstract class VehicleTypeFactory { id: record.id, type: record.type, description: record.description, + vehicleCount: record.vehicleCount, }; } diff --git a/src/factory/admin/unit/wearable/wearableType.ts b/src/factory/admin/unit/wearable/wearableType.ts index b574bae..89c1066 100644 --- a/src/factory/admin/unit/wearable/wearableType.ts +++ b/src/factory/admin/unit/wearable/wearableType.ts @@ -12,6 +12,7 @@ export default abstract class WearableTypeFactory { id: record.id, type: record.type, description: record.description, + wearableCount: record.wearableCount, }; } diff --git a/src/service/unit/equipment/equipmentTypeService.ts b/src/service/unit/equipment/equipmentTypeService.ts index b85b9f1..16a9527 100644 --- a/src/service/unit/equipment/equipmentTypeService.ts +++ b/src/service/unit/equipment/equipmentTypeService.ts @@ -19,7 +19,10 @@ export default abstract class EquipmentTypeService { search?: string; noLimit?: boolean; }): Promise<[Array, number]> { - let query = dataSource.getRepository(equipmentType).createQueryBuilder("equipmentType"); + let query = dataSource + .getRepository(equipmentType) + .createQueryBuilder("equipmentType") + .loadRelationCountAndMap("equipmentType.equipmentCount", "equipmentType.equipment"); if (search != "") { query = query.where({ diff --git a/src/service/unit/vehicle/vehicleTypeService.ts b/src/service/unit/vehicle/vehicleTypeService.ts index c1dbdf2..438d46b 100644 --- a/src/service/unit/vehicle/vehicleTypeService.ts +++ b/src/service/unit/vehicle/vehicleTypeService.ts @@ -19,7 +19,10 @@ export default abstract class VehicleTypeService { search?: string; noLimit?: boolean; }): Promise<[Array, number]> { - let query = dataSource.getRepository(vehicleType).createQueryBuilder("vehicleType"); + let query = dataSource + .getRepository(vehicleType) + .createQueryBuilder("vehicleType") + .loadRelationCountAndMap("vehicleType.vehicleCount", "vehicleType.vehicle"); if (search != "") { query = query.where({ diff --git a/src/service/unit/wearable/wearableTypeService.ts b/src/service/unit/wearable/wearableTypeService.ts index cd91a26..a9f06f3 100644 --- a/src/service/unit/wearable/wearableTypeService.ts +++ b/src/service/unit/wearable/wearableTypeService.ts @@ -19,7 +19,10 @@ export default abstract class WearableTypeService { search?: string; noLimit?: boolean; }): Promise<[Array, number]> { - let query = dataSource.getRepository(wearableType).createQueryBuilder("wearableType"); + let query = dataSource + .getRepository(wearableType) + .createQueryBuilder("wearableType") + .loadRelationCountAndMap("wearableType.wearableCount", "wearableType.wearable"); if (search != "") { query = query.where({ diff --git a/src/viewmodel/admin/unit/equipment/equipmentType.models.ts b/src/viewmodel/admin/unit/equipment/equipmentType.models.ts index 05ad905..b7a1648 100644 --- a/src/viewmodel/admin/unit/equipment/equipmentType.models.ts +++ b/src/viewmodel/admin/unit/equipment/equipmentType.models.ts @@ -2,4 +2,5 @@ export interface EquipmentTypeViewModel { id: string; type: string; description: string; + equipmentCount: number; } diff --git a/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts b/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts index 726311e..a005853 100644 --- a/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts +++ b/src/viewmodel/admin/unit/vehicle/vehicleType.models.ts @@ -2,4 +2,5 @@ export interface VehicleTypeViewModel { id: string; type: string; description: string; + vehicleCount: number; } diff --git a/src/viewmodel/admin/unit/wearable/wearableType.models.ts b/src/viewmodel/admin/unit/wearable/wearableType.models.ts index 73fd7c5..0c15a26 100644 --- a/src/viewmodel/admin/unit/wearable/wearableType.models.ts +++ b/src/viewmodel/admin/unit/wearable/wearableType.models.ts @@ -2,4 +2,5 @@ export interface WearableTypeViewModel { id: string; type: string; description: string; + wearableCount: number; } From 0f3e4488f4f0cb5c6ac8503e58c91f7194c5d0e4 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 11 Jul 2025 09:42:04 +0200 Subject: [PATCH 30/34] correct type inspectionPlans request --- .../admin/unit/inspectionPlanController.ts | 14 +++++++------- src/routes/admin/unit/inspectionPlan.ts | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/controller/admin/unit/inspectionPlanController.ts b/src/controller/admin/unit/inspectionPlanController.ts index 69e3e1e..1165485 100644 --- a/src/controller/admin/unit/inspectionPlanController.ts +++ b/src/controller/admin/unit/inspectionPlanController.ts @@ -51,8 +51,8 @@ export async function getAllInspectionPlans(req: Request, res: Response): Promis * @returns {Promise<*>} */ export async function getAllInspectionPlansForRelated(req: Request, res: Response): Promise { - let relation = req.params.related as "vehicle" | "equipment" | "wearable"; - let relationId = req.params.relatedId as string; + 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) ?? ""; @@ -60,12 +60,12 @@ export async function getAllInspectionPlansForRelated(req: Request, res: Respons let ids = ((req.query.ids ?? "") as string).split(",").filter((i) => i); let where; - if (relation == "equipment") { - where = { equipmentTypeId: relationId }; - } else if (relation == "vehicle") { - where = { vehicleTypeId: relationId }; + if (relation == "equipmentType") { + where = { equipmentTypeId: relationTypeId }; + } else if (relation == "vehicleType") { + where = { vehicleTypeId: relationTypeId }; } else { - where = { wearableTypeId: relationId }; + where = { wearableTypeId: relationTypeId }; } let [inspectionPlans, total] = await InspectionPlanService.getAllForRelated(where, { offset, diff --git a/src/routes/admin/unit/inspectionPlan.ts b/src/routes/admin/unit/inspectionPlan.ts index 4fbab19..914d9d3 100644 --- a/src/routes/admin/unit/inspectionPlan.ts +++ b/src/routes/admin/unit/inspectionPlan.ts @@ -22,14 +22,14 @@ router.get("/:id/points", async (req: Request, res: Response) => { }); router.get( - ["/vehicle/:relatedId", "/equipment/:relatedId", "/wearable/:relatedId"], + ["/vehicleType/:relatedTypeId", "/equipmentType/:relatedTypeId", "/wearableType/:relatedTypeId"], async (req: Request, res: Response) => { - if (req.path.startsWith("/vehicle")) { - req.params.related = "vehicle"; - } else if (req.path.startsWith("/equipment")) { - req.params.related = "equipment"; + if (req.path.startsWith("/vehicleType")) { + req.params.related = "vehicleType"; + } else if (req.path.startsWith("/equipmentType")) { + req.params.related = "equipmentType"; } else { - req.params.related = "wearable"; + req.params.related = "wearableType"; } await getAllInspectionPlansForRelated(req, res); From 9ef82adef74f15d3f773a2e16b599d519de6b00e Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Fri, 11 Jul 2025 14:02:36 +0200 Subject: [PATCH 31/34] inspection finish and print --- .../unit/inspection/inspectionCommand.ts | 4 + .../inspection/inspectionCommandHandler.ts | 72 ++++++---- .../inspectionPointResultCommand.ts | 2 +- .../inspectionPointResultCommandHandler.ts | 31 ++++- .../admin/unit/inspectionController.ts | 131 +++++++++++++++++- src/middleware/multer.ts | 25 ++++ src/migrations/1749361405703-UnitBase.ts | 21 +++ src/migrations/1752063536385-test.ts | 44 ------ src/routes/admin/unit/inspection.ts | 25 ++++ .../unit/inspection/inspectionService.ts | 16 ++- src/templates/inspection.body.template.html | 62 +++++++++ src/type/templateTypes.ts | 1 + 12 files changed, 358 insertions(+), 76 deletions(-) delete mode 100644 src/migrations/1752063536385-test.ts create mode 100644 src/templates/inspection.body.template.html diff --git a/src/command/unit/inspection/inspectionCommand.ts b/src/command/unit/inspection/inspectionCommand.ts index e3a7b9d..254d690 100644 --- a/src/command/unit/inspection/inspectionCommand.ts +++ b/src/command/unit/inspection/inspectionCommand.ts @@ -12,6 +12,10 @@ export interface UpdateInspectionCommand { nextInspection?: Date; } +export interface FinishInspectionCommand { + id: string; +} + export interface DeleteInspectionCommand { id: string; } diff --git a/src/command/unit/inspection/inspectionCommandHandler.ts b/src/command/unit/inspection/inspectionCommandHandler.ts index f287625..f6156b3 100644 --- a/src/command/unit/inspection/inspectionCommandHandler.ts +++ b/src/command/unit/inspection/inspectionCommandHandler.ts @@ -4,7 +4,12 @@ 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 } from "./inspectionCommand"; +import { + CreateInspectionCommand, + UpdateInspectionCommand, + DeleteInspectionCommand, + FinishInspectionCommand, +} from "./inspectionCommand"; export default abstract class InspectionCommandHandler { /** @@ -80,6 +85,26 @@ export default abstract class InspectionCommandHandler { }); } + /** + * @description finish inspection + * @param {FinishInspectionCommand} finishInspection + * @returns {Promise} + */ + static async finish(finishInspection: FinishInspectionCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(inspection) + .set({ + finishedAt: new Date(), + }) + .where("id = :id", { id: finishInspection.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new DatabaseActionException("FINISH", "inspection", err); + }); + } + /** * @description delete inspection * @param {DeleteInspectionCommand} deleteInspection @@ -89,31 +114,30 @@ export default abstract class InspectionCommandHandler { let deleteInspectionData = await InspectionService.getById(deleteInspection.id); return await dataSource .transaction(async (manager) => { - await manager + let latestInspection = await manager .createQueryBuilder() - .update(inspection) - .set({ - hasNewer: false, + .from(inspection, "sub") + .where({ + inspectionPlanId: deleteInspectionData.inspectionPlanId, + inspectionVersionedPlanId: deleteInspectionData.inspectionVersionedPlanId, + equipmentId: deleteInspectionData.equipmentId ?? IsNull(), + vehicleId: deleteInspectionData.vehicleId ?? IsNull(), + wearableId: deleteInspectionData.wearableId ?? IsNull(), }) - .where((qb) => { - const subQuery = qb - .createQueryBuilder() - .select("id") - .from(inspection, "sub") - .where({ - inspectionPlanId: deleteInspectionData.inspectionPlanId, - inspectionVersionedPlanId: deleteInspectionData.inspectionVersionedPlanId, - equipmentId: deleteInspectionData.equipmentId, - vehicleId: deleteInspectionData.vehicleId, - wearableId: deleteInspectionData.wearableId, - }) - .andWhere({ id: Not(deleteInspection.id) }) - .orderBy("sub.createdAt", "DESC") - .limit(1) - .getQuery(); - return "id = " + subQuery; - }) - .execute(); + .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() diff --git a/src/command/unit/inspection/inspectionPointResultCommand.ts b/src/command/unit/inspection/inspectionPointResultCommand.ts index 9fb36d6..c1893d3 100644 --- a/src/command/unit/inspection/inspectionPointResultCommand.ts +++ b/src/command/unit/inspection/inspectionPointResultCommand.ts @@ -1,4 +1,4 @@ -export interface CreateInspectionPointResultCommand { +export interface CreateOrUpdateInspectionPointResultCommand { inspectionId: string; inspectionPointId: string; value: string; diff --git a/src/command/unit/inspection/inspectionPointResultCommandHandler.ts b/src/command/unit/inspection/inspectionPointResultCommandHandler.ts index 23916dc..8ffeb6a 100644 --- a/src/command/unit/inspection/inspectionPointResultCommandHandler.ts +++ b/src/command/unit/inspection/inspectionPointResultCommandHandler.ts @@ -1,15 +1,17 @@ import { dataSource } from "../../../data-source"; import { inspectionPointResult } from "../../../entity/unit/inspection/inspectionPointResult"; import DatabaseActionException from "../../../exceptions/databaseActionException"; -import { CreateInspectionPointResultCommand } from "./inspectionPointResultCommand"; +import { CreateOrUpdateInspectionPointResultCommand } from "./inspectionPointResultCommand"; export default abstract class InspectionPointResultCommandHandler { /** * @description create inspectionPointResult - * @param {CreateInspectionPointResultCommand} createInspectionPointResult + * @param {CreateOrUpdateInspectionPointResultCommand} createInspectionPointResult * @returns {Promise} */ - static async createOrUpdate(createInspectionPointResult: CreateInspectionPointResultCommand): Promise { + static async createOrUpdate( + createInspectionPointResult: CreateOrUpdateInspectionPointResultCommand + ): Promise { return await dataSource .createQueryBuilder() .insert() @@ -25,7 +27,28 @@ export default abstract class InspectionPointResultCommandHandler { return result.identifiers[0].id; }) .catch((err) => { - throw new DatabaseActionException("CREATE", "inspectionPointResult", err); + throw new DatabaseActionException("CREATE or UPDATE", "inspectionPointResult", err); + }); + } + + /** + * @description create inspectionPointResult + * @param {Array} results + * @returns {Promise} + */ + static async createOrUpdateMultiple(results: Array): Promise { + 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); }); } } diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index fc126cd..9337899 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -4,11 +4,18 @@ import InspectionFactory from "../../../factory/admin/unit/inspection/inspection import { CreateInspectionCommand, DeleteInspectionCommand, + FinishInspectionCommand, UpdateInspectionCommand, } from "../../../command/unit/inspection/inspectionCommand"; import InspectionCommandHandler from "../../../command/unit/inspection/inspectionCommandHandler"; import BadRequestException from "../../../exceptions/badRequestException"; import ForbiddenRequestException from "../../../exceptions/forbiddenRequestException"; +import { CreateOrUpdateInspectionPointResultCommand } from "../../../command/unit/inspection/inspectionPointResultCommand"; +import InspectionPointResultCommandHandler from "../../../command/unit/inspection/inspectionPointResultCommandHandler"; +import { InspectionPointEnum } from "../../../enums/inspectionEnum"; +import multer from "multer"; +import { FileSystemHelper } from "../../../helpers/fileSystemHelper"; +import { PdfExport } from "../../../helpers/pdfExport"; /** * @description get all inspections sorted by id not having newer inspection @@ -76,13 +83,35 @@ export async function getAllInspectionsForRelated(req: Request, res: Response): let [inspections, total] = await InspectionService.getAllForRelated(where, { offset, count, noLimit }); res.json({ - inspections: InspectionFactory.mapToBase(inspections), + inspections: InspectionFactory.mapToBaseMinified(inspections), total: total, offset: offset, count: count, }); } +/** + * @description get inspection by id + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function getInspectionPrintoutById(req: Request, res: Response): Promise { + const inspectionId = req.params.id; + let inspection = await InspectionService.getById(inspectionId); + + if (inspection.finishedAt == null) + throw new ForbiddenRequestException("this inspection has not been finished yet and it so does not have a printout"); + + let filepath = FileSystemHelper.formatPath("inspection", inspection.id, "printout.pdf"); + + res.sendFile(filepath, { + headers: { + "Content-Type": "application/pdf", + }, + }); +} + /** * @description get inspection by id * @param req {Request} Express req object @@ -152,6 +181,106 @@ export async function updateInspectionById(req: Request, res: Response): Promise res.sendStatus(204); } +/** + * @description update inspection by id + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function updateInspectionResults(req: Request, res: Response): Promise { + const inspectionId = req.params.id; + const pointResults = JSON.parse(req.body.results) as Array<{ inspectionPointId: string; value: string }>; + const pointFiles = req.files as Array; + + let inspection = await InspectionService.getById(inspectionId); + + let updateResults: Array = pointResults.map((pr) => ({ + inspectionPointId: pr.inspectionPointId, + value: + inspection.inspectionVersionedPlan.inspectionPoints.find((ip) => ip.id == pr.inspectionPointId).type == + InspectionPointEnum.file && pr.value == "set" + ? pointFiles.find((f) => f.filename.startsWith(pr.inspectionPointId))?.filename + : pr.value, + inspectionId, + })); + await InspectionPointResultCommandHandler.createOrUpdateMultiple(updateResults); + + res.sendStatus(204); +} + +/** + * @description finish inspection by id + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function finishInspection(req: Request, res: Response): Promise { + const inspectionId = req.params.id; + + let inspection = await InspectionService.getById(inspectionId); + + function getValueToInspectionPoint(inspectionPointId: string) { + return inspection.pointResults.find((c) => c.inspectionPointId == inspectionPointId)?.value; + } + + let everythingFilled = inspection.inspectionVersionedPlan.inspectionPoints.every((p) => { + if (p.type == InspectionPointEnum.file) { + return getValueToInspectionPoint(p.id); + } else if (p.type == InspectionPointEnum.oknok) { + let value = getValueToInspectionPoint(p.id); + return (["true", "false"].includes(value) ? (value as "true" | "false") : "") != ""; + } else { + return !!getValueToInspectionPoint(p.id); + } + }); + if (!everythingFilled) throw new ForbiddenRequestException("fill out every field before finishing inspection"); + + let formattedInspection = InspectionFactory.mapToSingle(inspection); + let title = `Prüf-Ausdruck_${[formattedInspection.related.code ?? "", formattedInspection.related.name].join("_")}_${ + formattedInspection.inspectionPlan.title + }_${new Date(formattedInspection.finished ?? "").toLocaleDateString("de-de")}`; + + await PdfExport.renderFile({ + template: "inspection", + title, + filename: "printout", + folder: `inspection/${inspection.id}`, + data: { + inspector: `${req.userId}`, + context: formattedInspection.context || "---", + createdAt: formattedInspection.created, + finishedAt: formattedInspection.finished ?? new Date(), + nextInspection: formattedInspection.nextInspection, + related: formattedInspection.related, + plan: formattedInspection.inspectionPlan, + planVersion: formattedInspection.inspectionVersionedPlan.version, + planTitle: formattedInspection.inspectionPlan.title, + checks: formattedInspection.inspectionVersionedPlan.inspectionPoints + .sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)) + .map((ip) => ({ + title: ip.title, + description: ip.description, + type: ip.type, + min: ip.min, + max: ip.max, + value: + ip.type == InspectionPointEnum.file + ? "siehe Anhang" + : formattedInspection.checks.find((c) => c.inspectionPointId == ip.id).value, + })), + }, + }); + + // TODO: Anhang hinzufügen + + let finish: FinishInspectionCommand = { + id: inspectionId, + }; + await InspectionCommandHandler.finish(finish); + + res.sendStatus(204); +} + /** * @description delete inspection by id * @param req {Request} Express req object diff --git a/src/middleware/multer.ts b/src/middleware/multer.ts index ebcec4e..84a677c 100644 --- a/src/middleware/multer.ts +++ b/src/middleware/multer.ts @@ -3,6 +3,7 @@ import { FileSystemHelper } from "../helpers/fileSystemHelper"; import path from "path"; import BadRequestException from "../exceptions/badRequestException"; +/**Settings image upload */ export const clubImageStorage = multer.diskStorage({ destination: FileSystemHelper.formatPath("/app"), filename: function (req, file, cb) { @@ -33,3 +34,27 @@ export const clubImageUpload = clubImageMulter.fields([ { name: "icon", 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"); diff --git a/src/migrations/1749361405703-UnitBase.ts b/src/migrations/1749361405703-UnitBase.ts index 20e6908..97c657f 100644 --- a/src/migrations/1749361405703-UnitBase.ts +++ b/src/migrations/1749361405703-UnitBase.ts @@ -15,6 +15,8 @@ import { wearable_table, } from "./baseSchemaTables/unit"; import { maintenance_table, damage_report_table } from "./baseSchemaTables/unit_extend"; +import { availableTemplates } from "../type/templateTypes"; +import { template_usage_table } from "./baseSchemaTables/query_template"; export class UnitBase1749361405703 implements MigrationInterface { name = "UnitBase1749361405703"; @@ -36,6 +38,18 @@ export class UnitBase1749361405703 implements MigrationInterface { 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 { @@ -55,5 +69,12 @@ export class UnitBase1749361405703 implements MigrationInterface { 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(); } } diff --git a/src/migrations/1752063536385-test.ts b/src/migrations/1752063536385-test.ts deleted file mode 100644 index 2760925..0000000 --- a/src/migrations/1752063536385-test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class Test1752063536385 implements MigrationInterface { - name = 'Test1752063536385' - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_view","public"]); - await queryRunner.query(`DROP VIEW "membership_view"`); - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_total_view","public"]); - await queryRunner.query(`DROP VIEW "membership_total_view"`); - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_qualifications_view","public"]); - await queryRunner.query(`DROP VIEW "member_qualifications_view"`); - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_executive_positions_view","public"]); - await queryRunner.query(`DROP VIEW "member_executive_positions_view"`); - await queryRunner.query(`CREATE VIEW "member_executive_positions_view" AS SELECT "executivePosition"."id" AS "positionId", "executivePosition"."position" AS "position", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")) AS "exactDuration" FROM "member_executive_positions" "memberExecutivePositions" LEFT JOIN "executive_position" "executivePosition" ON "executivePosition"."id"="memberExecutivePositions"."executivePositionId" LEFT JOIN "member" "member" ON "member"."id"="memberExecutivePositions"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "executivePosition"."id", "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_executive_positions_view","SELECT \"executivePosition\".\"id\" AS \"positionId\", \"executivePosition\".\"position\" AS \"position\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE) - \"memberExecutivePositions\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\")) AS \"exactDuration\" FROM \"member_executive_positions\" \"memberExecutivePositions\" LEFT JOIN \"executive_position\" \"executivePosition\" ON \"executivePosition\".\"id\"=\"memberExecutivePositions\".\"executivePositionId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberExecutivePositions\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"executivePosition\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); - await queryRunner.query(`CREATE VIEW "member_qualifications_view" AS SELECT "qualification"."id" AS "qualificationId", "qualification"."qualification" AS "qualification", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")) AS "exactDuration" FROM "member_qualifications" "memberQualifications" LEFT JOIN "qualification" "qualification" ON "qualification"."id"="memberQualifications"."qualificationId" LEFT JOIN "member" "member" ON "member"."id"="memberQualifications"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "qualification"."id", "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_qualifications_view","SELECT \"qualification\".\"id\" AS \"qualificationId\", \"qualification\".\"qualification\" AS \"qualification\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE) - \"memberQualifications\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\")) AS \"exactDuration\" FROM \"member_qualifications\" \"memberQualifications\" LEFT JOIN \"qualification\" \"qualification\" ON \"qualification\".\"id\"=\"memberQualifications\".\"qualificationId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberQualifications\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"qualification\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); - await queryRunner.query(`CREATE VIEW "membership_view" AS SELECT "status"."id" AS "statusId", "status"."status" AS "status", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "status"."id", "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_view","SELECT \"status\".\"id\" AS \"statusId\", \"status\".\"status\" AS \"status\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"status\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); - await queryRunner.query(`CREATE VIEW "membership_total_view" AS SELECT "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_total_view","SELECT \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"member\".\"id\", \"salutation\".\"id\""]); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_total_view","public"]); - await queryRunner.query(`DROP VIEW "membership_total_view"`); - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","membership_view","public"]); - await queryRunner.query(`DROP VIEW "membership_view"`); - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_qualifications_view","public"]); - await queryRunner.query(`DROP VIEW "member_qualifications_view"`); - await queryRunner.query(`DELETE FROM "typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","member_executive_positions_view","public"]); - await queryRunner.query(`DROP VIEW "member_executive_positions_view"`); - await queryRunner.query(`CREATE VIEW "member_executive_positions_view" AS SELECT "executivePosition"."id" AS "positionId", "executivePosition"."position" AS "position", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberExecutivePositions"."end", CURRENT_DATE) - "memberExecutivePositions"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberExecutivePositions"."end", CURRENT_DATE), "memberExecutivePositions"."start")) AS "exactDuration" FROM "member_executive_positions" "memberExecutivePositions" LEFT JOIN "executive_position" "executivePosition" ON "executivePosition"."id"="memberExecutivePositions"."executivePositionId" LEFT JOIN "member" "member" ON "member"."id"="memberExecutivePositions"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "executivePosition"."id", "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_executive_positions_view","SELECT \"executivePosition\".\"id\" AS \"positionId\", \"executivePosition\".\"position\" AS \"position\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE) - \"memberExecutivePositions\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberExecutivePositions\".\"end\", CURRENT_DATE), \"memberExecutivePositions\".\"start\")) AS \"exactDuration\" FROM \"member_executive_positions\" \"memberExecutivePositions\" LEFT JOIN \"executive_position\" \"executivePosition\" ON \"executivePosition\".\"id\"=\"memberExecutivePositions\".\"executivePositionId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberExecutivePositions\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"executivePosition\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); - await queryRunner.query(`CREATE VIEW "member_qualifications_view" AS SELECT "qualification"."id" AS "qualificationId", "qualification"."qualification" AS "qualification", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("memberQualifications"."end", CURRENT_DATE) - "memberQualifications"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start"))) AS "durationInYears", SUM(AGE(COALESCE("memberQualifications"."end", CURRENT_DATE), "memberQualifications"."start")) AS "exactDuration" FROM "member_qualifications" "memberQualifications" LEFT JOIN "qualification" "qualification" ON "qualification"."id"="memberQualifications"."qualificationId" LEFT JOIN "member" "member" ON "member"."id"="memberQualifications"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "qualification"."id", "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","member_qualifications_view","SELECT \"qualification\".\"id\" AS \"qualificationId\", \"qualification\".\"qualification\" AS \"qualification\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE) - \"memberQualifications\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"memberQualifications\".\"end\", CURRENT_DATE), \"memberQualifications\".\"start\")) AS \"exactDuration\" FROM \"member_qualifications\" \"memberQualifications\" LEFT JOIN \"qualification\" \"qualification\" ON \"qualification\".\"id\"=\"memberQualifications\".\"qualificationId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"memberQualifications\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"qualification\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); - await queryRunner.query(`CREATE VIEW "membership_total_view" AS SELECT "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_total_view","SELECT \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"member\".\"id\", \"salutation\".\"id\""]); - await queryRunner.query(`CREATE VIEW "membership_view" AS SELECT "status"."id" AS "statusId", "status"."status" AS "status", "member"."id" AS "memberId", "member"."firstname" AS "memberFirstname", "member"."lastname" AS "memberLastname", "member"."nameaffix" AS "memberNameaffix", "member"."birthdate" AS "memberBirthdate", "salutation"."salutation" AS "memberSalutation", SUM(COALESCE("membership"."end", CURRENT_DATE) - "membership"."start") AS "durationInDays", SUM(EXTRACT(YEAR FROM AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start"))) AS "durationInYears", SUM(AGE(COALESCE("membership"."end", CURRENT_DATE), "membership"."start")) AS "exactDuration" FROM "membership" "membership" LEFT JOIN "membership_status" "status" ON "status"."id"="membership"."statusId" LEFT JOIN "member" "member" ON "member"."id"="membership"."memberId" LEFT JOIN "salutation" "salutation" ON "salutation"."id"="member"."salutationId" GROUP BY "status"."id", "member"."id", "salutation"."id"`); - await queryRunner.query(`INSERT INTO "typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["public","VIEW","membership_view","SELECT \"status\".\"id\" AS \"statusId\", \"status\".\"status\" AS \"status\", \"member\".\"id\" AS \"memberId\", \"member\".\"firstname\" AS \"memberFirstname\", \"member\".\"lastname\" AS \"memberLastname\", \"member\".\"nameaffix\" AS \"memberNameaffix\", \"member\".\"birthdate\" AS \"memberBirthdate\", \"salutation\".\"salutation\" AS \"memberSalutation\", SUM(COALESCE(\"membership\".\"end\", CURRENT_DATE) - \"membership\".\"start\") AS \"durationInDays\", SUM(EXTRACT(YEAR FROM AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\"))) AS \"durationInYears\", SUM(AGE(COALESCE(\"membership\".\"end\", CURRENT_DATE), \"membership\".\"start\")) AS \"exactDuration\" FROM \"membership\" \"membership\" LEFT JOIN \"membership_status\" \"status\" ON \"status\".\"id\"=\"membership\".\"statusId\" LEFT JOIN \"member\" \"member\" ON \"member\".\"id\"=\"membership\".\"memberId\" LEFT JOIN \"salutation\" \"salutation\" ON \"salutation\".\"id\"=\"member\".\"salutationId\" GROUP BY \"status\".\"id\", \"member\".\"id\", \"salutation\".\"id\""]); - } - -} diff --git a/src/routes/admin/unit/inspection.ts b/src/routes/admin/unit/inspection.ts index 57f6883..e57e1cd 100644 --- a/src/routes/admin/unit/inspection.ts +++ b/src/routes/admin/unit/inspection.ts @@ -8,7 +8,11 @@ import { getInspectionById, updateInspectionById, getAllInspectionsRunning, + updateInspectionResults, + getInspectionPrintoutById, + finishInspection, } from "../../../controller/admin/unit/inspectionController"; +import { inspectionFileUpload } from "../../../middleware/multer"; var router = express.Router({ mergeParams: true }); @@ -39,6 +43,10 @@ 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.post( "/", PermissionHelper.passCheckMiddleware("create", "unit", "inspection"), @@ -55,6 +63,23 @@ router.patch( } ); +router.patch( + "/:id/results", + PermissionHelper.passCheckMiddleware("update", "unit", "inspection"), + inspectionFileUpload, + async (req: Request, res: Response) => { + await updateInspectionResults(req, res); + } +); + +router.patch( + "/:id/finish", + PermissionHelper.passCheckMiddleware("update", "unit", "inspection"), + async (req: Request, res: Response) => { + await finishInspection(req, res); + } +); + router.delete( "/:id", PermissionHelper.passCheckMiddleware("delete", "unit", "inspection"), diff --git a/src/service/unit/inspection/inspectionService.ts b/src/service/unit/inspection/inspectionService.ts index 6e4e79b..5e85f83 100644 --- a/src/service/unit/inspection/inspectionService.ts +++ b/src/service/unit/inspection/inspectionService.ts @@ -20,6 +20,18 @@ export default abstract class InspectionService { .leftJoinAndSelect("inspection.vehicle", "vehicle") .leftJoinAndSelect("inspection.wearable", "wearable"); + private static minifiedQuery = () => + dataSource + .getRepository(inspection) + .createQueryBuilder("inspection") + .leftJoinAndSelect("inspection.inspectionPlan", "inspectionPlan") + .leftJoinAndSelect("inspectionPlan.equipmentType", "equipmentType") + .leftJoinAndSelect("inspectionPlan.vehicleType", "vehicleType") + .leftJoinAndSelect("inspectionPlan.wearableType", "wearableType") + .leftJoinAndSelect("inspection.equipment", "equipment") + .leftJoinAndSelect("inspection.vehicle", "vehicle") + .leftJoinAndSelect("inspection.wearable", "wearable"); + /** * @description get all inspections sorted by next inspection not having newer * @returns {Promise>} @@ -63,7 +75,7 @@ export default abstract class InspectionService { count?: number; noLimit?: boolean; }): Promise<[Array, number]> { - let query = this.query().where({ finishedAt: IsNull() }); + let query = this.minifiedQuery().where({ finishedAt: IsNull() }); if (!noLimit) { query = query.offset(offset).limit(count); @@ -96,7 +108,7 @@ export default abstract class InspectionService { noLimit?: boolean; } ): Promise<[Array, number]> { - let query = this.query().where(where); + let query = this.minifiedQuery().where(where); if (!noLimit) { query = query.offset(offset).limit(count); diff --git a/src/templates/inspection.body.template.html b/src/templates/inspection.body.template.html new file mode 100644 index 0000000..0d243ab --- /dev/null +++ b/src/templates/inspection.body.template.html @@ -0,0 +1,62 @@ + + + + + Prüfung + + +

{{planTitle}} {{related.name}} {{#if related.code}} {{related.code}}{{/if}}

+

Prüfer: {{inspector}}

+

durchgeführt am: {{longdate finishedAt}}

+ {{#if nextInspection}} +

nächste Prüfung am: {{longdate nextInspection}}

+ {{/if}} +
+

{{related.name}} in Betrieb genommen am: {{date related.commissioned}}

+
+

Kontext: {{context}}

+
+ +

Prüfpunkte:

+ + {{#each checks}} + + + + + {{/each}} +
+ {{this.title}} +
+ {{this.description}} +
{{this.value}}
+ + + diff --git a/src/type/templateTypes.ts b/src/type/templateTypes.ts index cede2bb..2f260e7 100644 --- a/src/type/templateTypes.ts +++ b/src/type/templateTypes.ts @@ -8,4 +8,5 @@ export const availableTemplates: Array = [ "listprint.member", "newsletter", "protocol", + "inspection", ]; From 98ce39efc5f9a6425e342d1b91c87b5477f76f18 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 12 Jul 2025 16:38:14 +0200 Subject: [PATCH 32/34] print file with appendix --- .../admin/unit/inspectionController.ts | 94 +++++++++++++++---- src/handlebars.config.ts | 4 + src/helpers/fileSystemHelper.ts | 2 +- src/helpers/pdfExport.ts | 2 +- src/index.ts | 2 + src/middleware/authenticate.ts | 2 + src/templates/inspection.body.template.html | 15 ++- 7 files changed, 97 insertions(+), 24 deletions(-) diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index 9337899..1b35af0 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -16,6 +16,8 @@ import { InspectionPointEnum } from "../../../enums/inspectionEnum"; import multer from "multer"; import { FileSystemHelper } from "../../../helpers/fileSystemHelper"; import { PdfExport } from "../../../helpers/pdfExport"; +import { PDFDocument } from "pdf-lib"; +import sharp from "sharp"; /** * @description get all inspections sorted by id not having newer inspection @@ -240,13 +242,37 @@ export async function finishInspection(req: Request, res: Response): Promise (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, - filename: "printout", - folder: `inspection/${inspection.id}`, + saveToDisk: false, data: { - inspector: `${req.userId}`, + inspector: `${req.lastname}, ${req.firstname}`, context: formattedInspection.context || "---", createdAt: formattedInspection.created, finishedAt: formattedInspection.finished ?? new Date(), @@ -255,23 +281,55 @@ export async function finishInspection(req: Request, res: Response): Promise (a.sort ?? 0) - (b.sort ?? 0)) - .map((ip) => ({ - title: ip.title, - description: ip.description, - type: ip.type, - min: ip.min, - max: ip.max, - value: - ip.type == InspectionPointEnum.file - ? "siehe Anhang" - : formattedInspection.checks.find((c) => c.inspectionPointId == ip.id).value, - })), + checks: inspectionPoints, }, }); - // TODO: Anhang hinzufügen + 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, diff --git a/src/handlebars.config.ts b/src/handlebars.config.ts index 19b32ad..6494994 100644 --- a/src/handlebars.config.ts +++ b/src/handlebars.config.ts @@ -59,3 +59,7 @@ Handlebars.registerHelper("longdatetimeWithWeekday", function (aString) { Handlebars.registerHelper("json", function (context) { return JSON.stringify(context); }); + +Handlebars.registerHelper("eq", function (p, q, options) { + return p == q ? options.fn(this) : options.inverse(this); +}); diff --git a/src/helpers/fileSystemHelper.ts b/src/helpers/fileSystemHelper.ts index 9bc409a..c97bf4f 100644 --- a/src/helpers/fileSystemHelper.ts +++ b/src/helpers/fileSystemHelper.ts @@ -15,7 +15,7 @@ export abstract class FileSystemHelper { return readFileSync(this.formatPath(...filePath), "utf8"); } - static readFileasBase64(...filePath: string[]) { + static readFileAsBase64(...filePath: string[]) { this.createFolder(...filePath); return readFileSync(this.formatPath(...filePath), "base64"); } diff --git a/src/helpers/pdfExport.ts b/src/helpers/pdfExport.ts index 429f551..b42564e 100644 --- a/src/helpers/pdfExport.ts +++ b/src/helpers/pdfExport.ts @@ -127,7 +127,7 @@ export abstract class PdfExport { const mergedPdf = await PDFDocument.create(); for (const pdfPath of pdfFilePaths) { - const pdfBytes = FileSystemHelper.readFileasBase64(inputFolder, pdfPath); + const pdfBytes = FileSystemHelper.readFileAsBase64(inputFolder, pdfPath); const pdf = await PDFDocument.load(pdfBytes); const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices()); copiedPages.forEach((page) => mergedPdf.addPage(page)); diff --git a/src/index.ts b/src/index.ts index 13de2ee..1e28a8c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,8 @@ declare global { export interface Request { userId: string; username: string; + firstname: string; + lastname: string; isOwner: boolean; permissions: PermissionObject; isPWA: boolean; diff --git a/src/middleware/authenticate.ts b/src/middleware/authenticate.ts index abeb832..c961b19 100644 --- a/src/middleware/authenticate.ts +++ b/src/middleware/authenticate.ts @@ -35,6 +35,8 @@ export default async function authenticate(req: Request, res: Response, next: Ne req.userId = decoded.userId; req.username = decoded.username; + req.firstname = decoded.firstname; + req.lastname = decoded.lastname; req.isOwner = decoded.isOwner; req.permissions = decoded.permissions; req.isWebApiRequest = decoded?.sub == "webapi_access_token"; diff --git a/src/templates/inspection.body.template.html b/src/templates/inspection.body.template.html index 0d243ab..cc2a6e5 100644 --- a/src/templates/inspection.body.template.html +++ b/src/templates/inspection.body.template.html @@ -17,16 +17,23 @@

Kontext: {{context}}


-

Prüfpunkte:

+

Prüfpunkte:

{{#each checks}} - + - {{/each}}
+ {{this.title}}
- {{this.description}} + {{#if this.description}} > {{this.description}} +
+ {{/if}} + (Typ: {{this.type}}) +
+ {{#eq this.type "file"}} {{#eq this.others "img"}} + + {{else}} siehe Anhang {{/eq}} {{else}} {{this.value}} {{/eq}} {{this.value}}
From 9a1bf6dfde04a6d1ab6abb0b54bfa83359346553 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sat, 12 Jul 2025 17:04:29 +0200 Subject: [PATCH 33/34] provide files for viewing of uploaded files to inspection points --- .../admin/unit/inspectionController.ts | 30 +++++++++++++++++++ src/routes/admin/unit/inspection.ts | 5 ++++ .../inspectionPointResultService.ts | 21 +++++++++++++ 3 files changed, 56 insertions(+) diff --git a/src/controller/admin/unit/inspectionController.ts b/src/controller/admin/unit/inspectionController.ts index 1b35af0..f91b3d0 100644 --- a/src/controller/admin/unit/inspectionController.ts +++ b/src/controller/admin/unit/inspectionController.ts @@ -18,6 +18,8 @@ import { FileSystemHelper } from "../../../helpers/fileSystemHelper"; import { PdfExport } from "../../../helpers/pdfExport"; import { PDFDocument } from "pdf-lib"; import sharp from "sharp"; +import InspectionPointService from "../../../service/unit/inspection/inspectionPointService"; +import InspectionPointResultService from "../../../service/unit/inspection/inspectionPointResultService"; /** * @description get all inspections sorted by id not having newer inspection @@ -114,6 +116,34 @@ export async function getInspectionPrintoutById(req: Request, res: Response): Pr }); } +/** + * @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 { + 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 diff --git a/src/routes/admin/unit/inspection.ts b/src/routes/admin/unit/inspection.ts index e57e1cd..6a43526 100644 --- a/src/routes/admin/unit/inspection.ts +++ b/src/routes/admin/unit/inspection.ts @@ -11,6 +11,7 @@ import { updateInspectionResults, getInspectionPrintoutById, finishInspection, + getInspectionPointUpload, } from "../../../controller/admin/unit/inspectionController"; import { inspectionFileUpload } from "../../../middleware/multer"; @@ -47,6 +48,10 @@ 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"), diff --git a/src/service/unit/inspection/inspectionPointResultService.ts b/src/service/unit/inspection/inspectionPointResultService.ts index d294139..deb56a8 100644 --- a/src/service/unit/inspection/inspectionPointResultService.ts +++ b/src/service/unit/inspection/inspectionPointResultService.ts @@ -21,4 +21,25 @@ export default abstract class InspectionPointResultService { throw new DatabaseActionException("SELECT", "inspectionPointResult", err); }); } + /** + * @description get inspectionPointResults by inspection and point + * @returns {Promise>} + */ + static async getForInspectionAndPoint( + inspectionId: string, + inspectionPointId: string + ): Promise { + return await dataSource + .getRepository(inspectionPointResult) + .createQueryBuilder("inspectionPointResult") + .leftJoinAndSelect("inspectionPointResult.inspectionPoint", "inspectionPoint") + .where({ inspectionId, inspectionPointId }) + .getOneOrFail() + .then((res) => { + return res; + }) + .catch((err) => { + throw new DatabaseActionException("SELECT", "inspectionPointResult", err); + }); + } } From a69c3e048e7b42b5e3e810866b165d6ac4a1abdc Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 14 Jul 2025 15:28:57 +0200 Subject: [PATCH 34/34] enable backups for unit --- src/entity/unit/damageReport.ts | 14 ++--- src/entity/unit/equipment/equipment.ts | 6 ++- src/entity/unit/equipment/equipmentType.ts | 2 +- src/entity/unit/inspection/inspection.ts | 2 +- src/entity/unit/maintenance.ts | 6 +-- src/entity/unit/vehicle/vehicle.ts | 6 ++- src/entity/unit/vehicle/vehicleType.ts | 2 +- src/entity/unit/wearable/wearable.ts | 6 ++- src/entity/unit/wearable/wearableType.ts | 2 +- src/helpers/backupHelper.ts | 60 ++++++++++++++++++++-- 10 files changed, 85 insertions(+), 21 deletions(-) diff --git a/src/entity/unit/damageReport.ts b/src/entity/unit/damageReport.ts index f080e38..0a4fd7e 100644 --- a/src/entity/unit/damageReport.ts +++ b/src/entity/unit/damageReport.ts @@ -30,37 +30,37 @@ export class damageReport { @Column({ nullable: true, default: null }) equipmentId?: string; - @Column({ nullable: true, default: null }) - maintenanceId?: string; - @Column({ nullable: true, default: null }) vehicleId?: string; @Column({ nullable: true, default: null }) wearableId?: string; - @ManyToOne(() => equipment, { + @Column({ nullable: true, default: null }) + maintenanceId?: string; + + @ManyToOne(() => equipment, (e) => e.reports, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) equipment?: equipment; - @ManyToOne(() => vehicle, { + @ManyToOne(() => vehicle, (v) => v.reports, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) vehicle?: vehicle; - @ManyToOne(() => wearable, { + @ManyToOne(() => wearable, (w) => w.reports, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) wearable?: wearable; - @ManyToOne(() => maintenance, { + @ManyToOne(() => maintenance, (m) => m.reports, { nullable: true, onDelete: "SET NULL", onUpdate: "RESTRICT", diff --git a/src/entity/unit/equipment/equipment.ts b/src/entity/unit/equipment/equipment.ts index bbd12a0..2d3b022 100644 --- a/src/entity/unit/equipment/equipment.ts +++ b/src/entity/unit/equipment/equipment.ts @@ -3,6 +3,7 @@ import { getTypeByORM } from "../../../migrations/ormHelper"; import { equipmentType } from "./equipmentType"; import { damageReport } from "../damageReport"; import { inspection } from "../inspection/inspection"; +import { maintenance } from "../maintenance"; @Entity() export class equipment { @@ -37,6 +38,9 @@ export class equipment { @OneToMany(() => damageReport, (d) => d.equipment, { cascade: ["insert"] }) reports: damageReport[]; - @OneToMany(() => inspection, (i) => i.equipment) + @OneToMany(() => maintenance, (m) => m.equipment, { cascade: ["insert"] }) + maintenances: maintenance[]; + + @OneToMany(() => inspection, (i) => i.equipment, { cascade: ["insert"] }) inspections: inspection[]; } diff --git a/src/entity/unit/equipment/equipmentType.ts b/src/entity/unit/equipment/equipmentType.ts index 1739cfa..40c363b 100644 --- a/src/entity/unit/equipment/equipmentType.ts +++ b/src/entity/unit/equipment/equipmentType.ts @@ -16,7 +16,7 @@ export class equipmentType { @OneToMany(() => equipment, (e) => e.equipmentType, { cascade: ["insert"] }) equipment: equipment[]; - @OneToMany(() => inspectionPlan, (ip) => ip.equipmentType) + @OneToMany(() => inspectionPlan, (ip) => ip.equipmentType, { cascade: ["insert"] }) inspectionPlans: inspectionPlan[]; equipmentCount: number; diff --git a/src/entity/unit/inspection/inspection.ts b/src/entity/unit/inspection/inspection.ts index f49b92d..eff01ec 100644 --- a/src/entity/unit/inspection/inspection.ts +++ b/src/entity/unit/inspection/inspection.ts @@ -77,6 +77,6 @@ export class inspection { }) wearable: wearable; - @OneToMany(() => inspectionPointResult, (ipr) => ipr.inspection) + @OneToMany(() => inspectionPointResult, (ipr) => ipr.inspection, { cascade: ["insert"] }) pointResults: inspectionPointResult[]; } diff --git a/src/entity/unit/maintenance.ts b/src/entity/unit/maintenance.ts index f3c9669..3c9b7c0 100644 --- a/src/entity/unit/maintenance.ts +++ b/src/entity/unit/maintenance.ts @@ -30,21 +30,21 @@ export class maintenance { @Column({ nullable: true, default: null }) wearableId?: string; - @ManyToOne(() => equipment, { + @ManyToOne(() => equipment, (e) => e.maintenances, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) equipment?: equipment; - @ManyToOne(() => vehicle, { + @ManyToOne(() => vehicle, (v) => v.maintenances, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", }) vehicle?: vehicle; - @ManyToOne(() => wearable, { + @ManyToOne(() => wearable, (w) => w.maintenances, { nullable: true, onDelete: "CASCADE", onUpdate: "RESTRICT", diff --git a/src/entity/unit/vehicle/vehicle.ts b/src/entity/unit/vehicle/vehicle.ts index c09a28d..3f75651 100644 --- a/src/entity/unit/vehicle/vehicle.ts +++ b/src/entity/unit/vehicle/vehicle.ts @@ -3,6 +3,7 @@ import { getTypeByORM } from "../../../migrations/ormHelper"; import { vehicleType } from "./vehicleType"; import { damageReport } from "../damageReport"; import { inspection } from "../inspection/inspection"; +import { maintenance } from "../maintenance"; @Entity() export class vehicle { @@ -37,6 +38,9 @@ export class vehicle { @OneToMany(() => damageReport, (d) => d.vehicle, { cascade: ["insert"] }) reports: damageReport[]; - @OneToMany(() => inspection, (i) => i.vehicle) + @OneToMany(() => maintenance, (m) => m.vehicle, { cascade: ["insert"] }) + maintenances: maintenance[]; + + @OneToMany(() => inspection, (i) => i.vehicle, { cascade: ["insert"] }) inspections: inspection[]; } diff --git a/src/entity/unit/vehicle/vehicleType.ts b/src/entity/unit/vehicle/vehicleType.ts index 2e83b23..2ed071a 100644 --- a/src/entity/unit/vehicle/vehicleType.ts +++ b/src/entity/unit/vehicle/vehicleType.ts @@ -16,7 +16,7 @@ export class vehicleType { @OneToMany(() => vehicle, (e) => e.vehicleType, { cascade: ["insert"] }) vehicle: vehicle[]; - @OneToMany(() => inspectionPlan, (ip) => ip.vehicleType) + @OneToMany(() => inspectionPlan, (ip) => ip.vehicleType, { cascade: ["insert"] }) inspectionPlans: inspectionPlan[]; vehicleCount: number; diff --git a/src/entity/unit/wearable/wearable.ts b/src/entity/unit/wearable/wearable.ts index 902d23a..2c5ce44 100644 --- a/src/entity/unit/wearable/wearable.ts +++ b/src/entity/unit/wearable/wearable.ts @@ -4,6 +4,7 @@ import { wearableType } from "./wearableType"; import { damageReport } from "../damageReport"; import { member } from "../../club/member/member"; import { inspection } from "../inspection/inspection"; +import { maintenance } from "../maintenance"; @Entity() export class wearable { @@ -48,6 +49,9 @@ export class wearable { @OneToMany(() => damageReport, (d) => d.wearable, { cascade: ["insert"] }) reports: damageReport[]; - @OneToMany(() => inspection, (i) => i.wearable) + @OneToMany(() => maintenance, (m) => m.wearable, { cascade: ["insert"] }) + maintenances: maintenance[]; + + @OneToMany(() => inspection, (i) => i.wearable, { cascade: ["insert"] }) inspections: inspection[]; } diff --git a/src/entity/unit/wearable/wearableType.ts b/src/entity/unit/wearable/wearableType.ts index 099ed26..a7d7538 100644 --- a/src/entity/unit/wearable/wearableType.ts +++ b/src/entity/unit/wearable/wearableType.ts @@ -16,7 +16,7 @@ export class wearableType { @OneToMany(() => wearable, (e) => e.wearableType, { cascade: ["insert"] }) wearable: wearable[]; - @OneToMany(() => inspectionPlan, (ip) => ip.wearableType) + @OneToMany(() => inspectionPlan, (ip) => ip.wearableType, { cascade: ["insert"] }) inspectionPlans: inspectionPlan[]; wearableCount: number; diff --git a/src/helpers/backupHelper.ts b/src/helpers/backupHelper.ts index 42632df..d510f8d 100644 --- a/src/helpers/backupHelper.ts +++ b/src/helpers/backupHelper.ts @@ -8,7 +8,6 @@ import DatabaseActionException from "../exceptions/databaseActionException"; import { availableTemplates } from "../type/templateTypes"; import SettingHelper from "./settingsHelper"; import { LoginRoutineEnum } from "../enums/loginRoutineEnum"; -import { education } from "../entity/configuration/education"; export type BackupSection = | "member" @@ -21,7 +20,9 @@ export type BackupSection = | "template" | "user" | "webapi" - | "settings"; + | "settings" + | "unitBase" + | "unitInstances"; export type BackupSectionRefered = { [key in BackupSection]?: Array; @@ -35,7 +36,7 @@ export type BackupFileContentSection = Array | { [key: string]: Array export default abstract class BackupHelper { // ! Order matters because of foreign keys 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: "protocol", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member { type: "newsletter", orderOnInsert: 3, orderOnClear: 1 }, // INSERT depends on member & query & calendar @@ -46,6 +47,8 @@ export default abstract class BackupHelper { { type: "user", orderOnInsert: 1, orderOnClear: 1 }, { type: "webapi", 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 = { @@ -83,6 +86,8 @@ export default abstract class BackupHelper { user: ["user", "user_permission", "role", "role_permission", "invite"], webapi: ["webapi", "webapi_permission"], settings: ["setting"], + unitBase: ["equipment_type", "vehicle_type", "wearable_type"], + unitInstances: ["equipment", "vehicle", "wearable"], }; private static transactionManager: EntityManager; @@ -162,7 +167,7 @@ export default abstract class BackupHelper { for (const section of sections.filter((s) => Object.keys(backup).includes(s.type))) { let refered = this.backupSectionRefered[section.type]; for (const ref of refered) { - await this.transactionManager.getRepository(ref).delete({}); + await this.transactionManager.getRepository(ref).deleteAll(); } } } @@ -229,6 +234,10 @@ export default abstract class BackupHelper { return await this.getWebapi(); case "settings": return await this.getSettings(); + case "unitBase": + return await this.getUnitBase(); + case "unitInstances": + return await this.getUnitInstances(); default: return []; } @@ -490,6 +499,27 @@ export default abstract class BackupHelper { .select(["setting.topic", "setting.key", "setting.value"]) .getMany(); } + private static async getUnitBase(): Promise<{ [key: string]: Array }> { + 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 }> { + 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(), + inspection: await dataSource.getRepository("inspection").find(), + inspection_point_result: await dataSource.getRepository("inspection_point_result").find(), + }; + } private static async setSectionData( section: BackupSection, @@ -507,6 +537,8 @@ export default abstract class BackupHelper { if (section == "user" && !Array.isArray(data)) await this.setUser(data); if (section == "webapi" && Array.isArray(data)) await this.setWebapi(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): Promise { @@ -870,4 +902,24 @@ export default abstract class BackupHelper { private static async setSettings(data: Array): Promise { await this.transactionManager.getRepository("setting").save(data); } + private static async setUnitBase(data: { [key: string]: Array }): Promise { + 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 }): Promise { + 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("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"]); + } }