diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6891a018b..fde9d6897 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,13 +34,13 @@ jobs: yarn setup-python - name: Up for tests API - run: docker-compose up --build -d api db test_db + run: docker compose up --build -d api db test_db - name: Check types run: yarn check-all - name: Down for tests API - run: docker-compose down + run: docker compose down # TODO reenable. Next13 is not ready yet for proper testing # + using a mix between pageDir and appDir make tests harder to dev diff --git a/packages/app/src/api/core-domain/repo/IDeclarationRepo.ts b/packages/app/src/api/core-domain/repo/IDeclarationRepo.ts index 3ce96a99b..1fe40e5c4 100644 --- a/packages/app/src/api/core-domain/repo/IDeclarationRepo.ts +++ b/packages/app/src/api/core-domain/repo/IDeclarationRepo.ts @@ -1,3 +1,4 @@ +import { type DeclarationRaw } from "@api/core-domain/infra/db/DeclarationRaw"; import { type Declaration, type DeclarationPK } from "@common/core-domain/domain/Declaration"; import { type DeclarationOpmc } from "@common/core-domain/domain/DeclarationOpmc"; import { type Siren } from "@common/core-domain/domain/valueObjects/Siren"; @@ -6,6 +7,7 @@ import { type Repo } from "@common/shared-domain"; export interface IDeclarationRepo extends Repo { count(): Promise; getAllBySiren(siren: Siren): Promise; + getAllSirenAndYear(): Promise>>; getOneDeclarationOpmc(id: DeclarationPK): Promise; limit(limit?: number): this; /** @deprecated - use saveWithIndex */ diff --git a/packages/app/src/api/core-domain/repo/impl/PostgresDeclarationRepo.ts b/packages/app/src/api/core-domain/repo/impl/PostgresDeclarationRepo.ts index c07d812e7..f82169e68 100644 --- a/packages/app/src/api/core-domain/repo/impl/PostgresDeclarationRepo.ts +++ b/packages/app/src/api/core-domain/repo/impl/PostgresDeclarationRepo.ts @@ -99,6 +99,12 @@ export class PostgresDeclarationRepo implements IDeclarationRepo { return raws.map(declarationMap.toDomain); } + + public async getAllSirenAndYear(): Promise>> { + const raws = await this.sql`select * from ${this.table} where data notnull ${this.postgresLimit}`; + + return raws; //.map(declarationMap.toDomain); + } public async getOne([siren, year]: DeclarationPK): Promise { try { const [raw] = await this.sql`select * from ${ diff --git a/packages/app/src/api/core-domain/useCases/referent/GetAllDeclarations.ts b/packages/app/src/api/core-domain/useCases/referent/GetAllDeclarations.ts new file mode 100644 index 000000000..4b18aad8c --- /dev/null +++ b/packages/app/src/api/core-domain/useCases/referent/GetAllDeclarations.ts @@ -0,0 +1,19 @@ +import { type DeclarationRaw } from "@api/core-domain/infra/db/DeclarationRaw"; +import { type IDeclarationRepo } from "@api/core-domain/repo/IDeclarationRepo"; +import { AppError, type UseCase } from "@common/shared-domain"; + +export class GetAllDeclarations implements UseCase>> { + constructor(private readonly declarationRepo: IDeclarationRepo) {} + + public async execute(): Promise>> { + try { + return await this.declarationRepo.getAllSirenAndYear(); + + // return declarations.map(declarationMap.toDTO).filter(d => d) as DeclarationDTO[]; + } catch (error: unknown) { + throw new GetAllDeclarationsError("Cannot get all declarations", error as Error); + } + } +} + +export class GetAllDeclarationsError extends AppError {} diff --git a/packages/app/src/app/(default)/aide-simulation/page.tsx b/packages/app/src/app/(default)/aide-index/page.tsx similarity index 100% rename from packages/app/src/app/(default)/aide-simulation/page.tsx rename to packages/app/src/app/(default)/aide-index/page.tsx diff --git a/packages/app/src/app/(default)/declaration-accessibilite/page.tsx b/packages/app/src/app/(default)/declaration-accessibilite/page.tsx index ae9ddee0a..58aab9554 100644 --- a/packages/app/src/app/(default)/declaration-accessibilite/page.tsx +++ b/packages/app/src/app/(default)/declaration-accessibilite/page.tsx @@ -27,7 +27,7 @@ const AccessibilityStatement = () => { )

Etat de conformité

-

Egapro est non conforme avec le RGAA. Le site n’a encore pas été audité.

+

Egapro est partiellement conforme.

Un audit{" "} ( - <> - { - e.preventDefault(); - signIn("moncomptepro", { redirect: false }); - }} - /> - - Consulter l'aide MonComptePro - - + { + e.preventDefault(); + signIn("moncomptepro", { redirect: false }); + }} + /> ); diff --git a/packages/app/src/app/(default)/login/page.tsx b/packages/app/src/app/(default)/login/page.tsx index 68da6d0a0..fcea6cb3b 100644 --- a/packages/app/src/app/(default)/login/page.tsx +++ b/packages/app/src/app/(default)/login/page.tsx @@ -97,9 +97,21 @@ const LoginPage = async ({ searchParams }: NextServerPageProps

- Si vous rencontrez des difficultés pour vous connecter, vous devez contacter le support{" "} + Si vous utilisez une protection contre les spams (ex. MailInBlack), vous devez contacter votre + service informatique pour qu'il autorise les mails en provenance de MonComptePro. +

+
+

+ Pour tout problème lié à MonComptePro, vous devez contacter le support dédié à cette adresse email{" "} - MonComptePro + contact@moncomptepro.beta.gouv.fr + +

+
+

+ Pour consulter l'aide MonComptePro,{" "} + + cliquez ici

diff --git a/packages/app/src/app/(default)/messages.tsx b/packages/app/src/app/(default)/messages.tsx index 8186fb631..de522caee 100644 --- a/packages/app/src/app/(default)/messages.tsx +++ b/packages/app/src/app/(default)/messages.tsx @@ -8,4 +8,4 @@ export const MANDATORY_FAVORABLE_POPULATION = "La population envers laquelle l' export const NOT_HIGHER_THAN_N_RESULT = (n: number) => `Le résultat ne peut pas être supérieur à ${n}`; export const NOT_ALL_EMPTY_CATEGORIES = "Au moins une catégorie doit avoir un écart renseigné"; export const MANDATORY_SIREN = "Le Siren est requis"; -export const INVALID_SIREN = "Le Siren est composé de 9 chiffres sans espace"; +export const INVALID_SIREN = "Le Siren n'est pas valide"; diff --git a/packages/app/src/app/(default)/mon-espace/mes-declarations/IndexList.tsx b/packages/app/src/app/(default)/mon-espace/mes-declarations/IndexList.tsx index 1e94cda24..e12b299aa 100644 --- a/packages/app/src/app/(default)/mon-espace/mes-declarations/IndexList.tsx +++ b/packages/app/src/app/(default)/mon-espace/mes-declarations/IndexList.tsx @@ -91,7 +91,11 @@ const formatTableData = (declarations: DeclarationDTO[], declarationOpmcList: De : capitalize(declaration.entreprise?.type), declaration.entreprise?.tranche ? CompanyWorkforceRange.Label[declaration.entreprise.tranche] : undefined, formatIsoToFr(declaration["declaration-existante"].date || ""), - declaration["resultat-global"]?.index || NC, + typeof declaration["resultat-global"]?.index === "number" ? ( + declaration["resultat-global"]?.index + ) : ( + NC + ), formatDeclarationOpmcStatus( getDeclarationOpmcStatus( declarationOpmcList.find(declarationOpmc => declarationOpmc.commencer?.annéeIndicateurs === rowYear), diff --git a/packages/app/src/app/(default)/script/actions.ts b/packages/app/src/app/(default)/script/actions.ts new file mode 100644 index 000000000..1e126ff05 --- /dev/null +++ b/packages/app/src/app/(default)/script/actions.ts @@ -0,0 +1,8 @@ +import { declarationRepo } from "@api/core-domain/repo"; +import { GetAllDeclarations } from "@api/core-domain/useCases/referent/GetAllDeclarations"; + +export async function getAllDeclarations() { + // handle default errors + const useCase = new GetAllDeclarations(declarationRepo); + return await useCase.execute(); +} diff --git a/packages/app/src/app/(default)/script/clean-invalids-siren/page.tsx b/packages/app/src/app/(default)/script/clean-invalids-siren/page.tsx new file mode 100644 index 000000000..8e3ce8147 --- /dev/null +++ b/packages/app/src/app/(default)/script/clean-invalids-siren/page.tsx @@ -0,0 +1,92 @@ +import { getAllDeclarations } from "../actions"; + +function validateSIREN(siren: string): boolean { + // Vérifie que la chaîne est composée de 9 chiffres + if (!/^\d{9}$/.test(siren)) { + return false; + } + + // Applique l'algorithme de Luhn + let sum = 0; + for (let i = 0; i < 9; i++) { + let num = parseInt(siren.charAt(i), 10); + + // Multiplie les chiffres en position paire par 2 + if (i % 2 === 1) { + num *= 2; + // Si le résultat est supérieur à 9, soustrait 9 + if (num > 9) { + num -= 9; + } + } + + sum += num; + } + + // Le numéro est valide si la somme est un multiple de 10 + return sum % 10 === 0; +} + +const CleanInvalidsSirenPage = async () => { + try { + const declarations = await getAllDeclarations(); + const invalidDeclarations = []; + for (const declaration of declarations) { + if (!declaration.data?.entreprise.siren) { + //console.log("No siren", declaration.siren); + } + if (!validateSIREN(declaration.data?.entreprise.siren || "")) { + console.log("Invalid siren", declaration.siren); + invalidDeclarations.push({ ...declaration, invalidSiren: declaration.siren }); + break; + } + if (!declaration.data?.entreprise.ues?.entreprises) { + //console.log("No ues", declaration.siren); + } + for (const entreprise of declaration.data?.entreprise.ues?.entreprises || []) { + if (!validateSIREN(entreprise.siren)) { + invalidDeclarations.push({ ...declaration, invalidSiren: entreprise.siren }); + console.log("Invalid ues siren", entreprise.siren); + break; + } + } + } + // const invalids = declarations + // .filter(declaration => new Siren(declaration.data?.entreprise.siren || "")) + // .filter(declaration => { + // if (!declaration.data?.entreprise.ues?.entreprises) { + // return true; + // } + // + // return declaration.data?.entreprise.ues?.entreprises.reduce((hasValidSirens, entreprise) => { + // if (!hasValidSirens) return false; + // try { + // new Siren(entreprise.siren); + // return true; + // } catch (e) { + // console.log("Invalid siren", entreprise.siren, e); + // return false; + // } + // }, true); + // }); + + return ( +
+

nombre de sirens invalides: {invalidDeclarations.length}

+
    + {invalidDeclarations.map((declaration, index) => ( +
  • + declaration siren:{declaration.siren}, declaration année: {declaration.year} invalid ues siren:{" "} + {declaration.invalidSiren} +
  • + ))} +
+
+ ); + } catch (e) { + console.log(e); + return

Error

; + } +}; + +export default CleanInvalidsSirenPage; diff --git a/packages/app/src/app/Footer.tsx b/packages/app/src/app/Footer.tsx index e8e54ff46..dd9506bec 100644 --- a/packages/app/src/app/Footer.tsx +++ b/packages/app/src/app/Footer.tsx @@ -12,9 +12,9 @@ const githubLink = { } satisfies DsfrFooterProps.LinkList.Link; const helpLink = { - text: "Consulter l'aide pour le calcul de l'index", + text: "Consulter l'aide concernant l'index", linkProps: { - href: "/aide-simulation", + href: "/aide-index", target: "_blank", }, } satisfies DsfrFooterProps.LinkList.Link; diff --git a/packages/app/src/common/core-domain/domain/valueObjects/ownership_request/ErrorDetail.ts b/packages/app/src/common/core-domain/domain/valueObjects/ownership_request/ErrorDetail.ts index eb7f88b49..7c300bfaf 100644 --- a/packages/app/src/common/core-domain/domain/valueObjects/ownership_request/ErrorDetail.ts +++ b/packages/app/src/common/core-domain/domain/valueObjects/ownership_request/ErrorDetail.ts @@ -12,7 +12,7 @@ export const errorDetailLabel: Record<(typeof errorDetailCodes)[number], string> EMAIL_DELIVERY_KO: "L'envoi du mail a échoué", ALREADY_PROCESSED: "La demande a déjà été traitée", INVALID_EMAIL: "L'email est invalide", - INVALID_SIREN: "Le Siren est composé de 9 chiffres sans espace", + INVALID_SIREN: "Le Siren n'est pas valide", NOT_FOUND_SIREN: "Le SIREN n'existe pas", };