Skip to content

Commit

Permalink
fix: ne pas envoyer d'email quand l'ics est undefined
Browse files Browse the repository at this point in the history
  • Loading branch information
Mzem committed Nov 6, 2024
1 parent 6682340 commit c3be71f
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 132 deletions.
2 changes: 1 addition & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ import { DiagorienteClient } from './infrastructure/clients/diagoriente-client'
import { EngagementClient } from './infrastructure/clients/engagement-client'
import { FirebaseClient } from './infrastructure/clients/firebase-client'
import { ImmersionClient } from './infrastructure/clients/immersion-client'
import { InvitationIcsClient } from './infrastructure/clients/invitation-ics.client.db'
import { InvitationIcsClient } from './infrastructure/clients/invitation-ics.client'
import { KeycloakClient } from './infrastructure/clients/keycloak-client.db'
import { MailBrevoService } from './infrastructure/clients/mail-brevo.service.db'
import { MatomoClient } from './infrastructure/clients/matomo-client'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
failure
} from '../../building-blocks/types/result'
import { Authentification } from '../../domain/authentification'
import { Evenement, EvenementService } from '../../domain/evenement'
import { Mail, MailServiceToken } from '../../domain/mail'
import {
Conseiller,
ConseillerRepositoryToken
} from '../../domain/milo/conseiller'
import { Evenement, EvenementService } from '../../domain/evenement'
import { Mail, MailServiceToken } from '../../domain/mail'
import { Notification } from '../../domain/notification/notification'
import {
PlanificateurService,
Expand Down Expand Up @@ -65,6 +65,10 @@ export class DeleteRendezVousCommandHandler extends CommandHandler<
)
)
}
const icsSequence =
await this.rendezVousRepository.getAndIncrementRendezVousIcsSequence(
rendezVous.id
)
await this.rendezVousRepository.delete(command.idRendezVous)

this.notificationService.notifierLesJeunesDuRdv(
Expand Down Expand Up @@ -94,7 +98,8 @@ export class DeleteRendezVousCommandHandler extends CommandHandler<
this.mailService.envoyerMailRendezVous(
createur,
rendezVous,
RendezVous.Operation.SUPPRESSION
RendezVous.Operation.SUPPRESSION,
icsSequence
)
}
return emptySuccess()
Expand Down
3 changes: 2 additions & 1 deletion src/domain/mail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export namespace Mail {
envoyerMailRendezVous(
conseiller: Conseiller,
rendezVous: RendezVous,
operation: RendezVous.Operation
operation: RendezVous.Operation,
icsSequence?: number
): Promise<void>

envoyerEmailJeuneArchive(
Expand Down
4 changes: 4 additions & 0 deletions src/domain/rendez-vous/rendez-vous.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ export namespace RendezVous {
delete(idRendezVous: string): Promise<void>

getAllAVenir(): Promise<RendezVous[]>

getAndIncrementRendezVousIcsSequence(
idRendezVous: string
): Promise<number | undefined>
}

export enum Periode {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,27 @@
import { Inject, Injectable } from '@nestjs/common'
import { QueryTypes, Sequelize } from 'sequelize'
import { SequelizeInjectionToken } from '../sequelize/providers'
import { Injectable } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import * as icsService from 'ics'
import { Attendee, EventAttributes } from 'ics'
import { Conseiller } from '../../domain/milo/conseiller'
import {
CodeTypeRendezVous,
mapCodeLabelTypeRendezVous,
RendezVous
} from '../../domain/rendez-vous/rendez-vous'
import * as icsService from 'ics'
import {
formaterDateRendezVous,
formaterHeureRendezVous,
ICS
} from './mail-brevo.service.db'
import { Attendee, EventAttributes } from 'ics'
import { ConfigService } from '@nestjs/config'

@Injectable()
export class InvitationIcsClient {
private noReplyContactEmail: string

constructor(
@Inject(SequelizeInjectionToken) private readonly sequelize: Sequelize,
private configService: ConfigService
) {
constructor(private configService: ConfigService) {
this.noReplyContactEmail =
this.configService.get('noReplyContactEmail') ?? ''
}
async getAndIncrementRendezVousIcsSequence(
idRendezVous: string
): Promise<number> {
const rendezVousIcsSequence = await this.sequelize.query(
` UPDATE rendez_vous SET ics_sequence = CASE
WHEN ics_sequence IS NOT NULL THEN ics_sequence + 1 ELSE 0 END
WHERE id = :idRendezVous
RETURNING ics_sequence;`,
{
type: QueryTypes.UPDATE,
replacements: { idRendezVous }
}
)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return rendezVousIcsSequence[0][0]['ics_sequence']
}

creerFichierInvitationRendezVous(
conseiller: Conseiller,
Expand Down
52 changes: 30 additions & 22 deletions src/infrastructure/clients/mail-brevo.service.db.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { HttpService } from '@nestjs/axios'
import { Injectable, Logger } from '@nestjs/common'
import { Inject, Injectable, Logger } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { firstValueFrom } from 'rxjs'
import { Conseiller } from '../../domain/milo/conseiller'
import { ArchiveJeune } from '../../domain/archive-jeune'
import { Authentification } from '../../domain/authentification'
import { Core, estPassEmploi } from '../../domain/core'
import { Jeune } from '../../domain/jeune/jeune'
import { Mail, MailDataDto } from '../../domain/mail'
import { Conseiller } from '../../domain/milo/conseiller'
import {
mapCodeLabelTypeRendezVous,
RendezVous
RendezVous,
RendezVousRepositoryToken
} from '../../domain/rendez-vous/rendez-vous'
import { InvitationIcsClient } from './invitation-ics.client.db'
import { Jeune } from '../../domain/jeune/jeune'
import { ArchiveJeune } from '../../domain/archive-jeune'
import { Authentification } from '../../domain/authentification'
import { Core, estPassEmploi } from '../../domain/core'
import { InvitationIcsClient } from './invitation-ics.client'

export type ICS = string

Expand All @@ -37,7 +38,9 @@ export class MailBrevoService implements Mail.Service {
constructor(
private invitationIcsClient: InvitationIcsClient,
private httpService: HttpService,
private configService: ConfigService
private configService: ConfigService,
@Inject(RendezVousRepositoryToken)
private readonly rendezVousRepository: RendezVous.Repository
) {
this.brevoUrl = this.configService.get('brevo').url
this.apiKey = this.configService.get('brevo').apiKey
Expand Down Expand Up @@ -109,26 +112,31 @@ export class MailBrevoService implements Mail.Service {
async envoyerMailRendezVous(
conseiller: Conseiller,
rendezVous: RendezVous,
operation: RendezVous.Operation
operation: RendezVous.Operation,
icsSequence?: number
): Promise<void> {
const rendezVousIcsSequence =
await this.invitationIcsClient.getAndIncrementRendezVousIcsSequence(
icsSequence ??
(await this.rendezVousRepository.getAndIncrementRendezVousIcsSequence(
rendezVous.id
)
const fichierInvitation =
this.invitationIcsClient.creerFichierInvitationRendezVous(
))

if (rendezVousIcsSequence) {
const fichierInvitation =
this.invitationIcsClient.creerFichierInvitationRendezVous(
conseiller,
rendezVous,
rendezVousIcsSequence,
operation
)
const mailDatadto = this.creerContenuMailRendezVous(
conseiller,
rendezVous,
rendezVousIcsSequence,
fichierInvitation,
operation
)
const mailDatadto = this.creerContenuMailRendezVous(
conseiller,
rendezVous,
fichierInvitation,
operation
)
await this.envoyer(mailDatadto)
await this.envoyer(mailDatadto)
}
}

async envoyerEmailJeuneArchive(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'
import { Op, Sequelize } from 'sequelize'
import { Op, QueryTypes, Sequelize } from 'sequelize'
import { RendezVous } from '../../../domain/rendez-vous/rendez-vous'
import { DateService } from '../../../utils/date-service'
import { ConseillerSqlModel } from '../../sequelize/models/conseiller.sql-model'
Expand Down Expand Up @@ -98,4 +98,22 @@ export class RendezVousRepositorySql implements RendezVous.Repository {
})
return rendezVousSql.map(toRendezVous)
}

async getAndIncrementRendezVousIcsSequence(
idRendezVous: string
): Promise<number | undefined> {
const rendezVousIcsSequence = await this.sequelize.query(
` UPDATE rendez_vous SET ics_sequence = CASE
WHEN ics_sequence IS NOT NULL THEN ics_sequence + 1 ELSE 0 END
WHERE id = :idRendezVous
RETURNING ics_sequence;`,
{
type: QueryTypes.UPDATE,
replacements: { idRendezVous }
}
)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return rendezVousIcsSequence[0][0]?.['ics_sequence']
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ describe('DeleteRendezVousCommandHandler', () => {
.withArgs(conseillerCreateur.id)
.resolves(conseillerCreateur)
planificateurService.supprimerRappelsParId.resolves()
rendezVousRepository.getAndIncrementRendezVousIcsSequence.resolves(
1
)

// When
await deleteRendezVousCommandHandler.handle(command)
Expand All @@ -140,7 +143,8 @@ describe('DeleteRendezVousCommandHandler', () => {
expect(mailService.envoyerMailRendezVous).to.have.been.calledWith(
conseillerCreateur,
rendezVous,
RendezVous.Operation.SUPPRESSION
RendezVous.Operation.SUPPRESSION,
1
)
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,78 +1,24 @@
import { ConseillerSqlModel } from '../../../src/infrastructure/sequelize/models/conseiller.sql-model'
import { JeuneSqlModel } from '../../../src/infrastructure/sequelize/models/jeune.sql-model'
import { RendezVousSqlModel } from '../../../src/infrastructure/sequelize/models/rendez-vous.sql-model'
import { unConseillerDto } from '../../fixtures/sql-models/conseiller.sql-model'
import { unJeuneDto } from '../../fixtures/sql-models/jeune.sql-model'
import { unRendezVousDto } from '../../fixtures/sql-models/rendez-vous.sql-model'
import { expect } from '../../utils'
import { InvitationIcsClient } from '../../../src/infrastructure/clients/invitation-ics.client.db'
import { unConseiller } from '../../fixtures/conseiller.fixture'
import { unRendezVous } from '../../fixtures/rendez-vous.fixture'
import { testConfig } from '../../utils/module-for-testing'
import { unJeune } from 'test/fixtures/jeune.fixture'
import {
CodeTypeRendezVous,
RendezVous
} from '../../../src/domain/rendez-vous/rendez-vous'
import {
DatabaseForTesting,
getDatabase
} from '../../utils/database-for-testing'
import { InvitationIcsClient } from '../../../src/infrastructure/clients/invitation-ics.client'
import { unConseiller } from '../../fixtures/conseiller.fixture'
import { unRendezVous } from '../../fixtures/rendez-vous.fixture'
import { expect } from '../../utils'
import { testConfig } from '../../utils/module-for-testing'

describe('InvitationIcsClient', () => {
let databaseForTesting: DatabaseForTesting
let invitationIcsClient: InvitationIcsClient
const config = testConfig()

before(() => {
databaseForTesting = getDatabase()
})
before(() => {})

beforeEach(async () => {
await databaseForTesting.cleanPG()
invitationIcsClient = new InvitationIcsClient(
databaseForTesting.sequelize,
config
)

// Given
await ConseillerSqlModel.creer(unConseillerDto())
await JeuneSqlModel.creer(unJeuneDto())
invitationIcsClient = new InvitationIcsClient(config)
})

describe('getAndIncrementRendezVousIcsSequence', () => {
describe('quand le rdv a une séquence ics qui est nulle', () => {
it('initialise la séquence ics à 0', async () => {
// Given
const idRdv = '6c242fa0-804f-11ec-a8a3-0242ac120002'
const unRendezVous = unRendezVousDto({
id: idRdv
})
await RendezVousSqlModel.create(unRendezVous)
// When
const rendezVousIcsSequence =
await invitationIcsClient.getAndIncrementRendezVousIcsSequence(idRdv)
// Then
expect(rendezVousIcsSequence).to.equal(0)
})
})
describe('quand le rdv a une séquence ics non nulle', () => {
it('incrémente la séquence ics', async () => {
// Given
const idRdv = '6c242fa0-804f-11ec-a8a3-0242ac120002'
const unRendezVous = unRendezVousDto({
id: idRdv,
icsSequence: 0
})
await RendezVousSqlModel.create(unRendezVous)
// When
const rendezVousIcsSequence =
await invitationIcsClient.getAndIncrementRendezVousIcsSequence(idRdv)
// Then
expect(rendezVousIcsSequence).to.equal(1)
})
})
})
describe('creerEvenementRendezVous', () => {
it('renvoie le bon évènement du rendez-vous en excluant un jeune sans email', async () => {
// Given
Expand Down
Loading

0 comments on commit c3be71f

Please sign in to comment.