diff --git a/back/src/bsds/resolvers/queries/__tests__/bsds.bsdd.integration.ts b/back/src/bsds/resolvers/queries/__tests__/bsds.bsdd.integration.ts index 26f3595d13..2adb7c4695 100644 --- a/back/src/bsds/resolvers/queries/__tests__/bsds.bsdd.integration.ts +++ b/back/src/bsds/resolvers/queries/__tests__/bsds.bsdd.integration.ts @@ -409,6 +409,7 @@ describe("Query.bsds workflow", () => { receivedAt: new Date().toISOString() as any, receivedBy: recipient.user.name, quantityReceived: 1, + quantityRefused: 0, signedAt: new Date().toISOString() as any, wasteAcceptationStatus: "ACCEPTED" } @@ -859,7 +860,8 @@ describe("Query.bsds workflow", () => { receivedAt: new Date().toISOString() as any, signedAt: new Date().toISOString() as any, receivedBy: "Destination", - quantityReceived: 1 + quantityReceived: 1, + quantityRefused: 0 } } }); diff --git a/back/src/forms/__tests__/validation.integration.ts b/back/src/forms/__tests__/validation.integration.ts index b70fa30cd3..05ec89ec9a 100644 --- a/back/src/forms/__tests__/validation.integration.ts +++ b/back/src/forms/__tests__/validation.integration.ts @@ -1111,6 +1111,7 @@ describe("receivedInfosSchema", () => { const receivedInfo: ReceivedFormInput = { wasteAcceptationStatus: "ACCEPTED", quantityReceived: 12.5, + quantityRefused: 0, wasteRefusalReason: "", receivedBy: "Jim", receivedAt: new Date("2020-01-17T10:12:00+0100"), @@ -1137,7 +1138,8 @@ describe("receivedInfosSchema", () => { describe("waste is refused", () => { const receivedInfo: ReceivedFormInput = { wasteAcceptationStatus: "REFUSED", - quantityReceived: 0, + quantityReceived: 10, + quantityRefused: 10, wasteRefusalReason: "non conformity", receivedBy: "Joe", receivedAt: new Date("2020-01-17T10:12:00+0100"), @@ -1165,6 +1167,7 @@ describe("receivedInfosSchema", () => { const receivedInfo: ReceivedFormInput = { wasteAcceptationStatus: "PARTIALLY_REFUSED", quantityReceived: 11, + quantityRefused: 6, wasteRefusalReason: "mixed waste", receivedBy: "Bill", receivedAt: new Date("2020-01-17T10:12:00+0100"), @@ -1187,23 +1190,44 @@ describe("receivedInfosSchema", () => { ); }); - it("should be invalid when quantity received is 0", async () => { - const validateFn = () => - receivedInfoSchema.validate({ ...receivedInfo, quantityReceived: 0 }); - await expect(validateFn()).rejects.toThrow( - "Réception : le poids doit être supérieur à 0 lorsque le déchet est accepté ou accepté partiellement" - ); - }); + // TODO: can no longer be tested because error on quantityRefused pops first + // it("should be invalid when quantity received is 0", async () => { + // const validateFn = () => + // receivedInfoSchema.validate({ + // ...receivedInfo, + // quantityReceived: 0, + // quantityRefused: 0 + // }); + // await expect(validateFn()).rejects.toThrow( + // "Réception : le poids doit être supérieur à 0 lorsque le déchet est accepté ou accepté partiellement" + // ); + // }); }); describe("quantityRefused", () => { const form = { receivedBy: "Bill", + createdAt: new Date("2025-03-20T10:12:00+0100"), receivedAt: new Date("2020-01-17T10:12:00+0100"), signedAt: new Date("2020-01-17T10:12:00+0100") }; - it("quantityRefused is not mandatory", async () => { + it("quantityRefused is not required if reception only", async () => { + // Given + const update = { + ...form, + quantityReceived: 10 + // No acceptation data, just plain reception + }; + + // When + const isValid = await receivedInfoSchema.validate(update); + + // Then + expect(isValid).toBeTruthy(); + }); + + it("quantityRefused is required if wasteAcceptationStatus + quantityReceived (PARTIALLY_REFUSED)", async () => { // Given const update = { ...form, @@ -1212,6 +1236,60 @@ describe("receivedInfosSchema", () => { quantityReceived: 10 }; + // When + const validateFn = () => receivedInfoSchema.validate(update); + + // Then + await expect(validateFn()).rejects.toThrow( + "La quantité refusée (quantityRefused) est requise" + ); + }); + + it("quantityRefused is required if wasteAcceptationStatus + quantityReceived (ACCEPTED)", async () => { + // Given + const update = { + ...form, + wasteAcceptationStatus: "ACCEPTED", + quantityReceived: 10 + }; + + // When + const validateFn = () => receivedInfoSchema.validate(update); + + // Then + await expect(validateFn()).rejects.toThrow( + "La quantité refusée (quantityRefused) est requise" + ); + }); + + it("quantityRefused is required if wasteAcceptationStatus + quantityReceived (REFUSED)", async () => { + // Given + const update = { + ...form, + wasteAcceptationStatus: "REFUSED", + wasteRefusalReason: "Because", + quantityReceived: 10 + }; + + // When + const validateFn = () => receivedInfoSchema.validate(update); + + // Then + await expect(validateFn()).rejects.toThrow( + "La quantité refusée (quantityRefused) est requise" + ); + }); + + it("quantityRefused can be 0 if waste is REFUSED and quantityReceived = 0", async () => { + // Given + const update = { + ...form, + wasteAcceptationStatus: "REFUSED", + wasteRefusalReason: "Because", + quantityReceived: 0, + quantityRefused: 0 + }; + // When const isValid = await receivedInfoSchema.validate(update); @@ -1235,24 +1313,21 @@ describe("receivedInfosSchema", () => { ); }); - it.each([null, undefined, 0])( - "waste is ACCEPTED > quantityReceived = 10 > quantityRefused can be %p", - async quantityRefused => { - // Given - const update = { - ...form, - wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 10, - quantityRefused - }; + it("waste is ACCEPTED > quantityReceived = 10 > quantityRefused must equal 0", async () => { + // Given + const update = { + ...form, + wasteAcceptationStatus: "ACCEPTED", + quantityReceived: 10, + quantityRefused: 0 + }; - // When - const isValid = await receivedInfoSchema.validate(update); + // When + const isValid = await receivedInfoSchema.validate(update); - // Then - expect(isValid).toBeTruthy(); - } - ); + // Then + expect(isValid).toBeTruthy(); + }); it.each([5, 10, 15])( "waste is ACCEPTED > quantityReceived = 10 > quantityRefused can NOT be %p", @@ -1275,25 +1350,22 @@ describe("receivedInfosSchema", () => { } ); - it.each([null, undefined, 10])( - "waste is REFUSED > quantityReceived = 10 > quantityRefused can be %p", - async quantityRefused => { - // Given - const update = { - ...form, - wasteAcceptationStatus: "REFUSED", - wasteRefusalReason: "Reason", - quantityReceived: 10, - quantityRefused - }; + it("waste is REFUSED > quantityReceived = 10 > quantityRefused must be quantityReceived", async () => { + // Given + const update = { + ...form, + wasteAcceptationStatus: "REFUSED", + wasteRefusalReason: "Reason", + quantityReceived: 10, + quantityRefused: 10 + }; - // When - const isValid = await receivedInfoSchema.validate(update); + // When + const isValid = await receivedInfoSchema.validate(update); - // Then - expect(isValid).toBeTruthy(); - } - ); + // Then + expect(isValid).toBeTruthy(); + }); it.each([0, 3, 15])( "waste is REFUSED > quantityReceived = 10 > quantityRefused can NOT be %p", @@ -2340,6 +2412,7 @@ describe("processedInfoSchema", () => { const receivedInfo: ReceivedFormInput = { wasteAcceptationStatus: "ACCEPTED", quantityReceived: 12.5, + quantityRefused: 0, wasteRefusalReason: "", receivedBy: "Jim", receivedAt: new Date("2020-01-17T10:12:00+0100"), diff --git a/back/src/forms/converter.ts b/back/src/forms/converter.ts index 6fa69d5a4b..72e719737e 100644 --- a/back/src/forms/converter.ts +++ b/back/src/forms/converter.ts @@ -382,8 +382,9 @@ export function flattenBsddRevisionRequestInput( wasteDetailsPackagingInfos: prismaJsonNoNull( chain(reviewContent, c => chain(c.wasteDetails, w => w.packagingInfos)) ), - wasteAcceptationStatus: chain(reviewContent, c => c.wasteAcceptationStatus), - wasteRefusalReason: chain(reviewContent, c => c.wasteRefusalReason), + // Retirés jusqu'à nouvel ordre! + // wasteAcceptationStatus: chain(reviewContent, c => c.wasteAcceptationStatus), + // wasteRefusalReason: chain(reviewContent, c => c.wasteRefusalReason), wasteDetailsSampleNumber: chain(reviewContent, c => chain(c.wasteDetails, w => w.sampleNumber) ), diff --git a/back/src/forms/examples/fixtures.ts b/back/src/forms/examples/fixtures.ts index 1fbfc13952..5001955a85 100644 --- a/back/src/forms/examples/fixtures.ts +++ b/back/src/forms/examples/fixtures.ts @@ -138,7 +138,8 @@ const receivedInfoInput = { receivedBy: "Antoine Derieux", receivedAt: "2020-04-05T11:18:00", signedAt: "2020-04-05T12:00:00", - quantityReceived: 1 + quantityReceived: 1, + quantityRefused: 0 }; const processedInfoInput = { @@ -168,6 +169,7 @@ const tempStoredInfosInput = { receivedAt: "2020-05-03T09:00:00", signedAt: "2020-05-03T09:00:00", quantityReceived: 1, + quantityRefused: 0, quantityType: "REAL" }; diff --git a/back/src/forms/resolvers/mutations/__tests__/createFormRevisionRequest.integration.ts b/back/src/forms/resolvers/mutations/__tests__/createFormRevisionRequest.integration.ts index 2583540f23..59440e6589 100644 --- a/back/src/forms/resolvers/mutations/__tests__/createFormRevisionRequest.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/createFormRevisionRequest.integration.ts @@ -352,16 +352,11 @@ describe("Mutation.createFormRevisionRequest", () => { } } }); - expect(errors).toEqual([ - expect.objectContaining({ - message: - "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + - " Il lui appartient de mettre à jour son profil.", - extensions: { - code: "BAD_USER_INPUT" - } - }) - ]); + expect(errors[0].message).toBe( + "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + + " Il lui appartient de mettre à jour son profil." + ); + expect(errors[0].extensions?.code).toBe("BAD_USER_INPUT"); } ); @@ -401,16 +396,12 @@ describe("Mutation.createFormRevisionRequest", () => { } } }); - expect(errors).toEqual([ - expect.objectContaining({ - message: - "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + - " Il lui appartient de mettre à jour son profil.", - extensions: { - code: "BAD_USER_INPUT" - } - }) - ]); + + expect(errors[0].message).toBe( + "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + + " Il lui appartient de mettre à jour son profil." + ); + expect(errors[0].extensions?.code).toBe("BAD_USER_INPUT"); } ); @@ -450,16 +441,11 @@ describe("Mutation.createFormRevisionRequest", () => { } } }); - expect(errors).toEqual([ - expect.objectContaining({ - message: - "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + - " Il lui appartient de mettre à jour son profil.", - extensions: { - code: "BAD_USER_INPUT" - } - }) - ]); + expect(errors[0].message).toBe( + "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + + " Il lui appartient de mettre à jour son profil." + ); + expect(errors[0].extensions?.code).toBe("BAD_USER_INPUT"); } ); @@ -499,16 +485,11 @@ describe("Mutation.createFormRevisionRequest", () => { } } }); - expect(errors).toEqual([ - expect.objectContaining({ - message: - "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + - " Il lui appartient de mettre à jour son profil.", - extensions: { - code: "BAD_USER_INPUT" - } - }) - ]); + expect(errors[0].message).toBe( + "Le sous-profil sélectionné par l'établissement destinataire ne lui permet pas de prendre en charge ce type de déchet." + + " Il lui appartient de mettre à jour son profil." + ); + expect(errors[0].extensions?.code).toBe("BAD_USER_INPUT"); } ); @@ -629,6 +610,7 @@ describe("Mutation.createFormRevisionRequest", () => { readableId: getReadableId(), ownerId: user.id, quantityReceived: 2.4, + quantityRefused: 0, wasteAcceptationStatus: "ACCEPTED", receivedAt: "2022-03-20T00:00:00.000Z", receivedBy: "John Doe", @@ -1822,72 +1804,9 @@ describe("Mutation.createFormRevisionRequest", () => { ); }); - describe("wasteAcceptationStatus & quantityRefused", () => { - it.each([Status.ACCEPTED, Status.TEMP_STORER_ACCEPTED])( - "can review BSD wasteAcceptationStatus if status is %p", - async status => { - // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: Status.ACCEPTED, - quantityReceived: 10, - receivedAt: new Date() - } - }); - - // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Raison", - quantityReceived: 0 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } - }); - - // Then - expect(errors).toBeUndefined(); - - const revisionRequest = - await prisma.bsddRevisionRequest.findFirstOrThrow({ - where: { bsddId: bsdd.id } - }); - - expect(revisionRequest.wasteAcceptationStatus).toEqual( - WasteAcceptationStatus.REFUSED - ); - expect(revisionRequest.wasteRefusalReason).toEqual("Raison"); - expect(revisionRequest.quantityReceived).toEqual(0); - expect(revisionRequest.quantityRefused).toEqual(null); - } - ); - - it("can NOT review BSD wasteAcceptationStatus if status is NOT ACCEPTED or TEMP_STORED_ACCEPTED", async () => { - // Given + describe("quantityReceived & quantityRefused", () => { + const createUserAndBSDD = async formOpt => { + // Companies & users const { company: recipientCompany } = await userWithCompanyFactory( "ADMIN", { @@ -1898,253 +1817,135 @@ describe("Mutation.createFormRevisionRequest", () => { } ); const { user, company } = await userWithCompanyFactory("ADMIN"); + + // Bsdd const bsdd = await formFactory({ ownerId: user.id, opt: { - status: Status.PROCESSED, emitterCompanySiret: company.siret, recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - quantityReceived: 10 + receivedAt: new Date(), + ...formOpt } }); - // When + return { + bsdd, + company, + user + }; + }; + + const createRevision = async (user, company, bsddId, revisionContent) => { const { mutate } = makeClient(user); - const { errors } = await mutate< + return await mutate< Pick, MutationCreateFormRevisionRequestArgs >(CREATE_FORM_REVISION_REQUEST, { variables: { input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Raison", - quantityReceived: 0 - }, + formId: bsddId, + content: revisionContent, comment: "A comment", authoringCompanySiret: company.siret! } } }); + }; + + it("cannot specify quantityRefused < quantityReceived if wasteAcceptationStatus = REFUSED", async () => { + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, + wasteRefusalReason: "Raison", + quantityReceived: 10 + }); + + // When + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10, + quantityRefused: 5 + }); // Then expect(errors).not.toBeUndefined(); expect(errors[0].message).toBe( - "Le statut d'acceptation des déchets n'est modifiable que si le bordereau est au stade de la réception." + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" ); - }); - - it.each([Status.ACCEPTED, Status.TEMP_STORER_ACCEPTED])( - "can review BSD wasteAcceptationStatus if status is %p with quantityRefused", - async status => { - // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - quantityReceived: 10, - receivedAt: new Date() - } - }); - - // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: - WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Raison", - quantityReceived: 10, - quantityRefused: 7 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } - }); - - // Then - expect(errors).toBeUndefined(); - const revisionRequest = - await prisma.bsddRevisionRequest.findFirstOrThrow({ - where: { bsddId: bsdd.id } - }); + // When 2: without quantityReceived + const { errors: errors2 } = await createRevision(user, company, bsdd.id, { + quantityRefused: 5 + }); - expect(revisionRequest.wasteAcceptationStatus).toEqual( - WasteAcceptationStatus.PARTIALLY_REFUSED - ); - expect(revisionRequest.wasteRefusalReason).toEqual("Raison"); - expect(revisionRequest.quantityReceived).toEqual(10); - expect(revisionRequest.quantityRefused).toEqual(7); - } - ); + // Then + expect(errors2).not.toBeUndefined(); + expect(errors2[0].message).toBe( + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" + ); + }); - it("can NOT review BSD wasteAcceptationStatus if not defined", async () => { + it("can specify quantityReceived != quantityRefused if wasteAcceptationStatus = REFUSED", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, + wasteRefusalReason: "Raison", + quantityReceived: 10, + quantityRefused: 10 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Raison", - quantityReceived: 0 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityRefused: 9 }); // Then expect(errors).not.toBeUndefined(); expect(errors[0].message).toBe( - "Le statut d'acceptation des déchets n'est modifiable que s'il a déjà une valeur." + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" ); }); - it("cannot specify quantityRefused < quantityReceived if wasteAcceptationStatus = REFUSED", async () => { + it("can specify quantityRefused = quantityReceived if wasteAcceptationStatus = REFUSED", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - quantityReceived: 10, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, + wasteRefusalReason: "Raison", + quantityReceived: 10 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Raison", - quantityReceived: 10, - quantityRefused: 5 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityRefused: 10 }); // Then - expect(errors).not.toBeUndefined(); - expect(errors[0].message).toBe( - "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" + expect(errors).toBeUndefined(); + + const revisionRequest = await prisma.bsddRevisionRequest.findFirstOrThrow( + { + where: { bsddId: bsdd.id } + } ); + + expect(revisionRequest.quantityRefused).toEqual(10); }); it("cannot specify quantityRefused > 0 if wasteAcceptationStatus = ACCEPTED", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 0, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, + quantityReceived: 5 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - quantityReceived: 10, - quantityRefused: 1 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10, + quantityRefused: 1 }); // Then @@ -2152,52 +1953,32 @@ describe("Mutation.createFormRevisionRequest", () => { expect(errors[0].message).toBe( "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" ); + + // When 2: without quantityReceived + const { errors: errors2 } = await createRevision(user, company, bsdd.id, { + quantityRefused: 1 + }); + + // Then + expect(errors2).not.toBeUndefined(); + expect(errors2[0].message).toBe( + "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" + ); }); it("cannot specify quantityRefused = quantityReceived if wasteAcceptationStatus = PARTIALLY_ACCEPTED", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 0, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 5 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 10, - quantityRefused: 10 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10, + quantityRefused: 10 }); // Then @@ -2205,50 +1986,32 @@ describe("Mutation.createFormRevisionRequest", () => { expect(errors[0].message).toBe( "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" ); + + // When 2: without quantityReceived + const { errors: errors2 } = await createRevision(user, company, bsdd.id, { + quantityRefused: 5 + }); + + // Then + expect(errors2).not.toBeUndefined(); + expect(errors2[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); }); it("bsdd waste is refused > should not be able to update quantityRefused to 0", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 0, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 10 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - quantityReceived: 10, - quantityRefused: 0 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10, + quantityRefused: 5 }); // Then @@ -2256,50 +2019,32 @@ describe("Mutation.createFormRevisionRequest", () => { expect(errors[0].message).toBe( "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" ); + + // When 2: without specifying quantityReceived + const { errors: errors2 } = await createRevision(user, company, bsdd.id, { + quantityRefused: 5 + }); + + // Then + expect(errors2).not.toBeUndefined(); + expect(errors2[0].message).toBe( + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" + ); }); it("bsdd waste is accepted > should not be able to update quantityRefused to > 0", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - wasteRefusalReason: "Reason", - quantityReceived: 0, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, + wasteRefusalReason: "Reason", + quantityReceived: 5 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - quantityReceived: 10, - quantityRefused: 10 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10, + quantityRefused: 2 }); // Then @@ -2307,50 +2052,32 @@ describe("Mutation.createFormRevisionRequest", () => { expect(errors[0].message).toBe( "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" ); + + // When 2: without specifying quantityReceived + const { errors: errors2 } = await createRevision(user, company, bsdd.id, { + quantityRefused: 2 + }); + + // Then + expect(errors2).not.toBeUndefined(); + expect(errors2[0].message).toBe( + "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" + ); }); it("bsdd waste is partially refused > should not be able to update quantityRefused to >= quantityReceived", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 0, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 5 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - quantityReceived: 10, - quantityRefused: 10 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 5, + quantityRefused: 5 }); // Then @@ -2358,98 +2085,80 @@ describe("Mutation.createFormRevisionRequest", () => { expect(errors[0].message).toBe( "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" ); + + // When 2: without specifying quantityReceived + const { errors: errors2 } = await createRevision(user, company, bsdd.id, { + quantityRefused: 5 + }); + + // Then + expect(errors2).not.toBeUndefined(); + expect(errors2[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); }); - it("one can update quantityRefused even if not undefined in original bsdd, without specifying the waste acceptation status", async () => { + it("one can update quantityRefused even if not defined in original bsdd", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 10 + }); + + // When + const { errors } = await createRevision(user, company, bsdd.id, { + quantityRefused: 5 + }); + + // Then + expect(errors).toBeUndefined(); + + const revisionRequest = await prisma.bsddRevisionRequest.findFirstOrThrow( { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] + where: { bsddId: bsdd.id } } ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 0, - receivedAt: new Date() - } + + expect(revisionRequest.quantityRefused).toEqual(5); + }); + + it("cannot specify quantityReceived < quantityRefused when waste is PARTIALLY_REFUSED", async () => { + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 15, + quantityRefused: 13 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - quantityReceived: 10, - quantityRefused: 5 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10 }); // Then - expect(errors).toBeUndefined(); + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure ou égale à la quantité réceptionnée (quantityReceived)" + ); }); - it("cannot specify quantityReceived < quantityRefused", async () => { + it("cannot specify quantityReceived = quantityRefused when waste is PARTIALLY_REFUSED", async () => { // Given - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", - { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] - } - ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - status: Status.ACCEPTED, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Reason", - quantityReceived: 15, - quantityRefused: 13, - receivedAt: new Date() - } + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 15, + quantityRefused: 13 }); // When - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { - quantityReceived: 10 - }, - comment: "A comment", - authoringCompanySiret: company.siret! - } - } + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 13 }); // Then @@ -2460,43 +2169,130 @@ describe("Mutation.createFormRevisionRequest", () => { }); it("should work for APPENDIX1_PRODUCER", async () => { - const { company: recipientCompany } = await userWithCompanyFactory( - "ADMIN", + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + emitterType: EmitterType.APPENDIX1_PRODUCER, + wasteDetailsCode: "13 01 12*" + }); + + // When + const { errors } = await createRevision(user, company, bsdd.id, { + wasteDetails: { sampleNumber: "Num échantillon" } + }); + + // Then + expect(errors).toBeUndefined(); + }); + + it("one can review quantityReceived and quantityRefused", async () => { + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 0 + }); + + // When + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10, + quantityRefused: 5 + }); + + // Then + expect(errors).toBeUndefined(); + + const revisionRequest = await prisma.bsddRevisionRequest.findFirstOrThrow( { - companyTypes: [CompanyType.WASTEPROCESSOR], - wasteProcessorTypes: [ - WasteProcessorType.DANGEROUS_WASTES_INCINERATION - ] + where: { bsddId: bsdd.id } } ); - const { user, company } = await userWithCompanyFactory("ADMIN"); - const bsdd = await formFactory({ - ownerId: user.id, - opt: { - emitterType: EmitterType.APPENDIX1_PRODUCER, - emitterCompanySiret: company.siret, - recipientCompanySiret: recipientCompany.siret, - wasteDetailsCode: "13 01 12*" + expect(revisionRequest.quantityReceived).toEqual(10); + expect(revisionRequest.quantityRefused).toEqual(5); + }); + + it("one can review quantityReceived and quantityRefused (with quantityRefused already set)", async () => { + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 10, + quantityRefused: 5 + }); + + // When + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 15, + quantityRefused: 10 + }); + + // Then + expect(errors).toBeUndefined(); + + const revisionRequest = await prisma.bsddRevisionRequest.findFirstOrThrow( + { + where: { bsddId: bsdd.id } } + ); + + expect(revisionRequest.quantityReceived).toEqual(15); + expect(revisionRequest.quantityRefused).toEqual(10); + }); + + it("one can review quantityReceived and not quantityRefused", async () => { + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 0 }); - const { mutate } = makeClient(user); - const { errors } = await mutate< - Pick, - MutationCreateFormRevisionRequestArgs - >(CREATE_FORM_REVISION_REQUEST, { - variables: { - input: { - formId: bsdd.id, - content: { wasteDetails: { sampleNumber: "Num échantillon" } }, - comment: "A comment", - authoringCompanySiret: company.siret! - } + // When + const { errors } = await createRevision(user, company, bsdd.id, { + quantityReceived: 10 + }); + + // Then + expect(errors).toBeUndefined(); + + const revisionRequest = await prisma.bsddRevisionRequest.findFirstOrThrow( + { + where: { bsddId: bsdd.id } } + ); + + expect(revisionRequest.quantityRefused).toEqual(null); + expect(revisionRequest.quantityReceived).toEqual(10); + }); + + it("one can review quantityRefused and not quantityReceived", async () => { + // Given + const { user, bsdd, company } = await createUserAndBSDD({ + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Reason", + quantityReceived: 10 + }); + + // When + const { errors } = await createRevision(user, company, bsdd.id, { + quantityRefused: 5 }); + // Then expect(errors).toBeUndefined(); + + const revisionRequest = await prisma.bsddRevisionRequest.findFirstOrThrow( + { + where: { bsddId: bsdd.id } + } + ); + + expect(revisionRequest.quantityRefused).toEqual(5); + expect(revisionRequest.quantityReceived).toEqual(null); }); }); diff --git a/back/src/forms/resolvers/mutations/__tests__/importPaperForm.integration.ts b/back/src/forms/resolvers/mutations/__tests__/importPaperForm.integration.ts index 794c51d472..0ba54d6841 100644 --- a/back/src/forms/resolvers/mutations/__tests__/importPaperForm.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/importPaperForm.integration.ts @@ -109,7 +109,8 @@ describe("mutation / importPaperForm", () => { signedAt: "2019-12-20T00:00:00.000Z" as any, receivedBy: "Mr Destination", wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - quantityReceived: 1.0 + quantityReceived: 1.0, + quantityRefused: 0 }, processedInfo: { processedAt: "2019-12-22T00:00:00.000Z" as any, @@ -450,7 +451,8 @@ describe("mutation / importPaperForm", () => { receivedAt: "2019-12-21T00:00:00.000Z" as any, receivedBy: "Mr Destination", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 1.0 + quantityReceived: 1.0, + quantityRefused: 0 }, processedInfo: { processedAt: "2019-12-22T00:00:00.000Z" as any, @@ -543,6 +545,10 @@ describe("mutation / importPaperForm", () => { receivedBy: importedData.receivedInfo.receivedBy, receivedAt: importedData.receivedInfo.receivedAt, quantityReceived: importedData.receivedInfo.quantityReceived, + quantityAccepted: + Number(importedData.receivedInfo.quantityReceived) - + Number(importedData.receivedInfo.quantityRefused), + quantityRefused: importedData.receivedInfo.quantityRefused, processingOperationDone: importedData.processedInfo.processingOperationDone, processingOperationDescription: diff --git a/back/src/forms/resolvers/mutations/__tests__/markAsAccepted.integration.ts b/back/src/forms/resolvers/mutations/__tests__/markAsAccepted.integration.ts index 908aef2155..b46cce4909 100644 --- a/back/src/forms/resolvers/mutations/__tests__/markAsAccepted.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/markAsAccepted.integration.ts @@ -5,6 +5,7 @@ import { EmptyReturnADR, Status, TransportMode, + User, UserRole, WasteAcceptationStatus } from "@prisma/client"; @@ -77,6 +78,7 @@ const createAndAcceptForm = async (createOpt, acceptOpt) => { signedBy: "Bill", wasteAcceptationStatus: "ACCEPTED", quantityReceived: 11, + quantityRefused: 0, ...acceptOpt } } @@ -138,7 +140,8 @@ describe("Test Form reception", () => { signedAt: "2019-01-17T10:22:00+0100", signedBy: "Bill", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 11 + quantityReceived: 11, + quantityRefused: 0 } } }); @@ -151,6 +154,7 @@ describe("Test Form reception", () => { expect(acceptedForm.wasteAcceptationStatus).toBe("ACCEPTED"); expect(acceptedForm.signedBy).toBe("Bill"); expect(acceptedForm.quantityReceived?.toNumber()).toBe(11); + expect(acceptedForm.quantityRefused?.toNumber()).toBe(0); // A StatusLog object is created const logs = await prisma.statusLog.findMany({ @@ -200,7 +204,8 @@ describe("Test Form reception", () => { signedAt: "2019-01-17T10:22:00+0100", signedBy: "Bill", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 11 + quantityReceived: 11, + quantityRefused: 0 } } }); @@ -213,6 +218,7 @@ describe("Test Form reception", () => { expect(acceptedForm.wasteAcceptationStatus).toBe("ACCEPTED"); expect(acceptedForm.signedBy).toBe("Bill"); expect(acceptedForm.quantityReceived?.toNumber()).toBe(11); + expect(acceptedForm.quantityRefused?.toNumber()).toBe(0); // A StatusLog object is created const logs = await prisma.statusLog.findMany({ @@ -349,7 +355,8 @@ describe("Test Form reception", () => { signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "REFUSED", wasteRefusalReason: "Lorem ipsum", - quantityReceived: 0 + quantityReceived: 0, + quantityRefused: 0 } } }); @@ -446,7 +453,8 @@ describe("Test Form reception", () => { signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "PARTIALLY_REFUSED", wasteRefusalReason: "Dolor sit amet", - quantityReceived: 12.5 + quantityReceived: 12.5, + quantityRefused: 7 } } }); @@ -458,6 +466,7 @@ describe("Test Form reception", () => { expect(frm.signedBy).toBe("Carol"); expect(frm.wasteRefusalReason).toBe("Dolor sit amet"); expect(frm.quantityReceived?.toNumber()).toBe(12.5); + expect(frm.quantityRefused?.toNumber()).toBe(7); // A StatusLog object is created const logs = await prisma.statusLog.findMany({ @@ -514,7 +523,8 @@ describe("Test Form reception", () => { signedAt: format(signedAt, f), signedBy: "Bill", wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - quantityReceived: 11 + quantityReceived: 11, + quantityRefused: 0 } } }); @@ -599,7 +609,8 @@ describe("Test Form reception", () => { wasteRefusalReason: "Parce que", signedAt: "2019-01-18" as any, signedBy: "John", - quantityReceived: 0 + quantityReceived: 0, + quantityRefused: 0 } } } @@ -653,6 +664,7 @@ describe("Test Form reception", () => { acceptedInfo: { wasteAcceptationStatus: "ACCEPTED", quantityReceived: 1, + quantityRefused: 0, signedAt: new Date("2022-01-01").toISOString() as any, signedBy: "John Snow" } @@ -695,6 +707,7 @@ describe("Test Form reception", () => { acceptedInfo: { wasteAcceptationStatus: "ACCEPTED", quantityReceived: 1, + quantityRefused: 0, signedAt: new Date("2022-01-01").toISOString() as any, signedBy: "John Snow" } @@ -761,6 +774,7 @@ describe("Test Form reception", () => { acceptedInfo: { wasteAcceptationStatus: "ACCEPTED", quantityReceived: 1, + quantityRefused: 0, signedAt: new Date("2022-01-01").toISOString() as any, signedBy: "Collecteur annexe 1" } @@ -776,52 +790,6 @@ describe("Test Form reception", () => { }); }); - it("should accept quantityRefused", async () => { - // Given - const { - emitterCompany, - recipient, - recipientCompany, - form: initialForm - } = await prepareDB(); - const form = await prisma.form.update({ - where: { id: initialForm.id }, - data: { - status: "RECEIVED", - receivedBy: "Bill", - receivedAt: new Date("2019-01-17T10:22:00+0100") - } - }); - await prepareRedis({ - emitterCompany, - recipientCompany - }); - - // When - const { mutate } = makeClient(recipient); - const { errors } = await mutate(MARK_AS_ACCEPTED, { - variables: { - id: form.id, - acceptedInfo: { - signedAt: "2019-01-17T10:22:00+0100", - signedBy: "Bill", - wasteAcceptationStatus: "PARTIALLY_REFUSED", - wasteRefusalReason: "Parce que", - quantityReceived: 11, - quantityRefused: 7 - } - } - }); - - // Then - expect(errors).toBeUndefined(); - const acceptedForm = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); - expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); - expect(acceptedForm.quantityRefused?.toNumber()).toEqual(7); - }); - // Bug was "Cannot destructure property 'prepareVariables' of 'mailTemplate' as it is undefined." // Use-case: // - Create a tmp storage BSD @@ -1240,4 +1208,220 @@ describe("Test Form reception", () => { "Vous ne pouvez préciser de retour à vide ADR que si le mode de transport est route (ROAD) ou null" ); }); + + describe("quantityRefused", () => { + const createBSDD = async (opt?) => { + const { + emitterCompany, + recipient, + recipientCompany, + form: initialForm + } = await prepareDB(); + + const form = await prisma.form.update({ + where: { id: initialForm.id }, + data: { + status: "RECEIVED", + receivedBy: "Bill", + receivedAt: new Date("2019-01-17T10:22:00+0100"), + createdAt: new Date("2025-03-20"), + ...opt + } + }); + + await prepareRedis({ + emitterCompany, + recipientCompany + }); + + return { recipient, form }; + }; + + const markBSDDAsAccepted = async ( + recipient: User, + formId: string, + wasteAcceptationStatus: WasteAcceptationStatus, + quantityReceived: number, + quantityRefused: number | null, + wasteRefusalReason?: string | null + ) => { + const { mutate } = makeClient(recipient); + return await mutate(MARK_AS_ACCEPTED, { + variables: { + id: formId, + acceptedInfo: { + signedAt: "2019-01-17T10:22:00+0100", + signedBy: "Bill", + wasteAcceptationStatus, + wasteRefusalReason, + quantityReceived, + quantityRefused + } + } + }); + }; + + describe("wasteAcceptationStatus = ACCEPTED", () => { + it("waste should be accepted", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "ACCEPTED", + 11, + 0 + ); + + // Then + expect(errors).toBeUndefined(); + const acceptedForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); + expect(acceptedForm.quantityRefused?.toNumber()).toEqual(0); + expect(acceptedForm.wasteAcceptationStatus).toBe("ACCEPTED"); + expect(acceptedForm.status).toBe("ACCEPTED"); + }); + + it("quantityRefused cannot be > 0", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "ACCEPTED", + 11, + 5 + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" + ); + }); + }); + + describe("wasteAcceptationStatus = REFUSED", () => { + it("waste should be refused", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "REFUSED", + 11, + 11, + "Pas bon" + ); + + // Then + expect(errors).toBeUndefined(); + const acceptedForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); + expect(acceptedForm.quantityRefused?.toNumber()).toEqual(11); + expect(acceptedForm.wasteAcceptationStatus).toBe("REFUSED"); + expect(acceptedForm.status).toBe("REFUSED"); + }); + + it("quantityRefused cannot be != quantityReceived", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "REFUSED", + 11, + 5, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" + ); + }); + }); + + describe("wasteAcceptationStatus = PARTIALLY_REFUSED", () => { + it("waste should be partially refused", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + 6, + "Pas bon" + ); + + // Then + expect(errors).toBeUndefined(); + const acceptedForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); + expect(acceptedForm.quantityRefused?.toNumber()).toEqual(6); + expect(acceptedForm.wasteAcceptationStatus).toBe("PARTIALLY_REFUSED"); + expect(acceptedForm.status).toBe("ACCEPTED"); + }); + + it("quantityRefused cannot be = quantityReceived", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + 11, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); + }); + + it("quantityRefused cannot be zero", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + 0, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); + }); + }); + }); }); diff --git a/back/src/forms/resolvers/mutations/__tests__/markAsProcessed.integration.ts b/back/src/forms/resolvers/mutations/__tests__/markAsProcessed.integration.ts index 4cfe9d5775..ec12ac0bab 100644 --- a/back/src/forms/resolvers/mutations/__tests__/markAsProcessed.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/markAsProcessed.integration.ts @@ -2293,4 +2293,42 @@ describe("mutation.markAsProcessed", () => { }) ]); }); + + it("should mark a form as processed even if quantityRefused is null (legacy BSDs)", async () => { + // Given + const { user, company } = await userWithCompanyFactory("ADMIN"); + const form = await formFactory({ + ownerId: user.id, + opt: { + status: "ACCEPTED", + quantityReceived: 10, + quantityRefused: null, + recipientCompanyName: company.name, + recipientCompanySiret: company.siret + } + }); + + // When + const { mutate } = makeClient(user); + const { errors } = await mutate(MARK_AS_PROCESSED, { + variables: { + id: form.id, + processedInfo: { + processingOperationDescription: "Une description", + processingOperationDone: "R 1", + destinationOperationMode: OperationMode.VALORISATION_ENERGETIQUE, + processedBy: "A simple bot", + processedAt: "2018-12-11T00:00:00.000Z" + } + } + }); + + // Then + expect(errors).toBeUndefined(); + const resultingForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id }, + include: { finalOperations: true } + }); + expect(resultingForm.status).toBe("PROCESSED"); + }); }); diff --git a/back/src/forms/resolvers/mutations/__tests__/markAsReceived.integration.ts b/back/src/forms/resolvers/mutations/__tests__/markAsReceived.integration.ts index 24542a8d12..d00b9e9ed5 100644 --- a/back/src/forms/resolvers/mutations/__tests__/markAsReceived.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/markAsReceived.integration.ts @@ -1,5 +1,12 @@ import { format } from "date-fns"; -import { CompanyType, EmitterType, Status, UserRole } from "@prisma/client"; +import { + CompanyType, + EmitterType, + Status, + User, + UserRole, + WasteAcceptationStatus +} from "@prisma/client"; import { resetDatabase } from "../../../../../integration-tests/helper"; import { prisma } from "@td/prisma"; import { sendMail } from "../../../../mailer/mailing"; @@ -230,7 +237,8 @@ describe("Test Form reception", () => { receivedAt: "2019-01-17T10:22:00+0100", signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 11 + quantityReceived: 11, + quantityRefused: 0 } } }); @@ -282,7 +290,8 @@ describe("Test Form reception", () => { receivedAt: "2019-01-17T10:22:00+0100", signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 0 + quantityReceived: 0, + quantityRefused: 0 } } }); @@ -306,58 +315,6 @@ describe("Test Form reception", () => { expect(frm.quantityReceived).toBe(null); }); - it("it should not mark a sent form as accepted if wasteAcceptationStatus is ACCEPTED but quantityReceived is missing", async () => { - const { - emitterCompany, - recipient, - recipientCompany, - form: initialForm - } = await prepareDB(); - const form = await prisma.form.update({ - where: { id: initialForm.id }, - data: { currentTransporterOrgId: siretify(3) } - }); - await prepareRedis({ - emitterCompany, - recipientCompany - }); - const frm1 = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); - - expect(frm1.quantityReceivedType).toBeNull(); - const { mutate } = makeClient(recipient); - const { errors } = await mutate(MARK_AS_RECEIVED, { - variables: { - id: form.id, - receivedInfo: { - receivedBy: "Bill", - receivedAt: "2019-01-17T10:22:00+0100", - signedAt: "2019-01-17T10:22:00+0100", - wasteAcceptationStatus: "ACCEPTED" - } - } - }); - - expect(errors).toEqual([ - expect.objectContaining({ - message: - "Réception : le poids est requis lorsque le déchet est accepté ou accepté partiellement.", - extensions: expect.objectContaining({ - code: ErrorCode.BAD_USER_INPUT - }) - }) - ]); - const frm = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); - // form was not accepted, still sent - expect(frm.status).toBe("SENT"); - expect(frm.wasteAcceptationStatus).toBe(null); - expect(frm.receivedBy).toBe(null); - expect(frm.quantityReceived).toBe(null); - }); - it("should not accept negative values", async () => { const { emitterCompany, recipient, recipientCompany, form } = await prepareDB(); @@ -438,7 +395,8 @@ describe("Test Form reception", () => { signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "REFUSED", wasteRefusalReason: "Lorem ipsum", - quantityReceived: 0 + quantityReceived: 0, + quantityRefused: 0 } } }); @@ -484,7 +442,8 @@ describe("Test Form reception", () => { signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "PARTIALLY_REFUSED", wasteRefusalReason: "Dolor sit amet", - quantityReceived: 12.5 + quantityReceived: 12.5, + quantityRefused: 7 } } }); @@ -496,6 +455,7 @@ describe("Test Form reception", () => { expect(frm.receivedBy).toBe("Carol"); expect(frm.wasteRefusalReason).toBe("Dolor sit amet"); expect(frm.quantityReceived?.toNumber()).toBe(12.5); + expect(frm.quantityRefused?.toNumber()).toBe(7); // A StatusLog object is created const logs = await prisma.statusLog.findMany({ @@ -627,7 +587,8 @@ describe("Test Form reception", () => { receivedBy: "Bill", receivedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 11 + quantityReceived: 11, + quantityRefused: 0 } } }); @@ -696,7 +657,8 @@ describe("Test Form reception", () => { receivedBy: "Bill", receivedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 11 + quantityReceived: 11, + quantityRefused: 0 } } }); @@ -855,7 +817,8 @@ describe("Test Form reception", () => { wasteRefusalReason: "Parce que", receivedAt: "2019-01-18" as any, receivedBy: "John", - quantityReceived: 0 + quantityReceived: 0, + quantityRefused: 0 } } } @@ -946,7 +909,8 @@ describe("Test Form reception", () => { receivedAt: "2019-01-17T10:22:00+0100", signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 50 + quantityReceived: 50, + quantityRefused: 0 } } }); @@ -982,7 +946,8 @@ describe("Test Form reception", () => { receivedAt: "2019-01-17T10:22:00+0100", signedAt: "2019-01-17T10:22:00+0100", wasteAcceptationStatus: "ACCEPTED", - quantityReceived: 30 + quantityReceived: 30, + quantityRefused: 0 } } }); @@ -1091,7 +1056,8 @@ describe("Test Form reception", () => { wasteAcceptationStatus: "ACCEPTED", receivedAt: new Date("2022-01-01").toISOString() as any, receivedBy: "John", - quantityReceived: 1 + quantityReceived: 1, + quantityRefused: 0 } } }); @@ -1288,46 +1254,6 @@ describe("Test Form reception", () => { }); }); - it("should work with quantityRefused", async () => { - // Given - const { - emitterCompany, - recipient, - recipientCompany, - form: initialForm - } = await prepareDB(); - const form = await prisma.form.update({ - where: { id: initialForm.id }, - data: { currentTransporterOrgId: siretify(3) } - }); - await prepareRedis({ - emitterCompany, - recipientCompany - }); - - // When - const { mutate } = makeClient(recipient); - await mutate(MARK_AS_RECEIVED, { - variables: { - id: form.id, - receivedInfo: { - receivedBy: "Carol", - receivedAt: "2019-01-17T10:22:00+0100", - signedAt: "2019-01-17T10:22:00+0100", - wasteAcceptationStatus: "PARTIALLY_REFUSED", - wasteRefusalReason: "Dolor sit amet", - quantityReceived: 12.5, - quantityRefused: 7.5 - } - } - }); - - // Then - const frm = await prisma.form.findUniqueOrThrow({ where: { id: form.id } }); - expect(frm.quantityReceived?.toNumber()).toEqual(12.5); - expect(frm.quantityRefused?.toNumber()).toEqual(7.5); - }); - it("when final destination refuses a BSD, a mail should be sent", async () => { // Given const emitter = await userWithCompanyFactory("MEMBER"); @@ -1574,8 +1500,7 @@ describe("Test Form reception", () => { expect(errors).toEqual([ expect.objectContaining({ - message: - "Réception : le poids est requis lorsque le déchet est accepté ou accepté partiellement." + message: "La quantité refusée (quantityRefused) est requise" }) ]); @@ -1585,4 +1510,303 @@ describe("Test Form reception", () => { // form was not accepted, still resent expect(frm.status).toBe("RESENT"); }); + + describe("quantityRefused", () => { + const createBSDD = async (opt?) => { + const { + emitterCompany, + recipient, + recipientCompany, + form: initialForm + } = await prepareDB(); + + const form = await prisma.form.update({ + where: { id: initialForm.id }, + data: { + currentTransporterOrgId: siretify(3), + ...opt + } + }); + + await prepareRedis({ + emitterCompany, + recipientCompany + }); + + return { recipient, form }; + }; + + const markBSDDAsReceived = async ( + recipient: User, + formId: string, + wasteAcceptationStatus: WasteAcceptationStatus, + quantityReceived: number, + quantityRefused: number | null, + wasteRefusalReason?: string | null + ) => { + const { mutate } = makeClient(recipient); + return await mutate(MARK_AS_RECEIVED, { + variables: { + id: formId, + receivedInfo: { + receivedBy: "Carol", + receivedAt: "2019-01-17T10:22:00+0100", + signedAt: "2019-01-17T10:22:00+0100", + wasteAcceptationStatus, + wasteRefusalReason, + quantityReceived, + quantityRefused + } + } + }); + }; + + it("quantityRefused is not required if reception only", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { mutate } = makeClient(recipient); + const { errors } = await mutate(MARK_AS_RECEIVED, { + variables: { + id: form.id, + receivedInfo: { + receivedBy: "Carol", + receivedAt: "2019-01-17T10:22:00+0100", + signedAt: "2019-01-17T10:22:00+0100", + quantityReceived: 10 + // No acceptation data + } + } + }); + + // Then + expect(errors).toBeUndefined(); + }); + + describe("wasteAcceptationStatus = ACCEPTED", () => { + it("waste should be accepted", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "ACCEPTED", + 11, + 0 + ); + + // Then + expect(errors).toBeUndefined(); + const acceptedForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); + expect(acceptedForm.quantityRefused?.toNumber()).toEqual(0); + expect(acceptedForm.wasteAcceptationStatus).toBe("ACCEPTED"); + expect(acceptedForm.status).toBe("ACCEPTED"); + }); + + it("quantityRefused is required", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "ACCEPTED", + 11, + null + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) est requise" + ); + }); + + it("quantityRefused cannot be > 0", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "ACCEPTED", + 11, + 5 + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" + ); + }); + }); + + describe("wasteAcceptationStatus = REFUSED", () => { + it("waste should be refused", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "REFUSED", + 11, + 11, + "Pas bon" + ); + + // Then + expect(errors).toBeUndefined(); + const acceptedForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); + expect(acceptedForm.quantityRefused?.toNumber()).toEqual(11); + expect(acceptedForm.wasteAcceptationStatus).toBe("REFUSED"); + expect(acceptedForm.status).toBe("REFUSED"); + }); + + it("quantityRefused is required", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "REFUSED", + 11, + null, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) est requise" + ); + }); + + it("quantityRefused cannot be != quantityReceived", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "REFUSED", + 11, + 5, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" + ); + }); + }); + + describe("wasteAcceptationStatus = PARTIALLY_REFUSED", () => { + it("waste should be partially refused", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + 6, + "Pas bon" + ); + + // Then + expect(errors).toBeUndefined(); + const acceptedForm = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + expect(acceptedForm.quantityReceived?.toNumber()).toEqual(11); + expect(acceptedForm.quantityRefused?.toNumber()).toEqual(6); + expect(acceptedForm.wasteAcceptationStatus).toBe("PARTIALLY_REFUSED"); + expect(acceptedForm.status).toBe("ACCEPTED"); + }); + + it("quantityRefused is required", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + null, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) est requise" + ); + }); + + it("quantityRefused cannot be = quantityReceived", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + 11, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); + }); + + it("quantityRefused cannot be zero", async () => { + // Given + const { recipient, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsReceived( + recipient, + form.id, + "PARTIALLY_REFUSED", + 11, + 0, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); + }); + }); + }); }); diff --git a/back/src/forms/resolvers/mutations/__tests__/markAsTempStored.integration.ts b/back/src/forms/resolvers/mutations/__tests__/markAsTempStored.integration.ts index da48a2d38a..16f13543be 100644 --- a/back/src/forms/resolvers/mutations/__tests__/markAsTempStored.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/markAsTempStored.integration.ts @@ -75,6 +75,7 @@ describe("{ mutation { markAsTempStored } }", () => { receivedAt: "2018-12-11T00:00:00.000Z", signedAt: "2018-12-11T00:00:00.000Z", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -168,6 +169,7 @@ describe("{ mutation { markAsTempStored } }", () => { receivedAt: "2018-12-11T00:00:00.000Z", signedAt: "2018-12-11T00:00:00.000Z", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -217,6 +219,7 @@ describe("{ mutation { markAsTempStored } }", () => { receivedBy: "John Doe", receivedAt: "2018-12-11T00:00:00.000Z", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -260,7 +263,8 @@ describe("{ mutation { markAsTempStored } }", () => { receivedBy: "John Doe", receivedAt: "2018-12-11T00:00:00.000Z", signedAt: "2018-12-11T00:00:00.000Z", - quantityReceived: 0, + quantityReceived: 5, + quantityRefused: 5, quantityType: "REAL" } } @@ -321,6 +325,7 @@ describe("{ mutation { markAsTempStored } }", () => { receivedAt: "2018-12-11T00:00:00.000Z", signedAt: "2018-12-11T00:00:00.000Z", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -453,7 +458,8 @@ describe("{ mutation { markAsTempStored } }", () => { receivedAt: "2019-01-18" as any, receivedBy: "John", quantityType: "REAL", - quantityReceived: 0 + quantityReceived: 2, + quantityRefused: 2 } } } @@ -516,6 +522,7 @@ describe("{ mutation { markAsTempStored } }", () => { receivedAt: "2018-12-11T00:00:00.000Z", signedAt: "2018-12-11T00:00:00.000Z", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -858,13 +865,14 @@ describe("{ mutation { markAsTempStored } }", () => { ); }); - test("[legacy] the temp storer of the BSD can mark it as PARTIALLY_REFUSED with quantityRefused = undefined", async () => { + test("can mark as TEMP_STORED without quantityRefused if no acceptation data", async () => { // Given const { user, company: tempStorerCompany } = await userWithCompanyFactory( "MEMBER" ); const emitterCompany = await companyFactory(); + const form = await formFactory({ ownerId: user.id, opt: { @@ -880,57 +888,62 @@ describe("{ mutation { markAsTempStored } }", () => { // When const { mutate } = makeClient(user); - const { errors, data } = await mutate>( - MARK_AS_TEMP_STORED, - { - variables: { - id: form.id, - tempStoredInfos: { - wasteAcceptationStatus: "PARTIALLY_REFUSED", - wasteRefusalReason: "Thats isn't what I was expecting man !", - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z", - signedAt: "2018-12-11T00:00:00.000Z", - quantityReceived: 10, - quantityType: "REAL" - } + const { errors } = await mutate(MARK_AS_TEMP_STORED, { + variables: { + id: form.id, + tempStoredInfos: { + receivedBy: "John Doe", + receivedAt: "2018-12-11T00:00:00.000Z", + quantityReceived: 2.4, + quantityType: "REAL" } } - ); + }); // Then expect(errors).toBeUndefined(); - expect( - data.markAsTempStored?.temporaryStorageDetail?.wasteDetails?.quantity - ).toEqual(10); - - const formAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); + }); - expect(formAfterMutation.status).toEqual("TEMP_STORER_ACCEPTED"); - expect(formAfterMutation.wasteAcceptationStatus).toEqual( - "PARTIALLY_REFUSED" + test("can not mark as ACCEPTED without quantityRefused if acceptation data", async () => { + // Given + const { user, company: tempStorerCompany } = await userWithCompanyFactory( + "MEMBER" ); - expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(10); - expect(formAfterMutation.quantityRefused).toBeNull(); - // check relevant statusLog is created - const statusLogs = await prisma.statusLog.findMany({ - where: { - form: { id: form.id }, - user: { id: user.id }, - status: "TEMP_STORER_ACCEPTED" + const emitterCompany = await companyFactory(); + + const form = await formFactory({ + ownerId: user.id, + opt: { + status: "SENT", + emitterCompanySiret: emitterCompany.siret, + recipientCompanySiret: tempStorerCompany.siret, + recipientIsTempStorage: true, + forwardedIn: { + create: { readableId: getReadableId(), ownerId: user.id } + } } }); - expect(statusLogs.length).toEqual(1); - expect(sendMail as jest.Mock).toHaveBeenCalledWith( - expect.objectContaining({ - subject: `Le déchet de l’entreprise ${form.emitterCompanyName} a été partiellement refusé à réception`, - body: expect.stringContaining(`
  • Quantité réelle présentée nette : 10 tonnes
  • -
  • Quantité refusée nette : Non renseignée
  • -
  • Quantité acceptée nette : Non renseignée
  • `) - }) + + // When + const { mutate } = makeClient(user); + const { errors } = await mutate(MARK_AS_TEMP_STORED, { + variables: { + id: form.id, + tempStoredInfos: { + receivedBy: "John Doe", + receivedAt: "2018-12-11T00:00:00.000Z", + wasteAcceptationStatus: "ACCEPTED", + quantityReceived: 2.4, + quantityType: "REAL" + } + } + }); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) est requise" ); }); }); diff --git a/back/src/forms/resolvers/mutations/__tests__/markAsTempStorerAccepted.integration.ts b/back/src/forms/resolvers/mutations/__tests__/markAsTempStorerAccepted.integration.ts index 5dac914a62..69f56f7dc3 100644 --- a/back/src/forms/resolvers/mutations/__tests__/markAsTempStorerAccepted.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/markAsTempStorerAccepted.integration.ts @@ -12,6 +12,7 @@ import { allowedFormats } from "../../../../common/dates"; import { CompanyType, Status, + User, UserRole, WasteAcceptationStatus } from "@prisma/client"; @@ -75,6 +76,7 @@ describe("{ mutation { markAsTempStorerAccepted } }", () => { signedAt: "2018-12-11T00:00:00.000Z", signedBy: "John Doe", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -118,6 +120,7 @@ describe("{ mutation { markAsTempStorerAccepted } }", () => { signedAt: "2018-12-11T00:00:00.000Z", signedBy: "John Doe", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -173,6 +176,7 @@ describe("{ mutation { markAsTempStorerAccepted } }", () => { signedBy: "John Doe", signedAt: "2018-12-11T00:00:00.000Z", quantityReceived: 0, + quantityRefused: 0, quantityType: "REAL" } } @@ -236,6 +240,7 @@ describe("{ mutation { markAsTempStorerAccepted } }", () => { signedAt: format(signedAt, f), signedBy: "John Doe", quantityReceived: 2.4, + quantityRefused: 0, quantityType: "REAL" } } @@ -322,7 +327,8 @@ describe("{ mutation { markAsTempStorerAccepted } }", () => { signedAt: "2019-01-18" as any, signedBy: "John", quantityType: "REAL", - quantityReceived: 0 + quantityReceived: 0, + quantityRefused: 0 } } }); @@ -352,378 +358,268 @@ describe("{ mutation { markAsTempStorerAccepted } }", () => { expect(appendix2Forms).toEqual([]); }); - test("user can mark BSD as ACCEPTED and specify quantityRefused = 0", async () => { - // Given - const { user, company: tempStorerCompany } = await userWithCompanyFactory( - "MEMBER" - ); - - const emitterCompany = await companyFactory(); - const form = await formFactory({ - ownerId: user.id, - opt: { - status: Status.TEMP_STORED, - emitterCompanySiret: emitterCompany.siret, - recipientCompanySiret: tempStorerCompany.siret, - recipientIsTempStorage: true, - forwardedIn: { - create: { readableId: getReadableId(), ownerId: user.id } - }, - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z" - } - }); - - // When - const { mutate } = makeClient(user); - const { errors } = await mutate>( - MARK_AS_TEMP_STORER_ACCEPTED, - { - variables: { - id: form.id, - tempStorerAcceptedInfo: { - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - wasteRefusalReason: "", - signedAt: "2019-01-18" as any, - signedBy: "John Doe", - quantityReceived: 2.4, - quantityRefused: 0, - quantityType: "REAL" - } - } - } - ); - - // Then - expect(errors).toBeUndefined(); - - const formAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); - - expect(formAfterMutation.status).toEqual("TEMP_STORER_ACCEPTED"); - expect(formAfterMutation.wasteAcceptationStatus).toEqual("ACCEPTED"); - expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); - expect(formAfterMutation.quantityRefused?.toNumber()).toEqual(0); - - const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.forwardedIn?.id } - }); - - expect(forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber()).toEqual( - 2.4 - ); - }); - - test("user cannot mark BSD as ACCEPTED and specify quantityRefused != 0", async () => { - // Given - const { user, company: tempStorerCompany } = await userWithCompanyFactory( - "MEMBER" - ); - - const emitterCompany = await companyFactory(); - const form = await formFactory({ - ownerId: user.id, - opt: { - status: Status.TEMP_STORED, - emitterCompanySiret: emitterCompany.siret, - recipientCompanySiret: tempStorerCompany.siret, - recipientIsTempStorage: true, - forwardedIn: { - create: { readableId: getReadableId(), ownerId: user.id } - }, - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z" - } - }); - - // When - const { mutate } = makeClient(user); - const { errors } = await mutate>( - MARK_AS_TEMP_STORER_ACCEPTED, - { - variables: { - id: form.id, - tempStorerAcceptedInfo: { - wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, - wasteRefusalReason: "", - signedAt: "2019-01-18" as any, - signedBy: "John Doe", - quantityReceived: 2.4, - quantityRefused: 1, - quantityType: "REAL" - } - } - } - ); - - // Then - expect(errors).not.toBeUndefined(); - expect(errors[0].message).toBe( - "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" - ); - }); - - test("user can mark BSD as REFUSED and specify quantityRefused = quantityReceived", async () => { - // Given - const { user, company: tempStorerCompany } = await userWithCompanyFactory( - "MEMBER" - ); - - const emitterCompany = await companyFactory(); - const form = await formFactory({ - ownerId: user.id, - opt: { - status: Status.TEMP_STORED, - emitterCompanySiret: emitterCompany.siret, - recipientCompanySiret: tempStorerCompany.siret, - recipientIsTempStorage: true, - forwardedIn: { - create: { readableId: getReadableId(), ownerId: user.id } - }, - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z" - } - }); - - // When - const { mutate } = makeClient(user); - const { errors } = await mutate>( - MARK_AS_TEMP_STORER_ACCEPTED, - { - variables: { - id: form.id, - tempStorerAcceptedInfo: { - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Thats isn't what I was expecting man !", - signedAt: "2019-01-18" as any, - signedBy: "John Doe", - quantityReceived: 2.4, - quantityRefused: 2.4, - quantityType: "REAL" - } - } - } - ); - - // Then - expect(errors).toBeUndefined(); - - const formAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); - - expect(formAfterMutation.status).toEqual("REFUSED"); - expect(formAfterMutation.wasteAcceptationStatus).toEqual("REFUSED"); - expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); - expect(formAfterMutation.quantityRefused?.toNumber()).toEqual(2.4); - - const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.forwardedIn?.id } - }); - - expect(forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber()).toEqual( - 0 - ); - - expect(sendMail as jest.Mock).toHaveBeenCalledWith( - expect.objectContaining({ - subject: `Le déchet de l’entreprise ${form.emitterCompanyName} a été totalement refusé à réception` - }) - ); - }); - - test("user cannot mark BSD as REFUSED and specify quantityRefused != quantityReceived", async () => { - // Given - const { user, company: tempStorerCompany } = await userWithCompanyFactory( - "MEMBER" - ); - - const emitterCompany = await companyFactory(); - const form = await formFactory({ - ownerId: user.id, - opt: { - status: Status.TEMP_STORED, - emitterCompanySiret: emitterCompany.siret, - recipientCompanySiret: tempStorerCompany.siret, - recipientIsTempStorage: true, - forwardedIn: { - create: { readableId: getReadableId(), ownerId: user.id } - }, - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z" - } - }); - - // When - const { mutate } = makeClient(user); - const { errors } = await mutate>( - MARK_AS_TEMP_STORER_ACCEPTED, - { - variables: { - id: form.id, - tempStorerAcceptedInfo: { - wasteAcceptationStatus: WasteAcceptationStatus.REFUSED, - wasteRefusalReason: "Thats isn't what I was expecting man !", - signedAt: "2019-01-18" as any, - signedBy: "John Doe", - quantityReceived: 2.4, - quantityRefused: 2.3, - quantityType: "REAL" - } + describe("quantityRefused", () => { + const createBSDD = async (opt?) => { + const { user, company: tempStorerCompany } = await userWithCompanyFactory( + "MEMBER" + ); + + const emitterCompany = await companyFactory(); + const form = await formFactory({ + ownerId: user.id, + opt: { + status: Status.TEMP_STORED, + emitterCompanySiret: emitterCompany.siret, + recipientCompanySiret: tempStorerCompany.siret, + recipientIsTempStorage: true, + forwardedIn: { + create: { readableId: getReadableId(), ownerId: user.id } + }, + receivedBy: "John Doe", + receivedAt: "2018-12-11T00:00:00.000Z", + createdAt: new Date("2025-03-20"), + ...opt } - } - ); - - // Then - expect(errors).not.toBeUndefined(); - expect(errors[0].message).toBe( - "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" - ); - }); - - test("user can mark BSD as PARTIALLY_REFUSED and specify quantityRefused", async () => { - // Given - const { user, company: tempStorerCompany } = await userWithCompanyFactory( - "MEMBER" - ); - - const emitterCompany = await companyFactory(); - const form = await formFactory({ - ownerId: user.id, - opt: { - status: Status.TEMP_STORED, - emitterCompanySiret: emitterCompany.siret, - recipientCompanySiret: tempStorerCompany.siret, - recipientIsTempStorage: true, - forwardedIn: { - create: { readableId: getReadableId(), ownerId: user.id } - }, - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z" - } - }); + }); - // When - const { mutate } = makeClient(user); - const { errors } = await mutate>( - MARK_AS_TEMP_STORER_ACCEPTED, - { - variables: { - id: form.id, - tempStorerAcceptedInfo: { - wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Thats isn't what I was expecting man !", - signedAt: "2019-01-18" as any, - signedBy: "John Doe", - quantityReceived: 2.4, - quantityRefused: 1.1, - quantityType: "REAL" + return { user, form }; + }; + + const markBSDDAsAccepted = async ( + user: User, + formId: string, + wasteAcceptationStatus: WasteAcceptationStatus, + quantityReceived: number, + quantityRefused: number | null, + wasteRefusalReason?: string | null + ) => { + const { mutate } = makeClient(user); + return await mutate>( + MARK_AS_TEMP_STORER_ACCEPTED, + { + variables: { + id: formId, + tempStorerAcceptedInfo: { + wasteAcceptationStatus, + wasteRefusalReason, + signedAt: "2019-01-18" as any, + signedBy: "John Doe", + quantityReceived, + quantityRefused, + quantityType: "REAL" + } } } - } - ); - - // Then - expect(errors).toBeUndefined(); - - const formAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } - }); - - expect(formAfterMutation.status).toEqual("TEMP_STORER_ACCEPTED"); - expect(formAfterMutation.wasteAcceptationStatus).toEqual( - "PARTIALLY_REFUSED" - ); - expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); - expect(formAfterMutation.quantityRefused?.toNumber()).toEqual(1.1); - - const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.forwardedIn?.id } - }); - - expect(forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber()).toEqual( - 1.3 - ); - - // Mail - expect.objectContaining({ - subject: `Le déchet de l’entreprise ${form.emitterCompanyName} a été partiellement refusé à réception`, - body: expect.stringContaining(`
  • Quantité réelle présentée nette : 2.4 tonnes
  • -
  • Quantité refusée nette : 1.1 tonnes
  • -
  • Quantité acceptée nette : 1.3 tonnes
  • `) - }); - }); - - test("[legacy] user can mark BSD as PARTIALLY_REFUSED with quantityRefused = undefined", async () => { - // Given - const { user, company: tempStorerCompany } = await userWithCompanyFactory( - "MEMBER" - ); + ); + }; + + describe("wasteAcceptationStatus = ACCEPTED", () => { + it("waste should be accepted", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.ACCEPTED, + 2.4, + 0 + ); + + // Then + expect(errors).toBeUndefined(); + + const formAfterMutation = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + + expect(formAfterMutation.status).toEqual("TEMP_STORER_ACCEPTED"); + expect(formAfterMutation.wasteAcceptationStatus).toEqual("ACCEPTED"); + expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); + expect(formAfterMutation.quantityRefused?.toNumber()).toEqual(0); + + const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ + where: { id: form.forwardedIn?.id } + }); + + expect( + forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber() + ).toEqual(2.4); + }); - const emitterCompany = await companyFactory(); - const form = await formFactory({ - ownerId: user.id, - opt: { - status: Status.TEMP_STORED, - emitterCompanySiret: emitterCompany.siret, - recipientCompanySiret: tempStorerCompany.siret, - recipientIsTempStorage: true, - forwardedIn: { - create: { readableId: getReadableId(), ownerId: user.id } - }, - receivedBy: "John Doe", - receivedAt: "2018-12-11T00:00:00.000Z" - } + it("quantityRefused must be zero", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.ACCEPTED, + 2.4, + 1 + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) ne peut être supérieure à zéro si le déchet est accepté (ACCEPTED)" + ); + }); }); - // When - const { mutate } = makeClient(user); - const { errors } = await mutate>( - MARK_AS_TEMP_STORER_ACCEPTED, - { - variables: { - id: form.id, - tempStorerAcceptedInfo: { - wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, - wasteRefusalReason: "Thats isn't what I was expecting man !", - signedAt: "2019-01-18" as any, - signedBy: "John Doe", - quantityReceived: 2.4, - quantityType: "REAL" - } - } - } - ); - - // Then - expect(errors).toBeUndefined(); + describe("wasteAcceptationStatus = REFUSED", () => { + it("waste should be refused", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.REFUSED, + 2.4, + 2.4, + "Pas bon" + ); + + // Then + expect(errors).toBeUndefined(); + + const formAfterMutation = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + + expect(formAfterMutation.status).toEqual("REFUSED"); + expect(formAfterMutation.wasteAcceptationStatus).toEqual("REFUSED"); + expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); + expect(formAfterMutation.quantityRefused?.toNumber()).toEqual(2.4); + + const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ + where: { id: form.forwardedIn?.id } + }); + + expect( + forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber() + ).toEqual(0); + + expect(sendMail as jest.Mock).toHaveBeenCalledWith( + expect.objectContaining({ + subject: `Le déchet de l’entreprise ${form.emitterCompanyName} a été totalement refusé à réception` + }) + ); + }); - const formAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.id } + it("quantityRefused must = quantityReceived", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.REFUSED, + 2.4, + 1, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être égale à la quantité reçue (quantityReceived) si le déchet est refusé (REFUSED)" + ); + }); }); - expect(formAfterMutation.status).toEqual("TEMP_STORER_ACCEPTED"); - expect(formAfterMutation.wasteAcceptationStatus).toEqual( - "PARTIALLY_REFUSED" - ); - expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); - expect(formAfterMutation.quantityRefused).toBeNull(); - - const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ - where: { id: form.forwardedIn?.id } - }); + describe("wasteAcceptationStatus = PARTIALLY_REFUSED", () => { + it("waste should be partially refused", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.PARTIALLY_REFUSED, + 2.4, + 1.1, + "Pas bon" + ); + + // Then + expect(errors).toBeUndefined(); + + const formAfterMutation = await prisma.form.findUniqueOrThrow({ + where: { id: form.id } + }); + + expect(formAfterMutation.status).toEqual("TEMP_STORER_ACCEPTED"); + expect(formAfterMutation.wasteAcceptationStatus).toEqual( + "PARTIALLY_REFUSED" + ); + expect(formAfterMutation.quantityReceived?.toNumber()).toEqual(2.4); + expect(formAfterMutation.quantityRefused?.toNumber()).toEqual(1.1); + + const forwardedFormAfterMutation = await prisma.form.findUniqueOrThrow({ + where: { id: form.forwardedIn?.id } + }); + + expect( + forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber() + ).toEqual(1.3); + + // Mail + expect.objectContaining({ + subject: `Le déchet de l’entreprise ${form.emitterCompanyName} a été partiellement refusé à réception`, + body: expect.stringContaining(`
  • Quantité réelle présentée nette : 2.4 tonnes
  • +
  • Quantité refusée nette : 1.1 tonnes
  • +
  • Quantité acceptée nette : 1.3 tonnes
  • `) + }); + }); - expect(forwardedFormAfterMutation.wasteDetailsQuantity?.toNumber()).toEqual( - 2.4 - ); + it("quantityRefused cannot = 0", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.PARTIALLY_REFUSED, + 2.4, + 0, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); + }); - // Mail - expect.objectContaining({ - subject: `Le déchet de l’entreprise ${form.emitterCompanyName} a été partiellement refusé à réception`, - body: expect.stringContaining(`
  • Quantité réelle présentée nette : 2.4 tonnes
  • -
  • Quantité refusée nette : Non renseignée
  • -
  • Quantité acceptée nette : Non renseignée
  • `) + it("quantityRefused cannot = quantityReceived", async () => { + // Given + const { user, form } = await createBSDD(); + + // When + const { errors } = await markBSDDAsAccepted( + user, + form.id, + WasteAcceptationStatus.PARTIALLY_REFUSED, + 2.4, + 2.4, + "Pas bon" + ); + + // Then + expect(errors).not.toBeUndefined(); + expect(errors[0].message).toBe( + "La quantité refusée (quantityRefused) doit être inférieure à la quantité reçue (quantityReceived) et supérieure à zéro si le déchet est partiellement refusé (PARTIALLY_REFUSED)" + ); + }); }); }); }); diff --git a/back/src/forms/resolvers/mutations/__tests__/submitFormRevisionRequestApproval.integration.ts b/back/src/forms/resolvers/mutations/__tests__/submitFormRevisionRequestApproval.integration.ts index 370ca0be1e..b149354326 100644 --- a/back/src/forms/resolvers/mutations/__tests__/submitFormRevisionRequestApproval.integration.ts +++ b/back/src/forms/resolvers/mutations/__tests__/submitFormRevisionRequestApproval.integration.ts @@ -1845,7 +1845,9 @@ describe("Mutation.submitFormRevisionRequestApproval", () => { where: { id: bsdd.id } }); - expect(updatedBsdd.wasteAcceptationStatus).toBe(Status.REFUSED); + expect(updatedBsdd.wasteAcceptationStatus).toBe( + WasteAcceptationStatus.REFUSED + ); expect(updatedBsdd.wasteRefusalReason).toBe("Reason"); expect(updatedBsdd.quantityReceived?.toNumber()).toBe(5); }); @@ -1905,7 +1907,7 @@ describe("Mutation.submitFormRevisionRequestApproval", () => { expect(updatedBsdd.quantityRefused?.toNumber()).toBe(3); }); - it("should NOT update the BSDD wasteAcceptationStatus if the BSDD status is no long ACCEPTED or TEMP_STORED_ACCEPTED", async () => { + it("should NOT update the BSDD wasteAcceptationStatus if the BSDD status is no longer ACCEPTED or TEMP_STORED_ACCEPTED", async () => { // Given const { company: companyOfSomeoneElse } = await userWithCompanyFactory( "ADMIN" @@ -1950,5 +1952,272 @@ describe("Mutation.submitFormRevisionRequestApproval", () => { "Le statut d'acceptation des déchets n'est modifiable que si le bordereau est au stade de la réception." ); }); + + it("should update quantityReceived only (BSD without quantityRefused)", async () => { + // Given + const { company: companyOfSomeoneElse } = await userWithCompanyFactory( + "ADMIN" + ); + const { user, company } = await userWithCompanyFactory("ADMIN"); + const { mutate } = makeClient(user); + + const bsdd = await formFactory({ + ownerId: user.id, + opt: { + emitterCompanySiret: companyOfSomeoneElse.siret, + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.ACCEPTED, + wasteRefusalReason: "Nope", + quantityReceived: 10 + } + }); + + const revisionRequest = await prisma.bsddRevisionRequest.create({ + data: { + bsddId: bsdd.id, + authoringCompanyId: companyOfSomeoneElse.id, + approvals: { create: { approverSiret: company.siret! } }, + quantityReceived: 5, + comment: "Comment" + } + }); + + // When + const { data } = await mutate< + Pick + >(SUBMIT_BSDD_REVISION_REQUEST_APPROVAL, { + variables: { + id: revisionRequest.id, + isApproved: true + } + }); + + // Then + expect(data.submitFormRevisionRequestApproval.status).toBe("ACCEPTED"); + + const updatedBsdd = await prisma.form.findFirstOrThrow({ + where: { id: bsdd.id } + }); + + expect(updatedBsdd.wasteAcceptationStatus).toBe( + WasteAcceptationStatus.ACCEPTED + ); + expect(updatedBsdd.quantityReceived?.toNumber()).toBe(5); + }); + + it("should update quantityReceived only (BSD with quantityRefused)", async () => { + // Given + const { company: companyOfSomeoneElse } = await userWithCompanyFactory( + "ADMIN" + ); + const { user, company } = await userWithCompanyFactory("ADMIN"); + const { mutate } = makeClient(user); + + const bsdd = await formFactory({ + ownerId: user.id, + opt: { + emitterCompanySiret: companyOfSomeoneElse.siret, + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Nope", + quantityReceived: 10, + quantityRefused: 5 + } + }); + + const revisionRequest = await prisma.bsddRevisionRequest.create({ + data: { + bsddId: bsdd.id, + authoringCompanyId: companyOfSomeoneElse.id, + approvals: { create: { approverSiret: company.siret! } }, + quantityReceived: 6, + comment: "Comment" + } + }); + + // When + const { data } = await mutate< + Pick + >(SUBMIT_BSDD_REVISION_REQUEST_APPROVAL, { + variables: { + id: revisionRequest.id, + isApproved: true + } + }); + + // Then + expect(data.submitFormRevisionRequestApproval.status).toBe("ACCEPTED"); + + const updatedBsdd = await prisma.form.findFirstOrThrow({ + where: { id: bsdd.id } + }); + + expect(updatedBsdd.wasteAcceptationStatus).toBe( + WasteAcceptationStatus.PARTIALLY_REFUSED + ); + expect(updatedBsdd.quantityReceived?.toNumber()).toBe(6); + expect(updatedBsdd.quantityRefused?.toNumber()).toBe(5); + }); + + it("should update quantityRefused", async () => { + // Given + const { company: companyOfSomeoneElse } = await userWithCompanyFactory( + "ADMIN" + ); + const { user, company } = await userWithCompanyFactory("ADMIN"); + const { mutate } = makeClient(user); + + const bsdd = await formFactory({ + ownerId: user.id, + opt: { + emitterCompanySiret: companyOfSomeoneElse.siret, + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Nope", + quantityReceived: 10, + quantityRefused: 5 + } + }); + + const revisionRequest = await prisma.bsddRevisionRequest.create({ + data: { + bsddId: bsdd.id, + authoringCompanyId: companyOfSomeoneElse.id, + approvals: { create: { approverSiret: company.siret! } }, + quantityRefused: 3, + comment: "Comment" + } + }); + + // When + const { data } = await mutate< + Pick + >(SUBMIT_BSDD_REVISION_REQUEST_APPROVAL, { + variables: { + id: revisionRequest.id, + isApproved: true + } + }); + + // Then + expect(data.submitFormRevisionRequestApproval.status).toBe("ACCEPTED"); + + const updatedBsdd = await prisma.form.findFirstOrThrow({ + where: { id: bsdd.id } + }); + + expect(updatedBsdd.wasteAcceptationStatus).toBe( + WasteAcceptationStatus.PARTIALLY_REFUSED + ); + expect(updatedBsdd.quantityReceived?.toNumber()).toBe(10); + expect(updatedBsdd.quantityRefused?.toNumber()).toBe(3); + }); + + it("should add quantityRefused even though none was specified in the original BSD", async () => { + // Given + const { company: companyOfSomeoneElse } = await userWithCompanyFactory( + "ADMIN" + ); + const { user, company } = await userWithCompanyFactory("ADMIN"); + const { mutate } = makeClient(user); + + const bsdd = await formFactory({ + ownerId: user.id, + opt: { + emitterCompanySiret: companyOfSomeoneElse.siret, + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Nope", + quantityReceived: 10 + } + }); + + const revisionRequest = await prisma.bsddRevisionRequest.create({ + data: { + bsddId: bsdd.id, + authoringCompanyId: companyOfSomeoneElse.id, + approvals: { create: { approverSiret: company.siret! } }, + quantityRefused: 3, + comment: "Comment" + } + }); + + // When + const { data } = await mutate< + Pick + >(SUBMIT_BSDD_REVISION_REQUEST_APPROVAL, { + variables: { + id: revisionRequest.id, + isApproved: true + } + }); + + // Then + expect(data.submitFormRevisionRequestApproval.status).toBe("ACCEPTED"); + + const updatedBsdd = await prisma.form.findFirstOrThrow({ + where: { id: bsdd.id } + }); + + expect(updatedBsdd.wasteAcceptationStatus).toBe( + WasteAcceptationStatus.PARTIALLY_REFUSED + ); + expect(updatedBsdd.quantityReceived?.toNumber()).toBe(10); + expect(updatedBsdd.quantityRefused?.toNumber()).toBe(3); + }); + + it("should not remove quantityRefused if specified in the original BSD", async () => { + // Given + const { company: companyOfSomeoneElse } = await userWithCompanyFactory( + "ADMIN" + ); + const { user, company } = await userWithCompanyFactory("ADMIN"); + const { mutate } = makeClient(user); + + const bsdd = await formFactory({ + ownerId: user.id, + opt: { + emitterCompanySiret: companyOfSomeoneElse.siret, + status: Status.ACCEPTED, + wasteAcceptationStatus: WasteAcceptationStatus.PARTIALLY_REFUSED, + wasteRefusalReason: "Nope", + quantityReceived: 10, + quantityRefused: 5 + } + }); + + const revisionRequest = await prisma.bsddRevisionRequest.create({ + data: { + bsddId: bsdd.id, + authoringCompanyId: companyOfSomeoneElse.id, + approvals: { create: { approverSiret: company.siret! } }, + quantityRefused: null, + comment: "Comment" + } + }); + + // When + const { data } = await mutate< + Pick + >(SUBMIT_BSDD_REVISION_REQUEST_APPROVAL, { + variables: { + id: revisionRequest.id, + isApproved: true + } + }); + + // Then + expect(data.submitFormRevisionRequestApproval.status).toBe("ACCEPTED"); + + const updatedBsdd = await prisma.form.findFirstOrThrow({ + where: { id: bsdd.id } + }); + + expect(updatedBsdd.wasteAcceptationStatus).toBe( + WasteAcceptationStatus.PARTIALLY_REFUSED + ); + expect(updatedBsdd.quantityReceived?.toNumber()).toBe(10); + expect(updatedBsdd.quantityRefused?.toNumber()).toBe(5); + }); }); }); diff --git a/back/src/forms/resolvers/mutations/createFormRevisionRequest.ts b/back/src/forms/resolvers/mutations/createFormRevisionRequest.ts index 8429e349c6..d364b2e90a 100644 --- a/back/src/forms/resolvers/mutations/createFormRevisionRequest.ts +++ b/back/src/forms/resolvers/mutations/createFormRevisionRequest.ts @@ -6,8 +6,7 @@ import { Prisma, RevisionRequestStatus, Status, - User, - WasteAcceptationStatus + User } from "@prisma/client"; import * as yup from "yup"; import { @@ -37,7 +36,7 @@ import { INVALID_PROCESSING_OPERATION, INVALID_WASTE_CODE } from "../../errors"; import { brokerSchemaFn, packagingInfoFn, - quantityRefused, + quantityRefusedNotRequired, traderSchemaFn } from "../../validation"; import { ForbiddenError, UserInputError } from "../../../common/errors"; @@ -48,6 +47,7 @@ import { canProcessNonDangerousWaste } from "../../../companies/companyProfilesRules"; import { INVALID_DESTINATION_SUBPROFILE } from "../../errors"; +import { isDefined } from "../../../common/helpers"; // If you modify this, also modify it in the frontend export const CANCELLABLE_BSDD_STATUSES: Status[] = [ @@ -281,23 +281,24 @@ async function getFlatContent( const { isCanceled, ...revisionFields } = flatContent; + // Retiré jusqu'à nouvel ordre! // Trying to change the acceptation status - if (content.wasteAcceptationStatus) { - if (!bsdd.wasteAcceptationStatus) { - throw new UserInputError( - "Le statut d'acceptation des déchets n'est modifiable que s'il a déjà une valeur." - ); - } - - if ( - content.wasteAcceptationStatus !== bsdd.wasteAcceptationStatus && - ![Status.ACCEPTED, Status.TEMP_STORER_ACCEPTED].includes(bsdd.status) - ) { - throw new UserInputError( - "Le statut d'acceptation des déchets n'est modifiable que si le bordereau est au stade de la réception." - ); - } - } + // if (content.wasteAcceptationStatus) { + // if (!bsdd.wasteAcceptationStatus) { + // throw new UserInputError( + // "Le statut d'acceptation des déchets n'est modifiable que s'il a déjà une valeur." + // ); + // } + + // if ( + // content.wasteAcceptationStatus !== bsdd.wasteAcceptationStatus && + // ![Status.ACCEPTED, Status.TEMP_STORER_ACCEPTED].includes(bsdd.status) + // ) { + // throw new UserInputError( + // "Le statut d'acceptation des déchets n'est modifiable que si le bordereau est au stade de la réception." + // ); + // } + // } if (!isCanceled && Object.keys(revisionFields).length === 0) { throw new UserInputError( @@ -363,7 +364,8 @@ async function getFlatContent( await validateWAsteAccordingToDestination(bsdd, flatContent); - // + const contentToValidate = getContentToValidate(bsdd, flatContent); + if (bsdd.emitterType === EmitterType.APPENDIX1_PRODUCER) { await appendix1ProducerRevisionRequestSchema.validate(flatContent, { strict: true @@ -379,7 +381,7 @@ async function getFlatContent( ); } } else { - await bsddRevisionRequestSchema.validate(flatContent, { + await bsddRevisionRequestSchema.validate(contentToValidate, { strict: true, abortEarly: false }); @@ -388,7 +390,7 @@ async function getFlatContent( // Double-check the waste quantities await bsddRevisionRequestWasteQuantitiesSchema.validate({ ...bsdd, - ...flatContent + ...contentToValidate }); if ( @@ -404,6 +406,37 @@ async function getFlatContent( return flatContent; } +const getContentToValidate = ( + bsdd: Form & { transporters: BsddTransporter[] }, + flatContent: ReturnType +) => { + // quantityReceived & quantityRefused sont liées pour la validation, il faut donc + // passer les deux + const isReviewingQuantities = + isDefined(flatContent.quantityReceived) || + isDefined(flatContent.quantityRefused); + + if (!isReviewingQuantities) return flatContent; + + let quantityReceived: number | null = null; + if (isDefined(flatContent.quantityReceived)) + quantityReceived = flatContent.quantityReceived; + else if (isDefined(bsdd.quantityReceived)) + quantityReceived = Number(bsdd.quantityReceived); + + let quantityRefused: number | null = null; + if (isDefined(flatContent.quantityRefused)) + quantityRefused = flatContent.quantityRefused; + else if (isDefined(bsdd.quantityRefused)) + quantityRefused = Number(bsdd.quantityRefused); + + return { + ...flatContent, + quantityReceived, + quantityRefused + }; +}; + async function getApproversSirets( bsdd: Form, content: RevisionRequestContent, @@ -459,23 +492,24 @@ function hasTemporaryStorageUpdate( } const bsddRevisionRequestWasteQuantitiesSchema = yup.object({ - wasteAcceptationStatus: yup.mixed(), - wasteRefusalReason: yup - .string() - .when("wasteAcceptationStatus", (wasteAcceptationStatus, schema) => - ["REFUSED", "PARTIALLY_REFUSED"].includes(wasteAcceptationStatus) - ? schema.ensure().required("Vous devez saisir un motif de refus") - : schema - .notRequired() - .nullable() - .test( - "is-empty", - "Le champ wasteRefusalReason ne doit pas être rensigné si le déchet est accepté ", - v => !v - ) - ), + // Retirés jusqu'à nouvel ordre! + // wasteAcceptationStatus: yup.mixed(), + // wasteRefusalReason: yup + // .string() + // .when("wasteAcceptationStatus", (wasteAcceptationStatus, schema) => + // ["REFUSED", "PARTIALLY_REFUSED"].includes(wasteAcceptationStatus) + // ? schema.ensure().required("Vous devez saisir un motif de refus") + // : schema + // .notRequired() + // .nullable() + // .test( + // "is-empty", + // "Le champ wasteRefusalReason ne doit pas être rensigné si le déchet est accepté ", + // v => !v + // ) + // ), quantityReceived: yup.number().min(0).nullable(), - quantityRefused + quantityRefused: quantityRefusedNotRequired }); async function recipify( diff --git a/back/src/forms/typeDefs/bsdd.inputs.graphql b/back/src/forms/typeDefs/bsdd.inputs.graphql index d20fa954d0..91e03b44e7 100644 --- a/back/src/forms/typeDefs/bsdd.inputs.graphql +++ b/back/src/forms/typeDefs/bsdd.inputs.graphql @@ -116,14 +116,12 @@ input AcceptedFormInput { quantityReceived: Float! """ - Quantité refusée nette (optionnelle) - - Si définie: + Quantité refusée nette: - doit être supérieure à 0 et inférieure ou égale à quantityReceived si le déchet est partiellement refusé. - doit être égale à 0 si le déchet est totalement accepté. - doit être égale à quantityReceived si le déchet est totalement refusé. """ - quantityRefused: Float + quantityRefused: Float! "Charte citerne - Est-ce que la citerne a été rincée ou non?" hasCiterneBeenWashedOut: Boolean @@ -162,9 +160,7 @@ input ReceivedFormInput { quantityReceived: Float """ - Quantité refusée nette (optionnelle) - - Si définie: + Quantité refusée nette: - doit être supérieure à 0 et inférieure ou égale à quantityReceived si le déchet est partiellement refusé. - doit être égale à 0 si le déchet est totalement accepté. - doit être égale à quantityReceived si le déchet est totalement refusé. @@ -786,14 +782,12 @@ input TempStorerAcceptedFormInput { quantityReceived: Float! """ - Quantité refusée nette (optionnelle) - - Si définie: + Quantité refusée nette: - doit être supérieure à 0 et inférieure ou égale à quantityReceived si le déchet est partiellement refusé. - doit être égale à 0 si le déchet est totalement accepté. - doit être égale à quantityReceived si le déchet est totalement refusé. """ - quantityRefused: Float + quantityRefused: Float! "Réelle ou estimée" quantityType: QuantityType! @@ -823,9 +817,7 @@ input TempStoredFormInput { quantityReceived: Float! """ - Quantité refusée nette (optionnelle) - - Si définie: + Quantité refusée nette: - doit être supérieure à 0 et inférieure ou égale à quantityReceived si le déchet est partiellement refusé. - doit être égale à 0 si le déchet est totalement accepté. - doit être égale à quantityReceived si le déchet est totalement refusé. @@ -985,11 +977,12 @@ input FormRevisionRequestContentInput { "Informations sur l'installation de destination ou d’entreposage ou de reconditionnement prévue (édition partielle uniquement)" recipient: FormRevisionRequestRecipientInput - "Statut d'acceptation du déchet (case 10)" - wasteAcceptationStatus: WasteAcceptationStatus + # Retirés jusqu'à nouvel ordre! + # "Statut d'acceptation du déchet (case 10)" + # wasteAcceptationStatus: WasteAcceptationStatus - "Raison du refus (case 10). Obligatoire en cas de refus de déchet" - wasteRefusalReason: String + # "Raison du refus (case 10). Obligatoire en cas de refus de déchet" + # wasteRefusalReason: String "Quantité reçue sur l'installation de destination, en tonnes" quantityReceived: Float diff --git a/back/src/forms/validation.ts b/back/src/forms/validation.ts index a1e242ccba..091bd6ffed 100644 --- a/back/src/forms/validation.ts +++ b/back/src/forms/validation.ts @@ -265,7 +265,7 @@ export const hasPipeline = (value: { }): boolean => value.wasteDetailsPackagingInfos?.some(i => i.type === "PIPELINE"); -export const quantityRefused = weight(WeightUnits.Tonne) +export const quantityRefusedNotRequired = weight(WeightUnits.Tonne) .min(0) .test( "not-defined-if-no-quantity-received", @@ -273,9 +273,8 @@ export const quantityRefused = weight(WeightUnits.Tonne) (value, context) => { const { quantityReceived } = context.parent; - const quantityReceivedIsDefined = - quantityReceived !== null && quantityReceived !== undefined; - const quantityRefusedIsDefined = value !== null && value !== undefined; + const quantityReceivedIsDefined = isDefined(quantityReceived); + const quantityRefusedIsDefined = isDefined(value); if (!quantityReceivedIsDefined && quantityRefusedIsDefined) return false; return true; @@ -332,8 +331,7 @@ export const quantityRefused = weight(WeightUnits.Tonne) (value, context) => { const { quantityReceived } = context.parent; - if (quantityReceived === null || quantityReceived === undefined) - return true; + if (!isDefined(quantityReceived)) return true; // Legacy if (value === null || value === undefined) return true; @@ -342,6 +340,22 @@ export const quantityRefused = weight(WeightUnits.Tonne) } ); +export const quantityRefused = quantityRefusedNotRequired.test( + "quantity-is-required", + "La quantité refusée (quantityRefused) est requise", + (value, context) => { + const { wasteAcceptationStatus } = context.parent; + + // La quantity refusée est obligatoire à l'étape d'acceptation, + // donc si wasteAcceptationStatus est renseigné + if (isDefined(wasteAcceptationStatus) && !isDefined(value)) { + return false; + } + + return true; + } +); + // ************************************************************* // DEFINES VALIDATION SCHEMA FOR INDIVIDUAL FRAMES IN BSD PAGE 1 // ************************************************************* diff --git a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/AcceptedInfo.tsx b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/AcceptedInfo.tsx deleted file mode 100644 index bd9a3dc84d..0000000000 --- a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/AcceptedInfo.tsx +++ /dev/null @@ -1,215 +0,0 @@ -import React from "react"; -import { Field, Form, Formik } from "formik"; -import * as yup from "yup"; -import NumberInput from "../../../../../form/common/components/custom-inputs/NumberInput"; -import DateInput from "../../../../../form/common/components/custom-inputs/DateInput"; -import { - InlineRadioButton, - RadioButton -} from "../../../../../form/common/components/custom-inputs/RadioButton"; -import { - WasteAcceptationStatus, - FormStatus, - Form as TdForm, - QuantityType -} from "@td/codegen-ui"; -import { textConfig } from "./ReceivedInfo"; -import { RedErrorMessage } from "../../../../../common/components"; -import EstimatedQuantityTooltip from "../../../../../common/components/EstimatedQuantityTooltip"; - -export type AcceptedInfoValues = { - signedBy: string; - signedAt: string; - quantityReceived: number | null; - wasteAcceptationStatus: WasteAcceptationStatus; - wasteRefusalReason: string; - quantityType?: QuantityType; -}; - -const validationSchema: yup.SchemaOf = yup.object({ - signedBy: yup.string().required("Le nom du responsable est un champ requis"), - signedAt: yup.string().required("La date de signature est un champ requis"), - quantityReceived: yup - .number() - .nullable() - .required("Le poids accepté est un champ requis"), - wasteAcceptationStatus: yup - .mixed() - .oneOf(Object.values(WasteAcceptationStatus)) - .required("Le statut d'acceptation du lot est un champ requis"), - wasteRefusalReason: yup.string().ensure(), - quantityType: yup.mixed() -}); - -/** - * Accepted info form shared between markAsAccepted and markAsTempStorerAccepted - */ -export default function AcceptedInfo({ - form, - close, - onSubmit -}: { - form: TdForm; - close: () => void; - onSubmit: (values: AcceptedInfoValues) => void; -}) { - return ( - - initialValues={{ - signedBy: "", - signedAt: new Date().toISOString(), - quantityReceived: null, - wasteAcceptationStatus: "" as WasteAcceptationStatus, - wasteRefusalReason: "" - }} - onSubmit={onSubmit} - validationSchema={validationSchema} - > - {({ isSubmitting, setFieldValue, values, handleReset }) => ( -
    -
    -
    -
    -

    Lot accepté:

    - { - // clear wasteRefusalReason if waste is accepted - setFieldValue("wasteRefusalReason", ""); - setFieldValue( - "wasteAcceptationStatus", - WasteAcceptationStatus.Accepted - ); - }} - /> - { - setFieldValue("quantityReceived", 0); - setFieldValue( - "wasteAcceptationStatus", - WasteAcceptationStatus.Refused - ); - }} - /> - -
    - -
    -
    -
    - - -
    - {form.recipient?.isTempStorage && form.status === FormStatus.Sent && ( -
    - Cette quantité est - - - Estimée - - } - component={RadioButton} - /> -
    - )} - {/* Display wasteRefusalReason field if waste is refused or partially refused*/} - {[ - WasteAcceptationStatus.Refused.toString(), - WasteAcceptationStatus.PartiallyRefused.toString() - ].includes(values.wasteAcceptationStatus) && ( -
    - - -
    - )} -
    - - -
    -
    - - -
    -

    - {values.wasteAcceptationStatus && - textConfig[values.wasteAcceptationStatus].validationText} -

    -
    - - - -
    -
    - )} - - ); -} diff --git a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/MarkAsAccepted.tsx b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/MarkAsAccepted.tsx deleted file mode 100644 index 39deb4039d..0000000000 --- a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/MarkAsAccepted.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import React from "react"; -import { - Mutation, - MutationMarkAsAcceptedArgs, - Query, - QueryFormArgs -} from "@td/codegen-ui"; -import { WorkflowActionProps } from "./WorkflowAction"; -import { gql, useMutation, useLazyQuery } from "@apollo/client"; -import { statusChangeFragment } from "../../../../../Apps/common/queries/fragments"; -import { TdModalTrigger } from "../../../../../Apps/common/Components/Modal/Modal"; -import { ActionButton } from "../../../../../common/components"; -import { Loader } from "../../../../../Apps/common/Components"; -import { IconWaterDam } from "../../../../../Apps/common/Components/Icons/Icons"; -import { NotificationError } from "../../../../../Apps/common/Components/Error/Error"; -import AcceptedInfo from "./AcceptedInfo"; -import { GET_FORM } from "../../../../../Apps/common/queries/bsdd/queries"; - -const MARK_AS_ACCEPTED = gql` - mutation MarkAsAccepted($id: ID!, $acceptedInfo: AcceptedFormInput!) { - markAsAccepted(id: $id, acceptedInfo: $acceptedInfo) { - ...StatusChange - } - } - ${statusChangeFragment} -`; - -export default function MarkAsAccepted({ form }: WorkflowActionProps) { - const [getBsdd, { error: bsddGetError, data, loading: bsddGetLoading }] = - useLazyQuery, QueryFormArgs>(GET_FORM, { - variables: { - id: form.id, - readableId: null - }, - fetchPolicy: "network-only" - }); - const [markAsAccepted, { loading, error }] = useMutation< - Pick, - MutationMarkAsAcceptedArgs - >(MARK_AS_ACCEPTED, { - onError: () => { - // The error is handled in the UI - } - }); - - const actionLabel = "Valider l'acceptation"; - - return ( - ( - } - onClick={() => { - getBsdd(); - open(); - }} - > - {actionLabel} - - )} - modalContent={close => { - if (!!bsddGetLoading) { - return ; - } - if (!!bsddGetError) { - return ( - - ); - } - - if (!!data?.form) { - return ( -
    - - markAsAccepted({ - variables: { - id: form.id, - acceptedInfo: { - ...values, - quantityReceived: values.quantityReceived ?? 0 - } - } - }) - } - /> - - {error && ( - - )} - {loading && } -
    - ); - } - - return null; - }} - /> - ); -} diff --git a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/MarkAsTempStorerAccepted.tsx b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/MarkAsTempStorerAccepted.tsx deleted file mode 100644 index 367661aced..0000000000 --- a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/MarkAsTempStorerAccepted.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import React from "react"; -import { - Mutation, - QuantityType, - MutationMarkAsTempStorerAcceptedArgs, - Query, - QueryFormArgs -} from "@td/codegen-ui"; -import { WorkflowActionProps } from "./WorkflowAction"; -import { gql, useMutation, useLazyQuery } from "@apollo/client"; - -import { statusChangeFragment } from "../../../../../Apps/common/queries/fragments"; -import { TdModalTrigger } from "../../../../../Apps/common/Components/Modal/Modal"; -import { ActionButton } from "../../../../../common/components"; -import { Loader } from "../../../../../Apps/common/Components"; -import { IconWarehouseStorage } from "../../../../../Apps/common/Components/Icons/Icons"; -import { NotificationError } from "../../../../../Apps/common/Components/Error/Error"; -import AcceptedInfo from "./AcceptedInfo"; -import { GET_FORM } from "../../../../../Apps/common/queries/bsdd/queries"; - -const MARK_TEMP_STORER_ACCEPTED = gql` - mutation MarkAsTempStorerAccepted( - $id: ID! - $tempStorerAcceptedInfo: TempStorerAcceptedFormInput! - ) { - markAsTempStorerAccepted( - id: $id - tempStorerAcceptedInfo: $tempStorerAcceptedInfo - ) { - ...StatusChange - } - } - ${statusChangeFragment} -`; - -export default function MarkAsTempStorerAccepted({ - form -}: WorkflowActionProps) { - const [getBsdd, { error: bsddGetError, data, loading: bsddGetLoading }] = - useLazyQuery, QueryFormArgs>(GET_FORM, { - variables: { - id: form.id, - readableId: null - }, - fetchPolicy: "network-only" - }); - const [markAsTempStorerAccepted, { loading, error }] = useMutation< - Pick, - MutationMarkAsTempStorerAcceptedArgs - >(MARK_TEMP_STORER_ACCEPTED, { - onError: () => { - // The error is handled in the UI - } - }); - - const actionLabel = "Valider l'acceptation de l'entreposage provisoire"; - - return ( - ( - } - onClick={() => { - getBsdd(); - open(); - }} - > - {actionLabel} - - )} - modalContent={close => { - if (!!bsddGetLoading) { - return ; - } - if (!!bsddGetError) { - return ( - - ); - } - if (!!data?.form) { - return ( -
    - - markAsTempStorerAccepted({ - variables: { - id: form.id, - tempStorerAcceptedInfo: { - ...values, - quantityReceived: values.quantityReceived ?? 0, - quantityType: values.quantityType ?? QuantityType.Real - } - } - }) - } - /> - {error && ( - - )} - {loading && } -
    - ); - } - - return null; - }} - /> - ); -}