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, 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 { validateOrReject } from "class-validator"; import { Request, Response } from "express"; import { Vote } from "le-coffre-resources/dist/SuperAdmin"; import { Service } from "typedi"; @Controller() @Service() export default class LiveVoteController extends ApiController { constructor( private liveVoteService: LiveVoteService, private usersService: UsersService, private notificationBuilder: NotificationBuilder, ) { super(); } /** * @description Create a new vote */ @Post("/api/v1/super-admin/live-votes", [authHandler, roleHandler]) protected async post(req: Request, response: Response) { try { const userId = req.body.user.userId; //init IUser resource with request body values const voteEntity = Vote.hydrate(req.body, { strategy: "excludeAll" }); //validate user await validateOrReject(voteEntity, { groups: ["createVote"] }); let voteFound = []; if (voteEntity.appointment.uid) { const appointment = await this.liveVoteService.getAppointmentByUid(voteEntity.appointment.uid); if (!appointment) { this.httpNotFoundRequest(response, "Appointment not found"); return; } if (appointment.status === EAppointmentStatus.CLOSED) { this.httpBadRequest(response, "Appointment is closed"); return; } voteFound = await this.liveVoteService.getVotes({ where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, }); } else { voteFound = await this.liveVoteService.getVotes({ where: { AND: [ { appointment: { AND: [{ user_uid: voteEntity.appointment.user.uid }, { status: EAppointmentStatus.OPEN }], }, }, { voter: { uid: userId } }, ], }, }); } if (voteFound.length) { this.httpBadRequest(response, "Voter already voted for this appointment"); return; } const voter = await this.usersService.getByUid(userId); voteEntity.voter = voter!; //call service to get prisma entity const voteEntityCreated = await this.liveVoteService.create(voteEntity); if (!voteEntityCreated) { this.httpBadRequest(response, "Appointment choice is not valid"); return; } //Hydrate ressource with prisma entity const vote = Vote.hydrate(voteEntityCreated, { strategy: "excludeAll" }); await this.notificationBuilder.sendVoteNotification(vote); //success this.httpCreated(response, vote); } catch (error) { this.httpInternalError(response, error); 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, { appointment: { include: { votes: true }, }, }); 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; } const vote = Vote.hydrate(voteFound, { strategy: "excludeAll" }); //call service to get prisma entity const voteEntity: Votes = await this.liveVoteService.deleteVote(uid); 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, voteToReturn); } catch (error) { this.httpInternalError(response, error); return; } } }