diff --git a/server/src/common/apis/apiAlternance.ts b/server/src/common/apis/apiAlternance.ts index 8e249c0e7..f99ab6278 100644 --- a/server/src/common/apis/apiAlternance.ts +++ b/server/src/common/apis/apiAlternance.ts @@ -3,6 +3,6 @@ import { ApiClient } from "api-alternance-sdk"; import config from "@/config"; export const apiAlternanceClient = new ApiClient({ - endpoint: "https://api-recette.apprentissage.beta.gouv.fr/api", + endpoint: "https://api.apprentissage.beta.gouv.fr/api", key: config.apiAlternance.key, }); diff --git a/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap b/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap index 135041f4b..9b94fc168 100644 --- a/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap +++ b/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap @@ -11497,6 +11497,14 @@ exports[`validation-schema should create validation schema for organismes: organ "bsonType": "bool", "description": "Le siret est fermé", }, + "fiabilisation_api_statut": { + "bsonType": "string", + "description": "Statut de fiabilisation venant de l'API de l'organisme", + "enum": [ + "FIABLE", + "NON_FIABLE", + ], + }, "fiabilisation_statut": { "bsonType": "string", "description": "Statut de fiabilisation de l'organisme", diff --git a/server/src/jobs/fiabilisation/uai-siret/update.ts b/server/src/jobs/fiabilisation/uai-siret/update.ts index 2202b835a..72487b0c4 100644 --- a/server/src/jobs/fiabilisation/uai-siret/update.ts +++ b/server/src/jobs/fiabilisation/uai-siret/update.ts @@ -1,12 +1,16 @@ import { PromisePool } from "@supercharge/promise-pool"; +import { AnyBulkWriteOperation } from "mongodb"; import { + IOrganisme, STATUT_CREATION_ORGANISME, + STATUT_FIABILISATION_API_ORGANISME, STATUT_FIABILISATION_COUPLES_UAI_SIRET, STATUT_FIABILISATION_ORGANISME, STATUT_PRESENCE_REFERENTIEL, } from "shared"; import { createOrganisme, findOrganismeById } from "@/common/actions/organismes/organismes.actions"; +import { apiAlternanceClient } from "@/common/apis/apiAlternance"; import logger from "@/common/logger"; import { fiabilisationUaiSiretDb, organismesDb, organismesReferentielDb } from "@/common/model/collections"; @@ -139,3 +143,56 @@ export const updateOrganismesFiablesFermes = async () => { } }); }; + +export const updateOrganismesFiabilisationApiUaiSiret = async () => { + const organismsToUpdate = await organismesDb().find({}).toArray(); + + const bulkOperations: AnyBulkWriteOperation[] = []; + + for (const organism of organismsToUpdate) { + const { _id, siret, uai } = organism; + + if (siret && uai) { + try { + const apiData = await apiAlternanceClient.organisme.recherche({ siret, uai }); + + if (apiData?.resultat?.status) { + const { ouvert, declaration_catalogue, validation_uai } = apiData.resultat.status; + const fiabilisationStatus = + ouvert && declaration_catalogue && validation_uai + ? STATUT_FIABILISATION_API_ORGANISME.FIABLE + : STATUT_FIABILISATION_API_ORGANISME.NON_FIABLE; + + bulkOperations.push({ + updateOne: { + filter: { _id }, + update: { $set: { fiabilisation_api_statut: fiabilisationStatus } }, + }, + }); + } else { + logger.warn(`Données API non valides pour le SIRET : ${siret}, UAI : ${uai}`); + } + } catch (error) { + console.error(`Échec de l'appel API pour le SIRET : ${siret}, UAI : ${uai}`, error); + } + } else { + bulkOperations.push({ + updateOne: { + filter: { _id }, + update: { $set: { fiabilisation_api_statut: STATUT_FIABILISATION_API_ORGANISME.NON_FIABLE } }, + }, + }); + + logger.warn(`SIRET ou UAI manquant pour l'organisme avec l'ID : ${_id}`); + } + } + + if (bulkOperations.length > 0) { + const bulkResult = await organismesDb().bulkWrite(bulkOperations); + logger.info(`Résultat de la mise à jour de la fiabilisation de l'API :`, bulkResult); + } else { + logger.info("Aucun organisme à mettre à jour."); + } + + return { status: "Mise à jour terminée", total: organismsToUpdate.length, updated: bulkOperations.length }; +}; diff --git a/server/src/jobs/jobs.ts b/server/src/jobs/jobs.ts index bb9e561f2..5af1639f9 100644 --- a/server/src/jobs/jobs.ts +++ b/server/src/jobs/jobs.ts @@ -19,7 +19,10 @@ import { hydrateRaisonSocialeEtEnseigneOFAInconnus } from "./fiabilisation/ofa-i import { getStats } from "./fiabilisation/stats"; import { buildFiabilisationUaiSiret } from "./fiabilisation/uai-siret/build"; import { resetOrganismesFiabilisationStatut } from "./fiabilisation/uai-siret/build.utils"; -import { updateOrganismesFiabilisationUaiSiret } from "./fiabilisation/uai-siret/update"; +import { + updateOrganismesFiabilisationApiUaiSiret, + updateOrganismesFiabilisationUaiSiret, +} from "./fiabilisation/uai-siret/update"; import { hydrateVoeuxEffectifsRelations } from "./hydrate/affelnet/hydrate-voeux-effectifs"; import { hydrateDeca } from "./hydrate/deca/hydrate-deca"; import { hydrateDecaRaw } from "./hydrate/deca/hydrate-deca-raw"; @@ -398,6 +401,9 @@ export async function setupJobProcessor() { const buildResults = await buildFiabilisationUaiSiret(); const updateResults = await updateOrganismesFiabilisationUaiSiret(); + // Mise à jour des données de fiabilisation des couples UAI - SIRET à partir de l'API apprentissage + await updateOrganismesFiabilisationApiUaiSiret(); + return { buildResults, updateResults }; }, }, diff --git a/shared/constants/fiabilisation.ts b/shared/constants/fiabilisation.ts index a6b8fca41..83c593408 100644 --- a/shared/constants/fiabilisation.ts +++ b/shared/constants/fiabilisation.ts @@ -9,6 +9,11 @@ export const STATUT_FIABILISATION_ORGANISME = { INCONNU_INSCRIPTION: "INCONNU_INSCRIPTION" as const, }; +export const STATUT_FIABILISATION_API_ORGANISME = { + FIABLE: "FIABLE" as const, + NON_FIABLE: "NON_FIABLE" as const, +}; + export const STATUT_FIABILISATION_COUPLES_UAI_SIRET = { FIABLE: "FIABLE" as const, A_FIABILISER: "A_FIABILISER" as const, diff --git a/shared/models/data/organismes.model.ts b/shared/models/data/organismes.model.ts index 4769521f5..4121b1b84 100644 --- a/shared/models/data/organismes.model.ts +++ b/shared/models/data/organismes.model.ts @@ -11,6 +11,7 @@ import { NATURE_ORGANISME_DE_FORMATION, SIRET_REGEX, STATUT_CREATION_ORGANISME, + STATUT_FIABILISATION_API_ORGANISME, STATUT_FIABILISATION_ORGANISME, STATUT_PRESENCE_REFERENTIEL, TETE_DE_RESEAUX_BY_ID, @@ -211,6 +212,9 @@ const zOrganisme = z fiabilisation_statut: zodEnumFromObjValues(STATUT_FIABILISATION_ORGANISME) .describe("Statut de fiabilisation de l'organisme") .optional(), + fiabilisation_api_statut: zodEnumFromObjValues(STATUT_FIABILISATION_API_ORGANISME) + .describe("Statut de fiabilisation venant de l'API de l'organisme") + .optional(), mode_de_transmission: z.enum(["API", "MANUEL"]).describe("Mode de transmission des effectifs").optional(), mode_de_transmission_configuration_date: z .date({ @@ -259,6 +263,7 @@ export type IOrganismeOptional = Pick< | "erps" | "relatedFormations" | "fiabilisation_statut" + | "fiabilisation_api_statut" | "ferme" | "qualiopi" | "prepa_apprentissage" @@ -273,6 +278,7 @@ export function defaultValuesOrganisme(): Pick< | "erps" | "relatedFormations" | "fiabilisation_statut" + | "fiabilisation_api_statut" | "ferme" | "qualiopi" | "prepa_apprentissage"