Skip to content

Commit

Permalink
fix: bug-siren (#779)
Browse files Browse the repository at this point in the history
* fix: error structure for api error

* fix: show error ASA Api returns an error + return an empty object when the siren is changed.

* feat: instant error if siren is unknown

* fix: a user can see a siren if it is free

* feat: take care of siren only if form is validated
  • Loading branch information
pom421 authored Jan 4, 2022
1 parent 99f2d78 commit 7c06fee
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 12 deletions.
6 changes: 3 additions & 3 deletions src/components/FieldSiren.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
)
})

Expand Down
21 changes: 17 additions & 4 deletions src/components/FieldSiren.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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 (
<div css={[customStyles, styles.formField]}>
Expand Down
9 changes: 7 additions & 2 deletions src/containers/Simulateur.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.",
Expand Down
5 changes: 2 additions & 3 deletions src/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ApiError extends Error {
}
this.response = response
this.jsonBody = jsonBody
this.name = "ApiError"
}
}

Expand All @@ -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)
})
}
Expand All @@ -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)
Expand Down
20 changes: 20 additions & 0 deletions src/utils/siren.ts
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 7c06fee

Please sign in to comment.