From 55c30256d317ba36815f13dcf56dfb446eaeb3eb Mon Sep 17 00:00:00 2001 From: jonat75 Date: Thu, 21 Dec 2023 16:48:33 +0100 Subject: [PATCH] fix: simulation to declaration in indicator 2 or 3 allows empty strings (#1941) --- .../(funnel)/(indicateurs2ou3)/Form.tsx | 44 +++++++++++++++++-- .../(funnel)/recapitulatif/simuToDecla.ts | 42 ++++++++++++------ .../computers/IndicateurDeuxComputer.ts | 10 ++++- .../core-domain/dtos/CreateSimulationDTO.ts | 20 ++++++--- 4 files changed, 91 insertions(+), 25 deletions(-) diff --git a/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/(indicateurs2ou3)/Form.tsx b/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/(indicateurs2ou3)/Form.tsx index 8dfcfeb04..78273ed1a 100644 --- a/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/(indicateurs2ou3)/Form.tsx +++ b/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/(indicateurs2ou3)/Form.tsx @@ -19,7 +19,15 @@ import { storePicker } from "@common/utils/zustand"; import { AideSimulationIndicateurDeux } from "@components/aide-simulation/IndicateurDeux"; import { AideSimulationIndicateurTrois } from "@components/aide-simulation/IndicateurTrois"; import { RadioOuiNon } from "@components/RHF/RadioOuiNon"; -import { AlternativeTable, type AlternativeTableProps, BackNextButtonsGroup, Box, FormLayout } from "@design-system"; +import { SkeletonForm } from "@components/utils/skeleton/SkeletonForm"; +import { + AlternativeTable, + type AlternativeTableProps, + BackNextButtonsGroup, + Box, + CenteredContainer, + FormLayout, +} from "@design-system"; import { ClientAnimate } from "@design-system/utils/client/ClientAnimate"; import { zodResolver } from "@hookform/resolvers/zod"; import { isEmpty } from "lodash"; @@ -28,7 +36,7 @@ import { type FieldErrors, FormProvider, useForm } from "react-hook-form"; import { type z } from "zod"; import { NAVIGATION, simulateurPath } from "../navigation"; -import { useSimuFunnelStore } from "../useSimuFunnelStore"; +import { useSimuFunnelStore, useSimuFunnelStoreHasHydrated } from "../useSimuFunnelStore"; import { getPourcentagesAugmentationPromotionsWithCount, prepareIndicateurUnComputer } from "../utils"; import { Indicateur2ou3Note } from "./Indicateur2ou3Note"; @@ -60,6 +68,23 @@ const schemaWithGlobalPourcentageVerification = (indicateur: Indic2or3FormProps[ path: ["root.totalPourcentages"], }); } + categories.forEach(category => { + const categoryValues = obj.pourcentages[category] ?? null; + if (categoryValues) { + if (categoryValues.women === "") + ctx.addIssue({ + code: zodFr.ZodIssueCode.custom, + message: "Ce champs est requis", + path: [`pourcentages.${category}.women`], + }); + if (categoryValues.men === "") + ctx.addIssue({ + code: zodFr.ZodIssueCode.custom, + message: "Ce champs est requis", + path: [`pourcentages.${category}.men`], + }); + } + }); } }); @@ -69,7 +94,7 @@ export const Indic2or3Form = ({ indicateur }: Indic2or3FormProps) => { const router = useRouter(); const [_funnel, saveFunnel] = useStore("funnel", "saveFunnel"); const funnel = _funnel as Partial | undefined; - prepareIndicateurUnComputer(indicateur1Computer, funnel as CreateSimulationDTO); + const hydrated = useSimuFunnelStoreHasHydrated(); const computer = indicateur === 2 ? indicateur2Computer : indicateur3Computer; const indicateurNav = indicateur === 2 ? NAVIGATION.indicateur2 : NAVIGATION.indicateur3; @@ -88,9 +113,20 @@ export const Indic2or3Form = ({ indicateur }: Indic2or3FormProps) => { handleSubmit, register, watch, + getValues, } = methods; - const computableCheck = watch("calculable"); + if (!hydrated) { + return ( + + + + ); + } + + prepareIndicateurUnComputer(indicateur1Computer, funnel as CreateSimulationDTO); + + const computableCheck = watch("calculable") || getValues("calculable"); const pourcentages = watch("pourcentages"); let pourcentagesWithCount = undefined as Percentages | undefined; diff --git a/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/recapitulatif/simuToDecla.ts b/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/recapitulatif/simuToDecla.ts index e249975fb..f1ba0b8a2 100644 --- a/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/recapitulatif/simuToDecla.ts +++ b/packages/app/src/app/(default)/index-egapro/simulateur/(funnel)/recapitulatif/simuToDecla.ts @@ -93,12 +93,20 @@ export const simuFunnelToDeclarationDTO = (simulation: CreateSimulationDTO): Dec dto["augmentations"] = { estCalculable: "oui", catégories: { - [CSP.Enum.OUVRIERS]: resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.OUVRIERS)), - [CSP.Enum.EMPLOYES]: resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.EMPLOYES)), - [CSP.Enum.TECHNICIENS_AGENTS_MAITRISES]: resultWithSign( - computerIndicateurDeux.computeGroup(CSP.Enum.TECHNICIENS_AGENTS_MAITRISES), - ), - [CSP.Enum.INGENIEURS_CADRES]: resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.INGENIEURS_CADRES)), + [CSP.Enum.OUVRIERS]: computerIndicateurDeux.canComputeGroup(CSP.Enum.OUVRIERS) + ? resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.OUVRIERS)) + : "", + [CSP.Enum.EMPLOYES]: computerIndicateurDeux.canComputeGroup(CSP.Enum.EMPLOYES) + ? resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.EMPLOYES)) + : "", + [CSP.Enum.TECHNICIENS_AGENTS_MAITRISES]: computerIndicateurDeux.canComputeGroup( + CSP.Enum.TECHNICIENS_AGENTS_MAITRISES, + ) + ? resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.TECHNICIENS_AGENTS_MAITRISES)) + : "", + [CSP.Enum.INGENIEURS_CADRES]: computerIndicateurDeux.canComputeGroup(CSP.Enum.INGENIEURS_CADRES) + ? resultWithSign(computerIndicateurDeux.computeGroup(CSP.Enum.INGENIEURS_CADRES)) + : "", }, note: resultIndicateurDeux.note, populationFavorable: toFavorablePopulation(resultIndicateurDeux.favorablePopulation), // TODO: Use the FavorablePopulation.Enum instead. @@ -112,14 +120,20 @@ export const simuFunnelToDeclarationDTO = (simulation: CreateSimulationDTO): Dec dto["promotions"] = { estCalculable: "oui", catégories: { - [CSP.Enum.OUVRIERS]: resultWithSign(computerIndicateurTrois.computeGroup(CSP.Enum.OUVRIERS)), - [CSP.Enum.EMPLOYES]: resultWithSign(computerIndicateurTrois.computeGroup(CSP.Enum.EMPLOYES)), - [CSP.Enum.TECHNICIENS_AGENTS_MAITRISES]: resultWithSign( - computerIndicateurTrois.computeGroup(CSP.Enum.TECHNICIENS_AGENTS_MAITRISES), - ), - [CSP.Enum.INGENIEURS_CADRES]: resultWithSign( - computerIndicateurTrois.computeGroup(CSP.Enum.INGENIEURS_CADRES), - ), + [CSP.Enum.OUVRIERS]: computerIndicateurTrois.canComputeGroup(CSP.Enum.OUVRIERS) + ? resultWithSign(computerIndicateurTrois.computeGroup(CSP.Enum.OUVRIERS)) + : "", + [CSP.Enum.EMPLOYES]: computerIndicateurTrois.canComputeGroup(CSP.Enum.EMPLOYES) + ? resultWithSign(computerIndicateurTrois.computeGroup(CSP.Enum.EMPLOYES)) + : "", + [CSP.Enum.TECHNICIENS_AGENTS_MAITRISES]: computerIndicateurTrois.canComputeGroup( + CSP.Enum.TECHNICIENS_AGENTS_MAITRISES, + ) + ? resultWithSign(computerIndicateurTrois.computeGroup(CSP.Enum.TECHNICIENS_AGENTS_MAITRISES)) + : "", + [CSP.Enum.INGENIEURS_CADRES]: computerIndicateurTrois.canComputeGroup(CSP.Enum.INGENIEURS_CADRES) + ? resultWithSign(computerIndicateurTrois.computeGroup(CSP.Enum.INGENIEURS_CADRES)) + : "", }, note: resultIndicateurTrois.note, populationFavorable: toFavorablePopulation(resultIndicateurTrois.favorablePopulation), diff --git a/packages/app/src/common/core-domain/computers/IndicateurDeuxComputer.ts b/packages/app/src/common/core-domain/computers/IndicateurDeuxComputer.ts index 58789d390..cdad679ee 100644 --- a/packages/app/src/common/core-domain/computers/IndicateurDeuxComputer.ts +++ b/packages/app/src/common/core-domain/computers/IndicateurDeuxComputer.ts @@ -33,7 +33,15 @@ export class IndicateurDeuxComputer extends AbstractGroupComputer= 10 && category.womenCount >= 10 && category.men && category.women)) { + if ( + !category || + !( + category.menCount >= 10 && + category.womenCount >= 10 && + typeof category.men === "number" && + typeof category.women === "number" + ) + ) { return false; } diff --git a/packages/app/src/common/core-domain/dtos/CreateSimulationDTO.ts b/packages/app/src/common/core-domain/dtos/CreateSimulationDTO.ts index ebf54d9c9..6e909142e 100644 --- a/packages/app/src/common/core-domain/dtos/CreateSimulationDTO.ts +++ b/packages/app/src/common/core-domain/dtos/CreateSimulationDTO.ts @@ -37,10 +37,18 @@ const positiveInt = zodFr .int("La valeur doit être un entier") .nonnegative({ message: "Le nombre ne peut pas être inférieur à 0" }); -const positivePercentageFloat = zodFr - .number({ invalid_type_error: "Le champ est requis" }) - .nonnegative("Le pourcentage ne peut pas être inférieur à 0") - .lte(100, "Le pourcentage ne peut pas être supérieur à 100%"); +const positivePercentageOrEmptyString = zodFr + .literal("", { + errorMap: () => ({ + message: "Le champ est requis", + }), + }) + .or( + zodFr + .number({ invalid_type_error: "Le champ est requis" }) + .nonnegative("Le pourcentage ne peut pas être inférieur à 0") + .lte(100, "Le pourcentage ne peut pas être supérieur à 100%"), + ); const singleAgeRangeSchema = zodFr.object({ women: positiveIntOrEmptyString, @@ -109,8 +117,8 @@ const indicateur2or3 = zodFr.discriminatedUnion("calculable", [ pourcentages: zodFr.record( zodFr.nativeEnum(CSP.Enum), zodFr.object({ - women: positivePercentageFloat, - men: positivePercentageFloat, + women: positivePercentageOrEmptyString, + men: positivePercentageOrEmptyString, }), ), }),