Skip to content

Commit

Permalink
feat: recupere liste beneficiaires a archiver (#1642)
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurlbrjc authored Dec 5, 2024
1 parent 087be90 commit d89626e
Show file tree
Hide file tree
Showing 15 changed files with 434 additions and 26 deletions.
6 changes: 5 additions & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ConfigModule } from '@nestjs/config'
import { APP_GUARD } from '@nestjs/core'
import { TerminusModule } from '@nestjs/terminus'
import { EmargerSessionMiloCommandHandler } from 'src/application/commands/milo/emarger-session-milo.command.handler'
import { GetBeneficiairesAArchiverQueryHandler } from 'src/application/queries/get-beneficiaires-a-archiver.query.handler'
import { GetTokenPoleEmploiQueryHandler } from 'src/application/queries/get-token-pole-emploi.query.handler'
import { GetAgendaSessionsConseillerMiloQueryHandler } from 'src/application/queries/milo/get-agenda-sessions-conseiller.milo.query.handler.db'
import { GetCompteursBeneficiaireMiloQueryHandler } from 'src/application/queries/milo/get-compteurs-portefeuille-milo.query.handler.db'
Expand All @@ -21,6 +22,7 @@ import { GetMonSuiviPoleEmploiQueryHandler } from 'src/application/queries/milo/
import { GetSessionsConseillerMiloQueryHandler } from 'src/application/queries/milo/get-sessions-conseiller.milo.query.handler.db'
import { GetSessionsJeuneMiloQueryHandler } from 'src/application/queries/milo/get-sessions-jeune.milo.query.handler.db'
import { EvenementEmploiCodePostalQueryGetter } from 'src/application/queries/query-getters/evenement-emploi-code-postal.query.getter'
import { GetBeneficiairesAArchiverQueryGetter } from 'src/application/queries/query-getters/get-beneficiaires-a-archiver.query.getter.db'
import { GetSessionsJeuneMiloQueryGetter } from 'src/application/queries/query-getters/milo/get-sessions-jeune.milo.query.getter.db'
import { RechercherMessageQueryHandler } from 'src/application/queries/rechercher-message.query.handler'
import { AntivirusClient } from 'src/infrastructure/clients/antivirus-client'
Expand Down Expand Up @@ -789,7 +791,9 @@ export function buildQueryCommandsProviders(): Provider[] {
GetTokenPoleEmploiQueryHandler,
GetMonSuiviPoleEmploiQueryHandler,
GetCompteursBeneficiaireMiloQueryHandler,
GetDemarchesConseillerQueryHandler
GetDemarchesConseillerQueryHandler,
GetBeneficiairesAArchiverQueryHandler,
GetBeneficiairesAArchiverQueryGetter
]
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Injectable } from '@nestjs/common'
import { ConseillerAuthorizer } from 'src/application/authorizers/conseiller-authorizer'
import { GetBeneficiairesAArchiverQueryGetter } from 'src/application/queries/query-getters/get-beneficiaires-a-archiver.query.getter.db'
import { IdentiteJeuneQueryModel } from 'src/application/queries/query-models/jeunes.query-model'
import { QueryHandler } from 'src/building-blocks/types/query-handler'
import { Result } from 'src/building-blocks/types/result'
import { Authentification } from 'src/domain/authentification'

type GetBeneficiairesAArchiverQuery = {
idConseiller: string
}

@Injectable()
export class GetBeneficiairesAArchiverQueryHandler extends QueryHandler<
GetBeneficiairesAArchiverQuery,
Result<IdentiteJeuneQueryModel[]>
> {
constructor(
private readonly conseillerAuthorizer: ConseillerAuthorizer,
private readonly queryGetter: GetBeneficiairesAArchiverQueryGetter
) {
super('GetBeneficiairesAArchiverQueryHandler')
}

async authorize(
query: GetBeneficiairesAArchiverQuery,
utilisateur: Authentification.Utilisateur
): Promise<Result> {
return this.conseillerAuthorizer.autoriserLeConseiller(
query.idConseiller,
utilisateur
)
}

async handle(
query: GetBeneficiairesAArchiverQuery
): Promise<Result<IdentiteJeuneQueryModel[]>> {
return this.queryGetter.handle(query.idConseiller)
}

async monitor(): Promise<void> {
return
}
}
26 changes: 20 additions & 6 deletions src/application/queries/get-detail-conseiller.query.handler.db.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Injectable } from '@nestjs/common'
import { GetBeneficiairesAArchiverQueryGetter } from 'src/application/queries/query-getters/get-beneficiaires-a-archiver.query.getter.db'
import { NonTrouveError } from '../../building-blocks/types/domain-error'
import { Query } from '../../building-blocks/types/query'
import { QueryHandler } from '../../building-blocks/types/query-handler'
Expand Down Expand Up @@ -30,7 +31,8 @@ export class GetDetailConseillerQueryHandler extends QueryHandler<
constructor(
private conseillerAuthorizer: ConseillerAuthorizer,
private conseillerMiloService: Conseiller.Milo.Service,
private configService: ConfigService
private configService: ConfigService,
private readonly getBeneficiairesAArchiverQueryGetter: GetBeneficiairesAArchiverQueryGetter
) {
super('GetDetailConseillerQueryHandler')
}
Expand Down Expand Up @@ -65,15 +67,27 @@ export class GetDetailConseillerQueryHandler extends QueryHandler<
return failure(new NonTrouveError('Conseiller', query.idConseiller))
}

const jeuneARecuperer = await JeuneSqlModel.findOne({
where: { idConseillerInitial: conseillerSqlModel.id },
attributes: ['id']
})
let jeuneARecuperer: JeuneSqlModel | null = null
try {
jeuneARecuperer = await JeuneSqlModel.findOne({
where: { idConseillerInitial: conseillerSqlModel.id },
attributes: ['id']
})
} catch {}

let nombreBeneficiairesAArchiver = 0
try {
nombreBeneficiairesAArchiver =
await this.getBeneficiairesAArchiverQueryGetter.count(
conseillerSqlModel.id
)
} catch {}

return success(
fromSqlToDetailConseillerQueryModel(
conseillerSqlModel,
Boolean(jeuneARecuperer)
Boolean(jeuneARecuperer),
nombreBeneficiairesAArchiver
)
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Inject, Injectable } from '@nestjs/common'
import { QueryTypes, Sequelize } from 'sequelize'
import { IdentiteJeuneQueryModel } from 'src/application/queries/query-models/jeunes.query-model'
import { Result, success } from 'src/building-blocks/types/result'
import { SequelizeInjectionToken } from 'src/infrastructure/sequelize/providers'
import { DateService } from 'src/utils/date-service'

@Injectable()
export class GetBeneficiairesAArchiverQueryGetter {
constructor(
private readonly dateService: DateService,
@Inject(SequelizeInjectionToken) private readonly sequelize: Sequelize
) {}

async handle(
idConseiller: string
): Promise<Result<IdentiteJeuneQueryModel[]>> {
const models =
await this.queryBeneficiairesAArchiver<IdentiteJeuneQueryModel>(
'id, nom, prenom',
idConseiller
)
return success(models)
}

async count(idConseiller: string): Promise<number> {
const rows = await this.queryBeneficiairesAArchiver<{ count: string }>(
'COUNT(id)',
idConseiller
)

return Number.parseInt(rows[0].count)
}

private async queryBeneficiairesAArchiver<T extends object>(
query: string,
idConseiller: string
): Promise<T[]> {
const ilYa6mois = this.dateService.now().minus({ month: 6 }).startOf('day')

return this.sequelize.query<T>(
`
SELECT ${query} FROM jeune
WHERE id_conseiller = :idConseiller
AND (
date_fin_cej < :date
OR date_derniere_actualisation_token < :date
OR (EXISTS (SELECT 1 FROM jeune_milo_a_archiver WHERE jeune_milo_a_archiver.id_jeune = jeune.id)) IS true
)
`,
{
type: QueryTypes.SELECT,
replacements: { idConseiller, date: ilYa6mois.toJSDate() }
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ export class DetailConseillerQueryModel {
@ApiProperty()
aDesBeneficiairesARecuperer: boolean

@ApiProperty()
beneficiairesAArchiver: number

@ApiProperty({ required: false })
dateSignatureCGU?: string

Expand Down
1 change: 0 additions & 1 deletion src/domain/milo/jeune.milo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export namespace JeuneMilo {
>

marquerAARchiver(id: string, aArchiver: boolean): Promise<void>
estAArchiver(id: string): Promise<boolean>
}

export function trierSituations(situations: Situation[]): Situation[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { ListeDeDiffusionSqlModel } from '../../sequelize/models/liste-de-diffus

export function fromSqlToDetailConseillerQueryModel(
conseillerSqlModel: ConseillerSqlModel,
aDesBeneficiairesARecuperer: boolean
aDesBeneficiairesARecuperer: boolean,
beneficiairesAArchiver: number
): DetailConseillerQueryModel {
const conseiller: DetailConseillerQueryModel = {
id: conseillerSqlModel.id,
Expand All @@ -16,7 +17,8 @@ export function fromSqlToDetailConseillerQueryModel(
dateVisionnageActus: conseillerSqlModel.dateVisionnageActus?.toISOString(),
agence: undefined,
notificationsSonores: conseillerSqlModel.notificationsSonores,
aDesBeneficiairesARecuperer: aDesBeneficiairesARecuperer
aDesBeneficiairesARecuperer,
beneficiairesAArchiver
}
if (conseillerSqlModel.agence) {
conseiller.agence = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,6 @@ export class MiloJeuneHttpSqlRepository implements JeuneMilo.Repository {
: undefined
}

async estAArchiver(id: string): Promise<boolean> {
const estAArchiver = await JeuneMiloAArchiverSqlModel.findByPk(id)
return Boolean(estAArchiver)
}

async marquerAARchiver(id: string, aArchiver: boolean): Promise<void> {
if (aArchiver) await JeuneMiloAArchiverSqlModel.upsert({ idJeune: id })
else await JeuneMiloAArchiverSqlModel.destroy({ where: { idJeune: id } })
Expand Down
21 changes: 20 additions & 1 deletion src/infrastructure/routes/conseillers.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '@nestjs/common'
import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'
import { DateTime } from 'luxon'
import { GetBeneficiairesAArchiverQueryHandler } from 'src/application/queries/get-beneficiaires-a-archiver.query.handler'
import { DeleteConseillerCommandHandler } from '../../application/commands/conseiller/delete-conseiller.command.handler'
import { ModifierConseillerCommandHandler } from '../../application/commands/conseiller/modifier-conseiller.command.handler'
import {
Expand Down Expand Up @@ -71,7 +72,8 @@ export class ConseillersController {
private readonly createListeDeDiffusionCommandHandler: CreateListeDeDiffusionCommandHandler,
private readonly getIdentitesJeunesQueryHandler: GetJeunesIdentitesQueryHandler,
private readonly deleteConseillerCommandHandler: DeleteConseillerCommandHandler,
private readonly getDemarchesConseillerQueryHandler: GetDemarchesConseillerQueryHandler
private readonly getDemarchesConseillerQueryHandler: GetDemarchesConseillerQueryHandler,
private readonly getBeneficiairesAArchiverQueryHandler: GetBeneficiairesAArchiverQueryHandler
) {}

@ApiOperation({
Expand Down Expand Up @@ -357,4 +359,21 @@ export class ConseillersController {
)
return handleResult(result)
}

@ApiOperation({
summary: 'Récupères l’identité des bénéficiaire à archiver du conseiller',
description: 'Autorisé pour tous les conseillers'
})
@Get(':idConseiller/beneficiaires-a-archiver')
async getBeneficiairesAArchiver(
@Param('idConseiller') idConseiller: string,
@Utilisateur() utilisateur: Authentification.Utilisateur
): Promise<IdentiteJeuneQueryModel[]> {
return handleResult(
await this.getBeneficiairesAArchiverQueryHandler.execute(
{ idConseiller },
utilisateur
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ConseillerAuthorizer } from 'src/application/authorizers/conseiller-authorizer'
import { GetBeneficiairesAArchiverQueryHandler } from 'src/application/queries/get-beneficiaires-a-archiver.query.handler'
import { GetBeneficiairesAArchiverQueryGetter } from 'src/application/queries/query-getters/get-beneficiaires-a-archiver.query.getter.db'
import { success } from 'src/building-blocks/types/result'
import { unUtilisateurConseiller } from 'test/fixtures/authentification.fixture'
import { expect, StubbedClass, stubClass } from 'test/utils'

describe('GetBeneficiaireAArchiverQueryHandler', () => {
let conseillerAuthorizer: ConseillerAuthorizer
let queryGetter: StubbedClass<GetBeneficiairesAArchiverQueryGetter>
let queryHandler: GetBeneficiairesAArchiverQueryHandler
beforeEach(async () => {
conseillerAuthorizer = stubClass(ConseillerAuthorizer)
queryGetter = stubClass(GetBeneficiairesAArchiverQueryGetter)
queryHandler = new GetBeneficiairesAArchiverQueryHandler(
conseillerAuthorizer,
queryGetter
)
})

describe('handle', () => {
it('recupère les bénéficiaires à archiver', async () => {
// Given
queryGetter.handle.resolves(
success([{ id: 'id-jeune-3', nom: 'Liskov', prenom: 'Barbara' }])
)

// When
const actual = await queryHandler.handle({
idConseiller: 'id-conseiller'
})

// Then
expect(queryGetter.handle).to.have.been.calledOnceWithExactly(
'id-conseiller'
)
expect(actual).to.deep.equal(
success([{ id: 'id-jeune-3', nom: 'Liskov', prenom: 'Barbara' }])
)
})
})

describe('authorize', () => {
it('appelle l’authorizer pour le conseiller', async () => {
// Given
const utilisateur = unUtilisateurConseiller()

// When
await queryHandler.authorize(
{ idConseiller: 'id-conseiller' },
utilisateur
)

// Then
expect(
conseillerAuthorizer.autoriserLeConseiller
).to.have.been.calledWithExactly('id-conseiller', utilisateur)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { SinonSandbox } from 'sinon'
import { GetBeneficiairesAArchiverQueryGetter } from '../../../src/application/queries/query-getters/get-beneficiaires-a-archiver.query.getter.db'
import { ConseillerAuthorizer } from '../../../src/application/authorizers/conseiller-authorizer'
import {
GetDetailConseillerQuery,
Expand Down Expand Up @@ -28,17 +29,23 @@ describe('GetDetailConseillerQueryHandler', () => {
let conseillerAuthorizer: StubbedClass<ConseillerAuthorizer>
let conseillerMiloService: StubbedClass<Conseiller.Milo.Service>
let getDetailConseillerQueryHandler: GetDetailConseillerQueryHandler
let getBeneficiairesAArchiverQueryGetter: StubbedClass<GetBeneficiairesAArchiverQueryGetter>
let sandbox: SinonSandbox

before(() => {
sandbox = createSandbox()
conseillerAuthorizer = stubClass(ConseillerAuthorizer)
conseillerMiloService = stubClass(Conseiller.Milo.Service)
getBeneficiairesAArchiverQueryGetter = stubClass(
GetBeneficiairesAArchiverQueryGetter
)
getBeneficiairesAArchiverQueryGetter.count.resolves(2)

getDetailConseillerQueryHandler = new GetDetailConseillerQueryHandler(
conseillerAuthorizer,
conseillerMiloService,
testConfig()
testConfig(),
getBeneficiairesAArchiverQueryGetter
)
})

Expand Down
Loading

0 comments on commit d89626e

Please sign in to comment.