From b9b258a1f6d6724f1051957096c89ff4eaad5277 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 13 Oct 2024 15:48:01 +0200 Subject: [PATCH] protcol data commands --- src/command/protocolAgendaCommand.ts | 6 ++ src/command/protocolAgendaCommandHandler.ts | 25 ++++++ src/command/protocolCommand.ts | 13 +++ src/command/protocolCommandHandler.ts | 53 +++++++++++ src/command/protocolDecisionCommand.ts | 6 ++ src/command/protocolDecisionCommandHandler.ts | 25 ++++++ src/command/protocolPresenceCommand.ts | 4 + src/command/protocolPresenceCommandHandler.ts | 65 ++++++++++++++ src/command/protocolVotingCommand.ts | 9 ++ src/command/protocolVotingCommandHandler.ts | 25 ++++++ src/controller/admin/protocolController.ts | 89 +++++++++++++++++++ src/entity/protocolPresence.ts | 4 +- src/routes/admin/protocol.ts | 15 ++-- src/service/protocolDecisionService.ts | 2 +- src/service/protocolPrecenseService.ts | 2 +- src/service/protocolVotingService.ts | 2 +- 16 files changed, 335 insertions(+), 10 deletions(-) create mode 100644 src/command/protocolAgendaCommand.ts create mode 100644 src/command/protocolAgendaCommandHandler.ts create mode 100644 src/command/protocolCommand.ts create mode 100644 src/command/protocolCommandHandler.ts create mode 100644 src/command/protocolDecisionCommand.ts create mode 100644 src/command/protocolDecisionCommandHandler.ts create mode 100644 src/command/protocolPresenceCommand.ts create mode 100644 src/command/protocolPresenceCommandHandler.ts create mode 100644 src/command/protocolVotingCommand.ts create mode 100644 src/command/protocolVotingCommandHandler.ts diff --git a/src/command/protocolAgendaCommand.ts b/src/command/protocolAgendaCommand.ts new file mode 100644 index 0000000..749390d --- /dev/null +++ b/src/command/protocolAgendaCommand.ts @@ -0,0 +1,6 @@ +export interface SynchronizeProtocolAgendaCommand { + id?: number; + topic: string; + context: string; + protocolId: number; +} diff --git a/src/command/protocolAgendaCommandHandler.ts b/src/command/protocolAgendaCommandHandler.ts new file mode 100644 index 0000000..d132558 --- /dev/null +++ b/src/command/protocolAgendaCommandHandler.ts @@ -0,0 +1,25 @@ +import { dataSource } from "../data-source"; +import { protocolAgenda } from "../entity/protocolAgenda"; +import InternalException from "../exceptions/internalException"; +import { SynchronizeProtocolAgendaCommand } from "./protocolAgendaCommand"; + +export default abstract class ProtocolAgendaCommandHandler { + /** + * @description sync protocolAgenda + * @param {Array} + * @returns {Promise} + */ + static async sync(syncProtocolAgenda: Array): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(protocolAgenda) + .values(syncProtocolAgenda) + .orUpdate(["topic", "context"], ["id"]) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed creating protocol", err); + }); + } +} diff --git a/src/command/protocolCommand.ts b/src/command/protocolCommand.ts new file mode 100644 index 0000000..42e9ce9 --- /dev/null +++ b/src/command/protocolCommand.ts @@ -0,0 +1,13 @@ +export interface CreateProtocolCommand { + title: string; + date: Date; +} + +export interface SynchronizeProtocolCommand { + id: number; + title: string; + date: Date; + starttime: Date; + endtime: Date; + summary: string; +} diff --git a/src/command/protocolCommandHandler.ts b/src/command/protocolCommandHandler.ts new file mode 100644 index 0000000..f2f293e --- /dev/null +++ b/src/command/protocolCommandHandler.ts @@ -0,0 +1,53 @@ +import { dataSource } from "../data-source"; +import { protocol } from "../entity/protocol"; +import InternalException from "../exceptions/internalException"; +import { CreateProtocolCommand, SynchronizeProtocolCommand } from "./protocolCommand"; + +export default abstract class ProtocolCommandHandler { + /** + * @description create protocol + * @param CreateProtocolCommand + * @returns {Promise} + */ + static async create(createProtocol: CreateProtocolCommand): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(protocol) + .values({ + title: createProtocol.title, + date: createProtocol.date, + }) + .execute() + .then((result) => { + return result.identifiers[0].id; + }) + .catch((err) => { + throw new InternalException("Failed creating protocol", err); + }); + } + + /** + * @description sync protocol + * @param SynchronizeProtocolCommand + * @returns {Promise} + */ + static async sync(syncProtocol: SynchronizeProtocolCommand): Promise { + return await dataSource + .createQueryBuilder() + .update(protocol) + .set({ + title: syncProtocol.title, + date: syncProtocol.date, + starttime: syncProtocol.starttime, + endtime: syncProtocol.endtime, + summary: syncProtocol.summary, + }) + .where("id = :id", { id: syncProtocol.id }) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed creating protocol", err); + }); + } +} diff --git a/src/command/protocolDecisionCommand.ts b/src/command/protocolDecisionCommand.ts new file mode 100644 index 0000000..61eb6f0 --- /dev/null +++ b/src/command/protocolDecisionCommand.ts @@ -0,0 +1,6 @@ +export interface SynchronizeProtocolDecisionCommand { + id?: number; + topic: string; + context: string; + protocolId: number; +} diff --git a/src/command/protocolDecisionCommandHandler.ts b/src/command/protocolDecisionCommandHandler.ts new file mode 100644 index 0000000..3925884 --- /dev/null +++ b/src/command/protocolDecisionCommandHandler.ts @@ -0,0 +1,25 @@ +import { dataSource } from "../data-source"; +import { protocolDecision } from "../entity/protocolDecision"; +import InternalException from "../exceptions/internalException"; +import { SynchronizeProtocolDecisionCommand } from "./protocolDecisionCommand"; + +export default abstract class ProtocolDecisionCommandHandler { + /** + * @description sync protocolDecision + * @param {Array} + * @returns {Promise} + */ + static async sync(syncProtocolDecisions: Array): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(protocolDecision) + .values(syncProtocolDecisions) + .orUpdate(["topic", "context"], ["id"]) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed creating protocol", err); + }); + } +} diff --git a/src/command/protocolPresenceCommand.ts b/src/command/protocolPresenceCommand.ts new file mode 100644 index 0000000..b39878b --- /dev/null +++ b/src/command/protocolPresenceCommand.ts @@ -0,0 +1,4 @@ +export interface SynchronizeProtocolPresenceCommand { + memberIds: Array; + protocolId: number; +} diff --git a/src/command/protocolPresenceCommandHandler.ts b/src/command/protocolPresenceCommandHandler.ts new file mode 100644 index 0000000..7d7a5f7 --- /dev/null +++ b/src/command/protocolPresenceCommandHandler.ts @@ -0,0 +1,65 @@ +import { DeleteResult, EntityManager, InsertResult } from "typeorm"; +import { dataSource } from "../data-source"; +import { protocolPresence } from "../entity/protocolPresence"; +import InternalException from "../exceptions/internalException"; +import ProtocolPresenceService from "../service/protocolPrecenseService"; +import { SynchronizeProtocolPresenceCommand } from "./protocolPresenceCommand"; + +export default abstract class ProtocolPresenceCommandHandler { + /** + * @description sync protocolPresence + * @param {SynchronizeProtocolPresenceCommand} + * @returns {Promise} + */ + static async sync(syncProtocolPresences: SynchronizeProtocolPresenceCommand): Promise { + let currentPresence = (await ProtocolPresenceService.getAll(syncProtocolPresences.protocolId)).map( + (r) => r.memberId + ); + + return await dataSource.manager + .transaction(async (manager) => { + let newMembers = syncProtocolPresences.memberIds.filter((r) => !currentPresence.includes(r)); + let removeMembers = currentPresence.filter((r) => !syncProtocolPresences.memberIds.includes(r)); + + await this.syncPresenceAdd(manager, syncProtocolPresences.protocolId, newMembers); + + await this.syncPresenceRemove(manager, syncProtocolPresences.protocolId, removeMembers); + }) + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed saving user roles", err); + }); + } + + private static async syncPresenceAdd( + manager: EntityManager, + protocolId: number, + memberIds: Array + ): Promise { + return await manager + .createQueryBuilder() + .insert() + .into(protocolPresence) + .values( + memberIds.map((m) => ({ + protocolId, + memberIds: m, + })) + ) + .execute(); + } + + private static async syncPresenceRemove( + manager: EntityManager, + protocolId: number, + memberIds: Array + ): Promise { + return await manager + .createQueryBuilder() + .delete() + .from(protocolPresence) + .where("memberId IN (:...ids)", { ids: memberIds }) + .andWhere("protcolId = :protocolId", { protocolId }) + .execute(); + } +} diff --git a/src/command/protocolVotingCommand.ts b/src/command/protocolVotingCommand.ts new file mode 100644 index 0000000..a707b64 --- /dev/null +++ b/src/command/protocolVotingCommand.ts @@ -0,0 +1,9 @@ +export interface SynchronizeProtocolVotingCommand { + id: number; + topic: string; + context: string; + favour: number; + abstain: number; + against: number; + protocolId: number; +} diff --git a/src/command/protocolVotingCommandHandler.ts b/src/command/protocolVotingCommandHandler.ts new file mode 100644 index 0000000..6ade2f1 --- /dev/null +++ b/src/command/protocolVotingCommandHandler.ts @@ -0,0 +1,25 @@ +import { dataSource } from "../data-source"; +import { protocolVoting } from "../entity/protocolVoting"; +import InternalException from "../exceptions/internalException"; +import { SynchronizeProtocolVotingCommand } from "./protocolVotingCommand"; + +export default abstract class ProtocolVotingCommandHandler { + /** + * @description sync protocolVoting + * @param {Array} + * @returns {Promise} + */ + static async sync(syncProtocolVotings: Array): Promise { + return await dataSource + .createQueryBuilder() + .insert() + .into(protocolVoting) + .values(syncProtocolVotings) + .orUpdate(["topic", "context", "favour", "abstain", "against"], ["id"]) + .execute() + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed creating protocol", err); + }); + } +} diff --git a/src/controller/admin/protocolController.ts b/src/controller/admin/protocolController.ts index 53444a5..51bf599 100644 --- a/src/controller/admin/protocolController.ts +++ b/src/controller/admin/protocolController.ts @@ -9,6 +9,18 @@ import ProtocolPresenceService from "../../service/protocolPrecenseService"; import ProtocolPresenceFactory from "../../factory/admin/protocolPresence"; import ProtocolVotingService from "../../service/protocolVotingService"; import ProtocolVotingFactory from "../../factory/admin/protocolVoting"; +import { CreateProtocolCommand, SynchronizeProtocolCommand } from "../../command/protocolCommand"; +import ProtocolCommandHandler from "../../command/protocolCommandHandler"; +import { SynchronizeProtocolAgendaCommand } from "../../command/protocolAgendaCommand"; +import ProtocolAgendaCommandHandler from "../../command/protocolAgendaCommandHandler"; +import { ProtocolAgendaViewModel } from "../../viewmodel/admin/protocolAgenda.models"; +import ProtocolDecisionCommandHandler from "../../command/protocolDecisionCommandHandler"; +import { ProtocolDecisionViewModel } from "../../viewmodel/admin/protocolDecision.models"; +import ProtocolPresenceCommandHandler from "../../command/protocolPresenceCommandHandler"; +import { SynchronizeProtocolPresenceCommand } from "../../command/protocolPresenceCommand"; +import { SynchronizeProtocolDecisionCommand } from "../../command/protocolDecisionCommand"; +import { SynchronizeProtocolVotingCommand } from "../../command/protocolVotingCommand"; +import { ProtocolVotingViewModel } from "../../viewmodel/admin/protocolVoting.models"; /** * @description get all protocols @@ -98,6 +110,25 @@ export async function getProtocolVotingsById(req: Request, res: Response): Promi res.json(ProtocolVotingFactory.mapToBase(votings)); } +/** + * @description create protocol + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function createProtocol(req: Request, res: Response): Promise { + let title = req.body.title; + let date = req.body.date; + + let createProtocol: CreateProtocolCommand = { + title, + date, + }; + let id = await ProtocolCommandHandler.create(createProtocol); + + res.send(id); +} + /** * @description synchronize protocol by id * @param req {Request} Express req object @@ -106,6 +137,21 @@ export async function getProtocolVotingsById(req: Request, res: Response): Promi */ export async function synchronizeProtocolById(req: Request, res: Response): Promise { let id = parseInt(req.params.id); + let title = req.body.title; + let date = req.body.date; + let starttime = req.body.starttime; + let endtime = req.body.endtime; + let summary = req.body.summary; + + let syncProtocol: SynchronizeProtocolCommand = { + id, + title, + date, + starttime, + endtime, + summary, + }; + await ProtocolCommandHandler.sync(syncProtocol); res.sendStatus(204); } @@ -118,6 +164,17 @@ export async function synchronizeProtocolById(req: Request, res: Response): Prom */ export async function synchronizeProtocolAgendaById(req: Request, res: Response): Promise { let protocolId = parseInt(req.params.protocolId); + let agenda = req.body.agenda as Array; + + let syncAgenda: Array = agenda.map( + (a: ProtocolAgendaViewModel): SynchronizeProtocolAgendaCommand => ({ + id: a.id ?? null, + topic: a.topic, + context: a.context, + protocolId, + }) + ); + await ProtocolAgendaCommandHandler.sync(syncAgenda); res.sendStatus(204); } @@ -130,6 +187,17 @@ export async function synchronizeProtocolAgendaById(req: Request, res: Response) */ export async function synchronizeProtocolDecisonsById(req: Request, res: Response): Promise { let protocolId = parseInt(req.params.protocolId); + let decisions = req.body.decisions as Array; + + let syncDecision: Array = decisions.map( + (d: ProtocolDecisionViewModel): SynchronizeProtocolDecisionCommand => ({ + id: d.id ?? null, + topic: d.topic, + context: d.context, + protocolId, + }) + ); + await ProtocolDecisionCommandHandler.sync(syncDecision); res.sendStatus(204); } @@ -142,6 +210,13 @@ export async function synchronizeProtocolDecisonsById(req: Request, res: Respons */ export async function synchronizeProtocolPrecenseById(req: Request, res: Response): Promise { let protocolId = parseInt(req.params.protocolId); + let presence = req.body.precense as Array; + + let syncPresence: SynchronizeProtocolPresenceCommand = { + memberIds: presence, + protocolId, + }; + await ProtocolPresenceCommandHandler.sync(syncPresence); res.sendStatus(204); } @@ -154,6 +229,20 @@ export async function synchronizeProtocolPrecenseById(req: Request, res: Respons */ export async function synchronizeProtocolVotingsById(req: Request, res: Response): Promise { let protocolId = parseInt(req.params.protocolId); + let decisions = req.body.decisions as Array; + + let syncDecision: Array = decisions.map( + (d: ProtocolVotingViewModel): SynchronizeProtocolVotingCommand => ({ + id: d.id ?? null, + topic: d.topic, + context: d.context, + favour: d.favour, + abstain: d.abstain, + against: d.abstain, + protocolId, + }) + ); + await ProtocolDecisionCommandHandler.sync(syncDecision); res.sendStatus(204); } diff --git a/src/entity/protocolPresence.ts b/src/entity/protocolPresence.ts index 975ee0c..5d80b10 100644 --- a/src/entity/protocolPresence.ts +++ b/src/entity/protocolPresence.ts @@ -5,10 +5,10 @@ import { member } from "./member"; @Entity() export class protocolPresence { @PrimaryColumn() - memberId: string; + memberId: number; @PrimaryColumn() - protocolId: string; + protocolId: number; @ManyToOne(() => member, { nullable: false, diff --git a/src/routes/admin/protocol.ts b/src/routes/admin/protocol.ts index 1870d50..5edbeee 100644 --- a/src/routes/admin/protocol.ts +++ b/src/routes/admin/protocol.ts @@ -1,5 +1,6 @@ import express, { Request, Response } from "express"; import { + createProtocol, getAllProtocols, getProtocolAgendaById, getProtocolById, @@ -39,23 +40,27 @@ router.get("/:protocolId/votings", async (req: Request, res: Response) => { await getProtocolVotingsById(req, res); }); -router.get("/:id/synchronize", async (req: Request, res: Response) => { +router.post("/", async (req: Request, res: Response) => { + await createProtocol(req, res); +}); + +router.put("/:id/synchronize", async (req: Request, res: Response) => { await synchronizeProtocolById(req, res); }); -router.get("/:protocolId/synchronize/agenda", async (req: Request, res: Response) => { +router.put("/:protocolId/synchronize/agenda", async (req: Request, res: Response) => { await synchronizeProtocolAgendaById(req, res); }); -router.get("/:protocolId/synchronize/decisions", async (req: Request, res: Response) => { +router.put("/:protocolId/synchronize/decisions", async (req: Request, res: Response) => { await synchronizeProtocolDecisonsById(req, res); }); -router.get("/:protocolId/synchronize/presence", async (req: Request, res: Response) => { +router.put("/:protocolId/synchronize/presence", async (req: Request, res: Response) => { await synchronizeProtocolPrecenseById(req, res); }); -router.get("/:protocolId/synchronize/votings", async (req: Request, res: Response) => { +router.put("/:protocolId/synchronize/votings", async (req: Request, res: Response) => { await synchronizeProtocolVotingsById(req, res); }); diff --git a/src/service/protocolDecisionService.ts b/src/service/protocolDecisionService.ts index b7a9051..b818313 100644 --- a/src/service/protocolDecisionService.ts +++ b/src/service/protocolDecisionService.ts @@ -11,7 +11,7 @@ export default abstract class ProtocolDecisionService { return await dataSource .getRepository(protocolDecision) .createQueryBuilder("protocolDecisions") - .where("protocolAgenda.protocolId = :protocolId", { protocolId }) + .where("protocolDecisions.protocolId = :protocolId", { protocolId }) .getMany() .then((res) => { return res; diff --git a/src/service/protocolPrecenseService.ts b/src/service/protocolPrecenseService.ts index bc32993..e66c946 100644 --- a/src/service/protocolPrecenseService.ts +++ b/src/service/protocolPrecenseService.ts @@ -11,7 +11,7 @@ export default abstract class ProtocolPresenceService { return await dataSource .getRepository(protocolPresence) .createQueryBuilder("protocolPresence") - .where("protocolAgenda.protocolId = :protocolId", { protocolId }) + .where("protocolPresence.protocolId = :protocolId", { protocolId }) .getMany() .then((res) => { return res; diff --git a/src/service/protocolVotingService.ts b/src/service/protocolVotingService.ts index 4f806d9..55792fe 100644 --- a/src/service/protocolVotingService.ts +++ b/src/service/protocolVotingService.ts @@ -11,7 +11,7 @@ export default abstract class ProtocolVotingService { return await dataSource .getRepository(protocolVoting) .createQueryBuilder("protocolVotings") - .where("protocolAgenda.protocolId = :protocolId", { protocolId }) + .where("protocolVotings.protocolId = :protocolId", { protocolId }) .getMany() .then((res) => { return res;