Skip to content

Commit

Permalink
feat(cron): Rappel action BO FUsager 609-610-611
Browse files Browse the repository at this point in the history
  • Loading branch information
l-scherer committed Oct 10, 2024
1 parent dcbdb56 commit e4e739f
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 3 deletions.
1 change: 1 addition & 0 deletions .env.dev.example.env
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ BACKEND_URL="http://localhost:3010"
BACKEND_CRON_REQUEST_DS8J15J_NOTIFY_CRON="0 22 * * *"
BACKEND_CRON_REQUEST_DS8J15J_DEADLINE_REMIND="15"
BACKEND_CRON_UPDATE_STATUT_DS_CRON="* * * * *"
BACKEND_CRON_REQUEST_ACTIONS_BO_CRON="0 9,12 * * 1-5"

# Tokens
TOKEN_SECRET="-----BEGIN EC PRIVATE KEY-----\nMIHcAgEBBEIAobMQpD5H2nAL7LrYLsxTxmE70HB6F3sWeAeq3DXdLQ/5zGFcV36e\nI9VdYyed8fzYq6t+RP42M7fDUzLAKpn46cKgBwYFK4EEACOhgYkDgYYABAFcZNGM\nL+ba9RXURG9yEUKzZsVt19jN+1xbjL1EIRC6IsvZeK58yd/Y924WtpklMSqMI6Fx\nSmGOpELXEe9BICNJHAG1x3KH0SUWN+gKC1mRbriSFd9HhrtRY7AgUdD6TR7H7un0\nxrJnFvr9iC1K+E6linASudSivbUhP8QzHt2k5JsTsQ==\n-----END EC PRIVATE KEY-----"
Expand Down
1 change: 1 addition & 0 deletions .kontinuous/env/dev/templates/backend.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ data:
BACKEND_CRON_REQUEST_DS8J15J_NOTIFY_CRON: "*/15 * * * *"
BACKEND_CRON_REQUEST_DS8J15J_DEADLINE_REMIND: "90"
BACKEND_CRON_UPDATE_STATUT_DS_CRON: "*/15 * * * *"
BACKEND_CRON_REQUEST_ACTIONS_BO_CRON: "0 9,12 * * 1-5"
3 changes: 2 additions & 1 deletion .kontinuous/env/preprod/templates/backend.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ data:
TMP_DIRECTORY: "/tmp"
BACKEND_CRON_REQUEST_DS8J15J_NOTIFY_CRON: "*/15 * * * *"
BACKEND_CRON_REQUEST_DS8J15J_DEADLINE_REMIND: "90"
BACKEND_CRON_UPDATE_STATUT_DS_CRON: "*/15 * * * *"
BACKEND_CRON_UPDATE_STATUT_DS_CRON: "*/15 * * * *"
BACKEND_CRON_REQUEST_ACTIONS_BO_CRON: "0 9,12 * * 1-5"
3 changes: 2 additions & 1 deletion .kontinuous/env/prod/templates/backend.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ data:
TMP_DIRECTORY: "/tmp"
BACKEND_CRON_REQUEST_DS8J15J_NOTIFY_CRON: "0 22 * * *"
BACKEND_CRON_REQUEST_DS8J15J_DEADLINE_REMIND: "15"
BACKEND_CRON_UPDATE_STATUT_DS_CRON: "0 02 * * *"
BACKEND_CRON_UPDATE_STATUT_DS_CRON: "0 02 * * *"
BACKEND_CRON_REQUEST_ACTIONS_BO_CRON: "0 8 * * 1"
4 changes: 4 additions & 0 deletions packages/backend/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ module.exports = {
process.env.BACKEND_CRON_REQUEST_DS8J15J_DEADLINE_REMIND,
name: "REQUEST_DS8J15J",
},
notifyactionsbo: {
cron: process.env.BACKEND_CRON_REQUEST_ACTIONS_BO_CRON,
name: "REQUEST_ACTIONS_BO",
},
update: {
cron: process.env.BACKEND_CRON_UPDATE_STATUT_DS_CRON,
name: "UPDATE_STATUT_DS",
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/crons/demandes-sejours/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
module.exports.notifyRappelActionsBO = require("./notifyRappelActionsBO").job;
module.exports.notifyRappelds8j15j = require("./notifyRappelds8j15j").job;
module.exports.updateStatutDS = require("./updateStatutDS").job;
266 changes: 266 additions & 0 deletions packages/backend/src/crons/demandes-sejours/notifyRappelActionsBO.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
const { CronJob } = require("cron");
const AppError = require("../../utils/error");

const run = require("../run");
const logger = require("../../utils/logger");
const pool = require("../../utils/pgpool").getPool();
const { statuts } = require("../../helpers/ds-statuts");
const Send = require("../../services/mail").mailService.send;
const sendTemplate = require("../../helpers/mail");

const {
senderEmail,
frontUsagersDomain,
frontBODomain,
} = require("../../config");

const { notifyRappelActionsBO } = require(".");

const { name, cron } = require("../../config").crons.request.notifyactionsbo;

const log = logger(module.filename);

const generateRappelQuery = (
statutsArray,
additionalColumns = "",
additionalJoins = "",
additionalGroupBy = "",
additionalOrderBy = "",
) => `
WITH hebergement_exploded AS (
SELECT
ds.id,
jsonb_array_elements(ds.hebergement->'hebergements') ->> 'dateDebut' AS date_debut_hebergement,
jsonb_array_elements(ds.hebergement->'hebergements') -> 'coordonnees' -> 'adresse' ->> 'codeInsee' AS code_insee
FROM
front.demande_sejour ds
)
SELECT
ds.id,
ds.id_fonctionnelle,
ds.date_debut,
ds.statut,
ds.libelle as titre,
TO_CHAR(ds.date_debut, 'DD/MM/YYYY') as date_debut,
use.mail,
${additionalColumns}
((ds.date_debut - ((10) * INTERVAL '1 day'))::date <= now()::date) as isalerte,
string_agg(com.label, ', ' ORDER BY he.date_debut_hebergement::date ASC) AS Communes
FROM
hebergement_exploded he
INNER JOIN front.demande_sejour ds ON ds.id = he.id
INNER JOIN geo.communes com ON com.code_insee = he.code_insee AND com.date_fin is null
${additionalJoins}
WHERE (ds.date_debut)::date>=now()::date
AND ds.statut IN (${statutsArray})
GROUP BY
ds.id,
ds.id_fonctionnelle,
ds.date_debut,
ds.statut,
ds.libelle,
use.mail,
${additionalGroupBy}
isalerte
ORDER BY
${additionalOrderBy}
isalerte DESC,
ds.date_debut ASC;
`;

const query = {
fetchRappelDSBO: generateRappelQuery(
`'${statuts.TRANSMISE}','${statuts.EN_COURS}','${statuts.TRANSMISE_8J}','${statuts.EN_COURS_8J}'`,
``,
` INNER JOIN geo.territoires ter ON ter.code = ds.departement_suivi INNER JOIN back.users use ON ter.code = use.ter_code `,
``,
`use.mail,`,
),
fetchRappelDSFUsager: generateRappelQuery(
`'${statuts.ATTENTE_8_JOUR}','${statuts.A_MODIFIER}','${statuts.A_MODIFIER_8J}'`,
`((ds.responsable_sejour::jsonb)->>'email')::text as mailresp, mail || ';' || ((ds.responsable_sejour::jsonb)->>'email')::text as mails,`,
` INNER JOIN front.user_organisme uso ON uso.org_id = ds.organisme_id INNER JOIN front.users use ON use.id = uso.use_id `,
`mailresp,`,
`mail,`,
),
};

const action = async () => {
log.i(`notifyRappelActionsBO - IN`);
// Création des contenus pour les envoies BackOffice
const { rowCount: countRappelActionsBO, rows: rowsRappelActionsBO } =
await pool.query(query.fetchRappelDSBO);
createContent({
isBO: true,
rowCount: countRappelActionsBO,
rows: rowsRappelActionsBO,
});
// Création des contenus pour les envoies FrontUsagers
const {
rowCount: countRappelActionsFUsager,
rows: rowsRappelActionsFUsager,
} = await pool.query(query.fetchRappelDSFUsager);
createContent({
isBO: false,
rowCount: countRappelActionsFUsager,
rows: rowsRappelActionsFUsager,
});

log.i(`notifyRappelds8j15j - DONE`);
};
async function createContent({ isBO, rowCount, rows }) {
if (rowCount === 0) return;
const mails = getUniqueMails({ isBO, rows });
for (const mail of mails) {
const emailContent = [];
emailContent.push(...generateInitialEmailContent());
const listeDsAvecAlerte = filterRowsWithAlert({ isBO, mail, rows });
emailContent.push(...appendContentForAlert({ listeDsAvecAlerte }));
const listeDsSansAlerte = filterRowsWithoutAlert({ isBO, mail, rows });
emailContent.push(...appendContentForNonAlert({ listeDsSansAlerte }));
try {
await sendMail({ emailContent, isBO, mail });
} catch (error) {
log.w(error);
}
}
}

function getUniqueMails({ isBO, rows }) {
return [
...new Set(
rows
.filter((ds) => (isBO ? ds.mail : ds.mails))
.map((ds) => (isBO ? ds.mail : ds.mails))
),
];
}

function generateInitialEmailContent() {
return [
"<p>Bonjour,</p>",
"<p>Vous trouverez ci-dessous la liste des déclarations VAO sur lesquelles une action de votre part est attendue,</p>",
];
}

function filterRowsWithAlert({ isBO, rows, mail }) {
return rows.filter(
(ds) => ds.isalerte && (isBO ? ds.mail === mail : ds.mails === mail)
);
}

function filterRowsWithoutAlert({ isBO, rows, mail }) {
return rows.filter(
(ds) => !ds.isalerte && (isBO ? ds.mail === mail : ds.mails === mail)
);
}

function appendContentForAlert({ listeDsAvecAlerte }) {
const newContent = [];
if (listeDsAvecAlerte.length > 0) {
newContent.push(
"<p><b>DECLARATIONS NECESSITANT UNE ACTION URGENTE DE VOTRE PART dont la date de début de séjour est à moins de 10 jours</b>",
);
newContent.push("<ul>");
for (const ds of listeDsAvecAlerte) {
const retourliste = createDSContent({ ds });
newContent.push(...retourliste);
}
newContent.push("</ul></p>");
}
return newContent;
}

function appendContentForNonAlert({ listeDsSansAlerte }) {
const newContent = [];
if (listeDsSansAlerte.length > 0) {
newContent.push(
"<p>AUTRES DECLARATIONS DE SEJOUR NECESSITANT UNE ACTION DE VOTRE PART",
);
newContent.push("<ul>");
for (const ds of listeDsSansAlerte) {
const retourliste = createDSContent({ ds });
newContent.push(...retourliste);
}
newContent.push("</ul></p>");
}
return newContent;
}

async function sendMail({ emailContent, mail, isBO }) {
await Send(
await sendNotificationMail({
content: emailContent.join("\n"),
email: mail.split(";"),
isBO,
}),
);
}

function createDSContent({ ds }) {
const content = [];
content.push(`<p>${ds.id_fonctionnelle} - ${ds.communes}<br>`);
content.push(`Statut de la déclaration : ${ds.statut}<br>`);
content.push(`Date de début du séjour : ${ds.date_debut}<br></p>`);
return content;
}

async function sendNotificationMail({ content, email, isBO }) {
log.i("sendNotificationMail - In", {
email,
});
const textDeFin = [];
let uriAppListeSejours = "";
if (isBO) {
uriAppListeSejours = frontBODomain + "/sejours";
} else {
uriAppListeSejours = frontUsagersDomain + "/demande-sejour/liste";
textDeFin.push(
`<p>Si vous avez des difficultés pour traiter vos déclarations, vous vous rappelons que vous pouvez <a href="https://vao-assistance.atlassian.net/servicedesk/customer/portals">contacter le support utilisateur</a>.</p>`,
);
textDeFin.push(
`<p>De plus, vous avez toujours la possibilité d’annuler des déclarations de séjours qui ne sont plus d’actualité pour garder votre tableau à jour.</p>`,
);
}
textDeFin.push(
`Vous pouvez accéder à la liste des déclarations de votre département en <a href=${uriAppListeSejours}>cliquant ici</a>`,
);

if (!email) {
const message = `Le paramètre email manque à la requête`;
log.w(`sendNotificationMail - ${message}`);
throw new AppError(message);
}
const html = sendTemplate.getBody(
``,
[
{
p: [
`
${content}
`,
textDeFin.join("\n"),
],
type: "p",
},
],
"L'équipe du SI VAO<br><br><i>Ce courriel est un message automatique, merci de ne pas répondre.</i>",
);
const params = {
from: senderEmail,
html: html,
notifyRappelActionsBO,
replyTo: senderEmail,
subject: `Séjours VAO – Récapitulatif des déclarations de séjour en attente de traitement de votre part`,
to: email,
};
log.d("sendNotificationMail post email", {
params,
});
return params;
}

const job = new CronJob(cron, run(name, action));

module.exports.job = job;
module.exports.action = action;
5 changes: 5 additions & 0 deletions packages/backend/src/crons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ const logger = require("../utils/logger");

const log = logger(module.filename);

const {
notifyRappelActionsBO: UsagerNotifyActionsBO,
} = require("./demandes-sejours");
const { notifyRappelds8j15j: UsagerNotify } = require("./demandes-sejours");
const { updateStatutDS: UpdateStatut } = require("./demandes-sejours");

module.exports.stop = function stop() {
log.i("Stopping crons...");

UsagerNotifyActionsBO.stop();
UsagerNotify.stop();
UpdateStatut.stop();

Expand All @@ -17,6 +21,7 @@ module.exports.stop = function stop() {
module.exports.start = function start() {
log.i("Starting crons...");

UsagerNotifyActionsBO.start();
UsagerNotify.start();
UpdateStatut.start();

Expand Down
1 change: 0 additions & 1 deletion packages/backend/src/services/DemandeSejour.js
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,6 @@ module.exports.getByDepartementCodes = async (
}

log.d({ paramsWithPagination, queryWithPagination });

const response = await pool.query(queryWithPagination, paramsWithPagination);

if (limit === null || response.rowCount < limit) {
Expand Down

0 comments on commit e4e739f

Please sign in to comment.