From f1b69ba24d961c031b4f54eeaf1cc5b0cbd0a1d8 Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Wed, 27 Jan 2021 20:01:00 +0100 Subject: [PATCH] fix: update mailing templates, user model wrong type and aptic structure handling when a structure is updated. --- src/configuration/config.ts | 4 ++ .../apticStructureDuplication.ejs | 13 +++++++ .../apticStructureDuplication.json | 3 ++ .../mail-templates/structureOutdatedInfo.ejs | 11 +++++- src/mailer/mailer.service.ts | 2 +- .../services/aptic-structures.service.ts | 38 +++++++++++++++++-- src/structures/services/structures.service.ts | 7 +++- src/users/interfaces/user.interface.ts | 4 +- src/users/schemas/user.schema.ts | 3 +- src/users/users.service.ts | 32 +++++++++++++++- 10 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 src/mailer/mail-templates/apticStructureDuplication.ejs create mode 100644 src/mailer/mail-templates/apticStructureDuplication.json diff --git a/src/configuration/config.ts b/src/configuration/config.ts index c11b20a7b..7bb9d6f5a 100644 --- a/src/configuration/config.ts +++ b/src/configuration/config.ts @@ -33,5 +33,9 @@ export const config = { ejs: 'structureOutdatedInfo.ejs', json: 'structureOutdatedInfo.json', }, + apticStructureDuplication: { + ejs: 'apticStructureDuplication.ejs', + json: 'apticStructureDuplication.json', + }, }, }; diff --git a/src/mailer/mail-templates/apticStructureDuplication.ejs b/src/mailer/mail-templates/apticStructureDuplication.ejs new file mode 100644 index 000000000..5ac784a9c --- /dev/null +++ b/src/mailer/mail-templates/apticStructureDuplication.ejs @@ -0,0 +1,13 @@ +Bonjour,<br /> +<br /> +La fiche structure: <strong><%= name %></strong> a été créée après récupération des données aptic. Elle correspond +potientiellement a la structure existante : <strong><%= duplicatedStructureName %></strong>. +<br /> +<br /> +Cordialement, +<br /> +<br /> +L'équipe RES'in +<br /> +<br /> +Ce mail est un mail automatique. Merci de ne pas y répondre. diff --git a/src/mailer/mail-templates/apticStructureDuplication.json b/src/mailer/mail-templates/apticStructureDuplication.json new file mode 100644 index 000000000..ec9e77ef5 --- /dev/null +++ b/src/mailer/mail-templates/apticStructureDuplication.json @@ -0,0 +1,3 @@ +{ + "subject": "Doublon Aptic" +} diff --git a/src/mailer/mail-templates/structureOutdatedInfo.ejs b/src/mailer/mail-templates/structureOutdatedInfo.ejs index 945129e78..49e0fa1ee 100644 --- a/src/mailer/mail-templates/structureOutdatedInfo.ejs +++ b/src/mailer/mail-templates/structureOutdatedInfo.ejs @@ -1,6 +1,15 @@ Bonjour<br /> <br /> -La fiche de votre structure: <strong><%= name %></strong> n'a pas été mise a jour depuis 6mois. +Vous recevez ce message, parce que votre structure <strong><%= name %></strong> est référencée sur RES'in, le réseau des +acteurs de l'inclusion numérique de la Métropole de Lyon. Pouvez-vous nous aider en vérifiant que vos données sont bien +à jour en +<a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/home?id=<%= id %>" + >cliquant ici</a +>. +<br /> +Cordialement, +<br /> +L'équipe RES'in <br /> <br /> Ce mail est un mail automatique. Merci de ne pas y répondre. diff --git a/src/mailer/mailer.service.ts b/src/mailer/mailer.service.ts index 83b2a4ba7..04027e30e 100644 --- a/src/mailer/mailer.service.ts +++ b/src/mailer/mailer.service.ts @@ -47,7 +47,7 @@ export class MailerService { }) .subscribe( (body) => { - Logger.log(`Send mail : ${subject} success`, 'Mailer'); + Logger.log(`Send mail - success : ${subject}`, 'Mailer'); return resolve(body); }, (err) => { diff --git a/src/structures/services/aptic-structures.service.ts b/src/structures/services/aptic-structures.service.ts index 9ba852e91..f2bd9fdc2 100644 --- a/src/structures/services/aptic-structures.service.ts +++ b/src/structures/services/aptic-structures.service.ts @@ -10,11 +10,13 @@ import { Model } from 'mongoose'; import { Structure, StructureDocument } from '../schemas/structure.schema'; import { ApticStructure } from '../schemas/aptic-structure.schema'; import { Address } from '../schemas/address.schema'; +import { UsersService } from '../../users/users.service'; @Injectable() export class ApticStructuresService { constructor( private readonly httpService: HttpService, + private readonly userService: UsersService, @InjectModel(Structure.name) private structureModel: Model<StructureDocument> ) {} @@ -52,11 +54,10 @@ export class ApticStructuresService { createdStructure.contactPhone = structure.presence_phone; createdStructure.labelsQualifications = ['passNumerique']; // Address - const address = new Address(); - address.street = structure.presence_address; - address.commune = structure.city; - createdStructure.address = address; + createdStructure.address = this.formatAddress(structure); createdStructure.save(); + // Send admin weird structure mail + this.verifyDuplication(createdStructure); } }); } @@ -126,4 +127,33 @@ export class ApticStructuresService { }, }); } + + private async verifyDuplication(createdStructure: StructureDocument): Promise<void> { + const sameAddrStructure = await this.structureModel + .findOne({ + _id: { $ne: createdStructure._id }, + address: createdStructure.address, + }) + .exec(); + if (sameAddrStructure) { + this.userService.sendAdminApticStructureMail(createdStructure.structureName, sameAddrStructure.structureName); + } + } + + /** + * Format aptic structure address + */ + private formatAddress(structure: ApticStructure): Address { + const address = new Address(); + const regexWithSpace = /\d+\s/g; // NOSONAR + const regex = /\d+/g; // NOSONAR + if (structure.presence_address.match(regex)) { + address.numero = structure.presence_address.match(regex)[0]; + address.street = structure.presence_address.replace(regexWithSpace, ''); + } else { + address.street = structure.presence_address; + } + address.commune = structure.city; + return address; + } } diff --git a/src/structures/services/structures.service.ts b/src/structures/services/structures.service.ts index 3d045c107..fd99c04e1 100644 --- a/src/structures/services/structures.service.ts +++ b/src/structures/services/structures.service.ts @@ -102,6 +102,8 @@ export class StructuresService { const result = await this.structureModel.findByIdAndUpdate(Types.ObjectId(idStructure), structure).exec(); if (!result) { throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST); + } else { + this.userService.removeOutdatedStructureFromArray(idStructure); } return this.findOne(idStructure); } @@ -269,7 +271,7 @@ export class StructuresService { if (user.structureOutdatedMailSent.includes(data.structure._id)) { return; } else { - this.sendOutdatedEmailToUser(data.owner.email, data.structure.structureName); + this.sendOutdatedEmailToUser(data.owner.email, data.structure.structureName, data.structure._id); user.structureOutdatedMailSent.push(data.structure._id); user.save(); } @@ -282,7 +284,7 @@ export class StructuresService { * a new account. * @param user User */ - private async sendOutdatedEmailToUser(userEmail: string, structureName: string): Promise<any> { + private async sendOutdatedEmailToUser(userEmail: string, structureName: string, id: string): Promise<any> { const config = this.mailerService.config; const ejsPath = this.mailerService.getTemplateLocation(config.templates.structureOutdatedInfo.ejs); const jsonConfig = this.mailerService.loadJsonConfig(config.templates.structureOutdatedInfo.json); @@ -290,6 +292,7 @@ export class StructuresService { const html = await ejs.renderFile(ejsPath, { config, name: structureName, + id: id, }); this.mailerService.send(userEmail, jsonConfig.subject, html); } diff --git a/src/users/interfaces/user.interface.ts b/src/users/interfaces/user.interface.ts index 9ca1767ff..312a31256 100644 --- a/src/users/interfaces/user.interface.ts +++ b/src/users/interfaces/user.interface.ts @@ -1,4 +1,4 @@ -import { Document } from 'mongoose'; +import { Document, Types } from 'mongoose'; export interface IUser extends Document { readonly _id: string; @@ -15,5 +15,5 @@ export interface IUser extends Document { newEmail: string; structuresLink: string[]; pendingStructuresLink: string[]; - structureOutdatedMailSent: string[]; + structureOutdatedMailSent: Types.ObjectId[]; } diff --git a/src/users/schemas/user.schema.ts b/src/users/schemas/user.schema.ts index 5accf9e7c..deadfe5a0 100644 --- a/src/users/schemas/user.schema.ts +++ b/src/users/schemas/user.schema.ts @@ -1,4 +1,5 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { Types } from 'mongoose'; import { UserRole } from '../enum/user-role.enum'; @Schema() export class User { @@ -42,7 +43,7 @@ export class User { pendingStructuresLink: string[]; @Prop({ default: null }) - structureOutdatedMailSent: string[]; + structureOutdatedMailSent: Types.ObjectId[]; } export const UserSchema = SchemaFactory.createForClass(User); diff --git a/src/users/users.service.ts b/src/users/users.service.ts index ca6bdc488..920a233da 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -3,7 +3,7 @@ import { InjectModel } from '@nestjs/mongoose'; import * as bcrypt from 'bcrypt'; import * as ejs from 'ejs'; import * as crypto from 'crypto'; -import { Model } from 'mongoose'; +import { Model, Types } from 'mongoose'; import { LoginDto } from '../auth/login-dto'; import { CreateUserDto } from './dto/create-user.dto'; import { User } from './schemas/user.schema'; @@ -128,7 +128,6 @@ export class UsersService { /** * Send to all admins validation email for structures * a new account. - * @param user User */ private async sendAdminStructureValidationMail(): Promise<any> { const config = this.mailerService.config; @@ -144,6 +143,25 @@ export class UsersService { }); } + /** + * Send to all admins mail for aptic duplicated data + */ + public async sendAdminApticStructureMail(structureName: string, duplicatedStructureName: string): Promise<any> { + const config = this.mailerService.config; + const ejsPath = this.mailerService.getTemplateLocation(config.templates.apticStructureDuplication.ejs); + const jsonConfig = this.mailerService.loadJsonConfig(config.templates.apticStructureDuplication.json); + + const html = await ejs.renderFile(ejsPath, { + config, + name: structureName, + duplicatedStructureName: duplicatedStructureName, + }); + const admins = await this.getAdmins(); + admins.forEach((admin) => { + this.mailerService.send(admin.email, jsonConfig.subject, html); + }); + } + /** * Send approval email for user * a new account. @@ -371,4 +389,14 @@ export class UsersService { ); } } + + public async removeOutdatedStructureFromArray(structureId: string): Promise<void> { + const users = await this.userModel.find({ structureOutdatedMailSent: Types.ObjectId(structureId) }).exec(); + users.forEach((user) => { + user.structureOutdatedMailSent = user.structureOutdatedMailSent.filter((item) => + Types.ObjectId(structureId).equals(item) + ); + user.save(); + }); + } } -- GitLab