Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(rs-2024): mise à jour des données de la rentrée scolaire 2024 #537

Merged
merged 4 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ services:
shm_size: 1gb
volumes:
- pilotage_postgres_data:/var/lib/postgresql/data:z
- ./server/seed/seed_schema.dump:/seed_schema.dump
- ./server/seed/seed_data.dump:/seed_data.dump
- ./server/seed/seed_schema.dump:/seed_schema.dump:ro
- ./server/seed/seed_data.dump:/seed_data.dump:ro
healthcheck:
test: ["CMD-SHELL", "sh -c 'pg_isready -U postgres -d postgres'"]
interval: 10s
Expand Down
2 changes: 1 addition & 1 deletion server/seed/generate-seed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ echo ""
# Générer le fichier de dump
echo "🌱 Génération de la seed contenant le schéma de la DB"
echo ""
pg_dump $DB_URL --format=custom --clean --if-exists --create --schema-only --file $SCHEMA_DUMP_FILE
pg_dump $DB_URL --format=custom --clean --if-exists --schema-only --file $SCHEMA_DUMP_FILE

echo "🤖 Génération de la seed contenant les données de la DB"
echo ""
Expand Down
Binary file modified server/seed/seed_data.dump
Binary file not shown.
Binary file modified server/seed/seed_schema.dump
Binary file not shown.
6 changes: 3 additions & 3 deletions server/src/commands.product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@ export function productCommands(cli: Command) {
...getImports({ type: "regroupements", schema: Schemas.regroupements }),
...getImports({
type: "attractivite_capacite",
years: ["2021", "2022", "2023"],
years: ["2021", "2022", "2023", "2024"],
schema: Schemas.attractivite_capacite,
}),
...getImports({
type: "BTS_attractivite_capacite",
years: ["2022", "2023"],
years: ["2022", "2023", "2024"],
schema: Schemas.BTS_attractivite_capacite,
}),
...getImports({
type: "constat",
years: ["2020", "2021", "2022", "2023"],
years: ["2020", "2021", "2022", "2023", "2024"],
schema: Schemas.constat,
}),
...getImports({ type: "nMef", schema: Schemas.nMef }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,17 @@ describe("GET /api/formation/:cfd", () => {
});

it("doit retourner qu'un CFD n'est pas enseigné dans une région", async () => {
const cfdNotInScope = "32322112";
const cfdNotInScope = "46033401";
const codeRegion = "84";
const response = await app.inject({
method: "GET",
url: `/api/formation/${cfdNotInScope}`,
url: `/api/formation/${cfdNotInScope}?codeRegion=${codeRegion}`,
});

expect(response.statusCode).toBe(200);
const result = await response.json<Response>();
expect(result.cfd).toBe(cfdNotInScope);
expect(result.libelle).toBe("BTSA - Sciences et technologies des aliments spe produits laitiers");
expect(result.libelle).toBe("DIV-4 - Gestion touristique : hospitalites, accueil et experience client");
expect(result.isInScope).toBe(false);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { sql } from "kysely";
import { CURRENT_IJ_MILLESIME, CURRENT_RENTREE } from "shared";
import type { Etablissement, EtablissementsOrderBy } from "shared/routes/schemas/get.formation.cfd.map.schema";

import { getKbdClient } from "@/db/db";
Expand Down Expand Up @@ -30,7 +31,7 @@ export const getEtablissements = async ({
.leftJoin("indicateurSortie", (join) =>
join
.onRef("indicateurSortie.formationEtablissementId", "=", "formationEtablissement.id")
.on("millesimeSortie", "=", "2021_2022")
.on("millesimeSortie", "=", CURRENT_IJ_MILLESIME)
)
.select([
"cfd",
Expand Down Expand Up @@ -100,7 +101,7 @@ export const getEtablissements = async ({
selectTauxPression("indicateurEntree", "niveauDiplome", true).as("tauxPression"),
])
.where((eb) =>
eb.or([eb("rentreeScolaire", "=", "2023"), eb("formationEtablissement.voie", "=", "apprentissage")])
eb.or([eb("rentreeScolaire", "=", CURRENT_RENTREE), eb("formationEtablissement.voie", "=", "apprentissage")])
)
)
.selectFrom("carto")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ describe("GET /api/formation/:cfd/indicators", () => {

expect(result.etablissements).toEqual(
expect.arrayContaining([
{ rentreeScolaire: "2020", nbEtablissements: 785 },
{ rentreeScolaire: "2020", nbEtablissements: 778 },
{ rentreeScolaire: "2021", nbEtablissements: 797 },
{ rentreeScolaire: "2022", nbEtablissements: 802 },
{ rentreeScolaire: "2023", nbEtablissements: 806 },
{ rentreeScolaire: "2024", nbEtablissements: 814 },
])
);
});
Expand Down Expand Up @@ -131,10 +132,10 @@ describe("GET /api/formation/:cfd/indicators", () => {

expect(result.effectifs).toEqual(
expect.arrayContaining([
{ rentreeScolaire: "2020", effectif: 23361 },
{ rentreeScolaire: "2021", effectif: 22823 },
{ rentreeScolaire: "2022", effectif: 22658 },
{ rentreeScolaire: "2023", effectif: 23268 },
{ rentreeScolaire: "2024", effectif: 23598 },
])
);
});
Expand Down Expand Up @@ -214,24 +215,27 @@ describe("GET /api/formation/:cfd/indicators", () => {
expect(result.tauxIJ.tauxPoursuite).toEqual(
expect.arrayContaining([
{ apprentissage: 0.2967, libelle: "2019+20", scolaire: 0.509 },
{ apprentissage: 0.4036, libelle: "2020+21", scolaire: 0.5379 },
{ apprentissage: 0.4036, libelle: "2020+21", scolaire: 0.5382 },
{ apprentissage: 0.3954, libelle: "2021+22", scolaire: 0.5504 },
{ apprentissage: 0.3791, libelle: "2022+23", scolaire: 0.5581 },
])
);

expect(result.tauxIJ.tauxInsertion).toEqual(
expect.arrayContaining([
{ apprentissage: 0.5937, libelle: "2019+20", scolaire: 0.3496 },
{ apprentissage: 0.6249, libelle: "2020+21", scolaire: 0.3531 },
{ apprentissage: 0.6272, libelle: "2020+21", scolaire: 0.3546 },
{ apprentissage: 0.6137, libelle: "2021+22", scolaire: 0.4291 },
{ apprentissage: 0.6037, libelle: "2022+23", scolaire: 0.4156 },
])
);

expect(result.tauxIJ.tauxDevenirFavorable).toEqual(
expect.arrayContaining([
{ apprentissage: 0.7143, libelle: "2019+20", scolaire: 0.6807 },
{ apprentissage: 0.7755, libelle: "2020+21", scolaire: 0.7011 },
{ apprentissage: 0.7769, libelle: "2020+21", scolaire: 0.7019 },
{ apprentissage: 0.7664, libelle: "2021+22", scolaire: 0.7433 },
{ apprentissage: 0.7539, libelle: "2022+23", scolaire: 0.7417 },
])
);
});
Expand All @@ -255,16 +259,18 @@ describe("GET /api/formation/:cfd/indicators", () => {
expect(result.tauxIJ.tauxInsertion).toEqual(
expect.arrayContaining([
{ apprentissage: 0.6362, libelle: "2019+20", scolaire: 0.4757 },
{ apprentissage: 0.7, libelle: "2020+21", scolaire: 0.468 },
{ apprentissage: 0.7, libelle: "2020+21", scolaire: 0.4691 },
{ apprentissage: 0.6719, libelle: "2021+22", scolaire: 0.4935 },
{ apprentissage: 0.6429, libelle: "2022+23", scolaire: 0.4911 },
])
);

expect(result.tauxIJ.tauxDevenirFavorable).toEqual(
expect.arrayContaining([
{ apprentissage: 0.7278, libelle: "2019+20", scolaire: 0.7428 },
{ apprentissage: 0.8125, libelle: "2020+21", scolaire: 0.7594 },
{ apprentissage: 0.8125, libelle: "2020+21", scolaire: 0.7599 },
{ apprentissage: 0.8047, libelle: "2021+22", scolaire: 0.7857 },
{ apprentissage: 0.792, libelle: "2022+23", scolaire: 0.7876 },
])
);
});
Expand All @@ -283,22 +289,25 @@ describe("GET /api/formation/:cfd/indicators", () => {
{ apprentissage: 0.2518, libelle: "2019+20", scolaire: 0.5095 },
{ apprentissage: 0.375, libelle: "2020+21", scolaire: 0.5478 },
{ apprentissage: 0.4047, libelle: "2021+22", scolaire: 0.5769 },
{ apprentissage: 0.4176, libelle: "2022+23", scolaire: 0.5826 },
])
);

expect(result.tauxIJ.tauxInsertion).toEqual(
expect.arrayContaining([
{ apprentissage: 0.6362, libelle: "2019+20", scolaire: 0.4757 },
{ apprentissage: 0.7, libelle: "2020+21", scolaire: 0.468 },
{ apprentissage: 0.7, libelle: "2020+21", scolaire: 0.4691 },
{ apprentissage: 0.6719, libelle: "2021+22", scolaire: 0.4935 },
{ apprentissage: 0.6429, libelle: "2022+23", scolaire: 0.4911 },
])
);

expect(result.tauxIJ.tauxDevenirFavorable).toEqual(
expect.arrayContaining([
{ apprentissage: 0.7278, libelle: "2019+20", scolaire: 0.7428 },
{ apprentissage: 0.8125, libelle: "2020+21", scolaire: 0.7594 },
{ apprentissage: 0.8125, libelle: "2020+21", scolaire: 0.7599 },
{ apprentissage: 0.8047, libelle: "2021+22", scolaire: 0.7857 },
{ apprentissage: 0.792, libelle: "2022+23", scolaire: 0.7876 },
])
);
});
Expand All @@ -324,16 +333,18 @@ describe("GET /api/formation/:cfd/indicators", () => {
expect(result.tauxIJ.tauxInsertion).toEqual(
expect.arrayContaining([
{ apprentissage: 0.6362, libelle: "2019+20", scolaire: 0.4757 },
{ apprentissage: 0.7, libelle: "2020+21", scolaire: 0.468 },
{ apprentissage: 0.7, libelle: "2020+21", scolaire: 0.4691 },
{ apprentissage: 0.6719, libelle: "2021+22", scolaire: 0.4935 },
{ apprentissage: 0.6429, libelle: "2022+23", scolaire: 0.4911 },
])
);

expect(result.tauxIJ.tauxDevenirFavorable).toEqual(
expect.arrayContaining([
{ apprentissage: 0.7278, libelle: "2019+20", scolaire: 0.7428 },
{ apprentissage: 0.8125, libelle: "2020+21", scolaire: 0.7594 },
{ apprentissage: 0.8125, libelle: "2020+21", scolaire: 0.7599 },
{ apprentissage: 0.8047, libelle: "2021+22", scolaire: 0.7857 },
{ apprentissage: 0.792, libelle: "2022+23", scolaire: 0.7876 },
])
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { hasContinuum } from "@/modules/data/utils/hasContinuum";
import { isInPerimetreIJEtablissement } from "@/modules/data/utils/isInPerimetreIJ";
import { isScolaireFormationHistorique } from "@/modules/data/utils/isScolaire";
import { notAnneeCommune } from "@/modules/data/utils/notAnneeCommune";
import { isHistoriqueCoExistant, notHistoriqueUnlessCoExistant } from "@/modules/data/utils/notHistorique";
import { openForRentreeScolaire } from "@/modules/data/utils/openForRentreeScolaire";
import { isHistoriqueCoExistant, notHistoriqueUnlessCoExistantIndicateurEntree } from "@/modules/data/utils/notHistorique";
import { openForRentreeScolaireIndicateurEntree } from "@/modules/data/utils/openForRentreeScolaire";
import { withTauxDevenirFavorableReg } from "@/modules/data/utils/tauxDevenirFavorable";
import { withInsertionReg } from "@/modules/data/utils/tauxInsertion6mois";
import { withPoursuiteReg } from "@/modules/data/utils/tauxPoursuite";
Expand Down Expand Up @@ -217,8 +217,8 @@ export const getFormationsQuery = async ({
eb.ref("formationView.isTransitionNumerique").as(TypeFormationSpecifiqueEnum["Transition numérique"]),
])
.where(isInPerimetreIJEtablissement)
.where((eb) => notHistoriqueUnlessCoExistant(eb, rentreeScolaire[0]))
.where((eb) => openForRentreeScolaire(eb, rentreeScolaire[0]))
.where(notHistoriqueUnlessCoExistantIndicateurEntree)
.where(openForRentreeScolaireIndicateurEntree)
.where((eb) =>
eb.or([
eb("indicateurEntree.rentreeScolaire", "is not", null),
Expand Down
127 changes: 110 additions & 17 deletions server/src/modules/data/usecases/getRegion/__tests__/getRegion.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { usePg } from "@tests/utils/pg.test.utils";
import { beforeAll, describe, expect, it } from "vitest";
import type { IResError } from "shared/models/errors";
import type { ROUTES } from "shared/routes/routes";
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
import type { z } from "zod";

import type { Server } from "@/server/server.js";
import createServer from "@/server/server.js";

type Response = z.infer<
(typeof ROUTES)["[GET]/region/:codeRegion"]["schema"]["response"]["200"]
>;

usePg();

describe("[GET]/region/:codeRegion", () => {
let app: Server;
let fixture: ReturnType<typeof fixtureBuilder>;

beforeAll(async () => {
app = await createServer();
Expand All @@ -16,22 +24,107 @@ describe("[GET]/region/:codeRegion", () => {
return async () => app.close();
}, 15_000);

beforeEach(() => {
fixture = fixtureBuilder(app);
});

it("doit retrouver les données de la région Auvergne-Rhône-Alpes (84) pour un BTS (320)", async () => {
const response = await app.inject({
method: "GET",
url: "/api/region/84?codeNiveauDiplome[]=320",
});

expect(response.statusCode).toBe(200);
expect(response.json()).toEqual({
libelleRegion: "Auvergne-Rhône-Alpes",
effectifEntree: 10165,
effectifTotal: 18403,
nbFormations: 96,
tauxRemplissage: 0.79200970621371,
tauxPoursuite: 0.476512025342837,
tauxInsertion: 0.640178358149534,
tauxDevenirFavorable: 0.811637697469885,
});
fixture.given.region("84");
fixture.given.codeNiveauDiplome("320");

await fixture.when.getRegion();

fixture.then.verifierLabelRegion("Auvergne-Rhône-Alpes");
fixture.then.verifierEffectifEntree(10154);
fixture.then.verifierEffectifTotal(18525);
fixture.then.verifierNbFormations(98);
fixture.then.verifierTauxRemplissage(0.8058);
fixture.then.verifierTauxPoursuite(0.4975);
fixture.then.verifierTauxInsertion(0.6417);
fixture.then.verifierTauxDevenirFavorable(0.82);
});

it("doit vérifier que des valeurs n'existent par pour des diplômes dans des régions", async () => {
fixture.given.region("27");
fixture.given.codeNiveauDiplome("561");

await fixture.when.getRegion();

fixture.then.verifierLabelRegion("Bourgogne-Franche-Comté");
fixture.then.verifierNbFormations(4);
fixture.then.verifierEffectifTotal(46);
fixture.then.verifierEffectifEntree(46);
fixture.then.verifierTauxRemplissage(undefined);
fixture.then.verifierTauxPoursuite(undefined);
fixture.then.verifierTauxInsertion(undefined);
fixture.then.verifierTauxDevenirFavorable(undefined);
});
});



const fixtureBuilder = (app: Server) => {
let codeRegion: string;
let codeNiveauDiplome: string;
let responseCode: number;
let responseBody: Response | IResError;

const rounded = (value?: number, precision: number = 4) => {
if (!value) return undefined;
return Math.round(value * 10 ** precision) / 10 ** precision;
};

return {
given: {
region: (code: string) => {
codeRegion = code;
},
codeNiveauDiplome: (code: string) => {
codeNiveauDiplome = code;
},
},
when: {
getRegion: async () => {
const response = await app.inject({
method: "GET",
url: `/api/region/${codeRegion}?codeNiveauDiplome[]=${codeNiveauDiplome}`,
});
responseCode = response.statusCode;
responseBody = response.json();
},
},
then: {
verifierReponseSucces: () => {
expect(responseCode).toBe(200);
},
verifierReponseErreur: () => {
expect(responseCode).toBe(400);
},
verifierLabelRegion: (label: string) => {
expect((responseBody as Response).libelleRegion).toBe(label);
},
verifierEffectifEntree: (effectif: number) => {
expect((responseBody as Response).effectifEntree).toBe(effectif);
},
verifierEffectifTotal: (effectif: number) => {
expect((responseBody as Response).effectifTotal).toBe(effectif);
},
verifierNbFormations: (nb: number) => {
expect((responseBody as Response).nbFormations).toBe(nb);
},
verifierTauxRemplissage: (taux?: number) => {
expect(rounded((responseBody as Response).tauxRemplissage)).toBe(taux);
},
verifierTauxPoursuite: (taux?: number) => {
expect(rounded((responseBody as Response).tauxPoursuite)).toBe(taux);
},
verifierTauxInsertion: (taux?: number) => {
expect(rounded((responseBody as Response).tauxInsertion)).toBe(taux);
},
verifierTauxDevenirFavorable: (taux?: number) => {
expect(rounded((responseBody as Response).tauxDevenirFavorable)).toBe(taux);
},
},
};
};

11 changes: 11 additions & 0 deletions server/src/modules/data/utils/notHistorique.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,14 @@ export const notHistoriqueUnlessCoExistantIndicateurRegionSortie = (
)
);
};

export const notHistoriqueUnlessCoExistantIndicateurEntree = (
eb: ExpressionBuilder<DB, "indicateurEntree" | "formationView">,
) => {
return eb.or([
eb("formationView.dateFermeture", "is", null),
eb("formationView.dateFermeture", ">", sql<Date>`(${eb.ref("indicateurEntree.rentreeScolaire")} || '-09-01')::Date`),
]);
};


Loading
Loading