diff --git a/src/components/FieldSiren.test.tsx b/src/components/FieldSiren.test.tsx index d63bf7382..550b99cc3 100644 --- a/src/components/FieldSiren.test.tsx +++ b/src/components/FieldSiren.test.tsx @@ -71,11 +71,11 @@ describe("isValidSiren", () => { }) test("returns an error message for an invalid siren", async () => { - expect(validator("005720784a")).toBe("ce champ n’est pas valide, renseignez un numéro SIREN de 9 chiffres") - expect(validator("a")).toBe("ce champ n’est pas valide, renseignez un numéro SIREN de 9 chiffres") + expect(validator("005720784a")).toBe("Ce champ n’est pas valide, renseignez un numéro SIREN de 9 chiffres.") + expect(validator("a")).toBe("Ce champ n’est pas valide, renseignez un numéro SIREN de 9 chiffres.") expect(validator("")).toBe("Ce champ ne peut être vide") await expect(validator("000000000")).resolves.toBe( - "Ce Siren n'existe pas, veuillez vérifier votre saisie, sinon veuillez contacter votre référent de l'égalité professionnelle", + "Ce Siren n'existe pas, veuillez vérifier votre saisie, sinon veuillez contacter votre référent de l'égalité professionnelle.", ) }) diff --git a/src/components/FieldSiren.tsx b/src/components/FieldSiren.tsx index 29dd260d3..806c4f383 100644 --- a/src/components/FieldSiren.tsx +++ b/src/components/FieldSiren.tsx @@ -3,7 +3,7 @@ import { css, jsx } from "@emotion/react" import { useField } from "react-final-form" import { Link } from "@chakra-ui/react" -import Input, { hasFieldError } from "./Input" +import Input from "./Input" import globalStyles from "../utils/globalStyles" import { isEmpty } from "../utils/object" import { composeValidators, required, simpleMemoize, ValidatorFunction } from "../utils/formHelpers" @@ -15,11 +15,13 @@ import { IconExternalLink } from "./ds/Icons" import React from "react" const nineDigits: ValidatorFunction = (value) => - value.length === 9 ? undefined : "ce champ n’est pas valide, renseignez un numéro SIREN de 9 chiffres" + value.length === 9 ? undefined : "Ce champ n’est pas valide, renseignez un numéro SIREN de 9 chiffres." const memoizedValidateSiren = simpleMemoize(async (siren: string) => await validateSiren(siren)) const NOT_ALLOWED_MESSAGE = "Vous n'êtes pas autorisé à déclarer pour ce SIREN." +const UNKNOWN_SIREN = + "Ce Siren n'existe pas, veuillez vérifier votre saisie, sinon veuillez contacter votre référent de l'égalité professionnelle." export const checkSiren = (updateSirenData: (data: EntrepriseType) => void) => async (siren: string) => { let result @@ -35,11 +37,13 @@ export const checkSiren = (updateSirenData: (data: EntrepriseType) => void) => a await ownersForSiren(siren) } catch (error) { console.error(error) + updateSirenData({}) return NOT_ALLOWED_MESSAGE } if (isEmpty(result?.jsonBody)) { - return "Ce Siren n'existe pas, veuillez vérifier votre saisie, sinon veuillez contacter votre référent de l'égalité professionnelle" + updateSirenData({}) + return UNKNOWN_SIREN } updateSirenData(result.jsonBody) @@ -66,8 +70,17 @@ function FieldSiren({ const field = useField(name, { validate: validator ? validator : sirenValidator(updateSirenData), }) + const { meta } = field + const { email } = useUser() - const error = hasFieldError(field.meta) + + // For required and 9digits validators, we want to display errors onBlur or onSubmit. + // But for sirenValidator, we want to display errors as soon as the API answers us. + const error = + (meta?.error && meta?.submitFailed) || + (meta?.error && meta?.touched) || + meta?.error === NOT_ALLOWED_MESSAGE || + meta?.error === UNKNOWN_SIREN return (
diff --git a/src/containers/Simulateur.tsx b/src/containers/Simulateur.tsx index 8ad4f90ad..f5ff1aca0 100644 --- a/src/containers/Simulateur.tsx +++ b/src/containers/Simulateur.tsx @@ -29,6 +29,7 @@ import InformationsDeclarant from "../views/InformationsDeclarant" import InformationsSimulation from "../views/InformationsSimulation" import Recapitulatif from "../views/Recapitulatif" import AskEmail from "../views/AskEmail" +import { sirenIsFree } from "../utils/siren" interface TokenInfo { email: string @@ -98,14 +99,18 @@ function Simulateur({ code, state, dispatch }: Props) { const simuData = indicatorsData?.jsonBody?.data - const siren = simuData?.informationsEntreprise?.siren + const siren = + simuData?.informationsEntreprise?.formValidated === "Valid" ? simuData?.informationsEntreprise?.siren : null + + // a free siren is a siren that has no owners already bound to it. + const freeSiren = await sirenIsFree(siren) if (siren) { if (!token) { // On ne peut pas voir une simulation avec un SIREN rempli et qu'on n'est pas authentifié. // Renvoi sur le formulaire d'email (cf. plus bas). setErrorMessage("Veuillez renseigner votre email pour accéder à cette simulation-déclaration.") - } else if (!isUserGrantedForSiren(siren)) { + } else if (!isUserGrantedForSiren(siren) && !freeSiren) { // On ne peut pas voir une simulation avec un SIREN rempli, si on est authentifiée et qu'on n'a pas les droits. setErrorMessage( "Vous n'êtes pas autorisé à accéder à cette simulation-déclaration, veuillez contacter votre référent de l'égalité professionnelle.", diff --git a/src/utils/api.js b/src/utils/api.js index 69a703ee6..2f8468941 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -17,6 +17,7 @@ class ApiError extends Error { } this.response = response this.jsonBody = jsonBody + this.name = "ApiError" } } @@ -30,7 +31,7 @@ function checkStatusAndParseJson(response) { return jsonPromise.then((jsonBody) => ({ response, jsonBody })) } else { return jsonPromise.then((jsonBody) => { - const apiError = new ApiError(response, jsonBody) + const apiError = new ApiError(response, jsonBody, "Erreur dans l'API") return Promise.reject.bind(Promise)(apiError) }) } @@ -54,8 +55,6 @@ function fetchResource(method, pathname, body) { origin = "http://127.0.0.1:2626" } - console.log("process.env.API_URL", process.env.REACT_APP_EGAPRO_API_URL) - if (process.env.REACT_APP_EGAPRO_API_URL) origin = process.env.REACT_APP_EGAPRO_API_URL return fetch(origin + pathname, requestObj).then(checkStatusAndParseJson) diff --git a/src/utils/siren.ts b/src/utils/siren.ts new file mode 100644 index 000000000..7e45d3e7f --- /dev/null +++ b/src/utils/siren.ts @@ -0,0 +1,20 @@ +import { ownersForSiren } from "./api" + +/** + * A SIREN is free if it has no owners already bound to it. + */ +export async function sirenIsFree(siren: string) { + let isFree = true + + try { + const { jsonBody } = await ownersForSiren(siren) + console.log("jsonBody", jsonBody) + isFree = jsonBody?.owners.length === 0 + } catch (ignore) { + // the API is designed to return an error if the user is not granted for the siren. This is what we want to ensure. + isFree = false + } + console.log("isFree", siren, isFree) + + return isFree +}