From fc7949fabe48d86698639f0aeb5e733258205a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20PENHO=C3=8BT?= Date: Wed, 28 Oct 2020 12:28:47 +0100 Subject: [PATCH] =?UTF-8?q?Relecture=20contr=C3=B4leur=20envois=20abonneme?= =?UTF-8?q?nts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/subscription.js | 95 +++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/controllers/subscription.js b/controllers/subscription.js index efca851..a9d9035 100644 --- a/controllers/subscription.js +++ b/controllers/subscription.js @@ -229,82 +229,86 @@ exports.notifyExpirationAccount= async(req, res, next) => } } -// Diffuse aux abonnés un nouvel élément de quiz, en parcourant ceux d'un même groupe, dans l'ordre où ils ont été enregistrés. -// Quand tous les éléments ont été envoyés, l'abonné reçoit en plus le quiz regroupant les questions des éléments du groupe. -// Si il n'y plus de nouveautés pour l'utilisateur, on lui envoie un quiz au hasard parmi ceux déjà envoyés pour le retester. +// Envoie aux abonnés les différents éléments des groupes de quizs dans l'ordre indiqué lors de leur enregistrement. +// Quand tous les éléments d'un groupe ont été envoyés, l'abonné reçoit le quiz regroupant les questions des éléments du groupe. +// Si l'utilisateur a déjà reçu tous les quizs, on lui envoie une nouvelle fois un quiz au hasard parmi ceux existants. exports.addNewQuestionnaireUsers = async(req, res, next) => { try { const db = require("../models/index"); // Utilisateurs dont l'abonnement est toujours actif et souhaitant recevoir des quizs le jour de la semaine en cours. - // Le tout en heure locale et en ignorant ceux qui ont déjà été traités ces dernières 24H. + // Le tout en heure locale et en ignorant ceux qui ont déjà été traités durant les dernières 24H. const subscriptionsOk = await db.sequelize.query("SELECT `Subscriptions`.`id` as SubscriptionId, `Subscriptions`.`lastProcessingAt`, `UserId`, `name`, `email`, `smtp`, `language`, `receiptDays`, ADDDATE(UTC_TIMESTAMP, INTERVAL `timeDifference` MINUTE) AS localDate FROM `Subscriptions` INNER JOIN `Users` ON `Subscriptions`.`UserId`=`Users`.`id` WHERE `status`='user' AND ADDDATE(`Subscriptions`.`createdAt`, `numberOfDays`) > UTC_TIMESTAMP HAVING HOUR(localDate) > "+config.hourGiveNewQuestionnaireBegin+" AND HOUR(localDate) < "+config.hourGiveNewQuestionnaireEnd+" AND LOCATE(DAYOFWEEK(localDate),receiptDays)!=0 AND SubscriptionId NOT IN (SELECT DISTINCT `SubscriptionId` FROM `Pauses` WHERE ADDDATE(`startingAt`, INTERVAL `timeDifference` MINUTE) <= localDate AND ADDDATE(`endingAT`, INTERVAL `timeDifference` MINUTE) > localDate) AND DATEDIFF(NOW(),`Subscriptions`.`lastProcessingAt`) >= 1 LIMIT "+config.maxQuestionnaireSendedAtSameTime, { type: QueryTypes.SELECT }); if(subscriptionsOk.length === 0) res.status(200).json({ message: txt.allSubscriptionProcessed }); else { - let lastSended, lastSendedGroup, lastSendedGroupNbElements, elementToSend, getElementToSend, accessSave, token, textMail, now=new Date(); + const now=new Date(); for (let i in subscriptionsOk) { - // On commence à chercher le dernier élément auquel il a été donné accès à l'utilisateur pour comparer sa date à celle du dernier envoi - lastSended = await db.sequelize.query("SELECT DATE_FORMAT(`QuestionnaireAccesses`.`createdAt`, \"%Y-%m-%d\") as `dateSended`, `QuestionnaireId`, `GroupId`, `rankInGroup` FROM `QuestionnaireAccesses` INNER JOIN `Questionnaires` WHERE `Questionnaires`.`id`=`QuestionnaireAccesses`.`QuestionnaireId` AND `UserId`="+subscriptionsOk[i].UserId+" AND `selfCreatedOk`= 0 AND `GroupId` IS NOT NULL ORDER BY `QuestionnaireAccesses`.`CreatedAt` DESC LIMIT 1", { type: QueryTypes.SELECT }); - elementToSend="", lastSendedGroup=""; - // Il y a déjà eu au moins un envoi et le dernier envoi était l'élément d'un quiz groupé : + // On commence à chercher le dernier élément envoyé à l'utilisateur pour comparer sa date d'enregistrement à celle du dernier envoi + const lastSended = await db.sequelize.query("SELECT DATE_FORMAT(`QuestionnaireAccesses`.`createdAt`, \"%Y-%m-%d\") as `dateSended`, `QuestionnaireId`, `GroupId`, `rankInGroup` FROM `QuestionnaireAccesses` INNER JOIN `Questionnaires` ON `Questionnaires`.`id`=`QuestionnaireAccesses`.`QuestionnaireId` WHERE `UserId`="+subscriptionsOk[i].UserId+" AND `selfCreatedOk`= 0 AND `GroupId` IS NOT NULL ORDER BY `QuestionnaireAccesses`.`CreatedAt` DESC LIMIT 1", { type: QueryTypes.SELECT }); + let elementToSend; + // Il y a déjà eu au moins un envoi et le dernier envoi était un des éléments d'un quiz groupé : if(lastSended.length !==0 && lastSended[0].dateSended == subscriptionsOk[i].lastProcessingAt) { - // Si l'élément envoyé était le dernier de son groupe, on va lui envoyer le lien du quiz du groupe : - lastSendedGroup = await groupCtrl.searchGroupById(lastSended[0].GroupId); - lastSendedGroupNbElements = lastSendedGroup.Questionnaires.length; - if(!tool.isEmpty(lastSendedGroupNbElements) && lastSendedGroup.Questionnaires[(lastSendedGroupNbElements-1)].id == lastSended[0].QuestionnaireId) - elementToSend = lastSendedGroup.Group; - else + const lastSendedGroup = await groupCtrl.searchGroupById(lastSended[0].GroupId); + if(!tool.isEmpty(lastSendedGroup)) { - // dans ce cas, on va envoyer l'élément suivant du groupe : - for(let j in lastSendedGroup.Questionnaires) - if(lastSendedGroup.Questionnaires[j].id == lastSended[0].QuestionnaireId) - elementToSend = await questionnaireCtrl.searchQuestionnaireById(lastSendedGroup.Questionnaires[(parseInt(j)+1)].id, true); + const lastSendedGroupNbElements = lastSendedGroup.Questionnaires.length; + // Si le dernier élément envoyé était le dernier de son groupe, on envoie le lien du quiz reprenant toutes les questions du groupe : + if(!tool.isEmpty(lastSendedGroupNbElements) && lastSendedGroup.Questionnaires[(lastSendedGroupNbElements-1)].id == lastSended[0].QuestionnaireId) + { + // Il faut que le quiz soi publié... Sinon on va envoyer un ancien quiz en attendant (cf + bas) + if(lastSendedGroup.Group.isPublishable) + elementToSend = lastSendedGroup.Group; + } + // Sinon l'élément suivant du groupe : + else + { + for(let j in lastSendedGroup.Questionnaires) + if(lastSendedGroup.Questionnaires[j].id == lastSended[0].QuestionnaireId) + elementToSend = await questionnaireCtrl.searchQuestionnaireById(lastSendedGroup.Questionnaires[(parseInt(j)+1)].id); + } } } else { - // Soit il s'agit du premier envoi d'un abonnement, soit le dernier envoi était un quiz groupé. - // Dans ces deux cas, on va envoyer le premier élément non encore envoyé d'un groupe : - getElementToSend = await db.sequelize.query("SELECT `Questionnaires`.`id` FROM `Questionnaires` INNER JOIN `Groups` WHERE `Questionnaires`.`GroupId`=`Groups`.`id` AND `Questionnaires`.`isPublished`=1 AND `Groups`.`language`='"+subscriptionsOk[i].language+"' AND `Groups`.`publishingAt` < NOW() AND `Questionnaires`.`id` NOT IN (SELECT `QuestionnaireId` FROM `QuestionnaireAccesses` where `UserId`="+subscriptionsOk[i].UserId+") ORDER BY `Groups`.`publishingAt`,`rankInGroup` ASC", { type: QueryTypes.SELECT }); + // Soit il s'agit du premier envoi d'un abonnement, soit le dernier envoi était le quiz d'un groupe. + // Dans ces deux cas, on va envoyer le premier élément non encore envoyé à cet abonné (le groupe peut ne pas être lui-même encore publié) : + const getElementToSend = await db.sequelize.query("SELECT `Questionnaires`.`id` FROM `Questionnaires` INNER JOIN `Groups` ON `Questionnaires`.`GroupId`=`Groups`.`id` WHERE `Questionnaires`.`isPublished`=1 AND `Groups`.`language`='"+subscriptionsOk[i].language+"' AND `Questionnaires`.`id` NOT IN (SELECT `QuestionnaireId` FROM `QuestionnaireAccesses` where `UserId`="+subscriptionsOk[i].UserId+") ORDER BY `Groups`.`publishingAt`,`rankInGroup` ASC", { type: QueryTypes.SELECT }); if(getElementToSend.length !== 0) - elementToSend = await questionnaireCtrl.searchQuestionnaireById(getElementToSend[0].id, true); + elementToSend = await questionnaireCtrl.searchQuestionnaireById(getElementToSend[0].id); } - // console.log(elementToSend); + // Token du lien de désinscription aux envois : + const token=jwt.sign({ userId: subscriptionsOk[i].UserId }, config.tokenPrivateKey, { expiresIn: config.tokenUnsubscribeLinkTimeInDays }); if(!tool.isEmpty(elementToSend)) { - token=jwt.sign({ userId: subscriptionsOk[i].UserId }, config.tokenPrivateKey, { expiresIn: config.tokenUnsubscribeLinkTimeInDays }); - if(elementToSend.Questionnaire !== undefined)// il s'agit de l'élément d'un group + if(elementToSend.Questionnaire !== undefined)// = Il s'agit de l'élément d'un group { - const mapMail = + const mapMail = // Pour version en texte brut du mail { USER_NAME: subscriptionsOk[i].name, QUESTIONNAIRE_URL: config.siteUrl+"/"+configQuestionnaires.dirWebQuestionnaires+"/"+elementToSend.Questionnaire.slug+".html", UNSUBSCRIBE_URL: config.siteUrl+"/"+configTpl.stopMailPage+token }; - const mailDatas = + const mailDatas = // Pour version HTML du mail (via template PUG) { mailSubject: elementToSend.Questionnaire.title, mailPreheader: elementToSend.Questionnaire.title, mailTitle: elementToSend.Questionnaire.title, - mailHeaderLinkUrl: config.siteUrl+"/"+configTpl.stopMailPage+token, + mailHeaderLinkUrl: mapMail.UNSUBSCRIBE_URL, mailHeaderLinkTxt: txt.mailStopMailLinkTxt, mailMainContent: elementToSend.Questionnaire.introduction, - mailMainContentLinks : elementToSend.Questionnaire.Links, - linksCTA: [{ url:config.siteUrl+"/"+configQuestionnaires.dirWebQuestionnaires+"/"+elementToSend.Questionnaire.slug+".html", txt:txtGeneral.btnShowOnWebSite.replace("#SITE_NAME", config.siteName) }], + linksCTA: [{ url:mapMail.QUESTIONNAIRE_URL, txt:txtGeneral.btnShowOnWebSite.replace("#SITE_NAME", config.siteName) }], mailRecipientAddress: subscriptionsOk[i].email } toolMail.sendMail(subscriptionsOk[i].smtp, subscriptionsOk[i].email, mailDatas.mailSubject, tool.replaceAll(txt.mailNewElementForGroupTxt, mapMail), "", mailDatas); - // on enregistre le fait que cet élément a déjà été envoyé : - accessSave = await db["QuestionnaireAccess"].create({ QuestionnaireId: elementToSend.Questionnaire.id, UserId: subscriptionsOk[i].UserId, selfCreatedOk: false }); - /// à remplacer pour fonction listant les derniers éléments "lus" par l'utilisateur : - //answerCtrl.creaUserQuestionnairesWithoutAnswerJson(subscriptionsOk[i].UserId); + // On enregistre le fait que cet élément a été envoyé à cet abonné : + db["QuestionnaireAccess"].create({ QuestionnaireId: elementToSend.Questionnaire.id, UserId: subscriptionsOk[i].UserId, selfCreatedOk: false }); } - else // envoi du quiz du groupe + else // = Envoi du quiz du groupe { const mapMail = { @@ -317,10 +321,10 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => mailSubject: elementToSend.title+" ("+txtQuestionnaire.questionnairesName+")", mailPreheader: elementToSend.title, mailTitle: elementToSend.title, - mailHeaderLinkUrl: config.siteUrl+"/"+configTpl.stopMailPage+token, + mailHeaderLinkUrl: mapMail.UNSUBSCRIBE_URL, mailHeaderLinkTxt: txt.mailStopMailLinkTxt, mailMainContent: elementToSend.introduction, - linksCTA: [{ url:config.siteUrl+"/"+configQuestionnaires.dirWebGroups+"/"+elementToSend.slug+".html", txt:txtQuestionnaire.btnShowQuestionnaire }], + linksCTA: [{ url:mapMail.QUESTIONNAIRE_URL, txt:txtQuestionnaire.btnShowQuestionnaire }], mailRecipientAddress: subscriptionsOk[i].email } toolMail.sendMail(subscriptionsOk[i].smtp, subscriptionsOk[i].email, mailDatas.mailSubject, tool.replaceAll(txt.mailNewQuestionnaireBodyTxt, mapMail), "", mailDatas); @@ -328,13 +332,12 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => } else { - // L'utilisateur a déjà reçu tous les élements et quizs des groupes publiés. Dans ces cas, on tire un au hasard un quiz groupé pour le lui renvoyer - getElementToSend = await db.sequelize.query("SELECT `id`, `title`, `slug`, `introduction` FROM `Groups` WHERE `publishingAt` < NOW() AND `language`='"+subscriptionsOk[i].language+"' ORDER BY RAND() LIMIT 1", { type: QueryTypes.SELECT }); - token=jwt.sign({ userId: subscriptionsOk[i].UserId }, config.tokenPrivateKey, { expiresIn: config.tokenUnsubscribeLinkTimeInDays }); + // L'utilisateur a déjà reçu tous les élements publiés. Dans ce cas, on tire au hasard un quiz groupé pour le lui envoyer une nouvelle fois. + const getElementToSend = await db.sequelize.query("SELECT `id`, `title`, `slug`, `introduction` FROM `Groups` WHERE `publishingAt` < NOW() AND `language`='"+subscriptionsOk[i].language+"' ORDER BY RAND() LIMIT 1", { type: QueryTypes.SELECT }); const mapMail = { USER_NAME: subscriptionsOk[i].name, - QUESTIONNAIRE_URL: config.siteUrl+"/"+configQuestionnaires.dirWebQuestionnaires+"/"+getElementToSend[0].slug+".html", + QUESTIONNAIRE_URL: config.siteUrl+"/"+configQuestionnaires.dirWebGroups+"/"+getElementToSend[0].slug+".html", UNSUBSCRIBE_URL: config.siteUrl+"/"+configTpl.stopMailPage+token }; const mailDatas= @@ -342,16 +345,16 @@ exports.addNewQuestionnaireUsers = async(req, res, next) => mailSubject: getElementToSend[0].title+" ("+txtQuestionnaire.questionnairesName+")", mailPreheader: getElementToSend[0].title, mailTitle: getElementToSend[0].title, - mailHeaderLinkUrl: config.siteUrl+"/"+configTpl.stopMailPage+token, + mailHeaderLinkUrl: mapMail.UNSUBSCRIBE_URL, mailHeaderLinkTxt: txt.mailStopMailLinkTxt, mailMainContent: "

"+txtQuestionnaireAccess.questionnaireRetryInfo+"

"+getElementToSend[0].introduction, - linksCTA: [{ url:config.siteUrl+"/"+configQuestionnaires.dirWebGroups+"/"+getElementToSend[0].slug+".html", txt:txtQuestionnaire.btnShowQuestionnaire }], + linksCTA: [{ url: mapMail.QUESTIONNAIRE_URL, txt:txtQuestionnaire.btnShowQuestionnaire }], mailRecipientAddress: subscriptionsOk[i].email } toolMail.sendMail(subscriptionsOk[i].smtp, subscriptionsOk[i].email, mailDatas.mailSubject, tool.replaceAll(txtQuestionnaireAccess.questionnaireRetryInfoTxt, mapMail), "", mailDatas); } - // dans tout les cas, on enregistre l'envoi : - //db["Subscription"].update({ lastProcessingAt: now }, { where: { id : subscriptionsOk[i].SubscriptionId }, limit:1 }); + // Dans tout les cas, on enregistre le fait que l'abonnement a été traité : + db["Subscription"].update({ lastProcessingAt: now }, { where: { id : subscriptionsOk[i].SubscriptionId }, limit:1 }); } res.status(200).json(subscriptionsOk); }