diff --git a/server/src/common/actions/effectifs.actions.ts b/server/src/common/actions/effectifs.actions.ts
index 603d54221..4929b0649 100644
--- a/server/src/common/actions/effectifs.actions.ts
+++ b/server/src/common/actions/effectifs.actions.ts
@@ -1,6 +1,7 @@
import Boom from "boom";
import { cloneDeep, isObject, merge, mergeWith, reduce, set, uniqBy } from "lodash-es";
import { ObjectId } from "mongodb";
+import { IEffectifCreationSchema } from "shared/models/apis/effectifsCreationSchema";
import { IEffectif } from "shared/models/data/effectifs.model";
import { IOrganisme } from "shared/models/data/organismes.model";
import { cyrb53Hash, normalize } from "shared/utils/crypt";
@@ -10,7 +11,6 @@ import { effectifsDb } from "@/common/model/collections";
import { defaultValuesEffectif } from "@/common/model/effectifs.model/effectifs.model";
import { stripEmptyFields } from "../utils/miscUtils";
-import { IEffectifCreationSchema } from "../validation/effectifsCreationSchema";
import { legacySchema } from "./effectif.legacy_schema";
import { getOrganismeById } from "./organismes/organismes.actions";
diff --git a/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap b/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap
index ed2248ccc..50134ff78 100644
--- a/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap
+++ b/server/src/common/mongodb/__snapshots__/validationSchema.test.ts.snap
@@ -7219,6 +7219,2202 @@ exports[`validation-schema should create validation schema for usersMigration: u
"bsonType": "date",
"description": "Date de création du compte",
},
+ "draft_effectif_form": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "annee_scolaire": {
+ "bsonType": "string",
+ "description": "Période scolaire",
+ },
+ "apprenant": {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "adresse": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "academie": {
+ "bsonType": "string",
+ "enum": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "22",
+ "23",
+ "24",
+ "25",
+ "27",
+ "28",
+ "31",
+ "32",
+ "33",
+ "43",
+ "44",
+ "70",
+ "77",
+ "78",
+ ],
+ },
+ "bassinEmploi": {
+ "bsonType": "string",
+ "description": "Code Bassin d'emploi",
+ },
+ "code_insee": {
+ "bsonType": "string",
+ "description": "Le code insee doit contenir 5 caractères",
+ "pattern": "^[0-9]{1}[0-9A-Z]{1}[0-9]{3}$",
+ },
+ "code_postal": {
+ "bsonType": "string",
+ "description": "Le code postal doit contenir 5 caractères",
+ "pattern": "^[0-9]{5}$",
+ },
+ "commune": {
+ "bsonType": "string",
+ "description": "Commune",
+ "maxLength": 80,
+ },
+ "complement": {
+ "bsonType": "string",
+ "description": "Complément d'adresse",
+ },
+ "complete": {
+ "bsonType": "string",
+ "description": "Adresse complète",
+ },
+ "departement": {
+ "bsonType": "string",
+ "enum": [
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "21",
+ "22",
+ "23",
+ "24",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "30",
+ "31",
+ "32",
+ "33",
+ "34",
+ "35",
+ "36",
+ "37",
+ "38",
+ "39",
+ "40",
+ "41",
+ "42",
+ "43",
+ "44",
+ "45",
+ "46",
+ "47",
+ "48",
+ "49",
+ "50",
+ "51",
+ "52",
+ "53",
+ "54",
+ "55",
+ "56",
+ "57",
+ "58",
+ "59",
+ "60",
+ "61",
+ "62",
+ "63",
+ "64",
+ "65",
+ "66",
+ "67",
+ "68",
+ "69",
+ "70",
+ "71",
+ "72",
+ "73",
+ "74",
+ "75",
+ "76",
+ "77",
+ "78",
+ "79",
+ "80",
+ "81",
+ "82",
+ "83",
+ "84",
+ "85",
+ "86",
+ "87",
+ "88",
+ "89",
+ "90",
+ "91",
+ "92",
+ "93",
+ "94",
+ "95",
+ "971",
+ "972",
+ "973",
+ "974",
+ "975",
+ "976",
+ "977",
+ "978",
+ "984",
+ "986",
+ "987",
+ "988",
+ "989",
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "09",
+ "2A",
+ "2B",
+ ],
+ },
+ "numero": {
+ "bsonType": "int",
+ "description": "N° de la voie",
+ },
+ "pays": {
+ "bsonType": "string",
+ "description": "Pays",
+ "enum": [
+ "AF",
+ "ZA",
+ "AL",
+ "DZ",
+ "DE",
+ "AD",
+ "AO",
+ "AG",
+ "SA",
+ "AR",
+ "AM",
+ "AU",
+ "AT",
+ "AZ",
+ "BS",
+ "BH",
+ "BD",
+ "BB",
+ "BE",
+ "BZ",
+ "BJ",
+ "BT",
+ "BY",
+ "MM",
+ "BO",
+ "BQ",
+ "BA",
+ "BW",
+ "BR",
+ "BN",
+ "BG",
+ "BF",
+ "BI",
+ "KH",
+ "CM",
+ "CA",
+ "CV",
+ "CF",
+ "CL",
+ "CN",
+ "CY",
+ "CO",
+ "KM",
+ "CG",
+ "CD",
+ "KR",
+ "KP",
+ "CR",
+ "CI",
+ "HR",
+ "CU",
+ "CW",
+ "DK",
+ "DJ",
+ "DO",
+ "DM",
+ "EG",
+ "SV",
+ "AE",
+ "EC",
+ "ER",
+ "ES",
+ "EE",
+ "SZ",
+ "US",
+ "ET",
+ "MK",
+ "FJ",
+ "FI",
+ "FR",
+ "GA",
+ "GM",
+ "GE",
+ "GH",
+ "GR",
+ "GD",
+ "GT",
+ "GN",
+ "GQ",
+ "GW",
+ "GY",
+ "HT",
+ "HN",
+ "HU",
+ "IN",
+ "ID",
+ "IR",
+ "IQ",
+ "IE",
+ "IS",
+ "IL",
+ "IT",
+ "JM",
+ "JP",
+ "JO",
+ "KZ",
+ "KE",
+ "KG",
+ "KI",
+ "XK",
+ "KW",
+ "LA",
+ "LS",
+ "LV",
+ "LB",
+ "LR",
+ "LY",
+ "LI",
+ "LT",
+ "LU",
+ "MG",
+ "MY",
+ "MW",
+ "MV",
+ "ML",
+ "MT",
+ "MA",
+ "MH",
+ "MU",
+ "MR",
+ "MX",
+ "FM",
+ "MD",
+ "MC",
+ "MN",
+ "ME",
+ "MZ",
+ "NA",
+ "NR",
+ "NP",
+ "NI",
+ "NE",
+ "NG",
+ "NO",
+ "NZ",
+ "OM",
+ "UG",
+ "UZ",
+ "PK",
+ "PW",
+ "PS",
+ "PA",
+ "PG",
+ "PY",
+ "NL",
+ "PE",
+ "PH",
+ "PL",
+ "PT",
+ "QA",
+ "RO",
+ "GB",
+ "RU",
+ "RW",
+ "KN",
+ "SM",
+ "SX",
+ "VC",
+ "LC",
+ "SB",
+ "WS",
+ "ST",
+ "SN",
+ "RS",
+ "SC",
+ "SL",
+ "SG",
+ "SK",
+ "SI",
+ "SO",
+ "SD",
+ "SS",
+ "LK",
+ "SE",
+ "CH",
+ "SR",
+ "SY",
+ "TJ",
+ "TZ",
+ "TD",
+ "CZ",
+ "TH",
+ "TL",
+ "TG",
+ "TO",
+ "TT",
+ "TN",
+ "TM",
+ "TR",
+ "TV",
+ "UA",
+ "UY",
+ "VU",
+ "VA",
+ "VE",
+ "VN",
+ "YE",
+ "ZM",
+ "ZW",
+ ],
+ },
+ "region": {
+ "bsonType": "string",
+ "enum": [
+ "11",
+ "24",
+ "27",
+ "28",
+ "32",
+ "44",
+ "52",
+ "53",
+ "75",
+ "76",
+ "84",
+ "93",
+ "94",
+ "977",
+ "978",
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "00",
+ ],
+ },
+ "repetition_voie": {
+ "bsonType": "string",
+ "description": "Indice de répétition du numéro de voie",
+ "enum": [
+ "B",
+ "T",
+ "Q",
+ "C",
+ ],
+ },
+ "voie": {
+ "bsonType": "string",
+ "description": "Nom de voie",
+ },
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "affelnet": {
+ "anyOf": [
+ {
+ "bsonType": "array",
+ "items": {
+ "bsonType": "string",
+ "description": "voeux affelnet de l'apprenant",
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "code_postal_de_naissance": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Le code postal doit contenir 5 caractères.
+Pour les jeunes résidents à l’étranger, il conviendra de mettre « 99 » suivi du numéro de pays.
+*Exemple : pour l’Allemagne le code pays est 109, il conviendra donc de saisir : « 99109 »*",
+ "pattern": "^[0-9]{5}$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "courriel": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "date_de_naissance": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date de naissance de l'apprenant",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_rqth": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date de la reconnaissance travailleur handicapé",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "dernier_diplome": {
+ "anyOf": [
+ {
+ "bsonType": "number",
+ "description": "Dernier diplôme obtenu",
+ "enum": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 99,
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "dernier_organisme_uai": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Numéro UAI de l’établissement fréquenté l’année dernière (N-1), si déjà en apprentissage, mettre l’UAI du site de formation
+ ou département.
+* Pour les apprentis en emploi l'année dernière, le numéro UAI n-1 à indiquer est le **995** qui signifie "Non concerné".
+
+* Si cette information n'est pas connue, le numéro UAI n-1 à indiquer est le **993** qui signifie "Inconnu" ",
+ "pattern": "^(0?[0-9][0-9]|0?2[AB]|0?9[012345]|97[1234678]|98[46789]|99[0135]|[0-9]{7}[a-zA-Z])$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "derniere_situation": {
+ "anyOf": [
+ {
+ "bsonType": "number",
+ "description": "Situation de l'apprenant N-1",
+ "enum": [
+ 1003,
+ 1005,
+ 1009,
+ 1013,
+ 1015,
+ 1017,
+ 1019,
+ 1021,
+ 1023,
+ 2001,
+ 2003,
+ 2005,
+ 2007,
+ 3001,
+ 3101,
+ 3003,
+ 3103,
+ 3009,
+ 3109,
+ 3011,
+ 3111,
+ 3031,
+ 3131,
+ 3032,
+ 3132,
+ 3033,
+ 3133,
+ 3117,
+ 3119,
+ 3021,
+ 3121,
+ 3023,
+ 3123,
+ 4001,
+ 4101,
+ 4003,
+ 4103,
+ 4005,
+ 4105,
+ 4007,
+ 4107,
+ 4009,
+ 4011,
+ 4111,
+ 4013,
+ 4113,
+ 4015,
+ 4115,
+ 4017,
+ 4117,
+ 4019,
+ 4119,
+ 4021,
+ 4121,
+ 4023,
+ 4123,
+ 4025,
+ 4125,
+ 4027,
+ 4127,
+ 5901,
+ 5903,
+ 5905,
+ 5907,
+ 5909,
+ 9900,
+ 9999,
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "has_nir": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "ine": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "inscription_sportif_haut_niveau": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "mineur": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "mineur_emancipe": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "nationalite": {
+ "anyOf": [
+ {
+ "bsonType": "number",
+ "description": "Apprenant étranger, non citoyen européen",
+ "enum": [
+ 1,
+ 2,
+ 3,
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "nom": {
+ "bsonType": "string",
+ "description": "Nom de l'apprenant",
+ "minLength": 1,
+ },
+ "organisme_gestionnaire": {
+ "bsonType": [
+ "number",
+ "null",
+ ],
+ },
+ "parcoursup": {
+ "anyOf": [
+ {
+ "bsonType": "array",
+ "items": {
+ "bsonType": "string",
+ "description": "voeux parcoursup de l'apprenant",
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "prenom": {
+ "bsonType": "string",
+ "description": "Prénom de l'apprenant",
+ "minLength": 1,
+ },
+ "regime_scolaire": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Régime scolaire (I : Interne, D : Demi-pensionnaire, E : Externe, IE : Interne externé)",
+ "enum": [
+ "I",
+ "D",
+ "E",
+ "IE",
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "representant_legal": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "adresse": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "academie": {
+ "bsonType": "string",
+ "enum": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "22",
+ "23",
+ "24",
+ "25",
+ "27",
+ "28",
+ "31",
+ "32",
+ "33",
+ "43",
+ "44",
+ "70",
+ "77",
+ "78",
+ ],
+ },
+ "bassinEmploi": {
+ "bsonType": "string",
+ "description": "Code Bassin d'emploi",
+ },
+ "code_insee": {
+ "bsonType": "string",
+ "description": "Le code insee doit contenir 5 caractères",
+ "pattern": "^[0-9]{1}[0-9A-Z]{1}[0-9]{3}$",
+ },
+ "code_postal": {
+ "bsonType": "string",
+ "description": "Le code postal doit contenir 5 caractères",
+ "pattern": "^[0-9]{5}$",
+ },
+ "commune": {
+ "bsonType": "string",
+ "description": "Commune",
+ "maxLength": 80,
+ },
+ "complement": {
+ "bsonType": "string",
+ "description": "Complément d'adresse",
+ },
+ "complete": {
+ "bsonType": "string",
+ "description": "Adresse complète",
+ },
+ "departement": {
+ "bsonType": "string",
+ "enum": [
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "21",
+ "22",
+ "23",
+ "24",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "30",
+ "31",
+ "32",
+ "33",
+ "34",
+ "35",
+ "36",
+ "37",
+ "38",
+ "39",
+ "40",
+ "41",
+ "42",
+ "43",
+ "44",
+ "45",
+ "46",
+ "47",
+ "48",
+ "49",
+ "50",
+ "51",
+ "52",
+ "53",
+ "54",
+ "55",
+ "56",
+ "57",
+ "58",
+ "59",
+ "60",
+ "61",
+ "62",
+ "63",
+ "64",
+ "65",
+ "66",
+ "67",
+ "68",
+ "69",
+ "70",
+ "71",
+ "72",
+ "73",
+ "74",
+ "75",
+ "76",
+ "77",
+ "78",
+ "79",
+ "80",
+ "81",
+ "82",
+ "83",
+ "84",
+ "85",
+ "86",
+ "87",
+ "88",
+ "89",
+ "90",
+ "91",
+ "92",
+ "93",
+ "94",
+ "95",
+ "971",
+ "972",
+ "973",
+ "974",
+ "975",
+ "976",
+ "977",
+ "978",
+ "984",
+ "986",
+ "987",
+ "988",
+ "989",
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "09",
+ "2A",
+ "2B",
+ ],
+ },
+ "numero": {
+ "bsonType": "int",
+ "description": "N° de la voie",
+ },
+ "pays": {
+ "bsonType": "string",
+ "description": "Pays",
+ "enum": [
+ "AF",
+ "ZA",
+ "AL",
+ "DZ",
+ "DE",
+ "AD",
+ "AO",
+ "AG",
+ "SA",
+ "AR",
+ "AM",
+ "AU",
+ "AT",
+ "AZ",
+ "BS",
+ "BH",
+ "BD",
+ "BB",
+ "BE",
+ "BZ",
+ "BJ",
+ "BT",
+ "BY",
+ "MM",
+ "BO",
+ "BQ",
+ "BA",
+ "BW",
+ "BR",
+ "BN",
+ "BG",
+ "BF",
+ "BI",
+ "KH",
+ "CM",
+ "CA",
+ "CV",
+ "CF",
+ "CL",
+ "CN",
+ "CY",
+ "CO",
+ "KM",
+ "CG",
+ "CD",
+ "KR",
+ "KP",
+ "CR",
+ "CI",
+ "HR",
+ "CU",
+ "CW",
+ "DK",
+ "DJ",
+ "DO",
+ "DM",
+ "EG",
+ "SV",
+ "AE",
+ "EC",
+ "ER",
+ "ES",
+ "EE",
+ "SZ",
+ "US",
+ "ET",
+ "MK",
+ "FJ",
+ "FI",
+ "FR",
+ "GA",
+ "GM",
+ "GE",
+ "GH",
+ "GR",
+ "GD",
+ "GT",
+ "GN",
+ "GQ",
+ "GW",
+ "GY",
+ "HT",
+ "HN",
+ "HU",
+ "IN",
+ "ID",
+ "IR",
+ "IQ",
+ "IE",
+ "IS",
+ "IL",
+ "IT",
+ "JM",
+ "JP",
+ "JO",
+ "KZ",
+ "KE",
+ "KG",
+ "KI",
+ "XK",
+ "KW",
+ "LA",
+ "LS",
+ "LV",
+ "LB",
+ "LR",
+ "LY",
+ "LI",
+ "LT",
+ "LU",
+ "MG",
+ "MY",
+ "MW",
+ "MV",
+ "ML",
+ "MT",
+ "MA",
+ "MH",
+ "MU",
+ "MR",
+ "MX",
+ "FM",
+ "MD",
+ "MC",
+ "MN",
+ "ME",
+ "MZ",
+ "NA",
+ "NR",
+ "NP",
+ "NI",
+ "NE",
+ "NG",
+ "NO",
+ "NZ",
+ "OM",
+ "UG",
+ "UZ",
+ "PK",
+ "PW",
+ "PS",
+ "PA",
+ "PG",
+ "PY",
+ "NL",
+ "PE",
+ "PH",
+ "PL",
+ "PT",
+ "QA",
+ "RO",
+ "GB",
+ "RU",
+ "RW",
+ "KN",
+ "SM",
+ "SX",
+ "VC",
+ "LC",
+ "SB",
+ "WS",
+ "ST",
+ "SN",
+ "RS",
+ "SC",
+ "SL",
+ "SG",
+ "SK",
+ "SI",
+ "SO",
+ "SD",
+ "SS",
+ "LK",
+ "SE",
+ "CH",
+ "SR",
+ "SY",
+ "TJ",
+ "TZ",
+ "TD",
+ "CZ",
+ "TH",
+ "TL",
+ "TG",
+ "TO",
+ "TT",
+ "TN",
+ "TM",
+ "TR",
+ "TV",
+ "UA",
+ "UY",
+ "VU",
+ "VA",
+ "VE",
+ "VN",
+ "YE",
+ "ZM",
+ "ZW",
+ ],
+ },
+ "region": {
+ "bsonType": "string",
+ "enum": [
+ "11",
+ "24",
+ "27",
+ "28",
+ "32",
+ "44",
+ "52",
+ "53",
+ "75",
+ "76",
+ "84",
+ "93",
+ "94",
+ "977",
+ "978",
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "00",
+ ],
+ },
+ "repetition_voie": {
+ "bsonType": "string",
+ "description": "Indice de répétition du numéro de voie",
+ "enum": [
+ "B",
+ "T",
+ "Q",
+ "C",
+ ],
+ },
+ "voie": {
+ "bsonType": "string",
+ "description": "Nom de voie",
+ },
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "courriel": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "meme_adresse": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "nom": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "pcs": {
+ "anyOf": [
+ {
+ "bsonType": "number",
+ "description": "Nomenclatures des professions et catégories socioprofessionnelles",
+ "enum": [
+ 10,
+ 21,
+ 22,
+ 23,
+ 31,
+ 33,
+ 34,
+ 37,
+ 38,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 61,
+ 66,
+ 69,
+ 71,
+ 72,
+ 73,
+ 76,
+ 81,
+ 82,
+ 99,
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "prenom": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "telephone": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Dans le cas d'un numéro français, il n'est pas
+ nécessaire de saisir le "0" car l'indicateur pays est
+ pré-renseigné.
+ Il doit contenir 9 chiffres après l'indicatif.",
+ "pattern": "^([+])?(\\d{7,12})$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "responsable_mail1": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "responsable_mail2": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "rqth": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "sexe": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Sexe de l'apprenant (M: Homme, F: Femme)",
+ "enum": [
+ "M",
+ "F",
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "situation_avant_contrat": {
+ "anyOf": [
+ {
+ "bsonType": "number",
+ "description": "Situation de l'apprenant avant le contrat",
+ "enum": [
+ 11,
+ 12,
+ 21,
+ 31,
+ 41,
+ 51,
+ 52,
+ 53,
+ 54,
+ 90,
+ 99,
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "telephone": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Téléphone de l'apprenant",
+ "pattern": "^([+])?(\\d{7,12})$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "type_cfa": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Type de CFA",
+ "enum": [
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "09",
+ "10",
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ },
+ },
+ "contrats": {
+ "bsonType": "array",
+ "items": {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "adresse": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "academie": {
+ "bsonType": "string",
+ "enum": [
+ "1",
+ "2",
+ "3",
+ "4",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "22",
+ "23",
+ "24",
+ "25",
+ "27",
+ "28",
+ "31",
+ "32",
+ "33",
+ "43",
+ "44",
+ "70",
+ "77",
+ "78",
+ ],
+ },
+ "bassinEmploi": {
+ "bsonType": "string",
+ "description": "Code Bassin d'emploi",
+ },
+ "code_insee": {
+ "bsonType": "string",
+ "description": "Le code insee doit contenir 5 caractères",
+ "pattern": "^[0-9]{1}[0-9A-Z]{1}[0-9]{3}$",
+ },
+ "code_postal": {
+ "bsonType": "string",
+ "description": "Le code postal doit contenir 5 caractères",
+ "pattern": "^[0-9]{5}$",
+ },
+ "commune": {
+ "bsonType": "string",
+ "description": "Commune",
+ "maxLength": 80,
+ },
+ "complement": {
+ "bsonType": "string",
+ "description": "Complément d'adresse",
+ },
+ "complete": {
+ "bsonType": "string",
+ "description": "Adresse complète",
+ },
+ "departement": {
+ "bsonType": "string",
+ "enum": [
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "21",
+ "22",
+ "23",
+ "24",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "30",
+ "31",
+ "32",
+ "33",
+ "34",
+ "35",
+ "36",
+ "37",
+ "38",
+ "39",
+ "40",
+ "41",
+ "42",
+ "43",
+ "44",
+ "45",
+ "46",
+ "47",
+ "48",
+ "49",
+ "50",
+ "51",
+ "52",
+ "53",
+ "54",
+ "55",
+ "56",
+ "57",
+ "58",
+ "59",
+ "60",
+ "61",
+ "62",
+ "63",
+ "64",
+ "65",
+ "66",
+ "67",
+ "68",
+ "69",
+ "70",
+ "71",
+ "72",
+ "73",
+ "74",
+ "75",
+ "76",
+ "77",
+ "78",
+ "79",
+ "80",
+ "81",
+ "82",
+ "83",
+ "84",
+ "85",
+ "86",
+ "87",
+ "88",
+ "89",
+ "90",
+ "91",
+ "92",
+ "93",
+ "94",
+ "95",
+ "971",
+ "972",
+ "973",
+ "974",
+ "975",
+ "976",
+ "977",
+ "978",
+ "984",
+ "986",
+ "987",
+ "988",
+ "989",
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "09",
+ "2A",
+ "2B",
+ ],
+ },
+ "numero": {
+ "bsonType": "int",
+ "description": "N° de la voie",
+ },
+ "pays": {
+ "bsonType": "string",
+ "description": "Pays",
+ "enum": [
+ "AF",
+ "ZA",
+ "AL",
+ "DZ",
+ "DE",
+ "AD",
+ "AO",
+ "AG",
+ "SA",
+ "AR",
+ "AM",
+ "AU",
+ "AT",
+ "AZ",
+ "BS",
+ "BH",
+ "BD",
+ "BB",
+ "BE",
+ "BZ",
+ "BJ",
+ "BT",
+ "BY",
+ "MM",
+ "BO",
+ "BQ",
+ "BA",
+ "BW",
+ "BR",
+ "BN",
+ "BG",
+ "BF",
+ "BI",
+ "KH",
+ "CM",
+ "CA",
+ "CV",
+ "CF",
+ "CL",
+ "CN",
+ "CY",
+ "CO",
+ "KM",
+ "CG",
+ "CD",
+ "KR",
+ "KP",
+ "CR",
+ "CI",
+ "HR",
+ "CU",
+ "CW",
+ "DK",
+ "DJ",
+ "DO",
+ "DM",
+ "EG",
+ "SV",
+ "AE",
+ "EC",
+ "ER",
+ "ES",
+ "EE",
+ "SZ",
+ "US",
+ "ET",
+ "MK",
+ "FJ",
+ "FI",
+ "FR",
+ "GA",
+ "GM",
+ "GE",
+ "GH",
+ "GR",
+ "GD",
+ "GT",
+ "GN",
+ "GQ",
+ "GW",
+ "GY",
+ "HT",
+ "HN",
+ "HU",
+ "IN",
+ "ID",
+ "IR",
+ "IQ",
+ "IE",
+ "IS",
+ "IL",
+ "IT",
+ "JM",
+ "JP",
+ "JO",
+ "KZ",
+ "KE",
+ "KG",
+ "KI",
+ "XK",
+ "KW",
+ "LA",
+ "LS",
+ "LV",
+ "LB",
+ "LR",
+ "LY",
+ "LI",
+ "LT",
+ "LU",
+ "MG",
+ "MY",
+ "MW",
+ "MV",
+ "ML",
+ "MT",
+ "MA",
+ "MH",
+ "MU",
+ "MR",
+ "MX",
+ "FM",
+ "MD",
+ "MC",
+ "MN",
+ "ME",
+ "MZ",
+ "NA",
+ "NR",
+ "NP",
+ "NI",
+ "NE",
+ "NG",
+ "NO",
+ "NZ",
+ "OM",
+ "UG",
+ "UZ",
+ "PK",
+ "PW",
+ "PS",
+ "PA",
+ "PG",
+ "PY",
+ "NL",
+ "PE",
+ "PH",
+ "PL",
+ "PT",
+ "QA",
+ "RO",
+ "GB",
+ "RU",
+ "RW",
+ "KN",
+ "SM",
+ "SX",
+ "VC",
+ "LC",
+ "SB",
+ "WS",
+ "ST",
+ "SN",
+ "RS",
+ "SC",
+ "SL",
+ "SG",
+ "SK",
+ "SI",
+ "SO",
+ "SD",
+ "SS",
+ "LK",
+ "SE",
+ "CH",
+ "SR",
+ "SY",
+ "TJ",
+ "TZ",
+ "TD",
+ "CZ",
+ "TH",
+ "TL",
+ "TG",
+ "TO",
+ "TT",
+ "TN",
+ "TM",
+ "TR",
+ "TV",
+ "UA",
+ "UY",
+ "VU",
+ "VA",
+ "VE",
+ "VN",
+ "YE",
+ "ZM",
+ "ZW",
+ ],
+ },
+ "region": {
+ "bsonType": "string",
+ "enum": [
+ "11",
+ "24",
+ "27",
+ "28",
+ "32",
+ "44",
+ "52",
+ "53",
+ "75",
+ "76",
+ "84",
+ "93",
+ "94",
+ "977",
+ "978",
+ "01",
+ "02",
+ "03",
+ "04",
+ "05",
+ "06",
+ "00",
+ ],
+ },
+ "repetition_voie": {
+ "bsonType": "string",
+ "description": "Indice de répétition du numéro de voie",
+ "enum": [
+ "B",
+ "T",
+ "Q",
+ "C",
+ ],
+ },
+ "voie": {
+ "bsonType": "string",
+ "description": "Nom de voie",
+ },
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "cause_rupture": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "date_debut": {
+ "bsonType": "date",
+ "description": "Date de début du contrat",
+ },
+ "date_fin": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date de fin du contrat",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_rupture": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date de rupture du contrat",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "denomination": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "naf": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Le Code NAF est composé de 4 chiffres et 1 lettre. Il est délivré par l'INSEE.[Informations sur le Code NAF.](https://www.economie.gouv.fr/entreprises/activite-entreprise-code-ape-code-naf)",
+ "pattern": "^[0-9]{2}\\.?[0-9]{0,2}[a-zA-Z]{0,1}$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "nombre_de_salaries": {
+ "anyOf": [
+ {
+ "bsonType": "int",
+ "description": "L'effectif salarié rempli automatiquement correspond à l'estimation de la base Entreprises de l'INSEE.
L'effectif renseigné est celui de l’entreprise dans sa globalité (et non seulement l’effectif de l’établissement d’exécution du contrat).",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "siret": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "N° SIRET de l'employeur",
+ "pattern": "^[0-9]{14}$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "type_employeur": {
+ "anyOf": [
+ {
+ "bsonType": "number",
+ "description": "Le type d'employeur doit être en adéquation avec son statut juridique.",
+ "enum": [
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ },
+ },
+ },
+ "formation": {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "annee": {
+ "anyOf": [
+ {
+ "bsonType": "int",
+ "description": "Numéro de l'année dans la formation (promo)",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "cause_exclusion": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "cfd": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Code CFD de la formation",
+ "pattern": "^[A-Z0-9]{8}$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_entree": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date d'entrée en formation",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_exclusion": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date d'exclusion",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_fin": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date de fin de la formation",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_inscription": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date d'inscription",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "date_obtention_diplome": {
+ "anyOf": [
+ {
+ "bsonType": "date",
+ "description": "Date d'obtention du diplôme",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "duree_formation_relle": {
+ "anyOf": [
+ {
+ "bsonType": "int",
+ "description": "Durée réelle de la formation en mois",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "duree_theorique": {
+ "anyOf": [
+ {
+ "bsonType": "int",
+ "description": "Durée théorique de la formation en année",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "duree_theorique_mois": {
+ "anyOf": [
+ {
+ "bsonType": "int",
+ "description": "Durée théorique de la formation en mois",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "formation_id": {
+ "anyOf": [
+ {
+ "bsonType": "objectId",
+ "description": "ID de la formation",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "formation_presentielle": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "libelle_court": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "libelle_long": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "niveau": {
+ "anyOf": [
+ {
+ "anyOf": [
+ {
+ "not": {},
+ },
+ {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "niveau_libelle": {
+ "anyOf": [
+ {
+ "anyOf": [
+ {
+ "not": {},
+ },
+ {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ ],
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "obtention_diplome": {
+ "bsonType": [
+ "bool",
+ "null",
+ ],
+ },
+ "periode": {
+ "anyOf": [
+ {
+ "bsonType": "array",
+ "description": "Période de la formation, en année (peut être sur plusieurs années)",
+ "items": {
+ "bsonType": "int",
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "referent_handicap": {
+ "anyOf": [
+ {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "email": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "nom": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ "prenom": {
+ "bsonType": [
+ "string",
+ "null",
+ ],
+ },
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ "rncp": {
+ "anyOf": [
+ {
+ "bsonType": "string",
+ "description": "Code RNCP de la formation à laquelle l'apprenant est inscrit",
+ "pattern": "^(RNCP)?[0-9]{2,5}$",
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
+ },
+ },
+ "organisme": {
+ "additionalProperties": false,
+ "bsonType": "object",
+ "properties": {
+ "organisme_formateur_id": {
+ "bsonType": "string",
+ },
+ "organisme_lieu_id": {
+ "bsonType": "string",
+ },
+ "organisme_responsable_id": {
+ "bsonType": "string",
+ },
+ "type_cfa": {
+ "bsonType": "string",
+ "description": "Type de CFA",
+ "pattern": "^(01|02|03|04|05|06|07|08|09|10)$",
+ },
+ },
+ },
+ },
+ },
+ {
+ "bsonType": "null",
+ },
+ ],
+ },
"email": {
"bsonType": "string",
"description": "Email utilisateur",
diff --git a/server/src/common/validation/dossierApprenantSchemaV1V2.ts b/server/src/common/validation/dossierApprenantSchemaV1V2.ts
index f10c957e7..c3f00ad9b 100644
--- a/server/src/common/validation/dossierApprenantSchemaV1V2.ts
+++ b/server/src/common/validation/dossierApprenantSchemaV1V2.ts
@@ -1,7 +1,6 @@
+import { primitivesV1, primitivesV3 } from "shared/models/data/zodPrimitives";
import { z } from "zod";
-import { primitivesV1, primitivesV3 } from "@/common/validation/utils/zodPrimitives";
-
/**
* Note: ce schema est seulement utilisé pour générer la documentation OpenAPI pour l'API v1.
* Les données entrantes de l'API V1 sont validées par dossierApprenantSchema (Joi).
diff --git a/server/src/common/validation/dossierApprenantSchemaV3.ts b/server/src/common/validation/dossierApprenantSchemaV3.ts
index b587868ae..43dc69f8e 100644
--- a/server/src/common/validation/dossierApprenantSchemaV3.ts
+++ b/server/src/common/validation/dossierApprenantSchemaV3.ts
@@ -1,8 +1,7 @@
import { NIR_LOOSE_REGEX } from "shared";
+import { primitivesV1, primitivesV3 } from "shared/models/data/zodPrimitives";
import { z } from "zod";
-import { primitivesV1, primitivesV3 } from "@/common/validation/utils/zodPrimitives";
-
export const stripModelAdditionalKeys = (validationSchema, data) => {
const strippedData = Object.keys(validationSchema.shape).reduce((acc, curr) => {
return data[curr] !== undefined
diff --git a/server/src/http/routes/admin.routes/transmissions.routes.ts b/server/src/http/routes/admin.routes/transmissions.routes.ts
index 4bf39064b..cbc094de7 100644
--- a/server/src/http/routes/admin.routes/transmissions.routes.ts
+++ b/server/src/http/routes/admin.routes/transmissions.routes.ts
@@ -1,4 +1,5 @@
import express from "express";
+import { extensions } from "shared/models/data/zodPrimitives";
import { z } from "zod";
import {
@@ -6,7 +7,6 @@ import {
getAllErrorsTransmissionStatusGroupedByOrganismeForAGivenDay,
} from "@/common/actions/indicateurs/transmissions/transmission.action";
import paginationSchema from "@/common/validation/paginationSchema";
-import { extensions } from "@/common/validation/utils/zodPrimitives";
import { returnResult } from "@/http/middlewares/helpers";
import validateRequestMiddleware from "@/http/middlewares/validateRequestMiddleware";
diff --git a/server/src/http/routes/specific.routes/transmission.routes.ts b/server/src/http/routes/specific.routes/transmission.routes.ts
index 6c280da95..62b002e57 100644
--- a/server/src/http/routes/specific.routes/transmission.routes.ts
+++ b/server/src/http/routes/specific.routes/transmission.routes.ts
@@ -1,5 +1,6 @@
import { ObjectId } from "bson";
import express from "express";
+import { extensions } from "shared/models/data/zodPrimitives";
import { z } from "zod";
import {
@@ -8,7 +9,6 @@ import {
getSuccessfulTransmissionStatusDetailsForAGivenDay,
} from "@/common/actions/indicateurs/transmissions/transmission.action";
import paginationSchema from "@/common/validation/paginationSchema";
-import { extensions } from "@/common/validation/utils/zodPrimitives";
import { returnResult, requireOrganismePermission } from "@/http/middlewares/helpers";
import validateRequestMiddleware from "@/http/middlewares/validateRequestMiddleware";
diff --git a/server/src/http/routes/specific.routes/user.routes.ts b/server/src/http/routes/specific.routes/user.routes.ts
new file mode 100644
index 000000000..faedef5db
--- /dev/null
+++ b/server/src/http/routes/specific.routes/user.routes.ts
@@ -0,0 +1,41 @@
+import express from "express";
+import { effectifCreationSchema } from "shared/models/apis/effectifsCreationSchema";
+
+import { usersMigrationDb } from "@/common/model/collections";
+import { AuthContext } from "@/common/model/internal/AuthContext";
+import { returnResult } from "@/http/middlewares/helpers";
+import validateRequestMiddleware from "@/http/middlewares/validateRequestMiddleware";
+
+export default () => {
+ const router = express.Router();
+
+ router.get("/effectif-draft", returnResult(getUserDraft));
+
+ router.put(
+ "/effectif-draft",
+ validateRequestMiddleware({ body: effectifCreationSchema.deepPartial() }),
+ returnResult(updateUserDraft)
+ );
+ return router;
+};
+
+const getUserDraft = async (req) => {
+ const user = req.user as AuthContext;
+ const found = await usersMigrationDb().findOne({ _id: user._id });
+ return found?.draft_effectif_form ?? {};
+};
+
+const updateUserDraft = async (req) => {
+ const user = req.user as AuthContext;
+ const updated = await usersMigrationDb().findOneAndUpdate(
+ {
+ _id: user._id,
+ },
+ {
+ $set: {
+ draft_effectif_form: req.body,
+ },
+ }
+ );
+ return updated.value?.draft_effectif_form;
+};
diff --git a/server/src/http/server.ts b/server/src/http/server.ts
index 47f164fd6..a30662179 100644
--- a/server/src/http/server.ts
+++ b/server/src/http/server.ts
@@ -10,6 +10,8 @@ import Joi from "joi";
import { ObjectId } from "mongodb";
import passport from "passport";
import { typesEffectifNominatif, CODE_POSTAL_REGEX } from "shared";
+import { effectifCreationSchema, IEffectifCreationSchema } from "shared/models/apis/effectifsCreationSchema";
+import { extensions, primitivesV1, primitivesV3 } from "shared/models/data/zodPrimitives";
import swaggerUi from "swagger-ui-express";
import { z } from "zod";
@@ -104,12 +106,10 @@ import { passwordSchema, validateFullObjectSchema, validateFullZodObjectSchema }
import { SReqPostVerifyUser } from "@/common/validation/ApiERPSchema";
import { configurationERPSchema } from "@/common/validation/configurationERPSchema";
import { dossierApprenantSchemaV3WithMoreRequiredFieldsValidatingUAISiret } from "@/common/validation/dossierApprenantSchemaV3";
-import { effectifCreationSchema, IEffectifCreationSchema } from "@/common/validation/effectifsCreationSchema";
import loginSchemaLegacy from "@/common/validation/loginSchemaLegacy";
import objectIdSchema from "@/common/validation/objectIdSchema";
import { registrationSchema, registrationUnknownNetworkSchema } from "@/common/validation/registrationSchema";
import userProfileSchema from "@/common/validation/userProfileSchema";
-import { extensions, primitivesV1, primitivesV3 } from "@/common/validation/utils/zodPrimitives";
import config from "@/config";
import { authMiddleware, checkActivationToken, checkPasswordToken } from "./helpers/passport-handlers";
@@ -137,6 +137,7 @@ import dossierApprenantRouter from "./routes/specific.routes/dossiers-apprenants
import { getOrganismeEffectifs, updateOrganismeEffectifs } from "./routes/specific.routes/organisme.routes";
import organismesRouter from "./routes/specific.routes/organismes.routes";
import transmissionRoutes from "./routes/specific.routes/transmission.routes";
+import userRoutes from "./routes/specific.routes/user.routes";
const openapiSpecs = JSON.parse(fs.readFileSync(openApiFilePath, "utf8"));
@@ -435,7 +436,8 @@ function setupRoutes(app: Application) {
has_accept_cgu_version: req.params.version,
});
})
- );
+ )
+ .use("/api/v1/user", userRoutes());
/********************************
* API pour un organisme *
diff --git a/server/tests/integration/common/validation/zodPrimitives.test.ts b/server/tests/integration/common/validation/zodPrimitives.test.ts
index e3807f566..13bd20c94 100644
--- a/server/tests/integration/common/validation/zodPrimitives.test.ts
+++ b/server/tests/integration/common/validation/zodPrimitives.test.ts
@@ -1,4 +1,4 @@
-import { primitivesV3 } from "@/common/validation/utils/zodPrimitives";
+import { primitivesV3 } from "shared/models/data/zodPrimitives";
describe("Regex primitivesV3", () => {
describe("derniere_situation", () => {
diff --git a/server/src/common/validation/effectifsCreationSchema.ts b/shared/models/apis/effectifsCreationSchema.ts
similarity index 89%
rename from server/src/common/validation/effectifsCreationSchema.ts
rename to shared/models/apis/effectifsCreationSchema.ts
index e96faebe0..4af09fa26 100644
--- a/server/src/common/validation/effectifsCreationSchema.ts
+++ b/shared/models/apis/effectifsCreationSchema.ts
@@ -1,9 +1,9 @@
+import { z } from "zod";
+
import { zApprenant } from "shared/models/data/effectifs/apprenant.part";
import { zContrat } from "shared/models/data/effectifs/contrat.part";
import { zFormationEffectif } from "shared/models/data/effectifs/formation.part";
-import { z } from "zod";
-
-import { primitivesV1, primitivesV3 } from "@/common/validation/utils/zodPrimitives";
+import { primitivesV1, primitivesV3 } from "shared/models/data/zodPrimitives";
export const effectifCreationSchema = z.object({
annee_scolaire: primitivesV1.formation.annee_scolaire,
diff --git a/shared/models/data/usersMigration.model.ts b/shared/models/data/usersMigration.model.ts
index 29150ceba..e7a406fb2 100644
--- a/shared/models/data/usersMigration.model.ts
+++ b/shared/models/data/usersMigration.model.ts
@@ -2,6 +2,8 @@ import type { CreateIndexesOptions, IndexSpecification } from "mongodb";
import { z } from "zod";
import { zObjectId } from "zod-mongodb-schema";
+import { effectifCreationSchema } from "../apis/effectifsCreationSchema";
+
export const collectionName = "usersMigration";
const indexes: [IndexSpecification, CreateIndexesOptions][] = [
@@ -65,6 +67,7 @@ export const zUsersMigration = z.object({
)
.optional(),
unsubscribe: z.boolean().optional().describe("unsubscribe email"),
+ draft_effectif_form: effectifCreationSchema.deepPartial().nullish(),
});
export type IUsersMigration = z.output;
diff --git a/server/src/common/validation/utils/zodPrimitives.ts b/shared/models/data/zodPrimitives.ts
similarity index 99%
rename from server/src/common/validation/utils/zodPrimitives.ts
rename to shared/models/data/zodPrimitives.ts
index 6c6f111c3..08f4b6117 100644
--- a/server/src/common/validation/utils/zodPrimitives.ts
+++ b/shared/models/data/zodPrimitives.ts
@@ -1,6 +1,8 @@
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
import { subDays } from "date-fns";
import { capitalize } from "lodash-es";
+import { z } from "zod";
+
import {
CODES_STATUT_APPRENANT_ENUM,
EFFECTIF_DERNIER_SITUATION,
@@ -11,10 +13,9 @@ import {
UAI_REGEX,
CODE_POSTAL_REGEX,
DERNIER_ORGANISME_UAI_REGEX,
-} from "shared";
-import { z } from "zod";
+} from "shared/constants";
-import { telephoneConverter } from "./frenchTelephoneNumber";
+import { telephoneConverter } from "../../../server/src/common/validation/utils/frenchTelephoneNumber";
extendZodWithOpenApi(z);