From 7a8b6b4226346f97fd5ac5363ea8ccc69500ea3c Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Wed, 27 Sep 2023 16:17:31 +0200 Subject: [PATCH 1/2] :sparkles: Refacto live vote controller --- src/app/api/notary/OfficeFoldersController.ts | 4 +- .../api/super-admin/AppointmentsController.ts | 77 ------------ src/app/api/super-admin/LiveVoteController.ts | 54 ++++++-- src/app/api/super-admin/VotesController.ts | 116 ------------------ src/app/index.ts | 6 - .../AppointmentsService.ts | 53 -------- .../LiveVoteService/LiveVoteService.ts | 44 +++++-- .../super-admin/VotesService/VotesService.ts | 35 ------ 8 files changed, 82 insertions(+), 307 deletions(-) delete mode 100644 src/app/api/super-admin/AppointmentsController.ts delete mode 100644 src/app/api/super-admin/VotesController.ts delete mode 100644 src/services/super-admin/AppointmentsService/AppointmentsService.ts delete mode 100644 src/services/super-admin/VotesService/VotesService.ts diff --git a/src/app/api/notary/OfficeFoldersController.ts b/src/app/api/notary/OfficeFoldersController.ts index 85b80173..342c50aa 100644 --- a/src/app/api/notary/OfficeFoldersController.ts +++ b/src/app/api/notary/OfficeFoldersController.ts @@ -58,8 +58,8 @@ export default class OfficeFoldersController extends ApiController { } const officeId: string = req.body.user.office_Id; - const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; - if(!query.where) query.where = { office: officeWhereInput}; + const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId }; + if (!query.where) query.where = { office: officeWhereInput }; query.where.office = officeWhereInput; //call service to get prisma entity const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query); diff --git a/src/app/api/super-admin/AppointmentsController.ts b/src/app/api/super-admin/AppointmentsController.ts deleted file mode 100644 index 1c3f7346..00000000 --- a/src/app/api/super-admin/AppointmentsController.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Response, Request } from "express"; -import { Controller, Get } from "@ControllerPattern/index"; -import ApiController from "@Common/system/controller-pattern/ApiController"; -import AppointmentsService from "@Services/super-admin/AppointmentsService/AppointmentsService"; -import { Service } from "typedi"; -import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; -import authHandler from "@App/middlewares/AuthHandler"; -import roleHandler from "@App/middlewares/RolesHandler"; - -@Controller() -@Service() -export default class AppointmentsController extends ApiController { - constructor(private appointmentsService: AppointmentsService) { - super(); - } - - /** - * @description Get all appointments - */ - @Get("/api/v1/super-admin/appointments", [authHandler, roleHandler]) - protected async get(req: Request, response: Response) { - try { - //get query - let query; - if (req.query["q"]) { - query = JSON.parse(req.query["q"] as string); - } - - //call service to get prisma entity - const appointmentsEntities = await this.appointmentsService.get(query); - - //Hydrate ressource with prisma entity - const appointments = Appointment.hydrateArray(appointmentsEntities, { strategy: "excludeAll" }); - - //success - this.httpSuccess(response, appointments); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } - - /** - * @description Get a specific appointment by uid - */ - @Get("/api/v1/super-admin/appointments/:uid", [authHandler, roleHandler]) - protected async getOneByUid(req: Request, response: Response) { - try { - const uid = req.params["uid"]; - if (!uid) { - this.httpBadRequest(response, "No uid provided"); - return; - } - - let query; - if (req.query["q"]) { - query = JSON.parse(req.query["q"] as string); - } - - const appointmentEntity = await this.appointmentsService.getByUid(uid, query); - - if (!appointmentEntity) { - this.httpNotFoundRequest(response, "appointment not found"); - return; - } - - //Hydrate ressource with prisma entity - const appointment = Appointment.hydrate(appointmentEntity, { strategy: "excludeAll" }); - - //success - this.httpSuccess(response, appointment); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } -} diff --git a/src/app/api/super-admin/LiveVoteController.ts b/src/app/api/super-admin/LiveVoteController.ts index 49881170..ade311ca 100644 --- a/src/app/api/super-admin/LiveVoteController.ts +++ b/src/app/api/super-admin/LiveVoteController.ts @@ -2,12 +2,10 @@ import authHandler from "@App/middlewares/AuthHandler"; import roleHandler from "@App/middlewares/RolesHandler"; import NotificationBuilder from "@Common/notifications/NotificationBuilder"; import ApiController from "@Common/system/controller-pattern/ApiController"; -import { Controller, Post } from "@ControllerPattern/index"; -import { EAppointmentStatus } from "@prisma/client"; -import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService"; +import { Controller, Delete, Post } from "@ControllerPattern/index"; +import { EAppointmentStatus, Votes } from "@prisma/client"; import LiveVoteService from "@Services/super-admin/LiveVoteService/LiveVoteService"; import UsersService from "@Services/super-admin/UsersService/UsersService"; -import VotesService from "@Services/super-admin/VotesService/VotesService"; import { validateOrReject } from "class-validator"; import { Request, Response } from "express"; import { Vote } from "le-coffre-resources/dist/SuperAdmin"; @@ -18,10 +16,8 @@ import { Service } from "typedi"; export default class LiveVoteController extends ApiController { constructor( private liveVoteService: LiveVoteService, - private votesService: VotesService, private usersService: UsersService, - private appointmentService: AppointmentService, - private notificationBuilder : NotificationBuilder, + private notificationBuilder: NotificationBuilder, ) { super(); } @@ -40,7 +36,7 @@ export default class LiveVoteController extends ApiController { let voteFound = []; if (voteEntity.appointment.uid) { - const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid); + const appointment = await this.liveVoteService.getAppointmentByUid(voteEntity.appointment.uid); if (!appointment) { this.httpNotFoundRequest(response, "Appointment not found"); return; @@ -49,11 +45,11 @@ export default class LiveVoteController extends ApiController { this.httpBadRequest(response, "Appointment is closed"); return; } - voteFound = await this.votesService.get({ + voteFound = await this.liveVoteService.getVotes({ where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, }); } else { - voteFound = await this.votesService.get({ + voteFound = await this.liveVoteService.getVotes({ where: { AND: [ { @@ -96,4 +92,42 @@ export default class LiveVoteController extends ApiController { return; } } + + /** + * @description Delete a specific vote + */ + @Delete("/api/v1/super-admin/live-votes/:uid", [authHandler, roleHandler]) + protected async deleteVote(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + const voteFound = await this.liveVoteService.getVoteByUid(uid); + + if (!voteFound) { + this.httpNotFoundRequest(response, "vote not found"); + return; + } + + if (voteFound.voter_uid !== req.body.user.userId) { + this.httpUnauthorized(response, "Can't delete a vote that's not yours"); + return; + } + + //call service to get prisma entity + const voteEntity: Votes = await this.liveVoteService.deleteVote(uid); + + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(voteEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } } diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts deleted file mode 100644 index 308e46e3..00000000 --- a/src/app/api/super-admin/VotesController.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { Response, Request } from "express"; -import { Controller, Delete, Get } from "@ControllerPattern/index"; -import ApiController from "@Common/system/controller-pattern/ApiController"; -import VotesService from "@Services/super-admin/VotesService/VotesService"; -import { Service } from "typedi"; -import { Vote } from "le-coffre-resources/dist/SuperAdmin"; -import authHandler from "@App/middlewares/AuthHandler"; -import { Votes } from "@prisma/client"; -import roleHandler from "@App/middlewares/RolesHandler"; - -@Controller() -@Service() -export default class VotesController extends ApiController { - constructor(private votesService: VotesService) { - super(); - } - - /** - * @description Get all votes - */ - @Get("/api/v1/super-admin/votes", [authHandler, roleHandler]) - protected async get(req: Request, response: Response) { - try { - //get query - let query; - if (req.query["q"]) { - query = JSON.parse(req.query["q"] as string); - } - - //call service to get prisma entity - const votesEntities = await this.votesService.get(query); - - //Hydrate ressource with prisma entity - const votes = Vote.hydrateArray(votesEntities, { strategy: "excludeAll" }); - - //success - this.httpSuccess(response, votes); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } - - /** - * @description Get a specific vote by uid - */ - @Get("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler]) - protected async getOneByUid(req: Request, response: Response) { - try { - const uid = req.params["uid"]; - if (!uid) { - this.httpBadRequest(response, "No uid provided"); - return; - } - - let query; - if (req.query["q"]) { - query = JSON.parse(req.query["q"] as string); - } - - const voteEntity = await this.votesService.getByUid(uid, query); - - if (!voteEntity) { - this.httpNotFoundRequest(response, "vote not found"); - return; - } - - //Hydrate ressource with prisma entity - const vote = Vote.hydrate(voteEntity, { strategy: "excludeAll" }); - - //success - this.httpSuccess(response, vote); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } - - /** - * @description Delete a specific vote - */ - @Delete("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler]) - protected async delete(req: Request, response: Response) { - try { - const uid = req.params["uid"]; - if (!uid) { - this.httpBadRequest(response, "No uid provided"); - return; - } - - const voteFound = await this.votesService.getByUid(uid); - - if (!voteFound) { - this.httpNotFoundRequest(response, "vote not found"); - return; - } - - if (voteFound.voter_uid !== req.body.user.userId) { - this.httpUnauthorized(response, "Can't delete a vote that's not yours"); - return; - } - - //call service to get prisma entity - const votetEntity: Votes = await this.votesService.delete(uid); - - //Hydrate ressource with prisma entity - const vote = Vote.hydrate(votetEntity, { strategy: "excludeAll" }); - - //success - this.httpSuccess(response, vote); - } catch (error) { - this.httpInternalError(response, error); - return; - } - } -} diff --git a/src/app/index.ts b/src/app/index.ts index fd205cf5..95ec5f7f 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -43,20 +43,16 @@ import DocumentsControllerCustomer from "./api/customer/DocumentsController"; import OfficeFoldersController from "./api/customer/OfficeFoldersController"; import OfficeFolderAnchorsController from "./api/notary/OfficeFolderAnchorsController"; import CustomersController from "./api/customer/CustomersController"; -import AppointmentsController from "./api/super-admin/AppointmentsController"; -import VotesController from "./api/super-admin/VotesController"; import LiveVoteController from "./api/super-admin/LiveVoteController"; import DocumentControllerId360 from "./api/id360/DocumentController"; import CustomerControllerId360 from "./api/id360/CustomerController"; import UserNotificationController from "./api/common/UserNotificationController"; - /** * @description This allow to declare all controllers used in the application */ export default { - start: () => { Container.get(HomeController); Container.get(UsersControllerSuperAdmin); @@ -67,8 +63,6 @@ export default { Container.get(DeedTypesControllerSuperAdmin); Container.get(DocumentsControllerSuperAdmin); Container.get(DocumentTypesControllerSuperAdmin); - Container.get(AppointmentsController); - Container.get(VotesController); Container.get(LiveVoteController); Container.get(IdNotUserController); Container.get(FranceConnectCustomerController); diff --git a/src/services/super-admin/AppointmentsService/AppointmentsService.ts b/src/services/super-admin/AppointmentsService/AppointmentsService.ts deleted file mode 100644 index 45d8b481..00000000 --- a/src/services/super-admin/AppointmentsService/AppointmentsService.ts +++ /dev/null @@ -1,53 +0,0 @@ -import BaseService from "@Services/BaseService"; -import { Service } from "typedi"; -import AppointmentsRepository from "@Repositories/AppointmentsRepository"; -import { Prisma, Appointments, EAppointmentStatus } from "@prisma/client"; - -@Service() -export default class AppointmentService extends BaseService { - constructor(private appointmentRepository: AppointmentsRepository) { - super(); - } - - /** - * @description : Get all appointments - * @throws {Error} If appointments cannot be get - */ - public get(query: Prisma.AppointmentsFindManyArgs) { - return this.appointmentRepository.findMany(query); - } - - /** - * @description : Modify a appointment - * @throws {Error} If appointment cannot be modified - */ - public async update(uid: string, status: EAppointmentStatus): Promise { - return this.appointmentRepository.update(uid, status); - } - - /** - * @description : Get a appointment by uid - * @throws {Error} If appointment cannot be get by uid - */ - public getByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise { - return this.appointmentRepository.findOneByUid(uid, query); - } - - /** - * @description : Get a appointment by uid - * @throws {Error} If appointment cannot be get by uid - */ - public getByUidWithVotes(uid: string) { - return this.appointmentRepository.findOneByUidWithVotes(uid); - } - - /** - * @description : delete a appointment by uid - * @throws {Error} If appointment cannot be get by uid - */ - public delete(uid: string) { - return this.appointmentRepository.delete(uid); - } - - -} diff --git a/src/services/super-admin/LiveVoteService/LiveVoteService.ts b/src/services/super-admin/LiveVoteService/LiveVoteService.ts index 5576bb28..028078f6 100644 --- a/src/services/super-admin/LiveVoteService/LiveVoteService.ts +++ b/src/services/super-admin/LiveVoteService/LiveVoteService.ts @@ -2,16 +2,16 @@ import BaseService from "@Services/BaseService"; import { Service } from "typedi"; import User, { Appointment, Role, Vote } from "le-coffre-resources/dist/SuperAdmin"; import VotesRepository from "@Repositories/VotesRepository"; -import { Appointments, EAppointmentStatus, EVote, Votes } from "@prisma/client"; -import AppointmentService from "../AppointmentsService/AppointmentsService"; +import { Appointments, EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client"; import UsersService from "../UsersService/UsersService"; import RolesService from "../RolesService/RolesService"; +import AppointmentsRepository from "@Repositories/AppointmentsRepository"; @Service() export default class LiveVoteService extends BaseService { constructor( private voteRepository: VotesRepository, - private appointmentService: AppointmentService, + private appointmentRepository: AppointmentsRepository, private userService: UsersService, private roleService: RolesService, ) { @@ -29,11 +29,39 @@ export default class LiveVoteService extends BaseService { return false; } + public getVotes(query: Prisma.VotesFindManyArgs) { + return this.voteRepository.findMany(query); + } + + /** + * @description : Get a vote by uid + * @throws {Error} If vote cannot be get by uid + */ + public getVoteByUid(uid: string, query?: Prisma.VotesInclude) { + return this.voteRepository.findOneByUid(uid, query); + } + + /** + * @description : delete a vote by uid + * @throws {Error} If vote cannot be get by uid + */ + public deleteVote(uid: string) { + return this.voteRepository.delete(uid); + } + + /** + * @description : Get a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public getAppointmentByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise { + return this.appointmentRepository.findOneByUid(uid, query); + } + public async getAppointmentWithVotes(vote: Vote): Promise { if (vote.appointment.uid) { - return this.appointmentService.getByUidWithVotes(vote.appointment.uid); + return this.appointmentRepository.findOneByUid(vote.appointment.uid); } - const appointmentByUser = await this.appointmentService.get({ + const appointmentByUser = await this.appointmentRepository.findMany({ where: { AND: [ { user_uid: vote.appointment.targeted_user.uid }, @@ -44,13 +72,13 @@ export default class LiveVoteService extends BaseService { include: { votes: true }, }); if (appointmentByUser.length >= 1) { - return this.appointmentService.getByUidWithVotes(appointmentByUser[0]!.uid); + return this.appointmentRepository.findOneByUidWithVotes(appointmentByUser[0]!.uid); } return null; } private async closeVote(appointment: Appointments, vote: Votes) { - await this.appointmentService.update(vote.appointment_uid, EAppointmentStatus.CLOSED); + await this.appointmentRepository.update(vote.appointment_uid, EAppointmentStatus.CLOSED); const user = await this.userService.getByUid(appointment.user_uid, { role: true }); const userEntity = User.hydrate(user!, { strategy: "excludeAll" }); @@ -90,7 +118,7 @@ export default class LiveVoteService extends BaseService { } const approvedChoice = await this.verifyVoterChoice(vote); - if(!approvedChoice) return null; + if (!approvedChoice) return null; return this.voteRepository.create(vote); } diff --git a/src/services/super-admin/VotesService/VotesService.ts b/src/services/super-admin/VotesService/VotesService.ts deleted file mode 100644 index fa32fb4d..00000000 --- a/src/services/super-admin/VotesService/VotesService.ts +++ /dev/null @@ -1,35 +0,0 @@ -import BaseService from "@Services/BaseService"; -import { Service } from "typedi"; -import VotesRepository from "@Repositories/VotesRepository"; -import { Prisma } from "@prisma/client"; - -@Service() -export default class VoteService extends BaseService { - constructor(private voteRepository: VotesRepository) { - super(); - } - - /** - * @description : Get all votes - * @throws {Error} If votes cannot be get - */ - public get(query: Prisma.VotesFindManyArgs) { - return this.voteRepository.findMany(query); - } - - /** - * @description : Get a vote by uid - * @throws {Error} If vote cannot be get by uid - */ - public getByUid(uid: string, query?: Prisma.VotesInclude) { - return this.voteRepository.findOneByUid(uid, query); - } - - /** - * @description : delete a vote by uid - * @throws {Error} If vote cannot be get by uid - */ - public delete(uid: string) { - return this.voteRepository.delete(uid); - } -} From 2fc307f3c3b44eb5c9bb87382e8fcf3bd1038e3c Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Wed, 27 Sep 2023 16:34:23 +0200 Subject: [PATCH 2/2] :sparkles: Delete appointment if no votes in appointment --- src/app/api/super-admin/LiveVoteController.ts | 16 ++++++++++++---- .../LiveVoteService/LiveVoteService.ts | 8 ++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/app/api/super-admin/LiveVoteController.ts b/src/app/api/super-admin/LiveVoteController.ts index ade311ca..65956b50 100644 --- a/src/app/api/super-admin/LiveVoteController.ts +++ b/src/app/api/super-admin/LiveVoteController.ts @@ -105,7 +105,11 @@ export default class LiveVoteController extends ApiController { return; } - const voteFound = await this.liveVoteService.getVoteByUid(uid); + const voteFound = await this.liveVoteService.getVoteByUid(uid, { + appointment: { + include: { votes: true }, + }, + }); if (!voteFound) { this.httpNotFoundRequest(response, "vote not found"); @@ -117,14 +121,18 @@ export default class LiveVoteController extends ApiController { return; } + const vote = Vote.hydrate(voteFound, { strategy: "excludeAll" }); + //call service to get prisma entity const voteEntity: Votes = await this.liveVoteService.deleteVote(uid); - //Hydrate ressource with prisma entity - const vote = Vote.hydrate(voteEntity, { strategy: "excludeAll" }); + if (vote.appointment.uid && vote.appointment.votes && vote.appointment.votes.length === 1) { + await this.liveVoteService.deleteAppointment(vote.appointment.uid); + } + const voteToReturn = Vote.hydrate(voteEntity, { strategy: "excludeAll" }); //success - this.httpSuccess(response, vote); + this.httpSuccess(response, voteToReturn); } catch (error) { this.httpInternalError(response, error); return; diff --git a/src/services/super-admin/LiveVoteService/LiveVoteService.ts b/src/services/super-admin/LiveVoteService/LiveVoteService.ts index 028078f6..a034f976 100644 --- a/src/services/super-admin/LiveVoteService/LiveVoteService.ts +++ b/src/services/super-admin/LiveVoteService/LiveVoteService.ts @@ -49,6 +49,14 @@ export default class LiveVoteService extends BaseService { return this.voteRepository.delete(uid); } + /** + * @description : delete an appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public deleteAppointment(uid: string) { + return this.appointmentRepository.delete(uid); + } + /** * @description : Get a appointment by uid * @throws {Error} If appointment cannot be get by uid