From d9d72409db75c376fcaf0f8647e12bc1152ea551 Mon Sep 17 00:00:00 2001 From: Sylvain Pontoreau Date: Mon, 9 Oct 2023 11:09:47 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20release=20(status,=20event?= =?UTF-8?q?=20emiiter,=20...)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../abandon/abandon.projector.ts" | 8 ++-- .../abandon/abandon.readmodel.ts" | 4 +- ...303\251ponseSign\303\251eAbandon.query.ts" | 4 +- .../laur\303\251at/laur\303\251at.setup.ts" | 2 +- .../abandon/abandon.aggregate.ts" | 39 ++++++++++++++----- .../laur\303\251at/abandon/abandon.error.ts" | 6 +++ .../laur\303\251at/abandon/abandon.event.ts" | 10 ++--- .../abandon/abandon.valueType.ts" | 2 +- .../accorder/accorderAbandon.command.ts" | 9 ++++- .../annuler/annulerAbandon.command.ts" | 2 +- .../confirmer/confirmerAbandon.command.ts" | 2 +- .../demander/demanderAbandon.command.ts" | 12 ++++-- .../demanderConfirmationAbandon.command.ts" | 35 +++++++++-------- .../rejeter/rejeterAbandon.command.ts" | 9 ++++- .../src/subscribe/eventStreamEmitter.ts | 6 ++- .../pg-projections/src/listProjection.ts | 3 +- scripts/migration-abandon/script.ts | 31 ++------------- 17 files changed, 105 insertions(+), 79 deletions(-) diff --git "a/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.projector.ts" "b/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.projector.ts" index a894569c26..26128f16c8 100644 --- "a/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.projector.ts" +++ "b/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.projector.ts" @@ -66,12 +66,12 @@ export const registerAbandonProjector = ({ statut: 'rejeté', }); break; - case 'ConfirmationAbandonDemandé-V1': + case 'ConfirmationAbandonDemandée-V1': await upsert(`abandon|${payload.identifiantProjet}`, { ...abandonToUpsert, - confirmationDemandéLe: payload.confirmationDemandéLe, - confirmationDemandéRéponseSignéeFormat: payload.réponseSignée.format, - statut: 'confirmation-demandé', + confirmationDemandéeLe: payload.confirmationDemandéeLe, + confirmationDemandéeRéponseSignéeFormat: payload.réponseSignée.format, + statut: 'confirmation-demandée', }); break; case 'AbandonConfirmé-V1': diff --git "a/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.readmodel.ts" "b/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.readmodel.ts" index 13841a2a2a..ba591ff0b5 100644 --- "a/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.readmodel.ts" +++ "b/packages/domain-views/src/projet/laur\303\251at/abandon/abandon.readmodel.ts" @@ -27,8 +27,8 @@ export type AbandonReadModel = ReadModel< rejetRéponseSignéeFormat?: string; rejetRejetéLe?: string; - confirmationDemandéLe?: string; - confirmationDemandéRéponseSignéeFormat?: string; + confirmationDemandéeLe?: string; + confirmationDemandéeRéponseSignéeFormat?: string; confirmationConfirméLe?: string; } >; diff --git "a/packages/domain-views/src/projet/laur\303\251at/abandon/consulter/consulterR\303\251ponseSign\303\251eAbandon.query.ts" "b/packages/domain-views/src/projet/laur\303\251at/abandon/consulter/consulterR\303\251ponseSign\303\251eAbandon.query.ts" index bf865ff581..0e4e9efe30 100644 --- "a/packages/domain-views/src/projet/laur\303\251at/abandon/consulter/consulterR\303\251ponseSign\303\251eAbandon.query.ts" +++ "b/packages/domain-views/src/projet/laur\303\251at/abandon/consulter/consulterR\303\251ponseSign\303\251eAbandon.query.ts" @@ -56,14 +56,14 @@ export const registerConsulterRéponseAbandonSignéeQuery = ({ ? abandon.accordAccordéLe : type === 'abandon-rejeté' ? abandon.rejetRejetéLe - : abandon.confirmationDemandéLe; + : abandon.confirmationDemandéeLe; const format = type === 'abandon-accordé' ? abandon.accordRéponseSignéeFormat : type === 'abandon-rejeté' ? abandon.rejetRéponseSignéeFormat - : abandon.confirmationDemandéRéponseSignéeFormat; + : abandon.confirmationDemandéeRéponseSignéeFormat; if (!date || !format) { return none; diff --git "a/packages/domain-views/src/projet/laur\303\251at/laur\303\251at.setup.ts" "b/packages/domain-views/src/projet/laur\303\251at/laur\303\251at.setup.ts" index c56a4ddca5..84a1e4355a 100644 --- "a/packages/domain-views/src/projet/laur\303\251at/laur\303\251at.setup.ts" +++ "b/packages/domain-views/src/projet/laur\303\251at/laur\303\251at.setup.ts" @@ -74,7 +74,7 @@ export const setupLauréatViews = async (dependencies: LauréatDependencies) => 'AbandonAnnulé-V1', 'AbandonConfirmé-V1', 'AbandonRejeté-V1', - 'ConfirmationAbandonDemandé-V1', + 'ConfirmationAbandonDemandée-V1', 'RebuildTriggered', ], eventHandler: async (event: AbandonEvent | RebuildTriggered) => { diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.aggregate.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.aggregate.ts" index 600b19b381..74ce568095 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.aggregate.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.aggregate.ts" @@ -5,7 +5,7 @@ import { AbandonEvent, AbandonAccordéEvent, AbandonRejetéEvent, - ConfirmationAbandonDemandéEvent, + ConfirmationAbandonDemandéeEvent, AbandonConfirméEvent, } from './abandon.event'; import { StatutAbandon } from './abandon.valueType'; @@ -23,6 +23,11 @@ type LoadAggregateFactoryDependencies = { loadAggregate: LoadAggregate }; export type Abandon = { getStatut: () => StatutAbandon; + estAccordé: () => boolean; + estRejeté: () => boolean; + estEnAttenteConfirmation: () => boolean; + estConfirmé: () => boolean; + estEnCours: () => boolean; demande: { raison: string; piéceJustificative?: { @@ -54,7 +59,23 @@ export type Abandon = { }; const getDefaultAggregate = (): Abandon => ({ - getStatut: function () { + estAccordé() { + return this.getStatut() === 'accordé'; + }, + estEnCours() { + const statusEnCours: Array = ['confirmation-demandée', 'confirmé', 'demandé']; + return statusEnCours.includes(this.getStatut()); + }, + estRejeté() { + return this.getStatut() === 'rejeté'; + }, + estEnAttenteConfirmation() { + return this.getStatut() === 'confirmation-demandée'; + }, + estConfirmé() { + return this.getStatut() === 'confirmé'; + }, + getStatut() { if (this.annuléLe) { return 'annulé'; } @@ -67,7 +88,7 @@ const getDefaultAggregate = (): Abandon => ({ } if (this.demande.confirmation && !this.demande.confirmation.confirméLe) { - return 'confirmation-demandé'; + return 'confirmation-demandée'; } if (this.demande.confirmation && this.demande.confirmation.confirméLe) { @@ -97,8 +118,8 @@ const abandonAggregateFactory: AggregateFactory = (events return updateAvecRejet(aggregate, payload); case 'AbandonAccordé-V1': return updateAvecAcceptation(aggregate, payload); - case 'ConfirmationAbandonDemandé-V1': - return updateAvecConfirmationAbandonDemandé(aggregate, payload); + case 'ConfirmationAbandonDemandée-V1': + return updateAvecConfirmationAbandonDemandée(aggregate, payload); case 'AbandonConfirmé-V1': return updateAvecAbandonConfirmé(aggregate, payload); case 'AbandonAnnulé-V1': @@ -169,17 +190,17 @@ const updateAvecAcceptation = (aggregate: Abandon, payload: AbandonAccordéEvent return newAggregate; }; -const updateAvecConfirmationAbandonDemandé = ( +const updateAvecConfirmationAbandonDemandée = ( aggregate: Abandon, - payload: ConfirmationAbandonDemandéEvent['payload'], + payload: ConfirmationAbandonDemandéeEvent['payload'], ) => { - const { confirmationDemandéLe, réponseSignée } = payload; + const { confirmationDemandéeLe, réponseSignée } = payload; let newAggregate: Abandon = { ...aggregate, }; newAggregate.demande.confirmation = { - demandéLe: convertirEnDateTime(confirmationDemandéLe), + demandéLe: convertirEnDateTime(confirmationDemandéeLe), réponseSignée, }; diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.error.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.error.ts" index 4980b14a25..3aa305ee63 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.error.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.error.ts" @@ -41,3 +41,9 @@ export class AucuneDemandeConfirmationAbandonError extends InvalidOperationError super(`Aucune demande de confirmation d'abandon en attente`); } } + +export class DemandeEnAttenteConfirmationError extends InvalidOperationError { + constructor() { + super(`L'abandon est en attente de confirmation`); + } +} diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.event.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.event.ts" index 118f752085..de551da44c 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.event.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.event.ts" @@ -49,11 +49,11 @@ export type AbandonAccordéEvent = DomainEvent< } >; -export type ConfirmationAbandonDemandéEvent = DomainEvent< - 'ConfirmationAbandonDemandé-V1', +export type ConfirmationAbandonDemandéeEvent = DomainEvent< + 'ConfirmationAbandonDemandée-V1', { - confirmationDemandéLe: string; - confirmationDemandéPar: RawIdentifiantUtilisateur; + confirmationDemandéeLe: string; + confirmationDemandéePar: RawIdentifiantUtilisateur; identifiantProjet: RawIdentifiantProjet; réponseSignée: { format: string; @@ -75,5 +75,5 @@ export type AbandonEvent = | AbandonAnnuléEvent | AbandonRejetéEvent | AbandonAccordéEvent - | ConfirmationAbandonDemandéEvent + | ConfirmationAbandonDemandéeEvent | AbandonConfirméEvent; diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.valueType.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.valueType.ts" index 4fc9d986c7..85eb5db985 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/abandon.valueType.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/abandon.valueType.ts" @@ -36,7 +36,7 @@ export type RéponseSignée = export type StatutAbandon = | 'demandé' | 'rejeté' - | 'confirmation-demandé' + | 'confirmation-demandée' | 'confirmé' | 'accordé' | 'annulé'; diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/accorder/accorderAbandon.command.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/accorder/accorderAbandon.command.ts" index 60ea10c739..584bf57ee4 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/accorder/accorderAbandon.command.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/accorder/accorderAbandon.command.ts" @@ -11,6 +11,7 @@ import { AbandonDéjàAccordéError, AbandonDéjàRejetéError, DemandeAbandonInconnuErreur, + DemandeEnAttenteConfirmationError, } from '../abandon.error'; import { IdentifiantUtilisateurValueType } from '../../../../domain.valueType'; @@ -48,14 +49,18 @@ export const registerAccorderAbandonCommand = ({ throw new DemandeAbandonInconnuErreur(); } - if (abandon.getStatut() === 'accordé') { + if (abandon.estAccordé()) { throw new AbandonDéjàAccordéError(); } - if (abandon.getStatut() === 'rejeté') { + if (abandon.estRejeté()) { throw new AbandonDéjàRejetéError(); } + if (abandon.estEnAttenteConfirmation()) { + throw new DemandeEnAttenteConfirmationError(); + } + await enregistrerRéponseSignée({ identifiantProjet, réponseSignée, diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/annuler/annulerAbandon.command.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/annuler/annulerAbandon.command.ts" index 54a26cf692..f48439f497 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/annuler/annulerAbandon.command.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/annuler/annulerAbandon.command.ts" @@ -38,7 +38,7 @@ export const registerAnnulerAbandonCommand = ({ throw new DemandeAbandonInconnuErreur(); } - if (abandon.getStatut() === 'accordé') { + if (abandon.estAccordé()) { throw new AbandonDéjàAccordéError(); } diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/confirmer/confirmerAbandon.command.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/confirmer/confirmerAbandon.command.ts" index 6362451145..80721898b9 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/confirmer/confirmerAbandon.command.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/confirmer/confirmerAbandon.command.ts" @@ -41,7 +41,7 @@ export const registerConfirmerAbandonCommand = ({ throw new DemandeAbandonInconnuErreur(); } - if (abandon.getStatut() !== 'confirmation-demandé') { + if (!abandon.estEnAttenteConfirmation()) { throw new AucuneDemandeConfirmationAbandonError(); } diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderAbandon.command.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderAbandon.command.ts" index 7ac3b05428..40f35981ac 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderAbandon.command.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderAbandon.command.ts" @@ -7,7 +7,7 @@ import { isSome } from '@potentiel/monads'; import { AbandonDemandéEvent } from '../abandon.event'; import { EnregistrerPiéceJustificativeAbandonPort } from '../abandon.port'; import { DateTimeValueType } from '../../../../common.valueType'; -import { DemandeAbandonEnCoursErreur } from '../abandon.error'; +import { AbandonDéjàAccordéError, DemandeAbandonEnCoursErreur } from '../abandon.error'; import { IdentifiantUtilisateurValueType } from '../../../../utilisateur/utilisateur.valueType'; export type DemanderAbandonCommand = Message< @@ -44,8 +44,14 @@ export const registerDemanderAbandonCommand = ({ }) => { const abandon = await loadAbandonAggregate(identifiantProjet); - if (isSome(abandon) && abandon.getStatut() !== 'annulé') { - throw new DemandeAbandonEnCoursErreur(); + if (isSome(abandon)) { + if (abandon.estAccordé()) { + throw new AbandonDéjàAccordéError(); + } + + if (abandon.estEnCours()) { + throw new DemandeAbandonEnCoursErreur(); + } } if (piéceJustificative) { diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderConfirmationAbandon.command.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderConfirmationAbandon.command.ts" index afa03d139f..081ddb48d0 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderConfirmationAbandon.command.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/demander/demanderConfirmationAbandon.command.ts" @@ -3,7 +3,7 @@ import { IdentifiantProjetValueType } from '../../../projet.valueType'; import { createAbandonAggregateId, loadAbandonAggregateFactory } from '../abandon.aggregate'; import { LoadAggregate, Publish } from '@potentiel/core-domain'; import { isNone } from '@potentiel/monads'; -import { ConfirmationAbandonDemandéEvent } from '../abandon.event'; +import { ConfirmationAbandonDemandéeEvent } from '../abandon.event'; import { DateTimeValueType } from '../../../../common.valueType'; import { AbandonDéjàAccordéError, @@ -50,19 +50,20 @@ export const registerDemanderConfirmationAbandonCommand = ({ throw new DemandeAbandonInconnuErreur(); } - const status = abandon.getStatut(); + if (abandon.estAccordé()) { + throw new AbandonDéjàAccordéError(); + } + + if (abandon.estRejeté()) { + throw new AbandonDéjàRejetéError(); + } + + if (abandon.estEnAttenteConfirmation()) { + throw new ConfirmationAbandonDéjàDemandéError(); + } - if (status !== 'demandé') { - switch (status) { - case 'accordé': - throw new AbandonDéjàAccordéError(); - case 'rejeté': - throw new AbandonDéjàRejetéError(); - case 'confirmé': - throw new AbandonDéjàConfirméError(); - case 'confirmation-demandé': - throw new ConfirmationAbandonDéjàDemandéError(); - } + if (abandon.estConfirmé()) { + throw new AbandonDéjàConfirméError(); } await enregistrerRéponseSignée({ @@ -71,15 +72,15 @@ export const registerDemanderConfirmationAbandonCommand = ({ dateDocumentRéponseSignée: dateDemandeConfirmationAbandon, }); - const event: ConfirmationAbandonDemandéEvent = { - type: 'ConfirmationAbandonDemandé-V1', + const event: ConfirmationAbandonDemandéeEvent = { + type: 'ConfirmationAbandonDemandée-V1', payload: { identifiantProjet: identifiantProjet.formatter(), réponseSignée: { format: réponseSignée.format, }, - confirmationDemandéLe: dateDemandeConfirmationAbandon.formatter(), - confirmationDemandéPar: confirmationDemandéePar.formatter(), + confirmationDemandéeLe: dateDemandeConfirmationAbandon.formatter(), + confirmationDemandéePar: confirmationDemandéePar.formatter(), }, }; diff --git "a/packages/domain/src/projet/laur\303\251at/abandon/rejeter/rejeterAbandon.command.ts" "b/packages/domain/src/projet/laur\303\251at/abandon/rejeter/rejeterAbandon.command.ts" index dfc50aab29..e8ce093e6f 100644 --- "a/packages/domain/src/projet/laur\303\251at/abandon/rejeter/rejeterAbandon.command.ts" +++ "b/packages/domain/src/projet/laur\303\251at/abandon/rejeter/rejeterAbandon.command.ts" @@ -11,6 +11,7 @@ import { AbandonDéjàAccordéError, AbandonDéjàRejetéError, DemandeAbandonInconnuErreur, + DemandeEnAttenteConfirmationError, } from '../abandon.error'; import { IdentifiantUtilisateurValueType } from '../../../../utilisateur/utilisateur.valueType'; @@ -48,14 +49,18 @@ export const registerRejeterAbandonCommand = ({ throw new DemandeAbandonInconnuErreur(); } - if (abandon.getStatut() === 'accordé') { + if (abandon.estAccordé()) { throw new AbandonDéjàAccordéError(); } - if (abandon.getStatut() === 'rejeté') { + if (abandon.estRejeté()) { throw new AbandonDéjàRejetéError(); } + if (abandon.estEnAttenteConfirmation()) { + throw new DemandeEnAttenteConfirmationError(); + } + await enregistrerRéponseSignée({ identifiantProjet, réponseSignée, diff --git a/packages/libraries/pg-event-sourcing/src/subscribe/eventStreamEmitter.ts b/packages/libraries/pg-event-sourcing/src/subscribe/eventStreamEmitter.ts index d9628d9c45..4e821f43ae 100644 --- a/packages/libraries/pg-event-sourcing/src/subscribe/eventStreamEmitter.ts +++ b/packages/libraries/pg-event-sourcing/src/subscribe/eventStreamEmitter.ts @@ -51,7 +51,11 @@ export class EventStreamEmitter extends EventEmitter { return; } - this.emit(this.#getChannelName(event.type), event); + if ( + notification.channel === `${this.#subscriber.streamCategory}|${this.#subscriber.name}` + ) { + this.emit(this.#getChannelName(event.type), event); + } } catch (error) { getLogger().error(new NotificationPayloadParseError(), { error, diff --git a/packages/libraries/pg-projections/src/listProjection.ts b/packages/libraries/pg-projections/src/listProjection.ts index e6934d802f..6d6dd6f663 100644 --- a/packages/libraries/pg-projections/src/listProjection.ts +++ b/packages/libraries/pg-projections/src/listProjection.ts @@ -41,8 +41,9 @@ export const listProjection = async ({ const totalResult = pagination ? await executeSelect<{ totalItems: string }>( - 'select count(key) as "totalItems" from domain_views.projection where key like $1', + `select count(key) as "totalItems" from domain_views.projection where key like $1 ${whereClause}`, `${type}|%`, + ...(where ? Object.values(where) : []), ) : [{ totalItems: result.length.toString() }]; diff --git a/scripts/migration-abandon/script.ts b/scripts/migration-abandon/script.ts index 9d48abc882..0506075e48 100644 --- a/scripts/migration-abandon/script.ts +++ b/scripts/migration-abandon/script.ts @@ -56,33 +56,10 @@ import { findProjection } from '@potentiel/pg-projections'; import { lookup } from 'mime-types'; import { isNone } from '@potentiel/monads'; -process.env.APPLICATION_NAME = 'potentiel-dev'; -process.env.APPLICATION_STAGE = 'development'; -process.env.LOGGER_LEVEL = 'warning'; - -// local -process.env.EVENT_STORE_CONNECTION_STRING = - 'postgres://potadmindb:localpwd@localhost:5432/potentiel'; - -// local -process.env.AWS_REGION = 'localhost'; -process.env.AWS_ACCESS_KEY_ID = 'minioadmin'; -process.env.AWS_SECRET_ACCESS_KEY = 'minioadmin'; -process.env.S3_ENDPOINT = 'http://localhost:9000'; -process.env.S3_BUCKET = 'potentiel'; - -// local -process.env.POSTGRESQL_ADDON_HOST = '127.0.0.1'; -process.env.POSTGRESQL_ADDON_PORT = '5432'; -process.env.POSTGRESQL_ADDON_USER = 'potadmindb'; -process.env.POSTGRESQL_ADDON_PASSWORD = 'localpwd'; -process.env.POSTGRESQL_ADDON_DB = 'potentiel'; -process.env.POSTGRESQL_POOL_MAX = '5'; - -const sourceEndPoint = ''; -const sourceAccessKeyId = ''; -const sourceSecretAccessKey = ''; -const sourceBucketName = ''; +const sourceEndPoint = process.env.SOURCE_ENDPOINT || ''; +const sourceAccessKeyId = process.env.SOURCE_ACCESS_KEY_ID || ''; +const sourceSecretAccessKey = process.env.SOURCE_SECRET_ACCESS_KEY || ''; +const sourceBucketName = process.env.SOURCE_BUCKET_NAME || ''; const source = new S3({ endpoint: sourceEndPoint,