Notif cron

This commit is contained in:
Vins 2023-09-26 11:39:21 +02:00
parent 6e811d1b03
commit 29a8e23c43
4 changed files with 178 additions and 85 deletions

View File

@ -1,56 +1,81 @@
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
import { Documents } from "@prisma/client";
import User, { Document, Vote } from "le-coffre-resources/dist/SuperAdmin";
import User, { Document, OfficeFolder, Vote } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
import NotificationsService from "@Services/common/NotificationsService/NotificationsService";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
@Service()
export default class NotificationBuilder {
public constructor(private notificationsService : NotificationsService, private documentsService: DocumentsService, private usersService: UsersService){}
public constructor(
private notificationsService: NotificationsService,
private documentsService: DocumentsService,
private usersService: UsersService,
private foldersService: OfficeFoldersService,
) {}
public async sendDocumentDepositedNotification(documentEntity: Documents){
if(documentEntity.document_status !== "DEPOSITED") return;
public async sendDocumentDepositedNotification(documentEntity: Documents) {
if (documentEntity.document_status !== "DEPOSITED") return;
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, { depositor: {include: {contact: true}}, folder:{include:{ office: true, stakeholders: true}} });
if(!documentPrisma) throw new Error("Document not found");
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, {
depositor: { include: { contact: true } },
folder: { include: { office: true, stakeholders: true } },
});
if (!documentPrisma) throw new Error("Document not found");
const document = Document.hydrate<Document>(documentPrisma);
this.notificationsService.create({
message: "Votre client " + document.depositor?.contact?.first_name + " " + document.depositor?.contact?.last_name + " vous a envoyé un document à valider",
message:
"Votre client " +
document.depositor?.contact?.first_name +
" " +
document.depositor?.contact?.last_name +
" vous a envoyé un document à valider",
redirection_url: "",
created_at: new Date(),
updated_at: new Date(),
user : document.folder!.stakeholders || [],
user: document.folder!.stakeholders || [],
});
}
public async sendDocumentAnchoredNotification(documentEntity: Documents){
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, { depositor: {include: {contact: true}}, folder:{include:{ folder_anchor : true ,office: true, stakeholders: true}} });
if(!documentPrisma) throw new Error("Document not found");
public async sendDocumentAnchoredNotification(documentEntity: Documents) {
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, {
depositor: { include: { contact: true } },
folder: { include: { folder_anchor: true, office: true, stakeholders: true } },
});
if (!documentPrisma) throw new Error("Document not found");
const document = Document.hydrate<Document>(documentPrisma);
if(document.folder?.anchor?.status !== "VERIFIED_ON_CHAIN") return;
if (document.folder?.anchor?.status !== "VERIFIED_ON_CHAIN") return;
this.notificationsService.create({
message: "Le dossier " + document.folder?.folder_number + " - " + document.folder?.name + " a été certifié. Vous pouvez désormais télécharger le certificat de dépôt pour le mettre dans la GED de votre logiciel de rédaction d'acte.",
message:
"Le dossier " +
document.folder?.folder_number +
" - " +
document.folder?.name +
" a été certifié. Vous pouvez désormais télécharger le certificat de dépôt pour le mettre dans la GED de votre logiciel de rédaction d'acte.",
redirection_url: "",
created_at: new Date(),
updated_at: new Date(),
user : document.folder!.stakeholders || [],
user: document.folder!.stakeholders || [],
});
}
public async sendVoteNotification(vote: Vote){
if(vote.appointment.status !== "OPEN") return;
const superAdminList = await this.usersService.get({where: {role : {label : "super-admin"}}});
public async sendVoteNotification(vote: Vote) {
if (vote.appointment.status !== "OPEN") return;
const superAdminList = await this.usersService.get({ where: { role: { label: "super-admin" } } });
let message = "";
if(vote.appointment.choice === "NOMINATE"){
message = "Un collaborateur souhaite attribuer le titre de Super Administrateur à " + vote.appointment.targeted_user + ". Cliquez ici pour voter."
}
else if(vote.appointment.choice === "DISMISS"){
message = "Un collaborateur souhaite retirer le titre de Super Administrateur à " + vote.appointment.targeted_user + ". Cliquez ici pour voter."
if (vote.appointment.choice === "NOMINATE") {
message =
"Un collaborateur souhaite attribuer le titre de Super Administrateur à " +
vote.appointment.targeted_user +
". Cliquez ici pour voter.";
} else if (vote.appointment.choice === "DISMISS") {
message =
"Un collaborateur souhaite retirer le titre de Super Administrateur à " +
vote.appointment.targeted_user +
". Cliquez ici pour voter.";
}
this.notificationsService.create({
@ -58,28 +83,58 @@ export default class NotificationBuilder {
redirection_url: "",
created_at: new Date(),
updated_at: new Date(),
user : superAdminList || [],
user: superAdminList || [],
});
}
public async sendDismissNotification(user: User){
public async sendDismissNotification(user: User) {
this.notificationsService.create({
message: "Vous n'avez désormais plus le rôle de Super Administrateur de la plateforme.",
redirection_url: "",
created_at: new Date(),
updated_at: new Date(),
user : [user] || [],
user: [user] || [],
});
}
public async sendNominateNotification(user: User){
public async sendNominateNotification(user: User) {
this.notificationsService.create({
message: "Vous avez désormais le rôle de Super Administrateur de la plateforme.",
redirection_url: "",
created_at: new Date(),
updated_at: new Date(),
user : [user] || [],
user: [user] || [],
});
}
public async sendDocumentExpiringSoonNotification(folderUid: string, expirationDate: Date) {
const day = expirationDate.getDate();
const month = expirationDate.getMonth() + 1; // Months are 0-based, so add 1
const year = expirationDate.getFullYear();
// Ensure that the day and month have two digits (e.g., 01, 02, 11)
const formattedDay = day < 10 ? `0${day}` : `${day}`;
const formattedMonth = month < 10 ? `0${month}` : `${month}`;
const formattedDate = `${formattedDay}/${formattedMonth}/${year}`;
const folderPrisma = await this.foldersService.getByUid(folderUid, { stakeholders: true, office: true });
if (!folderPrisma) throw new Error("Document not found");
const folder = OfficeFolder.hydrate<OfficeFolder>(folderPrisma);
this.notificationsService.create({
message:
"Vous devez valider le dossier " +
folder.folder_number +
" - " +
folder.name +
" avant le " +
formattedDate +
" (date limite d'expiration des documents).",
redirection_url: "",
created_at: new Date(),
updated_at: new Date(),
user: folder.stakeholders || [],
});
}
}

View File

@ -12,6 +12,7 @@ import CronService from "@Services/common/CronService/CronService";
const variables = await Container.get(BackendVariables).validate();
Container.get(CronService).archiveFiles();
await Container.get(CronService).updateUsers();
Container.get(CronService).checkDocumentsExpiration();
if(variables.ENV !== "dev"){
Container.get(CronService).sendMails();
Container.get(CronService).sendRecapMails();

View File

@ -3,14 +3,22 @@ import { CronJob } from "cron";
import MailchimpService from "../MailchimpService/MailchimpService";
import FilesService from "../FilesService/FilesService";
import IdNotService from "../IdNotService/IdNotService";
import { PrismaClient } from "@prisma/client";
import NotificationBuilder from "@Common/notifications/NotificationBuilder";
// import { PrismaClient } from "@prisma/client";
@Service()
export default class CronService {
constructor(private mailchimpService: MailchimpService, private filesService: FilesService, private idNotService: IdNotService) {}
constructor(
private mailchimpService: MailchimpService,
private filesService: FilesService,
private idNotService: IdNotService,
private notificationBuilder: NotificationBuilder
) {}
public async sendMails() {
const cronJob = new CronJob("*/15 * * * * *", async () => { // Every 15 seconds
const cronJob = new CronJob("*/15 * * * * *", async () => {
// Every 15 seconds
try {
await this.mailchimpService.sendEmails();
} catch (e) {
@ -25,7 +33,8 @@ export default class CronService {
}
public async sendRecapMails() {
const cronJob = new CronJob("0 20 * * FRI", async () => { // Every friday at 20:00
const cronJob = new CronJob("0 20 * * FRI", async () => {
// Every friday at 20:00
try {
await this.mailchimpService.sendRecapEmails();
} catch (e) {
@ -40,7 +49,8 @@ export default class CronService {
}
public async archiveFiles() {
const cronJob = new CronJob("0 0 * * MON", async () => { // Every monday at midnight
const cronJob = new CronJob("0 0 * * MON", async () => {
// Every monday at midnight
try {
await this.filesService.archiveOldFiles();
} catch (e) {
@ -54,7 +64,8 @@ export default class CronService {
}
}
public async updateUsers() {
const cronJob = new CronJob("0 0 * * *", async () => { // Once a day at midnight
const cronJob = new CronJob("0 0 * * *", async () => {
// Once a day at midnight
try {
await this.idNotService.updateOffices();
await this.idNotService.updateUsers();
@ -67,4 +78,33 @@ export default class CronService {
cronJob.start();
}
}
public async checkDocumentsExpiration() {
const cronJob = new CronJob("*/10 * * * * *", async () => {
// Once a day at midnight
try {
const prisma = new PrismaClient();
const expiringDocuments15Days: [{uid: string, expiration_date: Date}] = await prisma.$queryRaw
`SELECT distinct o.uid, f.created_at as expiration_date
FROM documents d
JOIN files f ON d.uid=f.document_uid
JOIN office_folders o ON o.uid=d.folder_uid
WHERE o.folder_anchor_uid IS null
AND d.document_status = 'DEPOSITED'
AND current_date = (DATE(f.created_at) + interval '3 months' - interval '2 days');`;
expiringDocuments15Days.forEach(expiringFolder => {
this.notificationBuilder.sendDocumentExpiringSoonNotification(expiringFolder.uid, expiringFolder.expiration_date);
});
} catch (e) {
console.error(e);
}
});
// Start job
if (!cronJob.running) {
cronJob.start();
}
}
}

View File

@ -4,13 +4,14 @@ import { Emails, PrismaClient } from "@prisma/client";
import { Service } from "typedi";
import MailchimpClient from "@mailchimp/mailchimp_transactional";
import { BackendVariables } from "@Common/config/variables/Variables";
import EmailBuilder from "@Common/emails/EmailBuilder";
// import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
@Service()
export default class MailchimpService extends BaseService {
private static readonly from = "vincent.alamelle@smart-chain.fr";
constructor(private emailRepository: EmailRepository, protected variables: BackendVariables) {
constructor(private emailRepository: EmailRepository, protected variables: BackendVariables, private emailBuilder: EmailBuilder) {
super();
}
@ -85,11 +86,7 @@ export default class MailchimpService extends BaseService {
}
private async sendEmail(email: Emails) {
console.log("sendEmail");
const apiKey = this.variables.MAILCHIMP_API_KEY;
console.log(apiKey);
const mailchimpApiClient = MailchimpClient(apiKey!);
await mailchimpApiClient.messages.sendTemplate({
@ -121,7 +118,7 @@ export default class MailchimpService extends BaseService {
public async sendRecapEmails() {
const prisma = new PrismaClient();
const usersToEmail = await prisma.$queryRaw
const usersToEmail: [{email: string, civility: string, last_name: string}] = await prisma.$queryRaw
`SELECT DISTINCT c.email, c.civility, c.last_name
FROM Contacts c
JOIN Users u ON c.uid = u.contact_uid
@ -129,6 +126,6 @@ export default class MailchimpService extends BaseService {
JOIN Documents d ON of.uid = d.folder_uid
WHERE d.document_status = 'DEPOSITED';`
console.log(usersToEmail);
await this.emailBuilder.sendRecapEmails(usersToEmail);
}
}