Skip to content

Commit 0f07285

Browse files
committed
WIP : notify agency users of establishment bannishment
1 parent 30664b2 commit 0f07285

3 files changed

Lines changed: 437 additions & 80 deletions

File tree

back/src/config/bootstrap/createUseCases.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ export const createUseCases = ({
521521
deps: {
522522
saveNotificationAndRelatedEvent,
523523
immersionBaseUrl: config.immersionFacileBaseUrl,
524+
timeGateway: gateways.timeGateway,
524525
},
525526
}),
526527
addExchangeToDiscussion: makeAddExchangeToDiscussion({
Lines changed: 163 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { uniq } from "ramda";
12
import {
23
type AbsoluteUrl,
34
type ConventionStatus,
@@ -8,10 +9,14 @@ import {
89
type WithSiretDto,
910
withSiretSchema,
1011
} from "shared";
12+
import { agencyWithRightToAgencyDto } from "../../../../utils/agency";
1113
import type { SaveNotificationAndRelatedEvent } from "../../../core/notifications/helpers/Notification";
14+
import type { TimeGateway } from "../../../core/time-gateway/ports/TimeGateway";
15+
import type { UnitOfWork } from "../../../core/unit-of-work/ports/UnitOfWork";
1216
import { useCaseBuilder } from "../../../core/useCaseBuilder";
17+
import type { EstablishmentAggregate } from "../../entities/EstablishmentAggregate";
1318

14-
const conventionStatusesAffectedByBannishment: ConventionStatus[] = [
19+
const conventionStatusesBeforeValidation: ConventionStatus[] = [
1520
"READY_TO_SIGN",
1621
"PARTIALLY_SIGNED",
1722
"IN_REVIEW",
@@ -31,6 +36,7 @@ export const makeNotifyEstablishmentUsersAndBeneficiariesThatEstablishmentIsBann
3136
.withDeps<{
3237
saveNotificationAndRelatedEvent: SaveNotificationAndRelatedEvent;
3338
immersionBaseUrl: AbsoluteUrl;
39+
timeGateway: TimeGateway;
3440
}>()
3541
.build(async ({ uow, inputParams, deps }) => {
3642
const { siret } = inputParams;
@@ -44,80 +50,167 @@ export const makeNotifyEstablishmentUsersAndBeneficiariesThatEstablishmentIsBann
4450
if (!establishment.establishment.isEstablishmentBanned)
4551
throw errors.establishment.establishmentNotBanned({ siret });
4652

47-
const userRightIds = establishment.userRights
48-
.filter(
49-
(right) =>
50-
onlyAdminUserRightsWithStatusAccepted(right) ||
51-
onlyContactUserRightsWithStatusAccepted(right),
52-
)
53-
.map((right) => right.userId);
54-
55-
const users = await uow.userRepository.getByIds(userRightIds);
56-
57-
await executeInSequence(users, (user) =>
58-
deps.saveNotificationAndRelatedEvent(uow, {
59-
kind: "email",
60-
templatedContent: {
61-
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_ESTABLISHMENT_USERS",
62-
recipients: [user.email],
63-
params: { businessName: establishment.establishment.name, siret },
64-
},
65-
followedIds: { establishmentSiret: siret },
66-
}),
53+
await notifyEstablishmentUsers(
54+
uow,
55+
deps.saveNotificationAndRelatedEvent,
56+
establishment,
6757
);
6858

69-
const discussions = await uow.discussionRepository.getDiscussions({
70-
filters: { sirets: [siret] },
71-
limit: 1000,
72-
});
73-
74-
const pendingDiscussions = discussions.filter(
75-
(d) => d.status === "PENDING",
59+
await notifyBeneficiaries(
60+
uow,
61+
deps.saveNotificationAndRelatedEvent,
62+
deps.immersionBaseUrl,
63+
establishment,
7664
);
7765

78-
await executeInSequence(pendingDiscussions, (discussion) =>
79-
deps.saveNotificationAndRelatedEvent(uow, {
80-
kind: "email",
81-
templatedContent: {
82-
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_BENEFICIARY",
83-
recipients: [discussion.potentialBeneficiary.email],
84-
params: {
85-
businessName: establishment.establishment.name,
86-
beneficiaryFirstName: discussion.potentialBeneficiary.firstName,
87-
beneficiaryLastName: discussion.potentialBeneficiary.lastName,
88-
immersionBaseUrl: deps.immersionBaseUrl,
89-
},
90-
},
91-
followedIds: { establishmentSiret: siret },
92-
}),
66+
await notifyValidatorsAndPreValidators(
67+
uow,
68+
deps.timeGateway,
69+
deps.saveNotificationAndRelatedEvent,
70+
deps.immersionBaseUrl,
71+
establishment,
9372
);
73+
});
74+
75+
const notifyEstablishmentUsers = async (
76+
uow: UnitOfWork,
77+
saveNotificationAndRelatedEvent: SaveNotificationAndRelatedEvent,
78+
bannedEstablishment: EstablishmentAggregate,
79+
) => {
80+
const userRightIds = bannedEstablishment.userRights
81+
.filter(
82+
(right) =>
83+
onlyAdminUserRightsWithStatusAccepted(right) ||
84+
onlyContactUserRightsWithStatusAccepted(right),
85+
)
86+
.map((right) => right.userId);
9487

95-
const conventions = await uow.conventionQueries.getConventions({
96-
filters: {
97-
withSirets: [siret],
98-
withStatuses: conventionStatusesAffectedByBannishment,
88+
const users = await uow.userRepository.getByIds(userRightIds);
89+
90+
await executeInSequence(users, (user) =>
91+
saveNotificationAndRelatedEvent(uow, {
92+
kind: "email",
93+
templatedContent: {
94+
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_ESTABLISHMENT_USERS",
95+
recipients: [user.email],
96+
params: {
97+
businessName: bannedEstablishment.establishment.name,
98+
siret: bannedEstablishment.establishment.siret,
9999
},
100-
sortBy: "dateStart",
101-
});
102-
103-
await executeInSequence(conventions, (convention) =>
104-
deps.saveNotificationAndRelatedEvent(uow, {
105-
kind: "email",
106-
templatedContent: {
107-
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_BENEFICIARY",
108-
recipients: [convention.signatories.beneficiary.email],
109-
params: {
110-
businessName: establishment.establishment.name,
111-
beneficiaryFirstName:
112-
convention.signatories.beneficiary.firstName,
113-
beneficiaryLastName: convention.signatories.beneficiary.lastName,
114-
immersionBaseUrl: deps.immersionBaseUrl,
115-
},
116-
},
117-
followedIds: {
118-
establishmentSiret: siret,
119-
conventionId: convention.id,
120-
},
121-
}),
122-
);
100+
},
101+
followedIds: {
102+
establishmentSiret: bannedEstablishment.establishment.siret,
103+
},
104+
}),
105+
);
106+
};
107+
108+
const notifyBeneficiaries = async (
109+
uow: UnitOfWork,
110+
saveNotificationAndRelatedEvent: SaveNotificationAndRelatedEvent,
111+
immersionBaseUrl: AbsoluteUrl,
112+
bannedEstablishment: EstablishmentAggregate,
113+
) => {
114+
const discussions = await uow.discussionRepository.getDiscussions({
115+
filters: { sirets: [bannedEstablishment.establishment.siret] },
116+
limit: 1000,
117+
});
118+
119+
const pendingDiscussions = discussions.filter((d) => d.status === "PENDING");
120+
121+
await executeInSequence(pendingDiscussions, (discussion) =>
122+
saveNotificationAndRelatedEvent(uow, {
123+
kind: "email",
124+
templatedContent: {
125+
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_BENEFICIARY",
126+
recipients: [discussion.potentialBeneficiary.email],
127+
params: {
128+
businessName: bannedEstablishment.establishment.name,
129+
beneficiaryFirstName: discussion.potentialBeneficiary.firstName,
130+
beneficiaryLastName: discussion.potentialBeneficiary.lastName,
131+
immersionBaseUrl: immersionBaseUrl,
132+
},
133+
},
134+
followedIds: {
135+
establishmentSiret: bannedEstablishment.establishment.siret,
136+
},
137+
}),
138+
);
139+
140+
const conventionsBeforeValidation =
141+
await uow.conventionQueries.getConventions({
142+
filters: {
143+
withSirets: [bannedEstablishment.establishment.siret],
144+
withStatuses: conventionStatusesBeforeValidation,
145+
},
146+
sortBy: "dateStart",
147+
});
148+
149+
await executeInSequence(conventionsBeforeValidation, (convention) =>
150+
saveNotificationAndRelatedEvent(uow, {
151+
kind: "email",
152+
templatedContent: {
153+
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_BENEFICIARY",
154+
recipients: [convention.signatories.beneficiary.email],
155+
params: {
156+
businessName: bannedEstablishment.establishment.name,
157+
beneficiaryFirstName: convention.signatories.beneficiary.firstName,
158+
beneficiaryLastName: convention.signatories.beneficiary.lastName,
159+
immersionBaseUrl: immersionBaseUrl,
160+
},
161+
},
162+
followedIds: {
163+
establishmentSiret: bannedEstablishment.establishment.siret,
164+
conventionId: convention.id,
165+
},
166+
}),
167+
);
168+
};
169+
170+
const notifyValidatorsAndPreValidators = async (
171+
uow: UnitOfWork,
172+
timeGateway: TimeGateway,
173+
saveNotificationAndRelatedEvent: SaveNotificationAndRelatedEvent,
174+
immersionBaseUrl: AbsoluteUrl,
175+
bannedEstablishment: EstablishmentAggregate,
176+
) => {
177+
const validatedConventions = await uow.conventionQueries.getConventions({
178+
filters: {
179+
withSirets: [bannedEstablishment.establishment.siret],
180+
withStatuses: ["ACCEPTED_BY_VALIDATOR"],
181+
endDate: { from: timeGateway.now() },
182+
},
183+
sortBy: "dateStart",
184+
});
185+
186+
await executeInSequence(validatedConventions, async (convention) => {
187+
const agency = await uow.agencyRepository.getById(convention.agencyId);
188+
if (!agency)
189+
throw errors.agency.notFound({ agencyId: convention.agencyId });
190+
191+
const agencyWithUserEmailNotificationActivated =
192+
await agencyWithRightToAgencyDto(uow, agency);
193+
194+
await saveNotificationAndRelatedEvent(uow, {
195+
kind: "email",
196+
templatedContent: {
197+
kind: "ESTABLISHMENT_BANNED_NOTIFICATION_TO_VALIDATOR_AND_PREVALIDATOR",
198+
recipients: uniq([
199+
...agencyWithUserEmailNotificationActivated.validatorEmails,
200+
...agencyWithUserEmailNotificationActivated.counsellorEmails,
201+
]),
202+
params: {
203+
businessName: bannedEstablishment.establishment.name,
204+
beneficiaryFirstName: convention.signatories.beneficiary.firstName,
205+
beneficiaryLastName: convention.signatories.beneficiary.lastName,
206+
immersionBaseUrl: immersionBaseUrl,
207+
conventionId: convention.id,
208+
},
209+
},
210+
followedIds: {
211+
establishmentSiret: bannedEstablishment.establishment.siret,
212+
conventionId: convention.id,
213+
},
123214
});
215+
});
216+
};

0 commit comments

Comments
 (0)