134 lines
4.6 KiB
TypeScript
134 lines
4.6 KiB
TypeScript
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, 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 appointmentRepository: AppointmentsRepository,
|
|
private userService: UsersService,
|
|
private roleService: RolesService,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
public async verifyVoterChoice(vote: Vote): Promise<boolean> {
|
|
const userWithRole = await this.userService.getByUidWithRole(vote.appointment.targeted_user.uid!);
|
|
if (userWithRole!.role.name === "super-admin" && vote.appointment.choice === EVote.DISMISS) {
|
|
return true;
|
|
}
|
|
if (userWithRole!.role.name !== "super-admin" && vote.appointment.choice === EVote.NOMINATE) {
|
|
return true;
|
|
}
|
|
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 : 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
|
|
*/
|
|
public getAppointmentByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise<Appointments | null> {
|
|
return this.appointmentRepository.findOneByUid(uid, query);
|
|
}
|
|
|
|
public async getAppointmentWithVotes(vote: Vote): Promise<Appointments | null> {
|
|
if (vote.appointment.uid) {
|
|
return this.appointmentRepository.findOneByUid(vote.appointment.uid);
|
|
}
|
|
const appointmentByUser = await this.appointmentRepository.findMany({
|
|
where: {
|
|
AND: [
|
|
{ user_uid: vote.appointment.targeted_user.uid },
|
|
{ status: EAppointmentStatus.OPEN },
|
|
{ choice: EVote[vote.appointment.choice as keyof typeof EVote] },
|
|
],
|
|
},
|
|
include: { votes: true },
|
|
});
|
|
if (appointmentByUser.length >= 1) {
|
|
return this.appointmentRepository.findOneByUidWithVotes(appointmentByUser[0]!.uid);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private async closeVote(appointment: Appointments, vote: Votes) {
|
|
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>(user!, { strategy: "excludeAll" });
|
|
|
|
return await this.updateRole(appointment, userEntity, vote);
|
|
}
|
|
|
|
private async updateRole(appointment: Appointments, userEntity: User, vote: Votes) {
|
|
if (appointment.choice === EVote.DISMISS) {
|
|
const roles = await this.roleService.get({ where: { name: "default" } });
|
|
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
|
|
userEntity.role = roleEntity;
|
|
await this.userService.update(appointment!.user_uid, userEntity);
|
|
return vote;
|
|
} else if (appointment.choice === EVote.NOMINATE) {
|
|
const roles = await this.roleService.get({ where: { name: "super-admin" } });
|
|
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
|
|
userEntity!.role = roleEntity;
|
|
await this.userService.update(appointment!.user_uid, userEntity);
|
|
return vote;
|
|
}
|
|
return vote;
|
|
}
|
|
|
|
/**
|
|
* @description : Create a vote
|
|
* @throws {Error} If vote couldn't be created
|
|
*/
|
|
public async create(vote: Vote): Promise<Votes | null> {
|
|
const appointment = await this.getAppointmentWithVotes(vote);
|
|
|
|
if (appointment) {
|
|
const appointmentEntity = Appointment.hydrate<Appointment>(appointment, { strategy: "excludeAll" });
|
|
if (appointmentEntity?.votes && appointmentEntity.votes.length >= 2) {
|
|
const voteCreated = await this.voteRepository.create(vote);
|
|
return this.closeVote(appointment, voteCreated);
|
|
}
|
|
}
|
|
|
|
const approvedChoice = await this.verifyVoterChoice(vote);
|
|
if (!approvedChoice) return null;
|
|
|
|
return this.voteRepository.create(vote);
|
|
}
|
|
}
|