169 lines
5.4 KiB
TypeScript
169 lines
5.4 KiB
TypeScript
import dayjs from "dayjs";
|
|
import axios from "axios";
|
|
import { logDone, logError, logIntent } from "../../config/logger.js";
|
|
import { Appointments, IAppointment, IAppointmentDocument } from "../Appointments/Appointments.js";
|
|
import { Companies } from "../Companies/Companies.js";
|
|
import { PlanSuscriptions } from "../PlanSubscriptions/PlanSubscriptions.js";
|
|
|
|
export type ApiVoidResult = {
|
|
success: boolean;
|
|
message: string;
|
|
};
|
|
|
|
export type SendWapSystemNotificationParams = {
|
|
appointmentId: string;
|
|
systemToken: string;
|
|
};
|
|
|
|
export class Notifications {
|
|
private users: string[] = [];
|
|
private companies: string[] = [];
|
|
private appointments: IAppointmentDocument[] = [];
|
|
private appointmentsCollection: Appointments;
|
|
constructor() {
|
|
this.users = [];
|
|
this.companies = [];
|
|
this.appointments = [];
|
|
this.appointmentsCollection = new Appointments();
|
|
}
|
|
|
|
private async loadUsers() {
|
|
logIntent("Cargando lista de usuarios.");
|
|
const loadedPlanIds = `${process.env.PLAN_LIST}`;
|
|
|
|
if (loadedPlanIds === "") {
|
|
logError("No se ha encontrado una lista de planes valida.", "");
|
|
process.exit(1);
|
|
}
|
|
|
|
const PLAN_IDS = loadedPlanIds.split(",");
|
|
const subs = new PlanSuscriptions();
|
|
const result = await subs.planSuscriptionList.find({ planId: { $in: PLAN_IDS } }).exec();
|
|
this.users = result.map((x) => String(x.userId));
|
|
logDone("Lista de usuarios cargada correctamente.");
|
|
}
|
|
|
|
private async loadCompanies() {
|
|
logIntent("Cargando lista de organizaciones.");
|
|
const orgs = new Companies();
|
|
|
|
for (const user of this.users) {
|
|
const organizations = await orgs.companyList
|
|
.find({ ownerId: user, automaticNotifications: true })
|
|
.exec();
|
|
|
|
for (const orgItem of organizations) {
|
|
this.companies.push(orgItem.id);
|
|
}
|
|
}
|
|
logDone("Lista de organizaciones cargada correctamente.");
|
|
}
|
|
|
|
private async loadAppointments() {
|
|
try {
|
|
logIntent("Cargando nuevo lote de notificaciones");
|
|
this.appointments = [];
|
|
const dateFrom = dayjs().clone().startOf("day");
|
|
const dateTo = dayjs().clone().endOf("day");
|
|
|
|
for (const company of this.companies) {
|
|
const result = await this.appointmentsCollection.appointmentsList
|
|
.findOne({
|
|
start: { $gte: dateFrom.toDate(), $lte: dateTo.toDate() },
|
|
companyId: company,
|
|
$and: [
|
|
{ $or: [{ notificated: false }, { notificated: { $exists: false } }] },
|
|
{
|
|
$or: [
|
|
{ notificationIntents: { $lt: 3 } },
|
|
{ notificationIntents: { $exists: false } },
|
|
],
|
|
},
|
|
],
|
|
})
|
|
.exec();
|
|
if (!result) {
|
|
continue;
|
|
}
|
|
this.appointments.push(result);
|
|
}
|
|
logDone("Nuevo lote de notificaciones cargado correctamente.");
|
|
} catch (error) {
|
|
logError("Error cargando nuevo lote de notificaciones:", error);
|
|
}
|
|
}
|
|
|
|
public async start() {
|
|
await this.loadUsers();
|
|
await this.loadCompanies();
|
|
await this.loadAppointments();
|
|
|
|
this.next();
|
|
}
|
|
public async next() {
|
|
const getDelay = () => {
|
|
const timeBase = Number(process.env.TIME_BASE ? process.env.TIME_BASE : 8);
|
|
const timeExtra = Number(process.env.TIME_EXTRA ? process.env.TIME_EXTRA : 8);
|
|
return Math.floor(Math.random() * timeBase) + timeExtra;
|
|
};
|
|
|
|
const app = this.appointments.shift();
|
|
|
|
if (!app) {
|
|
logDone("Se ha finalizado el envío del lote de notificaciones.");
|
|
setTimeout(() => {
|
|
this.reload();
|
|
}, getDelay() * 1000);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await this.send(String(app.id));
|
|
app.notificated = true;
|
|
} catch (error) {
|
|
app.notificationIntents = app.notificationIntents ? app.notificationIntents + 1 : 1;
|
|
logError("Error enviando notificación:", error);
|
|
}
|
|
|
|
await app.save();
|
|
|
|
setTimeout(() => {
|
|
this.next();
|
|
}, getDelay() * 1000);
|
|
}
|
|
|
|
public async reload() {
|
|
await this.loadAppointments();
|
|
if (this.appointments.length < 1) {
|
|
this.end();
|
|
}
|
|
this.next();
|
|
}
|
|
|
|
public async end() {
|
|
process.exit(0);
|
|
}
|
|
|
|
private async send(appointmentId: string): Promise<void> {
|
|
logIntent(`Enviando notificación para la cita ${appointmentId}.`);
|
|
|
|
const dataApi: SendWapSystemNotificationParams = {
|
|
appointmentId: appointmentId,
|
|
systemToken: `${process.env.API_KEY}`,
|
|
};
|
|
const response = await axios.post<ApiVoidResult>(`${process.env.API_URL}`, dataApi, {
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
|
|
const result: ApiVoidResult = response.data;
|
|
|
|
if (!result.success) {
|
|
throw new Error(result.message);
|
|
}
|
|
|
|
logDone("Notificación enviada correctamente.");
|
|
}
|
|
}
|