import EmailRepository from "@Repositories/EmailRepository"; import BaseService from "@Services/BaseService"; import { Emails, Prisma } from "@prisma/client"; import { Service } from "typedi"; import MailchimpClient from "@mailchimp/mailchimp_transactional"; import { BackendVariables } from "@Common/config/variables/Variables"; import UsersService from "@Services/super-admin/UsersService/UsersService"; import EmailBuilder from "@Common/emails/EmailBuilder"; @Service() export default class MailchimpService extends BaseService { private static readonly from = "vincent.alamelle@smart-chain.fr"; constructor( private emailRepository: EmailRepository, protected variables: BackendVariables, private usersService: UsersService, private emailBuilder: EmailBuilder, ) { super(); } /** * @description : Get all emails * @throws {Error} If emails cannot be get */ public async get(query: Prisma.EmailsFindManyArgs): Promise { return this.emailRepository.findMany(query); } /** * @description : Create a new email * @throws {Error} If email cannot be created */ public async create(emailEntity: Emails): Promise { emailEntity.from = MailchimpService.from; return this.emailRepository.create(emailEntity); } /** * @description : Modify an email * @throws {Error} If email cannot be modified */ public async update(uid: string, emailEntity: Emails): Promise { return this.emailRepository.update(uid, emailEntity); } /** * @description : Get a email by uid * @throws {Error} If email cannot be get */ public async getByUid(uid: string, query?: any): Promise { return this.emailRepository.findOneByUid(uid); } /** * @description : Function called by cron to send emails * @throws {Error} If email cannot be sent */ public async sendEmails() { const emailsToSend = await this.get({ where: { sentAt: null } }); const currentDate = new Date(); let nextTrySendDate = null; for (const email of emailsToSend) { //If tries exceed 10, we stop trying to send the email if (email.nbTrySend && email.nbTrySend > 9) continue; //If email has never been sent, we send it if (email.nbTrySend == 0) { nextTrySendDate = currentDate; } //If email has already been sent, we send it again every nbTrySend^2 minutes else { nextTrySendDate = new Date(email.lastTrySendDate!); nextTrySendDate.setMinutes(nextTrySendDate.getMinutes() + Math.pow(email.nbTrySend!, 2)); } //If the next try send date is passed, we send the email if (currentDate >= nextTrySendDate) { try { await this.sendEmail(email); email.sentAt = currentDate; } catch (error) { email.lastTrySendDate = currentDate; email.nbTrySend = email.nbTrySend! + 1; } await this.update(email.uid, email); } } } private async sendEmail(email: Emails) { const apiKey = this.variables.MAILCHIMP_API_KEY; const mailchimpApiClient = MailchimpClient(apiKey!); await mailchimpApiClient.messages.sendTemplate({ template_name: email.templateName, template_content: [], message: { global_merge_vars: this.buildVariables(email.templateVariables), from_email: email.from!, from_name: "LeCoffre.io", subject: email.subject, to: [ { email: email.to, type: "to", }, ], }, }); } private buildVariables(templateVariables: any) { return Object.keys(templateVariables).map((key) => { return { name: key, content: templateVariables[key], }; }); } public async sendRecapEmails() { const usersToEmail = await this.usersService.get({ where: { office_folders: { some:{ documents: { some: { document_status: "DEPOSITED" } } }} }, distinct: ["uid"], include: { contact: true } }); await this.emailBuilder.sendRecapEmails(usersToEmail); } }