mission base CRUD

This commit is contained in:
Julian Krauser 2025-02-20 12:01:02 +01:00
parent 4e6c6b138c
commit 7e96b6ca0c
15 changed files with 343 additions and 7 deletions

View file

@ -7,9 +7,9 @@ export default abstract class EquipmentCommandHandler {
/** /**
* @description create equipment * @description create equipment
* @param {CreateEquipmentCommand} createEquipment * @param {CreateEquipmentCommand} createEquipment
* @returns {Promise<number>} * @returns {Promise<string>}
*/ */
static async create(createEquipment: CreateEquipmentCommand): Promise<number> { static async create(createEquipment: CreateEquipmentCommand): Promise<string> {
return await dataSource return await dataSource
.createQueryBuilder() .createQueryBuilder()
.insert() .insert()

View file

@ -7,9 +7,9 @@ export default abstract class ForceCommandHandler {
/** /**
* @description create force * @description create force
* @param {CreateForceCommand} createForce * @param {CreateForceCommand} createForce
* @returns {Promise<number>} * @returns {Promise<string>}
*/ */
static async create(createForce: CreateForceCommand): Promise<number> { static async create(createForce: CreateForceCommand): Promise<string> {
return await dataSource return await dataSource
.createQueryBuilder() .createQueryBuilder()
.insert() .insert()

View file

@ -7,9 +7,9 @@ export default abstract class VehicleCommandHandler {
/** /**
* @description create vehicle * @description create vehicle
* @param {CreateVehicleCommand} createVehicle * @param {CreateVehicleCommand} createVehicle
* @returns {Promise<number>} * @returns {Promise<string>}
*/ */
static async create(createVehicle: CreateVehicleCommand): Promise<number> { static async create(createVehicle: CreateVehicleCommand): Promise<string> {
return await dataSource return await dataSource
.createQueryBuilder() .createQueryBuilder()
.insert() .insert()

View file

@ -0,0 +1,9 @@
export interface UpdateMissionCommand {
id: string;
title: string;
keyword?: string;
}
export interface DeleteMissionCommand {
id: string;
}

View file

@ -0,0 +1,66 @@
import { dataSource } from "../../../data-source";
import { mission } from "../../../entity/operation/mission";
import DatabaseActionException from "../../../exceptions/databaseActionException";
import { DeleteMissionCommand, UpdateMissionCommand } from "./missionCommand";
export default abstract class MissionCommandHandler {
/**
* @description create mission
* @returns {Promise<string>}
*/
static async create(): Promise<string> {
return await dataSource
.createQueryBuilder()
.insert()
.into(mission)
.values({
title: "",
})
.execute()
.then((result) => {
return result.identifiers[0].id;
})
.catch((err) => {
throw new DatabaseActionException("CREATE", "mission", err);
});
}
/**
* @description update mission
* @param {UpdateMissionCommand} updateMission
* @returns {Promise<void>}
*/
static async update(updateMission: UpdateMissionCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.update(mission)
.set({
title: updateMission.title,
keyword: updateMission.keyword,
})
.where("id = :id", { id: updateMission.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("UPDATE", "mission", err);
});
}
/**
* @description delete mission
* @param {DeleteMissionCommand} deleteMission
* @returns {Promise<void>}
*/
static async delete(deleteMission: DeleteMissionCommand): Promise<void> {
return await dataSource
.createQueryBuilder()
.delete()
.from(mission)
.where("id = :id", { id: deleteMission.id })
.execute()
.then(() => {})
.catch((err) => {
throw new DatabaseActionException("DELETE", "mission", err);
});
}
}

View file

@ -0,0 +1,91 @@
import { Request, Response } from "express";
import MissionService from "../../../service/operation/missionService";
import MissionFactory from "../../../factory/admin/operation/mission";
import { DeleteMissionCommand, UpdateMissionCommand } from "../../../command/operation/mission/missionCommand";
import MissionCommandHandler from "../../../command/operation/mission/missionCommandHandler";
/**
* @description get all missions
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getAllMissions(req: Request, res: Response): Promise<any> {
let offset = parseInt((req.query.offset as string) ?? "0");
let count = parseInt((req.query.count as string) ?? "25");
let noLimit = req.query.noLimit === "true";
let [missions, total] = await MissionService.getAll({ offset, count, noLimit });
res.json({
missions: MissionFactory.mapToBaseShort(missions),
total: total,
offset: offset,
count: count,
});
}
/**
* @description get mission by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function getMissionById(req: Request, res: Response): Promise<any> {
const missionId = req.params.id;
let mission = await MissionService.getById(missionId);
res.json(MissionFactory.mapToSingleShort(mission));
}
/**
* @description create mission
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function createMission(req: Request, res: Response): Promise<any> {
let missionId = await MissionCommandHandler.create();
// TODO: push notification to clients that new mission was created
res.status(200).send(missionId);
}
/**
* @description update mission by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function updateMissionById(req: Request, res: Response): Promise<any> {
const missionId = req.params.id;
const title = req.body.code;
const keyword = req.body.type || null;
let updateMission: UpdateMissionCommand = {
id: missionId,
title,
keyword,
};
await MissionCommandHandler.update(updateMission);
res.sendStatus(204);
}
/**
* @description delete mission by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function deleteMissionById(req: Request, res: Response): Promise<any> {
const missionId = req.params.id;
let deleteMission: DeleteMissionCommand = {
id: missionId,
};
await MissionCommandHandler.delete(deleteMission);
res.sendStatus(204);
}

View file

@ -15,6 +15,7 @@ import { reset } from "./entity/reset";
import { CreateSchema1739697068682 } from "./migrations/1739697068682-CreateSchema"; import { CreateSchema1739697068682 } from "./migrations/1739697068682-CreateSchema";
import { vehicle } from "./entity/configuration/vehicle"; import { vehicle } from "./entity/configuration/vehicle";
import { equipment } from "./entity/configuration/equipment"; import { equipment } from "./entity/configuration/equipment";
import { mission } from "./entity/operation/mission";
const dataSource = new DataSource({ const dataSource = new DataSource({
type: DB_TYPE as any, type: DB_TYPE as any,
@ -26,7 +27,7 @@ const dataSource = new DataSource({
synchronize: false, synchronize: false,
logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"], logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"],
bigNumberStrings: false, bigNumberStrings: false,
entities: [user, refresh, invite, reset, userPermission, role, rolePermission, force, vehicle, equipment], entities: [user, refresh, invite, reset, userPermission, role, rolePermission, force, vehicle, equipment, mission],
migrations: [CreateSchema1739697068682], migrations: [CreateSchema1739697068682],
migrationsRun: true, migrationsRun: true,
migrationsTransactionMode: "each", migrationsTransactionMode: "each",

View file

@ -0,0 +1,16 @@
import { Column, CreateDateColumn, Entity, PrimaryColumn } from "typeorm";
@Entity()
export class mission {
@PrimaryColumn({ generated: "uuid" })
id: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "varchar", length: 255, nullable: true })
keyword?: string;
@CreateDateColumn()
createdAt: Date;
}

View file

@ -0,0 +1,27 @@
import { mission } from "../../../entity/operation/mission";
import { MissionShortViewModel } from "../../../viewmodel/admin/operation/mission.models";
export default abstract class MissionFactory {
/**
* @description map record to mission
* @param {mission} record
* @returns {MissionShortViewModel}
*/
public static mapToSingleShort(record: mission): MissionShortViewModel {
return {
id: record.id,
title: record.title,
keyword: record.keyword,
createdAt: record.createdAt,
};
}
/**
* @description map records to mission
* @param {Array<mission>} records
* @returns {Array<MissionShortViewModel>}
*/
public static mapToBaseShort(records: Array<mission>): Array<MissionShortViewModel> {
return records.map((r) => this.mapToSingleShort(r));
}
}

View file

@ -10,6 +10,7 @@ import {
user_table, user_table,
} from "./baseSchemaTables/admin"; } from "./baseSchemaTables/admin";
import { equipment_table, force_table, vehicle_table } from "./baseSchemaTables/configuration"; import { equipment_table, force_table, vehicle_table } from "./baseSchemaTables/configuration";
import { mission_table } from "./baseSchemaTables/operation";
export class CreateSchema1739697068682 implements MigrationInterface { export class CreateSchema1739697068682 implements MigrationInterface {
name = "CreateSchema1739697068682"; name = "CreateSchema1739697068682";
@ -27,9 +28,13 @@ export class CreateSchema1739697068682 implements MigrationInterface {
await queryRunner.createTable(force_table, true, true, true); await queryRunner.createTable(force_table, true, true, true);
await queryRunner.createTable(equipment_table, true, true, true); await queryRunner.createTable(equipment_table, true, true, true);
await queryRunner.createTable(vehicle_table, true, true, true); await queryRunner.createTable(vehicle_table, true, true, true);
await queryRunner.createTable(mission_table, true, true, true);
} }
public async down(queryRunner: QueryRunner): Promise<void> { public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("mission", true, true, true);
await queryRunner.dropTable("vehicle", true, true, true); await queryRunner.dropTable("vehicle", true, true, true);
await queryRunner.dropTable("equipment", true, true, true); await queryRunner.dropTable("equipment", true, true, true);
await queryRunner.dropTable("force", true, true, true); await queryRunner.dropTable("force", true, true, true);

View file

@ -0,0 +1,12 @@
import { Table } from "typeorm";
import { getDefaultByORM, getTypeByORM, isUUIDPrimary } from "../ormHelper";
export const mission_table = new Table({
name: "mission",
columns: [
{ name: "id", ...getTypeByORM("uuid"), ...isUUIDPrimary },
{ name: "title", ...getTypeByORM("varchar") },
{ name: "keyword", ...getTypeByORM("varchar", true), default: getDefaultByORM("null") },
{ name: "createdAt", ...getTypeByORM("datetime", false, 6), default: getDefaultByORM("currentTimestamp") },
],
});

View file

@ -1,6 +1,8 @@
import express from "express"; import express from "express";
import PermissionHelper from "../../helpers/permissionHelper"; import PermissionHelper from "../../helpers/permissionHelper";
import mission from "./operation/mission";
import equipment from "./configuration/equipment"; import equipment from "./configuration/equipment";
import force from "./configuration/force"; import force from "./configuration/force";
import vehicle from "./configuration/vehicle"; import vehicle from "./configuration/vehicle";
@ -12,6 +14,8 @@ import backup from "./management/backup";
var router = express.Router({ mergeParams: true }); var router = express.Router({ mergeParams: true });
router.use("/mission", PermissionHelper.passCheckMiddleware("read", "operation", "mission"), mission);
router.use("/equipment", PermissionHelper.passCheckMiddleware("read", "configuration", "equipment"), equipment); router.use("/equipment", PermissionHelper.passCheckMiddleware("read", "configuration", "equipment"), equipment);
router.use("/force", PermissionHelper.passCheckMiddleware("read", "configuration", "force"), force); router.use("/force", PermissionHelper.passCheckMiddleware("read", "configuration", "force"), force);
router.use("/vehicle", PermissionHelper.passCheckMiddleware("read", "configuration", "vehicle"), vehicle); router.use("/vehicle", PermissionHelper.passCheckMiddleware("read", "configuration", "vehicle"), vehicle);

View file

@ -0,0 +1,45 @@
import express, { Request, Response } from "express";
import {
createMission,
deleteMissionById,
getAllMissions,
getMissionById,
updateMissionById,
} from "../../../controller/admin/operation/missionController";
import PermissionHelper from "../../../helpers/permissionHelper";
var router = express.Router({ mergeParams: true });
router.get("/", async (req: Request, res: Response) => {
await getAllMissions(req, res);
});
router.get("/:id", async (req: Request, res: Response) => {
await getMissionById(req, res);
});
router.post(
"/",
PermissionHelper.passCheckMiddleware("create", "operation", "mission"),
async (req: Request, res: Response) => {
await createMission(req, res);
}
);
router.patch(
"/:id",
PermissionHelper.passCheckMiddleware("update", "operation", "mission"),
async (req: Request, res: Response) => {
await updateMissionById(req, res);
}
);
router.delete(
"/:id",
PermissionHelper.passCheckMiddleware("delete", "operation", "mission"),
async (req: Request, res: Response) => {
await deleteMissionById(req, res);
}
);
export default router;

View file

@ -0,0 +1,54 @@
import { dataSource } from "../../data-source";
import { mission } from "../../entity/operation/mission";
import DatabaseActionException from "../../exceptions/databaseActionException";
export default abstract class MissionService {
/**
* @description get all missions
* @returns {Promise<[Array<mission>, number]>}
*/
static async getAll({
offset = 0,
count = 25,
noLimit = false,
}: {
offset?: number;
count?: number;
noLimit?: boolean;
}): Promise<[Array<mission>, number]> {
let query = dataSource.getRepository(mission).createQueryBuilder("mission");
if (!noLimit) {
query = query.offset(offset).limit(count);
}
return await query
.orderBy("mission.createdAt")
.getManyAndCount()
.then((res) => {
return res;
})
.catch((err) => {
throw new DatabaseActionException("SELECT", "mission", err);
});
}
/**
* @description get mission by id
* @param {string} id
* @returns {Promise<mission>}
*/
static async getById(id: string): Promise<mission> {
return dataSource
.getRepository(mission)
.createQueryBuilder("mission")
.where("mission.id = :id", { id: id })
.getOneOrFail()
.then((res) => {
return res;
})
.catch((err) => {
throw new DatabaseActionException("SELECT", "mission", err);
});
}
}

View file

@ -0,0 +1,6 @@
export interface MissionShortViewModel {
id: string;
title: string;
keyword?: string;
createdAt: Date;
}