From 3573f44c54467e6274f3e1402dd352e4ac3a4802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Soulas?= Date: Mon, 9 Sep 2024 16:19:46 +0200 Subject: [PATCH] feat(api,admin-react): allow funding on drop-out less than 6 month ago when proof received by admin --- .../cypress/e2e/candidacy/funding.cy.ts | 31 ++++++- .../candidacy/candidacy-drop-out-funding.json | 3 +- .../_components/useCandidacyFunding.hook.ts | 1 + .../[candidacyId]/funding/page.tsx | 1 + .../modules/candidacy/candidacy.graphql | 1 + .../unifvae/features/finance.unifvae.test.ts | 86 ++++++++++++------- .../unifvae/finance.unifvae.resolvers.ts | 1 + .../migration.sql | 2 + packages/reva-api/prisma/schema.prisma | 17 ++-- 9 files changed, 98 insertions(+), 45 deletions(-) create mode 100644 packages/reva-api/prisma/migrations/20240909082815_add_drop_out_proof_received_by_admin/migration.sql diff --git a/packages/reva-admin-react/cypress/e2e/candidacy/funding.cy.ts b/packages/reva-admin-react/cypress/e2e/candidacy/funding.cy.ts index 282c71338..413925516 100644 --- a/packages/reva-admin-react/cypress/e2e/candidacy/funding.cy.ts +++ b/packages/reva-admin-react/cypress/e2e/candidacy/funding.cy.ts @@ -1,12 +1,20 @@ import { stubQuery } from "../../utils/graphql"; import { sub } from "date-fns"; -function visitFunding({ dropOutCreationDate }: { dropOutCreationDate?: Date }) { +function visitFunding({ + dropOutCreationDate, + proofReceivedByAdmin, +}: { + dropOutCreationDate?: Date; + proofReceivedByAdmin?: boolean; +}) { cy.fixture("candidacy/candidacy-drop-out-funding.json").then( (candidacyDroppedOut) => { if (dropOutCreationDate) { candidacyDroppedOut.data.getCandidacyById.candidacyDropOut.createdAt = dropOutCreationDate; + candidacyDroppedOut.data.getCandidacyById.candidacyDropOut.proofReceivedByAdmin = + proofReceivedByAdmin; } else { delete candidacyDroppedOut.data.getCandidacyById.candidacyDropOut; } @@ -43,13 +51,19 @@ const sixMonthsAgoMinusOneMinute = sub(new Date(), { months: 6, minutes: -1 }); context("Funding form", () => { it("display a 'not available' alert when dropped-out less than 6 month ago", function () { - visitFunding({ dropOutCreationDate: sixMonthsAgoMinusOneMinute }); + visitFunding({ + dropOutCreationDate: sixMonthsAgoMinusOneMinute, + proofReceivedByAdmin: false, + }); cy.wait("@getCandidacyByIdFunding"); cy.get('[data-test="funding-request-not-available"]').should("exist"); }); it("do not display any alert when dropped-out 6 month ago", function () { - visitFunding({ dropOutCreationDate: sixMonthsAgo }); + visitFunding({ + dropOutCreationDate: sixMonthsAgo, + proofReceivedByAdmin: false, + }); cy.wait("@getCandidacyByIdFunding"); // Make sure the form is ready before testing non-existence of the alert cy.get('[data-test="funding-form"]').should("exist"); @@ -63,4 +77,15 @@ context("Funding form", () => { cy.get('[data-test="funding-form"]').should("exist"); cy.get('[data-test="funding-request-not-available"]').should("not.exist"); }); + + it("do not display any alert when dropped-out less than 6 month ago but with proof received by admin", function () { + visitFunding({ + dropOutCreationDate: sixMonthsAgoMinusOneMinute, + proofReceivedByAdmin: true, + }); + cy.wait("@getCandidacyByIdFunding"); + // Make sure the form is ready before testing non-existence of the alert + cy.get('[data-test="funding-form"]').should("exist"); + cy.get('[data-test="funding-request-not-available"]').should("not.exist"); + }); }); diff --git a/packages/reva-admin-react/cypress/fixtures/candidacy/candidacy-drop-out-funding.json b/packages/reva-admin-react/cypress/fixtures/candidacy/candidacy-drop-out-funding.json index 2fe452034..d90a241d5 100644 --- a/packages/reva-admin-react/cypress/fixtures/candidacy/candidacy-drop-out-funding.json +++ b/packages/reva-admin-react/cypress/fixtures/candidacy/candidacy-drop-out-funding.json @@ -34,7 +34,8 @@ ], "candidacyDropOut": { "createdAt": 1707305319452, - "droppedOutAt": 0 + "droppedOutAt": 0, + "proofReceivedByAdmin": false }, "certificateSkills": "RNCP A", "otherTraining": "Texte B", diff --git a/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/_components/useCandidacyFunding.hook.ts b/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/_components/useCandidacyFunding.hook.ts index 4ed15371b..faa9b418c 100644 --- a/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/_components/useCandidacyFunding.hook.ts +++ b/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/_components/useCandidacyFunding.hook.ts @@ -51,6 +51,7 @@ const getCandidacyByIdFunding = graphql(` } candidacyDropOut { createdAt + proofReceivedByAdmin } certificateSkills otherTraining diff --git a/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/page.tsx b/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/page.tsx index 1c2f60047..fc8887d90 100644 --- a/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/page.tsx +++ b/packages/reva-admin-react/src/app/(aap)/candidacies/[candidacyId]/funding/page.tsx @@ -240,6 +240,7 @@ const FundingPage = () => { {!isReadOnly && candidacy?.candidacyDropOut && + !candidacy.candidacyDropOut.proofReceivedByAdmin && isAfter( candidacy?.candidacyDropOut?.createdAt, sub(new Date(), { months: 6 }), diff --git a/packages/reva-api/modules/candidacy/candidacy.graphql b/packages/reva-api/modules/candidacy/candidacy.graphql index 4c4474153..21cd31c05 100644 --- a/packages/reva-api/modules/candidacy/candidacy.graphql +++ b/packages/reva-api/modules/candidacy/candidacy.graphql @@ -76,6 +76,7 @@ type CandidacyDropOut { createdAt: Timestamp! dropOutReason: DropOutReason! otherReasonContent: String + proofReceivedByAdmin: Boolean! status: CandidacyStatusStep! } diff --git a/packages/reva-api/modules/finance/unifvae/features/finance.unifvae.test.ts b/packages/reva-api/modules/finance/unifvae/features/finance.unifvae.test.ts index 4c9ef8e8a..005fcc40b 100644 --- a/packages/reva-api/modules/finance/unifvae/features/finance.unifvae.test.ts +++ b/packages/reva-api/modules/finance/unifvae/features/finance.unifvae.test.ts @@ -62,6 +62,45 @@ afterEach(async () => { await prismaClient.candidacyDropOut.deleteMany(); }); +const injectGraphqlFundingRequestCreation = async () => + injectGraphql({ + fastify: (global as any).fastify, + authorization: authorizationHeaderForUser({ + role: "manage_candidacy", + keycloakId: gestionaMaisonMereAapAccount1.keycloakId, + }), + payload: { + requestType: "mutation", + endpoint: "candidacy_createFundingRequestUnifvae", + returnFields: "{ id }", + arguments: { + candidacyId: candidacyUnifvae.id, + fundingRequest: { + ...fundingRequestSample, + }, + }, + enumFields: ["candidateGender"], + }, + }); + +const dropOutCandidacySixMonthsAgoMinusOneMinute = async ({ + proofReceivedByAdmin, +}: { + proofReceivedByAdmin: boolean; +}) => + prismaClient.candidacy.update({ + where: { id: candidacyUnifvae.id }, + data: { + candidacyDropOut: { + create: { + ...dropOutSixMonthsAgoMinusOneMinute, + dropOutReason: { connect: { label: "Autre" } }, + proofReceivedByAdmin, + }, + }, + }, + }); + test("should create fundingRequestUnifvae with matching batch", async () => { const resp = await injectGraphql({ fastify: (global as any).fastify, @@ -200,40 +239,11 @@ test("should fetch fundingRequestUnifvae", async () => { }); test("should fail to create fundingRequestUnifvae when candidacy was drop out less than 6 months ago then succeed after 6 months", async () => { - const createFundingRequest = async () => - await injectGraphql({ - fastify: (global as any).fastify, - authorization: authorizationHeaderForUser({ - role: "manage_candidacy", - keycloakId: gestionaMaisonMereAapAccount1.keycloakId, - }), - payload: { - requestType: "mutation", - endpoint: "candidacy_createFundingRequestUnifvae", - returnFields: "{ id }", - arguments: { - candidacyId: candidacyUnifvae.id, - fundingRequest: { - ...fundingRequestSample, - }, - }, - enumFields: ["candidateGender"], - }, - }); - - await prismaClient.candidacy.update({ - where: { id: candidacyUnifvae.id }, - data: { - candidacyDropOut: { - create: { - ...dropOutSixMonthsAgoMinusOneMinute, - dropOutReason: { create: { label: "dummy" } }, - }, - }, - }, + await dropOutCandidacySixMonthsAgoMinusOneMinute({ + proofReceivedByAdmin: false, }); - const resp = await createFundingRequest(); + const resp = await injectGraphqlFundingRequestCreation(); expect(resp.statusCode).toBe(200); const obj = resp.json(); @@ -251,8 +261,18 @@ test("should fail to create fundingRequestUnifvae when candidacy was drop out le }, }); - const resp2 = await createFundingRequest(); + const resp2 = await injectGraphqlFundingRequestCreation(); const obj2 = resp2.json(); expect(obj2).not.toHaveProperty("errors"); }); + +test("should allow the creation of fundingRequestUnifvae when candidacy was drop out less than 6 months ago but the proof was received by an admin", async () => { + await dropOutCandidacySixMonthsAgoMinusOneMinute({ + proofReceivedByAdmin: true, + }); + + const resp = await injectGraphqlFundingRequestCreation(); + const obj = resp.json(); + expect(obj).not.toHaveProperty("errors"); +}); diff --git a/packages/reva-api/modules/finance/unifvae/finance.unifvae.resolvers.ts b/packages/reva-api/modules/finance/unifvae/finance.unifvae.resolvers.ts index dab6a3365..006792b45 100644 --- a/packages/reva-api/modules/finance/unifvae/finance.unifvae.resolvers.ts +++ b/packages/reva-api/modules/finance/unifvae/finance.unifvae.resolvers.ts @@ -89,6 +89,7 @@ const unsafeResolvers = { if ( candidacy.candidacyDropOut && + !candidacy.candidacyDropOut.proofReceivedByAdmin && isAfter( candidacy.candidacyDropOut.createdAt, sub(new Date(), { months: 6 }), diff --git a/packages/reva-api/prisma/migrations/20240909082815_add_drop_out_proof_received_by_admin/migration.sql b/packages/reva-api/prisma/migrations/20240909082815_add_drop_out_proof_received_by_admin/migration.sql new file mode 100644 index 000000000..d97bd7292 --- /dev/null +++ b/packages/reva-api/prisma/migrations/20240909082815_add_drop_out_proof_received_by_admin/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "candidacy_drop_out" ADD COLUMN "proof_received_by_admin" BOOLEAN NOT NULL DEFAULT false; diff --git a/packages/reva-api/prisma/schema.prisma b/packages/reva-api/prisma/schema.prisma index 77c22cb54..52215df18 100644 --- a/packages/reva-api/prisma/schema.prisma +++ b/packages/reva-api/prisma/schema.prisma @@ -673,14 +673,15 @@ model DropOutReason { } model CandidacyDropOut { - candidacy Candidacy @relation(fields: [candidacyId], references: [id]) - candidacyId String @unique @map("candidacy_id") @db.Uuid - dropOutReason DropOutReason @relation(fields: [dropOutReasonId], references: [id]) - dropOutReasonId String @map("drop_out_reason_id") @db.Uuid - status CandidacyStatusStep - otherReasonContent String? @map("other_reason_content") - createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) - updatedAt DateTime? @map("updated_at") @db.Timestamptz(6) + candidacy Candidacy @relation(fields: [candidacyId], references: [id]) + candidacyId String @unique @map("candidacy_id") @db.Uuid + dropOutReason DropOutReason @relation(fields: [dropOutReasonId], references: [id]) + dropOutReasonId String @map("drop_out_reason_id") @db.Uuid + status CandidacyStatusStep + otherReasonContent String? @map("other_reason_content") + proofReceivedByAdmin Boolean @default(false) @map("proof_received_by_admin") + createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) + updatedAt DateTime? @map("updated_at") @db.Timestamptz(6) @@id([candidacyId]) @@map("candidacy_drop_out")