Skip to content

Commit

Permalink
feat: millesime unique pour Insersup (#314)
Browse files Browse the repository at this point in the history
  • Loading branch information
K4ST0R authored Nov 28, 2024
1 parent fcec2e9 commit ad3efe3
Show file tree
Hide file tree
Showing 18 changed files with 1,681 additions and 142 deletions.
39 changes: 39 additions & 0 deletions server/src/common/repositories/formationStats.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StatsRepository } from "./base.js";
import { dbCollection } from "#src/common/db/mongodb.js";
import { name } from "#src/common/db/collections/formationsStats.js";
import { getMillesimeFormationsYearFrom } from "#src/common/stats.js";

export class FormationStatsRepository extends StatsRepository {
constructor() {
Expand Down Expand Up @@ -33,6 +34,44 @@ export class FormationStatsRepository extends StatsRepository {

return result ? result.map((data) => data.millesime) : [];
}

// Retourne les formations du supérieur possédant un millésime aggregé et un millésime unique
async findMillesimeInDouble(millesime, filiere = "superieur") {
const millesimeYear = getMillesimeFormationsYearFrom(millesime);

return await dbCollection(this.getCollection())
.aggregate([
{ $match: { filiere, millesime: millesimeYear } },
{
$lookup: {
from: this.getCollection(),
localField: "uai",
foreignField: "uai",
as: "others",
let: { code_certification_base: "$code_certification" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ["$filiere", filiere] },
{ $eq: ["$$code_certification_base", "$code_certification"] },
{ $eq: ["$millesime", millesime] },
],
},
},
},
],
},
},
{
$match: {
"others.0": { $exists: true },
},
},
])
.toArray();
}
}

export default new FormationStatsRepository();
21 changes: 21 additions & 0 deletions server/src/common/stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ export function getLastMillesimesFormationsSup() {
return config.millesimes.formationsSup[config.millesimes.formationsSup.length - 1];
}

export function getLastMillesimesFormationsFor(filiere) {
return filiere === "superieur" ? getLastMillesimesFormationsSup() : getLastMillesimesFormations();
}

export function getLastMillesimesFormationsYearFor(filiere) {
const millesime = filiere === "superieur" ? getLastMillesimesFormationsSup() : getLastMillesimesFormations();
return millesime.split("_")[1];
}

export function getMillesimeFormationsFrom(millesime) {
return `${parseInt(millesime) - 1}_${millesime}`;
}

export function getMillesimeFormationsYearFrom(millesime) {
return millesime.split("_")[1];
}

export function getMillesimesRegionales() {
return config.millesimes.regionales;
}
Expand All @@ -92,6 +109,10 @@ export function getLastMillesimesRegionales() {
return config.millesimes.regionales[config.millesimes.regionales.length - 1];
}

export function isMillesimesYearSingle(millesime) {
return millesime.split("_").length === 1 ? true : false;
}

function divide({ dividend, divisor }) {
return {
compute: (data) => percentage(data[dividend], data[divisor]),
Expand Down
2 changes: 1 addition & 1 deletion server/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const config = {
millesimes: {
default: env.get("TRAJECTOIRES_PRO_MILLESIMES").default("2020,2021,2022").asArray(),
formations: env.get("TRAJECTOIRES_PRO_MILLESIMES_FORMATIONS").default("2019_2020,2020_2021,2021_2022").asArray(),
formationsSup: env.get("MILLESIMES_FORMATIONS_SUP").default("2020_2021,2021_2022").asArray(),
formationsSup: env.get("MILLESIMES_FORMATIONS_SUP").default("2019_2020,2020_2021,2021_2022").asArray(),
regionales: env.get("TRAJECTOIRES_PRO_MILLESIMES_REGIONALES").default("2019_2020,2020_2021,2021_2022").asArray(),
},
widget: {
Expand Down
6 changes: 3 additions & 3 deletions server/src/http/routes/certificationsRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export default () => {
{
...validators.codesCertifications(),
...validators.universe(),
millesime: Joi.string().default(getLastMillesimes()),
...validators.millesime(getLastMillesimes()),
...validators.vues(),
...validators.svg(),
},
Expand Down Expand Up @@ -164,7 +164,7 @@ export default () => {
hash: Joi.string(),
...validators.codesCertifications(),
...validators.universe(),
millesime: Joi.string().default(getLastMillesimes()),
...validators.millesime(getLastMillesimes()),
...validators.vues(),
...validators.widget("stats"),
},
Expand Down Expand Up @@ -236,7 +236,7 @@ export default () => {
{
...validators.codesCertifications(),
...validators.universe(),
millesime: Joi.string().default(null),
...validators.millesime(null),
...validators.vues(),
...validators.widget("stats"),
},
Expand Down
65 changes: 48 additions & 17 deletions server/src/http/routes/formationsRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import express from "express";
import { tryCatch } from "#src/http/middlewares/tryCatchMiddleware.js";
import { authMiddleware } from "#src/http/middlewares/authMiddleware.js";
import Joi from "joi";
import { flatten } from "lodash-es";
import * as validators from "#src/http/utils/validators.js";
import { validate } from "#src/http/utils/validators.js";
import { addCsvHeaders, addJsonHeaders, sendStats, sendImageOnError } from "#src/http/utils/responseUtils.js";
Expand All @@ -15,7 +16,11 @@ import { getStatsAsColumns } from "#src/common/utils/csvUtils.js";
import {
getLastMillesimesFormations,
getLastMillesimesFormationsSup,
getLastMillesimesFormationsYearFor,
getMillesimeFormationsFrom,
getMillesimeFormationsYearFrom,
transformDisplayStat,
isMillesimesYearSingle,
} from "#src/common/stats.js";
import BCNRepository from "#src/common/repositories/bcn.js";
import BCNSiseRepository from "#src/common/repositories/bcnSise.js";
Expand All @@ -36,7 +41,12 @@ async function formationStats({ uai, codeCertificationWithType, millesime }) {
const result = await FormationStatsRepository.first({
uai,
code_certification: code_certification,
millesime: formatMillesime(millesime),
millesime: [
millesime,
isMillesimesYearSingle(millesime)
? getMillesimeFormationsFrom(millesime)
: getMillesimeFormationsYearFrom(millesime),
],
});

if (!result) {
Expand Down Expand Up @@ -99,12 +109,35 @@ export default () => {
...(millesimes.length === 0
? {
$or: [
{ filiere: "superieur", millesime: getLastMillesimesFormationsSup() },
{ filiere: { $ne: "superieur" }, millesime: getLastMillesimesFormations() },
{
filiere: "superieur",
millesime: {
$in: [
getMillesimeFormationsYearFrom(getLastMillesimesFormationsSup()),
getLastMillesimesFormationsSup(),
],
},
},
{
filiere: { $ne: "superieur" },
millesime: {
$in: [
getMillesimeFormationsYearFrom(getLastMillesimesFormations()),
getLastMillesimesFormations(),
],
},
},
],
}
: {
millesime: millesimes,
millesime: flatten(
millesimes.map((m) => {
return [
m,
isMillesimesYearSingle(m) ? getMillesimeFormationsFrom(m) : getMillesimeFormationsYearFrom(m),
];
})
),
}),
},
{
Expand Down Expand Up @@ -161,15 +194,14 @@ export default () => {
...validators.uai(),
...validators.codeCertification(),
...validators.universe(),
millesime: Joi.string().default(null),
...validators.millesime(null),
...validators.svg(),
}
);
const codeCertificationWithType = formatCodeCertificationWithType(code_certification);
const millesime =
millesimeBase ||
(codeCertificationWithType.filiere === "superieur" && getLastMillesimesFormationsSup()) ||
getLastMillesimesFormations();
const millesime = formatMillesime(
millesimeBase || getLastMillesimesFormationsYearFor(codeCertificationWithType.filiere)
);

return sendImageOnError(
async () => {
Expand Down Expand Up @@ -200,21 +232,20 @@ export default () => {
hash: Joi.string(),
...validators.uai(),
...validators.codeCertification(),
millesime: Joi.string().default(""),
...validators.millesime(null),
...validators.widget("stats"),
}
);

const codeCertificationWithType = formatCodeCertificationWithType(code_certification);
const millesime =
millesimeBase ||
(codeCertificationWithType.filiere === "superieur" && getLastMillesimesFormationsSup()) ||
getLastMillesimesFormations();
const millesime = formatMillesime(
millesimeBase || getLastMillesimesFormationsYearFor(codeCertificationWithType.filiere)
);

try {
const stats = await formationStats({ uai, codeCertificationWithType, millesime });
const etablissement = await AcceEtablissementRepository.first({ numero_uai: uai });
const data = await formatDataWidget({ stats, millesime, etablissement });
const data = await formatDataWidget({ stats, etablissement });

const widget = await getUserWidget({
hash,
Expand All @@ -240,7 +271,7 @@ export default () => {
options,
data: {
error: err.name,
millesimes: formatMillesime(millesime).split("_"),
millesimes: millesime.split("_"),
code_certification,
uai,
},
Expand All @@ -260,7 +291,7 @@ export default () => {
{
...validators.uai(),
...validators.codeCertification(),
millesime: Joi.string().default(null),
...validators.millesime(null),
...validators.widget("stats"),
}
);
Expand Down
6 changes: 3 additions & 3 deletions server/src/http/routes/regionalesRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export default () => {
...validators.region(),
...validators.codesCertifications(),
...validators.universe(),
millesime: Joi.string().default(getLastMillesimesRegionales()),
...validators.millesime(getLastMillesimesRegionales()),
...validators.vues(),
...validators.svg(),
},
Expand Down Expand Up @@ -203,7 +203,7 @@ export default () => {
...validators.region(),
...validators.codesCertifications(),
...validators.universe(),
millesime: Joi.string().default(getLastMillesimesRegionales()),
...validators.millesime(getLastMillesimesRegionales()),
...validators.vues(),
...validators.widget("stats"),
},
Expand Down Expand Up @@ -280,7 +280,7 @@ export default () => {
...validators.region(),
...validators.codesCertifications(),
...validators.universe(),
millesime: Joi.string().default(null),
...validators.millesime(null),
...validators.vues(),
...validators.widget("stats"),
},
Expand Down
24 changes: 23 additions & 1 deletion server/src/http/utils/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,22 @@ const customJoi = Joi.extend(

return { value, errors: errors ? helpers.error("codes_certification.invalid") : null };
},
}),

(joi) => ({
type: "millesime",
base: joi.string(),
messages: {
"millesime.invalid": "{{#label}} must have format XXXX or XXXX-1_XXXX",
},
validate(value, helpers) {
const part = value.match(/^([0-9]{4})(_([0-9]{4}))?$/);
if (!part || (part[3] && parseInt(part[3]) < parseInt(part[1]))) {
return { value, errors: helpers.error("millesime.invalid") };
}

return { value, errors: null };
},
})
);

Expand Down Expand Up @@ -164,6 +180,12 @@ export function region() {
};
}

export function millesime(defaultMillesime = null) {
return {
millesime: customJoi.millesime().default(defaultMillesime),
};
}

export function exports() {
return {
ext: Joi.string().valid("json", "csv").default("json"),
Expand Down Expand Up @@ -209,7 +231,7 @@ export function vues() {

export function statsList(defaultMillesimes = []) {
return {
millesimes: arrayOf(Joi.string().required()).default(defaultMillesimes),
millesimes: arrayOf(customJoi.millesime().required()).default(defaultMillesimes),
code_certifications: customJoi.codesCertification(),
...universe("code_certifications"),
...exports(),
Expand Down
4 changes: 2 additions & 2 deletions server/src/http/utils/widgetUtils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { buildDescriptionFiliere, buildDescription } from "#src/common/stats.js";
import { formatMillesime } from "#src/http/utils/formatters.js";

export async function formatDataWidget({ stats, millesime, region = null, etablissement = null }) {
export async function formatDataWidget({ stats, region = null, etablissement = null }) {
const description = buildDescription(stats);

const data = {
Expand All @@ -12,7 +12,7 @@ export async function formatDataWidget({ stats, millesime, region = null, etabli
{ name: "emploi", value: stats.taux_en_emploi_6_mois },
{ name: "autres", value: stats.taux_autres_6_mois },
],
millesimes: formatMillesime(millesime).split("_"),
millesimes: formatMillesime(stats.millesime).split("_"),
description,
// TODO: fix libelle BCN
formationLibelle: stats.libelle,
Expand Down
12 changes: 12 additions & 0 deletions server/src/jobs/stats/computeUAI.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ async function computeUAIBase(millesime, result, handleError) {
async (stats) => {
const { uai, code_formation_diplome, millesime, filiere } = stats;

// On ne connait pas le type de l'uai pour le supérieur
if (filiere === "superieur") {
return {
uai: stats.uai,
uai_type: "inconnu",
uai_donnee: stats.uai,
uai_donnee_type: "inconnu",
code_certification: stats.code_certification,
millesime: millesime,
};
}

// Le lieu de formation, le formateur et le gestionnaire sont identiques pour la voie scolaire
if (filiere !== "apprentissage") {
return {
Expand Down
Loading

0 comments on commit ad3efe3

Please sign in to comment.