Skip to content

Commit 8120157

Browse files
authored
Feat generate sms inserasaf (#3892)
1 parent c228625 commit 8120157

File tree

8 files changed

+171
-10
lines changed

8 files changed

+171
-10
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { MessageSms } from "@domifa/common";
2+
import { MigrationInterface, QueryRunner } from "typeorm";
3+
import { messageSmsRepository } from "../database";
4+
import { appLogger } from "../util";
5+
import { domifaConfig } from "../config";
6+
7+
export class ManualMigration1756117243339 implements MigrationInterface {
8+
name = "CreateSmsForUserUsager1756117243339";
9+
10+
public async up(queryRunner: QueryRunner): Promise<void> {
11+
if (domifaConfig().envId === "prod") {
12+
appLogger.warn(
13+
"Début de la migration : Création des SMS pour les comptes usagers"
14+
);
15+
16+
// Récupération de tous les user_usager avec les informations nécessaires via jointure
17+
const userUsagers = await queryRunner.query(`
18+
SELECT
19+
uu.id,
20+
uu."usagerUUID",
21+
uu."structureId",
22+
uu.login,
23+
u.ref as "usagerRef",
24+
u.telephone,
25+
u."dateNaissance"
26+
FROM user_usager uu
27+
INNER JOIN usager u ON uu."usagerUUID" = u.uuid
28+
WHERE u.telephone IS NOT NULL
29+
AND (u.options ->> 'portailUsagerEnabled')::boolean = true
30+
AND u."structureId" = 2165
31+
AND (u.telephone->>'numero') IS NOT NULL
32+
AND (u.telephone->>'numero') != ''
33+
`);
34+
35+
appLogger.warn(`Nombre d'utilisateurs trouvés : ${userUsagers.length}`);
36+
37+
const smsToSave: MessageSms[] = [];
38+
const scheduledDate = new Date();
39+
40+
for (const userUsager of userUsagers) {
41+
const { login, telephone, usagerRef, structureId } = userUsager;
42+
43+
const phoneNumber = telephone?.numero || "";
44+
45+
if (!phoneNumber) {
46+
appLogger.warn(
47+
`Numéro de téléphone manquant pour l'usager ${userUsager.usagerUUID}`
48+
);
49+
continue;
50+
}
51+
52+
// Contenu du SMS
53+
const smsContent = `Nouveau portail Inserasaf pour consulter votre courrier !
54+
Connexion: https://urlr.me/JCdwYs
55+
ID: ${login}
56+
MDP: votre date de naissance
57+
DomiFa`;
58+
59+
smsToSave.push({
60+
usagerRef: usagerRef,
61+
structureId: structureId,
62+
content: smsContent,
63+
senderName: "DomiFa",
64+
status: "TO_SEND",
65+
smsId: "idMonDomiFa",
66+
phoneNumber: phoneNumber,
67+
scheduledDate,
68+
errorCount: 0,
69+
});
70+
}
71+
72+
if (smsToSave?.length > 0) {
73+
await messageSmsRepository.save(smsToSave);
74+
appLogger.warn(`Migration terminée : ${smsToSave.length} SMS créés`);
75+
} else {
76+
appLogger.warn("Aucun SMS à créer");
77+
}
78+
}
79+
}
80+
81+
public async down(): Promise<void> {
82+
appLogger.warn(
83+
"Début du rollback : Suppression des SMS de création de compte"
84+
);
85+
}
86+
}

packages/backend/src/modules/sms/services/message-sms-sender.service.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,13 @@ import {
1010
import { domifaConfig } from "../../../config";
1111
import { messageSmsRepository } from "../../../database";
1212
import { phoneUtil, appLogger } from "../../../util";
13+
import { SmsToSend } from "../types";
1314

1415
@Injectable()
1516
export class MessageSmsSenderService {
1617
constructor(private readonly httpService: HttpService) {}
1718

18-
public async sendSms(message: {
19-
content: string;
20-
phoneNumber: string;
21-
senderName: string;
22-
structureId: number;
23-
uuid: string;
24-
errorCount: number;
25-
}): Promise<void> {
19+
public async sendSms(message: SmsToSend): Promise<void> {
2620
const parsedValue = phoneUtil.parse(message.phoneNumber);
2721

2822
if (!phoneUtil.isValidNumber(parsedValue)) {
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { appLogger } from "../../../../util";
2+
import { messageSmsRepository } from "../../../../database";
3+
4+
import { Cron, CronExpression } from "@nestjs/schedule";
5+
import { Injectable } from "@nestjs/common";
6+
import { domifaConfig } from "../../../../config";
7+
import { isCronEnabled } from "../../../../config/services/isCronEnabled.service";
8+
import { MessageSmsSenderService } from "../message-sms-sender.service";
9+
import { SmsToSend } from "../../types";
10+
@Injectable()
11+
export class CronSmsInteractionSenderService {
12+
constructor(
13+
private readonly messageSmsSenderService: MessageSmsSenderService
14+
) {}
15+
16+
@Cron(CronExpression.EVERY_10_MINUTES, {
17+
timeZone: "Europe/Paris",
18+
disabled: !isCronEnabled() || !domifaConfig().sms.enabled,
19+
})
20+
protected async processSMSBatch() {
21+
appLogger.info("[SMS BATCH] Début d'envoi d'un batch de 500 SMS");
22+
23+
try {
24+
const now = new Date();
25+
const currentHour = now.getHours();
26+
27+
if (currentHour >= 20) {
28+
appLogger.info(
29+
`[SMS BATCH] Hors plage horaire (${currentHour}h) - Arrêt de l'envoi`
30+
);
31+
return;
32+
}
33+
34+
const smsToSend = (await messageSmsRepository.find({
35+
where: {
36+
status: "TO_SEND",
37+
smsId: "idMonDomiFa",
38+
},
39+
order: {
40+
createdAt: "ASC",
41+
},
42+
take: 500,
43+
})) as SmsToSend[];
44+
45+
if (smsToSend.length === 0) {
46+
appLogger.info(
47+
"[SMS BATCH] Aucun SMS d'identifiants Mon DomiFa à envoyer"
48+
);
49+
return;
50+
}
51+
52+
appLogger.info(
53+
`[SMS BATCH] ${smsToSend.length} SMS d'identifiants Mon DomiFa trouvés pour envoi`
54+
);
55+
56+
for (const message of smsToSend) {
57+
await this.messageSmsSenderService.sendSms(message);
58+
}
59+
60+
appLogger.info(
61+
`[SMS BATCH] Batch terminé - ${smsToSend.length} SMS traités`
62+
);
63+
} catch (error) {
64+
appLogger.error("[SMS BATCH] Erreur lors de l'envoi du batch:", error);
65+
}
66+
}
67+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { MessageSms } from "@domifa/common";
2+
3+
export interface SmsToSend
4+
extends Pick<
5+
MessageSms,
6+
"content" | "phoneNumber" | "senderName" | "structureId" | "errorCount"
7+
> {
8+
uuid: string;
9+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// @index('./*', f => `export * from '${f.path}'`)
2+
export * from "./SmsToSend.interface";
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { type InteractionType } from "../../interactions";
22
import { type MessageSmsReminders } from "./MessageSmsReminders.type";
33

4-
export type MessageSmsId = InteractionType | MessageSmsReminders;
4+
export type MessageSmsId =
5+
| InteractionType
6+
| MessageSmsReminders
7+
| "idMonDomiFa";

packages/frontend/src/app/modules/shared/services/auth.service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { Store } from "@ngrx/store";
1818
})
1919
export class AuthService {
2020
public currentUserSubject: BehaviorSubject<UserStructure | null>;
21-
2221
private readonly endPoint = environment.apiUrl + "structures/auth";
2322

2423
constructor(

packages/frontend/src/app/modules/usager-profil/constants/SMS_LABELS.const.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ export const SMS_LABELS: {
1313
visite: "Passage enregistré",
1414
echeanceDeuxMois: "Sms rappel de renouvellement",
1515
dernierPassageTroisMois: "Avertissement dernier passage plus de 3 mois",
16+
idMonDomiFa: "Envoi des identifiants Mon DomiFa",
1617
decision: "Nouvelle décision",
1718
};

0 commit comments

Comments
 (0)