Skip to content

Commit e33eec7

Browse files
committed
exclude assessments two days ago and after
Signed-off-by: Benjamin Bohec <bbohec.pro@gmail.com>
1 parent 5278cbb commit e33eec7

8 files changed

Lines changed: 179 additions & 295 deletions

back/src/adapters/primary/routers/convention/authenticatedConventionRoutes.e2e.test.ts

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -403,25 +403,6 @@ describe("authenticatedConventionRoutes", () => {
403403
},
404404
},
405405
});
406-
407-
expectToEqual(inMemoryUow.conventionQueries.paginatedConventionsParams, [
408-
{
409-
agencyUserId: validator.id,
410-
filters: {
411-
dateStart: { from: "2023-01-01" },
412-
statuses: ["ACCEPTED_BY_VALIDATOR", "PARTIALLY_SIGNED"],
413-
dateEnd: { from: "2019-08-01T10:10:00.000Z" },
414-
},
415-
pagination: {
416-
page: 1,
417-
perPage: 10,
418-
},
419-
sort: {
420-
by: "dateStart",
421-
direction: "desc",
422-
},
423-
},
424-
]);
425406
});
426407

427408
it("200 - Successfully gets conventions with assessment completion status filter - signed", async () => {
@@ -477,24 +458,6 @@ describe("authenticatedConventionRoutes", () => {
477458
},
478459
},
479460
});
480-
481-
expectToEqual(inMemoryUow.conventionQueries.paginatedConventionsParams, [
482-
{
483-
agencyUserId: validator.id,
484-
filters: {
485-
assessmentCompletionStatus: ["finalized"],
486-
dateEnd: { from: "2019-08-01T10:10:00.000Z" },
487-
},
488-
pagination: {
489-
page: 1,
490-
perPage: 10,
491-
},
492-
sort: {
493-
by: "dateStart",
494-
direction: "desc",
495-
},
496-
},
497-
]);
498461
});
499462

500463
it("200 - Successfully gets conventions with assessment completion status filter - to-be-completed", async () => {
@@ -527,24 +490,6 @@ describe("authenticatedConventionRoutes", () => {
527490
},
528491
},
529492
});
530-
531-
expectToEqual(inMemoryUow.conventionQueries.paginatedConventionsParams, [
532-
{
533-
agencyUserId: validator.id,
534-
filters: {
535-
assessmentCompletionStatus: ["to-complete"],
536-
dateEnd: { from: "2019-08-01T10:10:00.000Z" },
537-
},
538-
pagination: {
539-
page: 1,
540-
perPage: 10,
541-
},
542-
sort: {
543-
by: "dateStart",
544-
direction: "desc",
545-
},
546-
},
547-
]);
548493
});
549494

550495
it("200 - Successfully gets conventions with agencyIds filter", async () => {
@@ -607,24 +552,6 @@ describe("authenticatedConventionRoutes", () => {
607552
},
608553
},
609554
});
610-
611-
expectToEqual(inMemoryUow.conventionQueries.paginatedConventionsParams, [
612-
{
613-
agencyUserId: validator.id,
614-
filters: {
615-
agencyIds: [peAgency.id],
616-
dateEnd: { from: "2019-08-01T10:10:00.000Z" },
617-
},
618-
pagination: {
619-
page: 1,
620-
perPage: 10,
621-
},
622-
sort: {
623-
by: "dateStart",
624-
direction: "desc",
625-
},
626-
},
627-
]);
628555
});
629556
});
630557

back/src/domains/convention/adapters/InMemoryConventionQueries.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { addDays, isAfter, isBefore, subMonths } from "date-fns";
1+
import { addDays, isAfter, isBefore, subDays, subMonths } from "date-fns";
22
import { propEq, toPairs } from "ramda";
33
import {
44
type AgencyId,
@@ -52,13 +52,6 @@ import type { InMemoryConventionRepository } from "./InMemoryConventionRepositor
5252
const logger = createLogger(__filename);
5353

5454
export class InMemoryConventionQueries implements ConventionQueries {
55-
public paginatedConventionsParams: GetPaginatedConventionsForAgencyUserParams[] =
56-
[];
57-
58-
public getConventionsWithUnfinalizedAssessmentForAgencyUserParams: Parameters<
59-
ConventionQueries["getConventionsWithUnfinalizedAssessmentForAgencyUser"]
60-
>[0][] = [];
61-
6255
constructor(
6356
private readonly conventionRepository: InMemoryConventionRepository,
6457
private readonly agencyRepository: InMemoryAgencyRepository,
@@ -169,8 +162,6 @@ export class InMemoryConventionQueries implements ConventionQueries {
169162
public async getPaginatedConventionsForAgencyUser(
170163
params: GetPaginatedConventionsForAgencyUserParams,
171164
): Promise<DataWithPagination<ConventionReadDto>> {
172-
this.paginatedConventionsParams.push(params);
173-
174165
const { filters = {}, pagination, sort, agencyUserId } = params;
175166
const agencyIdsForUser = this.#getAgencyIdsForAgencyUser(agencyUserId);
176167

@@ -403,12 +394,6 @@ export class InMemoryConventionQueries implements ConventionQueries {
403394
pagination: Required<PaginationQueryParams>;
404395
now: Date;
405396
}): Promise<DataWithPagination<ConventionWithUnfinalizedAssessment>> {
406-
this.getConventionsWithUnfinalizedAssessmentForAgencyUserParams.push({
407-
userAgencyIds,
408-
pagination,
409-
now,
410-
});
411-
412397
if (userAgencyIds.length === 0)
413398
return {
414399
data: [],
@@ -421,6 +406,7 @@ export class InMemoryConventionQueries implements ConventionQueries {
421406
};
422407

423408
const threeMonthsAgo = subMonths(now, 3);
409+
const twoDaysAgo = subDays(now, 2);
424410
const signatureReleaseThreshold = addDays(
425411
ASSESSEMENT_SIGNATURE_RELEASE_DATE,
426412
1,
@@ -467,11 +453,17 @@ export class InMemoryConventionQueries implements ConventionQueries {
467453
createdAt,
468454
signatureReleaseThreshold,
469455
);
456+
const isCreatedAtLeastTwoDaysAgo = isBefore(createdAt, twoDaysAgo);
470457
const isWithinThreeMonths = !isBefore(createdAt, threeMonthsAgo);
471458
const isUnsigned =
472459
"signedAt" in assessment && assessment.signedAt === null;
473460

474-
if (!isAfterSignatureRelease || !isWithinThreeMonths || !isUnsigned)
461+
if (
462+
!isAfterSignatureRelease ||
463+
!isWithinThreeMonths ||
464+
!isUnsigned ||
465+
!isCreatedAtLeastTwoDaysAgo
466+
)
475467
return [];
476468

477469
return [

back/src/domains/convention/adapters/PgConventionQueries.integration.test.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { addDays, subDays, subMonths } from "date-fns";
1+
import { addDays, subDays, subMilliseconds, subMonths } from "date-fns";
22
import { sql } from "kysely";
33
import type { Pool } from "pg";
44
import {
@@ -3740,6 +3740,7 @@ describe("Pg implementation of ConventionQueries", () => {
37403740
describe("getConventionsWithUnfinalizedAssessmentForAgencyUser", () => {
37413741
const now = new Date("2026-06-15T10:00:00Z");
37423742
const threeMonthsAgo = subMonths(now, 3);
3743+
const twoDaysAgo = subDays(now, 2);
37433744
const lessThanThreeMonthsAgo = addDays(threeMonthsAgo, 2);
37443745
const moreThanThreeMonthsAgo = subDays(threeMonthsAgo, 2);
37453746
const afterSignatureRelease = addDays(
@@ -3982,6 +3983,70 @@ describe("Pg implementation of ConventionQueries", () => {
39823983
expectToEqual(result.data, []);
39833984
});
39843985

3986+
it("excludes assessments created two days ago", async () => {
3987+
const assessment = new AssessmentDtoBuilder()
3988+
.withConventionId(validatedConventionEnded5DaysAgo.id)
3989+
.withCreatedAt(twoDaysAgo.toISOString())
3990+
.build();
3991+
3992+
await conventionRepository.save(validatedConventionEnded5DaysAgo);
3993+
await assessmentRepo.save(
3994+
createAssessmentEntity(assessment, validatedConventionEnded5DaysAgo),
3995+
);
3996+
3997+
const result =
3998+
await conventionQueries.getConventionsWithUnfinalizedAssessmentForAgencyUser(
3999+
{
4000+
userAgencyIds: [agencyIdA],
4001+
pagination: { page: 1, perPage: 10 },
4002+
now,
4003+
},
4004+
);
4005+
4006+
expectToEqual(result.data, []);
4007+
});
4008+
4009+
it("include assessments created juste before two days ago", async () => {
4010+
const assessment = new AssessmentDtoBuilder()
4011+
.withConventionId(validatedConventionEnded5DaysAgo.id)
4012+
.withCreatedAt(subMilliseconds(twoDaysAgo, 1).toISOString())
4013+
.build();
4014+
4015+
await conventionRepository.save(validatedConventionEnded5DaysAgo);
4016+
await assessmentRepo.save(
4017+
createAssessmentEntity(assessment, validatedConventionEnded5DaysAgo),
4018+
);
4019+
4020+
const result =
4021+
await conventionQueries.getConventionsWithUnfinalizedAssessmentForAgencyUser(
4022+
{
4023+
userAgencyIds: [agencyIdA],
4024+
pagination: { page: 1, perPage: 10 },
4025+
now,
4026+
},
4027+
);
4028+
4029+
expectToEqual(result.data, [
4030+
{
4031+
assessment: {
4032+
createdAt: assessment.createdAt,
4033+
endedWithAJob: assessment.endedWithAJob,
4034+
signedAt: assessment.signedAt,
4035+
status: assessment.status,
4036+
},
4037+
beneficiary: {
4038+
firstname:
4039+
validatedConventionEnded5DaysAgo.signatories.beneficiary
4040+
.firstName,
4041+
lastname:
4042+
validatedConventionEnded5DaysAgo.signatories.beneficiary.lastName,
4043+
},
4044+
dateEnd: validatedConventionEnded5DaysAgo.dateEnd,
4045+
id: validatedConventionEnded5DaysAgo.id,
4046+
},
4047+
]);
4048+
});
4049+
39854050
it("excludes assessments already signed (finalized)", async () => {
39864051
await conventionRepository.save(validatedConventionEnded5DaysAgo);
39874052
const assessment = new AssessmentDtoBuilder()

back/src/domains/convention/adapters/PgConventionQueries.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { addDays, subMonths } from "date-fns";
1+
import { addDays, subDays, subMonths } from "date-fns";
22
import { sql } from "kysely";
33
import { andThen } from "ramda";
44
import {
@@ -483,6 +483,7 @@ export class PgConventionQueries implements ConventionQueries {
483483
};
484484

485485
const threeMonthsAgo = subMonths(now, 3);
486+
const twoDaysAgo = subDays(now, 2);
486487
const signatureReleaseThreshold = addDays(
487488
ASSESSEMENT_SIGNATURE_RELEASE_DATE,
488489
1,
@@ -523,7 +524,8 @@ export class PgConventionQueries implements ConventionQueries {
523524
.where("ia.signed_at", "is", null)
524525
.where("ia.status", "!=", "DID_NOT_SHOW")
525526
.where("ia.created_at", ">", signatureReleaseThreshold)
526-
.where("ia.created_at", ">=", threeMonthsAgo);
527+
.where("ia.created_at", ">=", threeMonthsAgo)
528+
.where("ia.created_at", "<", twoDaysAgo);
527529

528530
const paginatedUnfinalizedAssessmentQuery = conventionsWithoutAssessmentRows
529531
.select((eb) => [

back/src/domains/convention/use-cases/GetConventionsForAgencyUser.unit.test.ts

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
type DataWithPagination,
99
expectToEqual,
1010
type GetConventionsForAgencyUserParams,
11-
maxPerPageInWebPagination,
1211
} from "shared";
1312
import { toAgencyWithRights } from "../../../utils/agency";
1413
import { CustomTimeGateway } from "../../core/time-gateway/adapters/CustomTimeGateway";
@@ -79,66 +78,7 @@ describe("GetConventionsForAgencyUser", () => {
7978
uow.conventionRepository.setConventions(conventions);
8079
});
8180

82-
describe("Pagination", () => {
83-
it("should limit perPage to maxPerPageInWebPagination (100) even if a larger value is provided", async () => {
84-
const params: GetConventionsForAgencyUserParams = {
85-
filters: {},
86-
pagination: {
87-
page: 1,
88-
perPage: 500, // Much larger than the max
89-
},
90-
};
91-
92-
await getConventionsForAgencyUser.execute(params, currentUser);
93-
94-
const calls = uow.conventionQueries.paginatedConventionsParams;
95-
expect(calls.length).toBe(1);
96-
expect(calls[0].pagination.perPage).toBe(maxPerPageInWebPagination);
97-
});
98-
});
99-
10081
describe("Filtering", () => {
101-
it("should pass filters to the query", async () => {
102-
const params: GetConventionsForAgencyUserParams = {
103-
filters: {
104-
statuses: ["ACCEPTED_BY_VALIDATOR"],
105-
},
106-
};
107-
108-
await getConventionsForAgencyUser.execute(params, currentUser);
109-
110-
const calls = uow.conventionQueries.paginatedConventionsParams;
111-
expect(calls.length).toBe(1);
112-
expect(calls[0].filters).toEqual({
113-
...params.filters,
114-
dateEnd: {
115-
from: subMonths(timeGateway.now(), 25).toISOString(),
116-
},
117-
});
118-
});
119-
it("should pass filters dates to the query", async () => {
120-
const params: GetConventionsForAgencyUserParams = {
121-
filters: {
122-
dateEnd: {
123-
from: subMonths(timeGateway.now(), 25).toISOString(),
124-
},
125-
},
126-
};
127-
128-
await getConventionsForAgencyUser.execute(params, currentUser);
129-
130-
const calls = uow.conventionQueries.paginatedConventionsParams;
131-
expectToEqual(calls, [
132-
{
133-
filters: params.filters,
134-
pagination: {
135-
page: 1,
136-
perPage: 20,
137-
},
138-
agencyUserId: currentUser.id,
139-
},
140-
]);
141-
});
14282
it("should filter out conventions that are older than 25 months by default", async () => {
14383
const conventionOutOfRange = new ConventionDtoBuilder()
14484
.withId("convention-id-1")

back/src/domains/convention/use-cases/GetConventionsWithUnfinalizedAssessment.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {
2+
type AgencyRole,
23
type ConnectedUser,
34
type ConventionWithUnfinalizedAssessment,
45
type DataWithPagination,
6+
errors,
57
getPaginationParamsForWeb,
68
paginationRequiredQueryParamsSchema,
79
} from "shared";
@@ -20,14 +22,26 @@ export const makeGetConventionsWithUnfinalizedAssessment = useCaseBuilder(
2022
.withCurrentUser<ConnectedUser>()
2123
.withDeps<{ timeGateway: TimeGateway }>()
2224
.build(async ({ inputParams, uow, currentUser, deps }) => {
23-
const pagination = getPaginationParamsForWeb(inputParams);
25+
const allowedAgencyRoles: AgencyRole[] = [
26+
"agency-admin",
27+
"agency-viewer",
28+
"counsellor",
29+
"validator",
30+
];
31+
32+
const allowedAgencyRights = currentUser.agencyRights.filter((agencyRight) =>
33+
agencyRight.roles.some((role) => allowedAgencyRoles.includes(role)),
34+
);
35+
36+
if (!allowedAgencyRights.length)
37+
throw errors.agencies.noAgencyRights(currentUser.id);
2438

2539
return uow.conventionQueries.getConventionsWithUnfinalizedAssessmentForAgencyUser(
2640
{
27-
userAgencyIds: currentUser.agencyRights
28-
.filter((agencyRight) => agencyRight.roles.length > 0)
29-
.map((agencyRight) => agencyRight.agency.id),
30-
pagination,
41+
userAgencyIds: allowedAgencyRights.map(
42+
(agencyRight) => agencyRight.agency.id,
43+
),
44+
pagination: getPaginationParamsForWeb(inputParams),
3145
now: deps.timeGateway.now(),
3246
},
3347
);

0 commit comments

Comments
 (0)