From ba110bd000c1f7540b4f2d06fc923c6581565540 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 17:58:22 +0200 Subject: [PATCH 01/21] added endpoint to claculate evnet statistics --- .../src/controllers/event.controller.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libs/api/core/feature/src/controllers/event.controller.ts b/libs/api/core/feature/src/controllers/event.controller.ts index 7af2049d..9983a2fe 100644 --- a/libs/api/core/feature/src/controllers/event.controller.ts +++ b/libs/api/core/feature/src/controllers/event.controller.ts @@ -546,6 +546,24 @@ export class EventController { return this.eventService.getEventFloorLayoutImage(extractRequest); } + @Get('getEventStatistics') + @SetMetadata('role', Role.VIEWER) + @UseGuards(JwtGuard,RbacGuard, CsrfGuard) + async getEventStatistics( + @Req() req: Request, + @Query() query: any + ): Promise { + const request: any = req; + + if (request.user['email'] == undefined || request.user['email'] == null) + throw new HttpException('Bad Request: Manager email not provided', 400); + + const extractRequest: IGetEventFloorlayoutImageRequest = { + eventId: query.eventId, + }; + return this.eventService.getEventStatistics(extractRequest); + } + } function computePreviousDayDate(): Date{ From 56dd392c1743b4dcd7ee2e2ea43dc0cd389cd90f Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 17:58:43 +0200 Subject: [PATCH 02/21] added dervice to calculate event statistics --- libs/api/event/feature/src/event.service.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/api/event/feature/src/event.service.ts b/libs/api/event/feature/src/event.service.ts index cc18b002..bac0d91e 100644 --- a/libs/api/event/feature/src/event.service.ts +++ b/libs/api/event/feature/src/event.service.ts @@ -68,6 +68,8 @@ import { IDeleteEventImageRequest, DeleteEventImageCommand, IDeleteEventImageResponse, + IGetEventStatisticsRequest, + GetEventStatisticsQuery, } from '@event-participation-trends/api/event/util'; import { Injectable } from '@nestjs/common'; import { CommandBus, QueryBus } from '@nestjs/cqrs'; @@ -190,4 +192,8 @@ export class EventService { async deleteImage(request: IDeleteEventImageRequest) { return await this.commandBus.execute(new DeleteEventImageCommand(request)); } + + async getEventStatistics(request: IGetEventStatisticsRequest) { + return await this.queryBus.execute(new GetEventStatisticsQuery(request)); + } } \ No newline at end of file From 500e497bfa3aec5e9ba90f0c1f5e370835088d46 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 17:59:04 +0200 Subject: [PATCH 03/21] adde query handler to calculate event statistics --- .../queries/get-event-statistics.handler.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 libs/api/event/feature/src/queries/get-event-statistics.handler.ts diff --git a/libs/api/event/feature/src/queries/get-event-statistics.handler.ts b/libs/api/event/feature/src/queries/get-event-statistics.handler.ts new file mode 100644 index 00000000..58cd08f1 --- /dev/null +++ b/libs/api/event/feature/src/queries/get-event-statistics.handler.ts @@ -0,0 +1,40 @@ +import { EventRepository } from '@event-participation-trends/api/event/data-access'; +import { GetEventStatisticsQuery, IGetEventStatisticsResponse } from '@event-participation-trends/api/event/util'; +import { UserRepository } from '@event-participation-trends/api/user/data-access'; +import { QueryHandler, IQueryHandler } from '@nestjs/cqrs'; +import { Types } from 'mongoose'; + +@QueryHandler(GetEventStatisticsQuery) +export class GetEventStatisticsHandler implements IQueryHandler { + constructor( + private readonly eventRepository: EventRepository, + private readonly userRepository: UserRepository, + ) {} + + async execute(query: GetEventStatisticsQuery) { + + const eventIdObj = query.request.eventId; + const devices = await this.eventRepository.getDevicePosotions(eventIdObj); + + let total_attendance =0; + let average_attendance =0; + let peak_attendance= 0; + let turnover_rate =0; + let average_attendance_time =0; + let max_attendance_time =0; + + //compute statistics begin + + //compute statistics end + + return { + total_attendance: total_attendance, + average_attendance: average_attendance, + peak_attendance: peak_attendance, + turnover_rate: turnover_rate, + average_attendance_time: average_attendance_time, + max_attendance_time: max_attendance_time, + } + } + +} \ No newline at end of file From a53e697fb302314eb6805a474036cb26c15053e5 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 17:59:40 +0200 Subject: [PATCH 04/21] added query to clacuate event statistics --- .../api/event/util/src/queries/get-event-statistics.query.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 libs/api/event/util/src/queries/get-event-statistics.query.ts diff --git a/libs/api/event/util/src/queries/get-event-statistics.query.ts b/libs/api/event/util/src/queries/get-event-statistics.query.ts new file mode 100644 index 00000000..8a8ab200 --- /dev/null +++ b/libs/api/event/util/src/queries/get-event-statistics.query.ts @@ -0,0 +1,5 @@ +import { IGetEventStatisticsRequest } from "../requests"; + +export class GetEventStatisticsQuery { + constructor(public readonly request: IGetEventStatisticsRequest) {} + } \ No newline at end of file From 2168f6257a73879061a1900f45b29d71de1c79a1 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 18:00:05 +0200 Subject: [PATCH 05/21] added request format for computeing event statatistics --- .../event/util/src/requests/get-event-statistics.request.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 libs/api/event/util/src/requests/get-event-statistics.request.ts diff --git a/libs/api/event/util/src/requests/get-event-statistics.request.ts b/libs/api/event/util/src/requests/get-event-statistics.request.ts new file mode 100644 index 00000000..2066bf15 --- /dev/null +++ b/libs/api/event/util/src/requests/get-event-statistics.request.ts @@ -0,0 +1,4 @@ + +export interface IGetEventStatisticsRequest { + eventId: string | undefined | null, +} \ No newline at end of file From 115a771ba3baf04b08d802c8ad322d0e5a67c4a7 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 18:00:22 +0200 Subject: [PATCH 06/21] added response format for computeing event statatistics --- .../util/src/responses/get-event-statistics.response.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 libs/api/event/util/src/responses/get-event-statistics.response.ts diff --git a/libs/api/event/util/src/responses/get-event-statistics.response.ts b/libs/api/event/util/src/responses/get-event-statistics.response.ts new file mode 100644 index 00000000..16526308 --- /dev/null +++ b/libs/api/event/util/src/responses/get-event-statistics.response.ts @@ -0,0 +1,9 @@ + +export interface IGetEventStatisticsResponse { + total_attendance: number | undefined |null, + average_attendance: number | undefined |null, + peak_attendance: number | undefined |null, + turnover_rate: number | undefined |null, + average_attendance_time: number | undefined |null, + max_attendance_time: number | undefined |null, +} \ No newline at end of file From adbf96d25e32ff070cfddcb4565c56f457004fdd Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 18:00:51 +0200 Subject: [PATCH 07/21] linkinf for feature to calcualte event statistics --- libs/api/event/feature/src/event.module.ts | 2 ++ libs/api/event/feature/src/queries/index.ts | 3 ++- libs/api/event/util/src/queries/index.ts | 3 ++- libs/api/event/util/src/requests/index.ts | 3 ++- libs/api/event/util/src/responses/index.ts | 3 ++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libs/api/event/feature/src/event.module.ts b/libs/api/event/feature/src/event.module.ts index bd27dea9..d2bba772 100644 --- a/libs/api/event/feature/src/event.module.ts +++ b/libs/api/event/feature/src/event.module.ts @@ -35,6 +35,7 @@ import { GetFloorplanBoundariesQueryHandler, GetAllActiveEventsHandler, GetEventFloorlayoutImageHandler, + GetEventStatisticsHandler, } from './queries'; import { @@ -111,6 +112,7 @@ export const QueryHandlers = [ GetFloorplanBoundariesQueryHandler, GetAllActiveEventsHandler, GetEventFloorlayoutImageHandler, + GetEventStatisticsHandler, ]; diff --git a/libs/api/event/feature/src/queries/index.ts b/libs/api/event/feature/src/queries/index.ts index b558a7ac..83758b7b 100644 --- a/libs/api/event/feature/src/queries/index.ts +++ b/libs/api/event/feature/src/queries/index.ts @@ -9,4 +9,5 @@ export * from './get-event-categories.handler'; export * from './get-managed-event-categories.handler'; export * from './get-floorplan-boundaries.handler'; export * from './get-all-active-events.handler'; -export * from './get-event-floorlayout-image.handler'; \ No newline at end of file +export * from './get-event-floorlayout-image.handler'; +export * from './get-event-statistics.handler'; \ No newline at end of file diff --git a/libs/api/event/util/src/queries/index.ts b/libs/api/event/util/src/queries/index.ts index 481868fa..b2eb2b49 100644 --- a/libs/api/event/util/src/queries/index.ts +++ b/libs/api/event/util/src/queries/index.ts @@ -10,4 +10,5 @@ export * from './get-event-categories.query'; export * from './get-managed-event-categories.query'; export * from './get-floorplan-boundaries.query'; export * from './get-all-active-events.query'; -export * from './get-event-floorlayout-image.query'; \ No newline at end of file +export * from './get-event-floorlayout-image.query'; +export * from './get-event-statistics.query'; \ No newline at end of file diff --git a/libs/api/event/util/src/requests/index.ts b/libs/api/event/util/src/requests/index.ts index 0f8d9669..5e9c0150 100644 --- a/libs/api/event/util/src/requests/index.ts +++ b/libs/api/event/util/src/requests/index.ts @@ -22,4 +22,5 @@ export * from './get-floorplan-boundaries.request'; export * from './delete-event.request'; export * from './upload-image.request'; export * from './get-event-floorlayout-image.request'; -export * from './delete-event-image.request'; \ No newline at end of file +export * from './delete-event-image.request'; +export * from './get-event-statistics.request'; \ No newline at end of file diff --git a/libs/api/event/util/src/responses/index.ts b/libs/api/event/util/src/responses/index.ts index a1ebe7d8..2cd2b16e 100644 --- a/libs/api/event/util/src/responses/index.ts +++ b/libs/api/event/util/src/responses/index.ts @@ -24,4 +24,5 @@ export * from './delete-event.response'; export * from './get-all-active-events.response'; export * from './upload-image.response'; export * from './get-event-floorlayout-image.response'; -export * from './delete-event-image.respons'; \ No newline at end of file +export * from './delete-event-image.respons'; +export * from './get-event-statistics.response'; \ No newline at end of file From 6af14df6a05c26f7fff889eba6e89825ac3bb9a5 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:27:39 +0200 Subject: [PATCH 08/21] added endpoint for updating event floor layout image details --- .../src/controllers/event.controller.ts | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/libs/api/core/feature/src/controllers/event.controller.ts b/libs/api/core/feature/src/controllers/event.controller.ts index 9983a2fe..bfb8d68c 100644 --- a/libs/api/core/feature/src/controllers/event.controller.ts +++ b/libs/api/core/feature/src/controllers/event.controller.ts @@ -41,6 +41,10 @@ import { IGetEventFloorlayoutImageRequest, IDeleteEventImageRequest, IDeleteEventImageResponse, + IUpdateEventFloorLayoutImgRequest, + IUpdateEventFloorLayoutImgResponse, + IGetEventFloorlayoutImageResponse, + IGetEventStatisticsResponse, } from '@event-participation-trends/api/event/util'; import { Body, @@ -534,7 +538,7 @@ export class EventController { async getFloorLayoutImage( @Req() req: Request, @Query() query: any - ): Promise { + ): Promise { const request: any = req; if (request.user['email'] == undefined || request.user['email'] == null) @@ -552,7 +556,7 @@ export class EventController { async getEventStatistics( @Req() req: Request, @Query() query: any - ): Promise { + ): Promise { const request: any = req; if (request.user['email'] == undefined || request.user['email'] == null) @@ -564,6 +568,33 @@ export class EventController { return this.eventService.getEventStatistics(extractRequest); } + @Post('updateEventFloorlayoutImage') + @SetMetadata('role',Role.MANAGER) + @UseGuards(JwtGuard, RbacGuard, CsrfGuard) + async updateEventFloorlayoutImage( + @Req() req: Request, + @Body() requestBody: IUpdateEventFloorLayoutImgRequest, + ): Promise { + const request: any = req; + + if(!requestBody.imageId) + throw new HttpException("Bad Request: imageId not provided", 400); + + if(!requestBody.eventId) + throw new HttpException("Bad Request: eventId not provided", 400); + + const extractRequest: IUpdateEventFloorLayoutImgRequest = { + eventId: requestBody.eventId, + imageId: requestBody.imageId, + managerEmail: request.user['email'], + imgBase64: requestBody.imgBase64, + imageObj: requestBody.imageObj, + imageScale: requestBody.imageScale, + imageType: requestBody.imageType, + }; + return this.eventService.updateEventFloorLayoutImage(extractRequest); +} + } function computePreviousDayDate(): Date{ From 9e7392130fe135b0fbc91b1663453530fe398ccc Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:28:29 +0200 Subject: [PATCH 09/21] added email subject for floorlayout image updates --- libs/api/email/util/src/enums/email-subjects.enum.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/api/email/util/src/enums/email-subjects.enum.ts b/libs/api/email/util/src/enums/email-subjects.enum.ts index a0437b62..571b8157 100644 --- a/libs/api/email/util/src/enums/email-subjects.enum.ts +++ b/libs/api/email/util/src/enums/email-subjects.enum.ts @@ -8,4 +8,5 @@ export enum EmailSubject{ ROLE_CHANGED= "Event Participation Trends: Role Change", EVENT_DETAILS_UPDATED= "Event Participation Trends: Event Details Updated", EVENT_DELETED= "Event Participation Trends: Event Deleted", + EVENT_FLOORLAYOUT_IMAGE_UPDATED = "Event Participation Trends: Event Floorlayout image Updated", } \ No newline at end of file From de7c89f44a1d5c6941c6a23b32a7a5e7eaf2233a Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:28:50 +0200 Subject: [PATCH 10/21] added db funcitons for updating event floorlayout image --- .../event/data-access/src/event.repository.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libs/api/event/data-access/src/event.repository.ts b/libs/api/event/data-access/src/event.repository.ts index 2f627169..eeabfdd9 100644 --- a/libs/api/event/data-access/src/event.repository.ts +++ b/libs/api/event/data-access/src/event.repository.ts @@ -274,4 +274,28 @@ export class EventRepository { return await this.eventModel.find( {Manager: {$eq: managerID}}).select("Category").distinct("Category"); } + + async updateEventFloorlayoutImageimgBase64(imageId: Types.ObjectId, imgBase64: string){ + return await this.imageModel.updateOne( + {_id :{$eq: imageId}}, + {$set: {imageBase64 :imgBase64}}) + } + + async updateEventFloorlayoutImageimageObj(imageId: Types.ObjectId, imageObj: string){ + return await this.imageModel.updateOne( + {_id :{$eq: imageId}}, + {$set: {imageObj :imageObj}}) + } + + async updateEventFloorlayoutImageimageScale(imageId: Types.ObjectId, imageScale: number){ + return await this.imageModel.updateOne( + {_id :{$eq: imageId}}, + {$set: {imageScale :imageScale}}) + } + + async updateEventFloorlayoutImageimageType(imageId: Types.ObjectId, imageType: string){ + return await this.imageModel.updateOne( + {_id :{$eq: imageId}}, + {$set: {imageType :imageType}}) + } } \ No newline at end of file From e31753ce7ed59f6dff023130fdcd1d9c86bee076 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:29:30 +0200 Subject: [PATCH 11/21] added service for updating event floorlayout image details --- libs/api/event/feature/src/event.service.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/api/event/feature/src/event.service.ts b/libs/api/event/feature/src/event.service.ts index bac0d91e..569e7133 100644 --- a/libs/api/event/feature/src/event.service.ts +++ b/libs/api/event/feature/src/event.service.ts @@ -70,6 +70,11 @@ import { IDeleteEventImageResponse, IGetEventStatisticsRequest, GetEventStatisticsQuery, + IUpdateEventFloorLayoutImgRequest, + UpdateEventFloorLayoutImgCommand, + IUpdateEventFloorLayoutImgResponse, + IGetEventStatisticsResponse, + IGetEventFloorlayoutImageResponse, } from '@event-participation-trends/api/event/util'; import { Injectable } from '@nestjs/common'; import { CommandBus, QueryBus } from '@nestjs/cqrs'; @@ -186,7 +191,7 @@ export class EventService { } async getEventFloorLayoutImage(request: IGetEventFloorlayoutImageRequest) { - return await this.queryBus.execute(new GetEventFloorlayoutImageQuery(request)); + return await this.queryBus.execute(new GetEventFloorlayoutImageQuery(request)); } async deleteImage(request: IDeleteEventImageRequest) { @@ -194,6 +199,10 @@ export class EventService { } async getEventStatistics(request: IGetEventStatisticsRequest) { - return await this.queryBus.execute(new GetEventStatisticsQuery(request)); + return await this.queryBus.execute(new GetEventStatisticsQuery(request)); + } + + async updateEventFloorLayoutImage(request: IUpdateEventFloorLayoutImgRequest) { + return await this.commandBus.execute(new UpdateEventFloorLayoutImgCommand(request)); } } \ No newline at end of file From e16342370114123bc966a669dbaa1b891aedd565 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:30:12 +0200 Subject: [PATCH 12/21] added event handler for updating floorlayout image details --- .../update-event-floorlayout.handler.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 libs/api/event/feature/src/events/update-event-floorlayout.handler.ts diff --git a/libs/api/event/feature/src/events/update-event-floorlayout.handler.ts b/libs/api/event/feature/src/events/update-event-floorlayout.handler.ts new file mode 100644 index 00000000..3bbc169b --- /dev/null +++ b/libs/api/event/feature/src/events/update-event-floorlayout.handler.ts @@ -0,0 +1,60 @@ +import { IUpdateFloorLayoutImage, UpdateEventFloorLayoutImgEvent } from '@event-participation-trends/api/event/util'; +import { EventRepository } from '@event-participation-trends/api/event/data-access'; +import { IEventHandler, EventsHandler } from '@nestjs/cqrs'; +import { EmailService } from '@event-participation-trends/api/email/feature' +import { EmailContent, EmailSubject} from '@event-participation-trends/api/email/util'; +import { UserRepository } from '@event-participation-trends/api/user/data-access'; + +@EventsHandler(UpdateEventFloorLayoutImgEvent) +export class UpdateEventFloorLayoutImgEventHandler implements IEventHandler { + constructor( + private readonly eventRepository: EventRepository, + private readonly userRepository: UserRepository, + private readonly emailService: EmailService, + ) {} + + async handle(event: UpdateEventFloorLayoutImgEvent) { + console.log(`${UpdateEventFloorLayoutImgEventHandler.name}`); + + const request = event.event; + + if(request.eventId && request.imageId){ + let emailContent= "Updated Event Floorlayout Image: "+ EmailContent.NEW_LINE; + const eventDoc = await this.eventRepository.getEventById(request.eventId); + emailContent += "Event Name: " + eventDoc[0].Name + EmailContent.NEW_LINE; + + if(request.imgBase64){ + await this.eventRepository.updateEventFloorlayoutImageimgBase64(request.imageId, request.imgBase64); + emailContent+= "\t imgBase64 has been updated" + EmailContent.NEW_LINE; + } + + if(request.imageObj){ + await this.eventRepository.updateEventFloorlayoutImageimageObj(request.imageId, request.imageObj); + emailContent+= "\t New imageObj: "+ request.imageObj + EmailContent.NEW_LINE; + } + + if(request.imageScale){ + await this.eventRepository.updateEventFloorlayoutImageimageScale(request.imageId, request.imageScale); + emailContent+= "\t New imageScale: "+ request.imageScale.toString() + EmailContent.NEW_LINE; + } + + if(request.imageType){ + await this.eventRepository.updateEventFloorlayoutImageimageType(request.imageId,request.imageType); + emailContent+= "\t New imageType: "+ request.imageType + EmailContent.NEW_LINE; + } + + let userDoc; + if(eventDoc[0].Manager != null && eventDoc[0].Manager != undefined) + userDoc = await this.userRepository.getUserById(eventDoc[0].Manager); + + if(userDoc != undefined && userDoc != null && userDoc[0]) + this.emailService.sendEmail( + userDoc[0]?.Email || "", + EmailSubject.EVENT_FLOORLAYOUT_IMAGE_UPDATED, + emailContent + ); + + } + } + +} \ No newline at end of file From 8e0486d11bdbd1b3b9453e67cd4122d43e131b5b Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:30:31 +0200 Subject: [PATCH 13/21] added command for updating floorlayout image details --- .../src/commands/update-event-floorlayout-image.command.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 libs/api/event/util/src/commands/update-event-floorlayout-image.command.ts diff --git a/libs/api/event/util/src/commands/update-event-floorlayout-image.command.ts b/libs/api/event/util/src/commands/update-event-floorlayout-image.command.ts new file mode 100644 index 00000000..100ebb38 --- /dev/null +++ b/libs/api/event/util/src/commands/update-event-floorlayout-image.command.ts @@ -0,0 +1,5 @@ +import { IUpdateEventFloorLayoutImgRequest} from '../requests'; + +export class UpdateEventFloorLayoutImgCommand { + constructor(public readonly request: IUpdateEventFloorLayoutImgRequest) {} +} \ No newline at end of file From 861ef67cec22a4cb99f8bae537c214d82ce01107 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:30:46 +0200 Subject: [PATCH 14/21] added event for updating floorlayout image details --- .../event/util/src/events/update-floorlayout-image.event.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 libs/api/event/util/src/events/update-floorlayout-image.event.ts diff --git a/libs/api/event/util/src/events/update-floorlayout-image.event.ts b/libs/api/event/util/src/events/update-floorlayout-image.event.ts new file mode 100644 index 00000000..5e63e7b2 --- /dev/null +++ b/libs/api/event/util/src/events/update-floorlayout-image.event.ts @@ -0,0 +1,5 @@ +import { IUpdateFloorLayoutImage } from '../interfaces'; + +export class UpdateEventFloorLayoutImgEvent{ + constructor(public readonly event: IUpdateFloorLayoutImage) {} +} \ No newline at end of file From a2d2ddf09c6f19145b8ff6f91c5a8bc035702107 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:31:31 +0200 Subject: [PATCH 15/21] added command handler for updating floorlayout image details --- .../update-event-floorlayout.handler.ts | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 libs/api/event/feature/src/commands/update-event-floorlayout.handler.ts diff --git a/libs/api/event/feature/src/commands/update-event-floorlayout.handler.ts b/libs/api/event/feature/src/commands/update-event-floorlayout.handler.ts new file mode 100644 index 00000000..e0362b7e --- /dev/null +++ b/libs/api/event/feature/src/commands/update-event-floorlayout.handler.ts @@ -0,0 +1,52 @@ +import { UpdateEventFloorLayoutImgCommand, IUpdateFloorLayoutImage, IUpdateEventFloorLayoutImgResponse } from '@event-participation-trends/api/event/util'; +import { CommandHandler, EventPublisher, ICommandHandler } from '@nestjs/cqrs'; +import { Status } from'@event-participation-trends/api/user/util'; +import { UpdateFloorLayoutImage } from '../models'; +import { Types } from 'mongoose'; +import { EventRepository } from '@event-participation-trends/api/event/data-access'; +import { UserRepository } from '@event-participation-trends/api/user/data-access'; +import { HttpException } from '@nestjs/common'; + +@CommandHandler(UpdateEventFloorLayoutImgCommand) +export class UpdateEventFloorLayoutImgHandler implements ICommandHandler { + constructor( + private readonly publisher: EventPublisher, + private readonly eventRepository: EventRepository, + private readonly userRepository: UserRepository, + ) {} + + async execute(command: UpdateEventFloorLayoutImgCommand) { + console.log(`${UpdateEventFloorLayoutImgHandler.name}`); + + const request = command.request; + + const eventIdObj = request.eventId; + const imageIdObj = request.imageId; + + const eventDoc = await this.eventRepository.getEventById(eventIdObj); + const userDoc = await this.userRepository.getUser(request.managerEmail || ""); + const imageDoc = await this.eventRepository.getImageById(imageIdObj); + + if(eventDoc && userDoc && !eventDoc[0].Manager?.equals(userDoc[0]._id)) + throw new HttpException(`Bad Request: Manager with Email ${request.managerEmail} does not manage Event with id ${request.eventId}`, 400); + + if(imageDoc && imageDoc[0].eventId && !eventDoc[0]._id?.equals(imageDoc[0].eventId)) + throw new HttpException(`Bad Request: Manager with Email ${request.managerEmail} does not manage photo with id ${request.imageId}`, 400); + + const data: IUpdateFloorLayoutImage={ + eventId: eventIdObj, + imageId: imageIdObj, + managerEmail: request.managerEmail, + imgBase64: request.imgBase64, + imageObj: request.imageObj, + imageScale: request.imageScale, + imageType: request.imageType, + } + + const event = this.publisher.mergeObjectContext(UpdateFloorLayoutImage.fromData(data)); + event.update(); + event.commit(); + + return { status : Status.SUCCESS }; + } +} \ No newline at end of file From c28687f7fcdb181c46f4707d0f261129beab6451 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:31:53 +0200 Subject: [PATCH 16/21] added model for updating floorlayout image details --- .../models/update-image-floorlayout.model.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 libs/api/event/feature/src/models/update-image-floorlayout.model.ts diff --git a/libs/api/event/feature/src/models/update-image-floorlayout.model.ts b/libs/api/event/feature/src/models/update-image-floorlayout.model.ts new file mode 100644 index 00000000..ca72c446 --- /dev/null +++ b/libs/api/event/feature/src/models/update-image-floorlayout.model.ts @@ -0,0 +1,49 @@ +import { + IUpdateFloorLayoutImage, + UpdateEventFloorLayoutImgEvent, + } from '@event-participation-trends/api/event/util'; +import { Types } from 'mongoose'; +import { AggregateRoot } from '@nestjs/cqrs'; + +export class UpdateFloorLayoutImage extends AggregateRoot implements IUpdateFloorLayoutImage { + constructor( + public eventId: Types.ObjectId | undefined | null, + public imageId: Types.ObjectId | undefined | null, + public managerEmail: string | undefined | null, + public imgBase64: string | undefined | null, + public imageObj: string | undefined | null, + public imageScale: number | undefined | null, + public imageType: string | undefined | null, + ){ + super(); + } + + update(){ + this.apply(new UpdateEventFloorLayoutImgEvent(this.toJSON())); + } + + static fromData(event: IUpdateFloorLayoutImage): UpdateFloorLayoutImage { + const instance = new UpdateFloorLayoutImage( + event.eventId, + event.imageId, + event.managerEmail, + event.imgBase64, + event.imageObj, + event.imageScale, + event.imageType, + ); + return instance; + } + + toJSON(): IUpdateFloorLayoutImage { + return { + eventId: this.eventId, + imageId: this.imageId, + managerEmail: this.managerEmail, + imgBase64: this.imgBase64, + imageObj: this.imageObj, + imageScale: this.imageScale, + imageType: this.imageType, + }; + } +} \ No newline at end of file From 7d5b98c5dcab2b8178074958c6d2b3238fcaecfb Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:32:08 +0200 Subject: [PATCH 17/21] added interface for updating floorlayout image details --- .../interfaces/update-floorlayout-image.interface.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 libs/api/event/util/src/interfaces/update-floorlayout-image.interface.ts diff --git a/libs/api/event/util/src/interfaces/update-floorlayout-image.interface.ts b/libs/api/event/util/src/interfaces/update-floorlayout-image.interface.ts new file mode 100644 index 00000000..e42ea33a --- /dev/null +++ b/libs/api/event/util/src/interfaces/update-floorlayout-image.interface.ts @@ -0,0 +1,11 @@ +import { Types } from "mongoose"; + +export interface IUpdateFloorLayoutImage{ + eventId: Types.ObjectId | undefined | null; + imageId: Types.ObjectId | undefined | null; + managerEmail: string | undefined | null; + imgBase64: string | undefined | null; + imageObj: string | undefined | null; + imageScale: number | undefined | null; + imageType: string | undefined | null; +} \ No newline at end of file From 2738ce0d34b3bc7bbdeb21920f8d7c3e31c13a34 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:32:30 +0200 Subject: [PATCH 18/21] added request format for updating floorlayout image details --- .../requests/update-event-floorlayout-image.request.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 libs/api/event/util/src/requests/update-event-floorlayout-image.request.ts diff --git a/libs/api/event/util/src/requests/update-event-floorlayout-image.request.ts b/libs/api/event/util/src/requests/update-event-floorlayout-image.request.ts new file mode 100644 index 00000000..688ad0d9 --- /dev/null +++ b/libs/api/event/util/src/requests/update-event-floorlayout-image.request.ts @@ -0,0 +1,10 @@ + +export interface IUpdateEventFloorLayoutImgRequest{ + eventId: string | undefined | null; + imageId: string | undefined | null; + managerEmail: string | undefined | null; + imgBase64: string | undefined | null; + imageObj: string | undefined | null; + imageScale: number | undefined | null; + imageType: string | undefined | null; +} \ No newline at end of file From 129dbd0984774f815bfa5a887fb8c0d6426fed11 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:32:43 +0200 Subject: [PATCH 19/21] added response format for updating floorlayout image details --- .../src/responses/update-event-floorlayout-image.response.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 libs/api/event/util/src/responses/update-event-floorlayout-image.response.ts diff --git a/libs/api/event/util/src/responses/update-event-floorlayout-image.response.ts b/libs/api/event/util/src/responses/update-event-floorlayout-image.response.ts new file mode 100644 index 00000000..e3e187e0 --- /dev/null +++ b/libs/api/event/util/src/responses/update-event-floorlayout-image.response.ts @@ -0,0 +1,5 @@ +import { Status } from '@event-participation-trends/api/user/util'; + +export interface IUpdateEventFloorLayoutImgResponse{ + status: Status | undefined | null; +} \ No newline at end of file From 35894ac4b4a1987e4f32553993ecdb3949ad0ec5 Mon Sep 17 00:00:00 2001 From: LucaLoubser Date: Mon, 11 Sep 2023 23:33:11 +0200 Subject: [PATCH 20/21] linking for feature to update event floor layout image --- libs/api/event/feature/src/commands/index.ts | 3 ++- libs/api/event/feature/src/event.module.ts | 4 ++++ libs/api/event/feature/src/events/index.ts | 3 ++- libs/api/event/feature/src/models/index.ts | 3 ++- libs/api/event/util/src/commands/index.ts | 3 ++- libs/api/event/util/src/events/index.ts | 3 ++- libs/api/event/util/src/interfaces/index.ts | 3 ++- libs/api/event/util/src/requests/index.ts | 3 ++- libs/api/event/util/src/responses/index.ts | 3 ++- 9 files changed, 20 insertions(+), 8 deletions(-) diff --git a/libs/api/event/feature/src/commands/index.ts b/libs/api/event/feature/src/commands/index.ts index 5dec798b..9e2443a1 100644 --- a/libs/api/event/feature/src/commands/index.ts +++ b/libs/api/event/feature/src/commands/index.ts @@ -15,4 +15,5 @@ export * from './remove-event-from-viewers.handler'; export * from './upload-image.handler'; export * from './add-image-to-event.handler'; export * from './delete-event-image.handler'; -export * from './remove-image-from-event.handler'; \ No newline at end of file +export * from './remove-image-from-event.handler'; +export * from './update-event-floorlayout.handler'; \ No newline at end of file diff --git a/libs/api/event/feature/src/event.module.ts b/libs/api/event/feature/src/event.module.ts index d2bba772..1af8f856 100644 --- a/libs/api/event/feature/src/event.module.ts +++ b/libs/api/event/feature/src/event.module.ts @@ -21,6 +21,7 @@ import { AddImageToEventHandler, RemoveEventImageHandler, DeleteEventImageHandler, + UpdateEventFloorLayoutImgHandler, } from './commands'; import { @@ -55,6 +56,7 @@ import { AddImageToEventEventHandler, RemoveEventImageEventHandler, DeleteEventImageEventHandler, + UpdateEventFloorLayoutImgEventHandler, } from './events'; import { GetAllViewRequestsHandler } from './queries/get-all-view-requests.handler'; @@ -78,6 +80,7 @@ export const CommandHandlers = [ AddImageToEventHandler, RemoveEventImageHandler, DeleteEventImageHandler, + UpdateEventFloorLayoutImgHandler, ] export const EventHandlers = [ @@ -97,6 +100,7 @@ export const EventHandlers = [ AddImageToEventEventHandler, RemoveEventImageEventHandler, DeleteEventImageEventHandler, + UpdateEventFloorLayoutImgEventHandler, ]; export const QueryHandlers = [ diff --git a/libs/api/event/feature/src/events/index.ts b/libs/api/event/feature/src/events/index.ts index 35473015..a78a7100 100644 --- a/libs/api/event/feature/src/events/index.ts +++ b/libs/api/event/feature/src/events/index.ts @@ -14,4 +14,5 @@ export * from './remove-event-from-viewers.handler'; export * from './upload-image-event.handler'; export * from './add-image-to-event.event'; export * from './delete-event-image.handler'; -export * from './remove-image-from-event.handler'; \ No newline at end of file +export * from './remove-image-from-event.handler'; +export * from './update-event-floorlayout.handler'; \ No newline at end of file diff --git a/libs/api/event/feature/src/models/index.ts b/libs/api/event/feature/src/models/index.ts index baddd53f..f848d349 100644 --- a/libs/api/event/feature/src/models/index.ts +++ b/libs/api/event/feature/src/models/index.ts @@ -9,4 +9,5 @@ export * from './stall.model'; export * from './update-stall.model'; export * from './delete-event.model'; export * from './image.model'; -export * from './add-image.model'; \ No newline at end of file +export * from './add-image.model'; +export * from './update-image-floorlayout.model'; \ No newline at end of file diff --git a/libs/api/event/util/src/commands/index.ts b/libs/api/event/util/src/commands/index.ts index 0825fdbd..b37feff1 100644 --- a/libs/api/event/util/src/commands/index.ts +++ b/libs/api/event/util/src/commands/index.ts @@ -15,4 +15,5 @@ export * from './remove-event-from-viewers.command'; export * from './upload-image.command'; export * from './add-image-to-event.command'; export * from './delete-event-image.command'; -export * from './remove-image-from-event.command'; \ No newline at end of file +export * from './remove-image-from-event.command'; +export * from './update-event-floorlayout-image.command'; \ No newline at end of file diff --git a/libs/api/event/util/src/events/index.ts b/libs/api/event/util/src/events/index.ts index 7a246078..2075099f 100644 --- a/libs/api/event/util/src/events/index.ts +++ b/libs/api/event/util/src/events/index.ts @@ -15,4 +15,5 @@ export * from './remove-event-from-viewers.event'; export * from './upload-image.event'; export * from './add-image-to-event.event'; export * from './delete-event-image.event'; -export * from './remove-image-from-event.event'; \ No newline at end of file +export * from './remove-image-from-event.event'; +export * from './update-floorlayout-image.event'; \ No newline at end of file diff --git a/libs/api/event/util/src/interfaces/index.ts b/libs/api/event/util/src/interfaces/index.ts index e9648c33..49206d4d 100644 --- a/libs/api/event/util/src/interfaces/index.ts +++ b/libs/api/event/util/src/interfaces/index.ts @@ -13,4 +13,5 @@ export * from './position.interface'; export * from './add-device-position.interface'; export * from './delete-event.interface'; export * from './image.interface'; -export * from './add-image-to-event.interface'; \ No newline at end of file +export * from './add-image-to-event.interface'; +export * from './update-floorlayout-image.interface'; \ No newline at end of file diff --git a/libs/api/event/util/src/requests/index.ts b/libs/api/event/util/src/requests/index.ts index 5e9c0150..4d54eeed 100644 --- a/libs/api/event/util/src/requests/index.ts +++ b/libs/api/event/util/src/requests/index.ts @@ -23,4 +23,5 @@ export * from './delete-event.request'; export * from './upload-image.request'; export * from './get-event-floorlayout-image.request'; export * from './delete-event-image.request'; -export * from './get-event-statistics.request'; \ No newline at end of file +export * from './get-event-statistics.request'; +export * from './update-event-floorlayout-image.request'; \ No newline at end of file diff --git a/libs/api/event/util/src/responses/index.ts b/libs/api/event/util/src/responses/index.ts index 2cd2b16e..1bb78ac2 100644 --- a/libs/api/event/util/src/responses/index.ts +++ b/libs/api/event/util/src/responses/index.ts @@ -25,4 +25,5 @@ export * from './get-all-active-events.response'; export * from './upload-image.response'; export * from './get-event-floorlayout-image.response'; export * from './delete-event-image.respons'; -export * from './get-event-statistics.response'; \ No newline at end of file +export * from './get-event-statistics.response'; +export * from './update-event-floorlayout-image.response'; \ No newline at end of file From fd10de43e7b510f6922818c87785336d9ef6828c Mon Sep 17 00:00:00 2001 From: DieSeeKat Date: Tue, 12 Sep 2023 20:37:43 +0200 Subject: [PATCH 21/21] Add statistics generation --- .../queries/get-event-statistics.handler.ts | 140 ++++++++++++++---- 1 file changed, 109 insertions(+), 31 deletions(-) diff --git a/libs/api/event/feature/src/queries/get-event-statistics.handler.ts b/libs/api/event/feature/src/queries/get-event-statistics.handler.ts index 58cd08f1..18e82741 100644 --- a/libs/api/event/feature/src/queries/get-event-statistics.handler.ts +++ b/libs/api/event/feature/src/queries/get-event-statistics.handler.ts @@ -1,40 +1,118 @@ import { EventRepository } from '@event-participation-trends/api/event/data-access'; -import { GetEventStatisticsQuery, IGetEventStatisticsResponse } from '@event-participation-trends/api/event/util'; +import { + GetEventStatisticsQuery, + IGetEventStatisticsResponse, +} from '@event-participation-trends/api/event/util'; import { UserRepository } from '@event-participation-trends/api/user/data-access'; import { QueryHandler, IQueryHandler } from '@nestjs/cqrs'; import { Types } from 'mongoose'; @QueryHandler(GetEventStatisticsQuery) -export class GetEventStatisticsHandler implements IQueryHandler { - constructor( - private readonly eventRepository: EventRepository, - private readonly userRepository: UserRepository, - ) {} - - async execute(query: GetEventStatisticsQuery) { - - const eventIdObj = query.request.eventId; - const devices = await this.eventRepository.getDevicePosotions(eventIdObj); - - let total_attendance =0; - let average_attendance =0; - let peak_attendance= 0; - let turnover_rate =0; - let average_attendance_time =0; - let max_attendance_time =0; - - //compute statistics begin - - //compute statistics end - - return { - total_attendance: total_attendance, - average_attendance: average_attendance, - peak_attendance: peak_attendance, - turnover_rate: turnover_rate, - average_attendance_time: average_attendance_time, - max_attendance_time: max_attendance_time, +export class GetEventStatisticsHandler + implements + IQueryHandler +{ + constructor( + private readonly eventRepository: EventRepository, + private readonly userRepository: UserRepository + ) {} + + async execute(query: GetEventStatisticsQuery) { + const eventIdObj = (query.request.eventId); + const events = await this.eventRepository.getDevicePosotions(eventIdObj); + + let total_attendance = 0; + let average_attendance = 0; + let peak_attendance = 0; + let turnover_rate = 0; + let average_attendance_time = 0; + let max_attendance_time = 0; + + if (events.length == 0) { + return { + total_attendance: total_attendance, + average_attendance: average_attendance, + peak_attendance: peak_attendance, + turnover_rate: turnover_rate, + average_attendance_time: average_attendance_time, + max_attendance_time: max_attendance_time, + }; + } + + turnover_rate = 0; + + const devices = events[0].Devices ? events[0].Devices : []; + + //compute statistics begin + + const uniqueDevices = new Set(); + + const devicesOverTime = new Map>(); + const deviceTimeRange = new Map(); + + // iterate over all devices + + for (const device of devices) { + if (!device.timestamp || !device.id) { + continue; + } + + uniqueDevices.add(device.id); + + if (deviceTimeRange.has(device.id)) { + const range = deviceTimeRange.get(device.id); + if (range) { + if (device.timestamp < range.start) { + range.start = device.timestamp; + } + if (device.timestamp > range.end) { + range.end = device.timestamp; + } } + } + + const deviceSet = devicesOverTime.get(device.timestamp); + if (deviceSet) { + deviceSet.add(device.id); + } else { + devicesOverTime.set(device.timestamp, new Set([device.id])); + } + } + + // compute average attendance + + let total_unique_devices = 0; + + for (const [key, value] of devicesOverTime.entries()) { + if (value.size > peak_attendance) { + peak_attendance = value.size; + } + total_unique_devices += value.size; } -} \ No newline at end of file + let total_attendance_time = 0; + + for (const [key, value] of deviceTimeRange.entries()) { + const diff = value.end.getTime() - value.start.getTime(); + total_attendance_time += diff; + if (diff > max_attendance_time) { + max_attendance_time = diff; + } + } + + total_attendance = uniqueDevices.size; + average_attendance = total_unique_devices / devicesOverTime.size; + average_attendance_time = total_attendance_time / deviceTimeRange.size; + + //compute statistics end + + return { + total_attendance: total_attendance, + average_attendance: average_attendance, + peak_attendance: peak_attendance, + turnover_rate: turnover_rate, + average_attendance_time: average_attendance_time, + max_attendance_time: max_attendance_time, + }; + } +}