Skip to content

Commit

Permalink
feat: importation des indicateurs régionales
Browse files Browse the repository at this point in the history
  • Loading branch information
K4ST0R committed Oct 7, 2024
1 parent c864f69 commit ed5e1f4
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 18 deletions.
2 changes: 2 additions & 0 deletions server/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { importRome } from "./jobs/rome/importRome.js";
import { importRomeMetier } from "./jobs/rome/importRomeMetier.js";
import { importFormationSimilaire } from "./jobs/formations/importFormationSimilaire";
import { importFichesFormationsTmp } from "./jobs/formations/importFichesFormationsTmp";
import { importIndicateurPoursuiteRegionale } from "./jobs/exposition/importIndicateurPoursuiteRegionale";

const cli = new Command();

Expand Down Expand Up @@ -59,6 +60,7 @@ const formationEtablissementJobs = [
{ name: "feRCO", job: importRCO },
{ name: "feFE", job: importFormationEtablissement },
{ name: "feIndicateurEntree", job: importIndicateurEntree },
{ name: "feIndicateurPoursuiteRegionale", job: importIndicateurPoursuiteRegionale },
{ name: "feIndicateurPoursuite", job: importIndicateurPoursuite },
{ name: "feFormationTag", job: computeFormationTag },
{ name: "feFormationSimilaire", job: importFormationSimilaire },
Expand Down
3 changes: 3 additions & 0 deletions server/src/common/repositories/rawData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export enum RawDataType {

RCO_certifInfo = "RCO_certifInfo",
RCO_certificationRome = "RCO_certificationRome",

EXPOSITION_regionales = "EXPOSITION_regionales",
}
export interface RawData {
[RawDataType.CatalogueApprentissage]: any;
Expand All @@ -32,6 +34,7 @@ export interface RawData {
[RawDataType.ONISEP_ideoFormationsInitiales]: any;
[RawDataType.RCO_certifInfo]: any;
[RawDataType.RCO_certificationRome]: any;
[RawDataType.EXPOSITION_regionales]: any;
}

export class RawDataRepository extends SqlRepository<DB, "rawData"> {
Expand Down
71 changes: 71 additions & 0 deletions server/src/jobs/exposition/importIndicateurPoursuiteRegionale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Readable } from "stream";
import { oleoduc, writeData, transformData, filterData, flattenArray } from "oleoduc";
import { range } from "lodash-es";
import { getLoggerWithContext } from "#src/common/logger.js";
import RawDataRepository, { RawDataType } from "#src/common/repositories/rawData";
import { ExpositionApi } from "#src/services/exposition/ExpositionApi.js";

const logger = getLoggerWithContext("import");

export async function importIndicateurPoursuiteRegionale() {
logger.info(`Importation des indicateurs de poursuite (données InserJeunes)`);
const stats = { total: 0, created: 0, updated: 0, failed: 0 };
const expositionApiOptions = { retry: { retries: 5 } };
const expositionApi = new ExpositionApi(expositionApiOptions);

const limitPerPage = 1000;

function handleError(e, context, msg = `Impossible d'importer les stats régionales`) {
logger.error({ err: e, ...context }, msg);
stats.failed++;
return null; //ignore chunk
}

await RawDataRepository.deleteAll(RawDataType.EXPOSITION_regionales);

await oleoduc(
Readable.from([
await expositionApi
.fetchRegionalesStats(1, 1)
.catch((e) => handleError(e, {}, "Impossible de récupérer le nombre de page des stats régionales")),
]),
transformData((result) => {
const nbPages = Math.ceil(result.pagination.total / limitPerPage);
const pages = range(1, nbPages + 1);

logger.info(`Récupération des stats régionales pour ${nbPages} pages`);

return pages;
}),
flattenArray(),
transformData(async (page) => {
try {
logger.info(`Récupération des stats régionales pour la page ${page}`);
const formations = await expositionApi.fetchRegionalesStats(page, limitPerPage);
return formations.regionales;
} catch (err) {
return handleError(err, { page });
}
}),
flattenArray(),
filterData((data) => {
return data.code_certification_type === "mef11" || data.code_certification_type === "cfd";
}),
writeData(
async (data) => {
try {
await RawDataRepository.insertRaw(RawDataType.EXPOSITION_regionales, { data });

logger.info(`Indicateur de poursuite régionales ${data.region.nom} ajoutée`);
stats.created++;
} catch (e) {
logger.error(e, `Impossible d'ajouter les indicateurs de poursuite régionales ${data.region.nom}`);
stats.failed++;
}
},
{ parallel: 1 }
)
);

return stats;
}
7 changes: 6 additions & 1 deletion server/src/jobs/formations/importFormationEtablissement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ const logger = getLoggerWithContext("import");
export const formatDuree = (duree) => duree + " an" + (duree !== "1" ? "s" : "");

async function streamCAFormations({ stats }) {
const codesDiplomeToFilter = [
"561", // CS3
];
return compose(
// On ne renvoi que les formations post 3ème publié
await RawDataRepository.search(RawDataType.CatalogueApprentissage, { affelnet_previous_statut: "publié" }),
filterData(({ data }) => data.uai_formation),
filterData(
({ data }) => data.uai_formation && !codesDiplomeToFilter.find((code) => data.cfd.substr(0, 3) === code)
),
transformData(async ({ data }) => {
stats.total++;

Expand Down
20 changes: 20 additions & 0 deletions server/src/services/exposition/ExpositionApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,26 @@ class ExpositionApi extends RateLimitedApi {
return response;
});
}

async fetchRegionalesStats(page = 1, itemsPerPage = 1000) {
return this.execute(async () => {
if (!this.isAuthenticated() || this.isAccessTokenExpired()) {
await this.login();
}

const response = await fetchJsonWithRetry(
`${ExpositionApi.baseApiUrl}/inserjeunes/regionales?page=${page}&items_par_page=${itemsPerPage}`,
{
headers: {
...this.getAuthHeaders(),
},
},
{ ...this.retry }
);

return response;
});
}
}

export { ExpositionApi };
13 changes: 11 additions & 2 deletions shared/services/regions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,17 @@ export function findRegionByCode(code: string) {
return REGIONS.find((region) => region.code === code) || null;
}

export function findAcademieByPostcode(postcode: string) {
const departementCode = postcode.match(/^(97|98)/) ? postcode.substring(0, 3) : postcode.substring(0, 2);
export function codePostalToDepartement(postcode: string): string {
return postcode.match(/^(97|98)/) ? postcode.substring(0, 3) : postcode.substring(0, 2);
}

export function findRegionByCodePostal(postcode: string) {
const departement = codePostalToDepartement(postcode);
return REGIONS.find((region) => region.departements.find((d) => d.code == departement)) || null;
}

export function findAcademieByPostcode(postcode: string): string | null {
const departementCode = codePostalToDepartement(postcode);

for (const region of REGIONS) {
for (const departement of region.departements) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ function FormationBlockAdmissionScolaire({

return (
<Box style={{ marginTop: "2rem" }}>
<Typography variant="h3" style={{ marginBottom: "1rem" }}>
<Typography variant="h3" style={{ marginBottom: "1.5rem" }}>
Est-ce facile d’y rentrer ?
</Typography>
<Box>
<Box style={{ fontWeight: "500" }}>
<>
{admissionLevel === "easy" && (
<Box>
Expand Down Expand Up @@ -79,8 +79,8 @@ function FormationBlockAdmissionScolaire({
)}
</>
</Box>
<Box sx={{ width: "300px", marginLeft: { sm: "0", md: "2rem" }, marginTop: "1rem" }}>
<Grid container columnSpacing={4} rowSpacing={2}>
<Box sx={{ width: "300px", fontSize: "0.875rem", marginLeft: { sm: "0", md: "3rem" }, marginTop: "1.5rem" }}>
<Grid container columnSpacing={3} rowSpacing={20}>
<Grid item xs={4} style={{ textAlign: "center", color: fr.colors.decisions.text.title.blueFrance.default }}>
Vœux n°1
</Grid>
Expand Down
12 changes: 8 additions & 4 deletions ui/app/(accompagnateur)/details/[id]/FormationResume.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { css } from "@emotion/react";
import { useTheme } from "@mui/material/styles";
import { useRouter } from "next/navigation";
import { isNil } from "lodash-es";

function FormationResumeBlock({
title,
Expand Down Expand Up @@ -84,7 +85,7 @@ function FormationResumeBlockAdmission({
formationEtablissement: FormationEtablissement;
formation: Formation;
}) {
const tauxPression = formationEtablissement?.indicateurEntree?.tauxPression;
const { tauxPression, effectifs, capacite } = formationEtablissement?.indicateurEntree || {};
const admissionLevel =
tauxPression === undefined
? "unknow"
Expand All @@ -94,6 +95,7 @@ function FormationResumeBlockAdmission({
? "average"
: "hard";

console.log(formationEtablissement?.indicateurEntree);
return (
<FormationResumeBlock title={"L'admission"} icon={"ri-calendar-check-line"} anchor="l-admission">
<>
Expand All @@ -102,9 +104,11 @@ function FormationResumeBlockAdmission({
<Tag square level="easy">
Taux de pression faible
</Tag>
<Tag square level="easy">
Nombreuses places
</Tag>
{!isNil(effectifs) && !isNil(capacite) && capacite - effectifs > 0 && (
<Tag square level="easy">
Places libres l’an dernier
</Tag>
)}
</>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import useGetFormations from "../hooks/useGetFormations";
import { useFormationsSearch } from "../context/FormationsSearchContext";
import { isNil } from "lodash-es";
import { UserLocation } from "#/types/userLocation";
import { pluralize } from "#/app/utils/stringUtils";

const FormationsMap = dynamic(() => import("#/app/(accompagnateur)/components/FormationsMap"), {
ssr: false,
Expand Down Expand Up @@ -127,6 +128,9 @@ export default function ResearchFormationsResult({
const formationsIsochrone = useMemo(() => formations.filter((f) => !isNil(f.etablissement.accessTime)), [formations]);
const formationsCar = useMemo(() => formations.filter((f) => isNil(f.etablissement.accessTime)), [formations]);

const totalIsochrone = useMemo(() => pagination?.totalIsochrone || 0, [pagination]);
const totalCar = useMemo(() => (pagination ? pagination.total - (pagination.totalIsochrone || 0) : 0), [pagination]);

if (isLoading) {
return (
<Box
Expand Down Expand Up @@ -199,7 +203,7 @@ export default function ResearchFormationsResult({
<Grid container spacing={2}>
<Grid item xs={12}>
<Typography variant="h6">
À pied ou en transports en commun : {pagination?.totalIsochrone} formations
À pied ou en transports en commun : {totalIsochrone} {pluralize("formation", totalIsochrone)}
</Typography>
</Grid>

Expand All @@ -226,8 +230,7 @@ export default function ResearchFormationsResult({
<Grid container spacing={2} style={{ marginTop: "2rem" }}>
<Grid item xs={12}>
<Typography variant="h6">
Un peu plus loin dans l&apos;académie, en voiture :{" "}
{pagination ? pagination.total - (pagination.totalIsochrone || 0) : 0} formations
Un peu plus loin dans l&apos;académie, en voiture : {totalCar} {pluralize("formation", totalCar)}
</Typography>
</Grid>

Expand Down
4 changes: 2 additions & 2 deletions ui/app/(accompagnateur)/recherche/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ function ResearchFormationsParameter() {

export default function Page() {
return (
<>
<div>
<Title pageTitle="Recherche de formations" />
<Suspense>
<SearchHeader />
<FormationsSearchProvider>
<ResearchFormationsParameter />
</FormationsSearchProvider>
</Suspense>
</>
</div>
);
}
4 changes: 2 additions & 2 deletions ui/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function MainLayout({ children }: { children: JSX.Element }) {
<>
<Title />
<Layout header={<Header title={title} tagline={tagline} />} title={title}>
<>
<div>
{children}
<ConsentBannerAndConsentManagement />
<Footer
Expand Down Expand Up @@ -50,7 +50,7 @@ export default function MainLayout({ children }: { children: JSX.Element }) {
},
]}
/>
</>
</div>
</Layout>
</>
</RootLayout>
Expand Down
3 changes: 3 additions & 0 deletions ui/app/utils/stringUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function pluralize(str: string, count: number): string {
return str + (count > 1 ? "s" : "");
}

0 comments on commit ed5e1f4

Please sign in to comment.