Skip to content

Commit

Permalink
fix: suppression de buildMongoFilters (#3463)
Browse files Browse the repository at this point in the history
  • Loading branch information
moroine authored Jan 9, 2024
1 parent 552d12d commit 5f5cd06
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 369 deletions.
143 changes: 8 additions & 135 deletions server/src/common/actions/helpers/filters.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { subYears } from "date-fns";
import { getAnneesScolaireListFromDate } from "shared";
import { z } from "zod";

import { SIRET_REGEX } from "@/common/constants/validations";
import { escapeRegExp } from "@/common/utils/regexUtils";
import { isValidUAI } from "@/common/utils/validationUtils";

export const organismeLookup = {
from: "organismes",
localField: "organisme_id",
Expand All @@ -20,63 +14,22 @@ export interface FilterConfiguration {
transformValue?: (value: any) => any;
}

export const organismesFiltersSchema = {
export const territoireFiltersSchema = {
organisme_regions: z.preprocess((str: any) => str.split(","), z.array(z.string())).optional(),
organisme_departements: z.preprocess((str: any) => str.split(","), z.array(z.string())).optional(),
organisme_academies: z.preprocess((str: any) => str.split(","), z.array(z.string())).optional(),
organisme_bassinsEmploi: z.preprocess((str: any) => str.split(","), z.array(z.string())).optional(),
};

export type OrganismesFilters = z.infer<z.ZodObject<typeof organismesFiltersSchema>>;

export const organismesFiltersConfigurations: { [key in keyof Required<OrganismesFilters>]: FilterConfiguration } = {
organisme_departements: {
matchKey: "adresse.departement",
transformValue: (value) => ({ $in: value }),
},
organisme_regions: {
matchKey: "adresse.region",
transformValue: (value) => ({ $in: value }),
},
organisme_academies: {
matchKey: "adresse.academie",
transformValue: (value) => ({ $in: value }),
},
organisme_bassinsEmploi: {
matchKey: "adresse.bassinEmploi",
transformValue: (value) => ({ $in: value }),
},
};
export type TerritoireFilters = z.infer<z.ZodObject<typeof territoireFiltersSchema>>;

export const effectifsFiltersSchema = {
...organismesFiltersSchema,
date: z.preprocess((str: any) => new Date(str), z.date()),
// Filtre des effectifs par territoire
export const effectifsFiltersTerritoireSchema = {
...territoireFiltersSchema,
date: z.preprocess((str: any) => new Date(str ?? Date.now()), z.date()),
};

export type EffectifsFilters = z.infer<z.ZodObject<typeof effectifsFiltersSchema>>;

export const effectifsFiltersConfigurations: { [key in keyof Required<EffectifsFilters>]: FilterConfiguration } = {
date: {
matchKey: "annee_scolaire",
transformValue: (value) => ({ $in: getAnneesScolaireListFromDate(value) }),
},
organisme_departements: {
matchKey: "_computed.organisme.departement",
transformValue: (value) => ({ $in: value }),
},
organisme_regions: {
matchKey: "_computed.organisme.region",
transformValue: (value) => ({ $in: value }),
},
organisme_academies: {
matchKey: "_computed.organisme.academie",
transformValue: (value) => ({ $in: value }),
},
organisme_bassinsEmploi: {
matchKey: "_computed.organisme.bassinEmploi",
transformValue: (value) => ({ $in: value }),
},
};
export type EffectifsFiltersTerritoire = z.infer<z.ZodObject<typeof effectifsFiltersTerritoireSchema>>;

// [min, max[
const intervalParTrancheAge = {
Expand All @@ -90,7 +43,7 @@ const intervalParTrancheAge = {
* Utilisé pour la recherche détaillée des indicateurs effectifs
*/
export const fullEffectifsFiltersSchema = {
...effectifsFiltersSchema,
...effectifsFiltersTerritoireSchema,
organisme_search: z.string().optional(),
organisme_reseaux: z.preprocess((str: any) => str.split(","), z.array(z.string())).optional(),
// apprenant_genre: z.string(),
Expand All @@ -110,83 +63,3 @@ export const fullEffectifsFiltersSchema = {
};

export type FullEffectifsFilters = z.infer<z.ZodObject<typeof fullEffectifsFiltersSchema>>;

export const fullEffectifsFiltersConfigurations: {
[key in keyof Required<FullEffectifsFilters>]: FilterConfiguration;
} = {
...effectifsFiltersConfigurations,
organisme_search: {
matchKey: "$or",
transformValue: (value) => {
if (isValidUAI(value)) {
return [{ "_computed.organisme.uai": value }];
}
if (SIRET_REGEX.test(value)) {
return [{ "_computed.organisme.siret": value }];
}
if (/^\d{3,}$/.test(value)) {
return [{ "_computed.organisme.siret": new RegExp(escapeRegExp(value)) }];
}
return [{ "_computed.organisme.nom": new RegExp(escapeRegExp(value)) }]; // TODO probablement ajouter un champ nom (enseigne + raison_sociale) de l'organisme
},
},
organisme_reseaux: {
matchKey: "_computed.organisme.reseaux",
transformValue: (value) => ({ $in: value }),
},

// apprenant_genre: {
// matchKey: "", // encore inconnu, INE ou civilité avec api v3 ?
// },
apprenant_tranchesAge: {
matchKey: "$or",
transformValue: (keys) =>
keys.map((key) => {
const [min, max] = intervalParTrancheAge[key];
return {
"apprenant.date_de_naissance": {
$lt: subYears(new Date(), min),
$gte: subYears(new Date(), max),
},
};
}),
},
// apprenant_rqth: {
// matchKey: "", // inconnu
// },

formation_annees: {
matchKey: "formation.annee",
transformValue: (value) => ({ $in: value }),
},
formation_niveaux: {
matchKey: "formation.niveau",
transformValue: (value) => ({ $in: value }),
},
formation_cfds: {
matchKey: "formation.cfd",
transformValue: (value) => ({ $in: value }),
},
formation_secteursProfessionnels: {
matchKey: "_computed.formation.codes_rome",
transformValue: (value) => ({ $in: value }),
},
};

export function buildMongoFilters<
Filters extends { [s: string]: any },
FiltersConfiguration = { [key in keyof Required<OrganismesFilters>]: FilterConfiguration },
>(filters: Filters, filtersConfiguration: FiltersConfiguration): any[] {
return Object.entries(filters).reduce((matchFilters, [filterName, filterValue]) => {
const filterConfiguration = filtersConfiguration[filterName];
if (!filterConfiguration) {
return matchFilters;
}
return [
...matchFilters,
{
[filterConfiguration.matchKey]: filterConfiguration.transformValue?.(filterValue) ?? filterValue,
},
];
}, [] as any[]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { strict as assert } from "assert";

import { buildEffectifMongoFilters } from "./effectifs-filters";

const currentDate = new Date("2023-02-14T10:00:00Z");

describe("Filtres Indicateurs", () => {
describe("buildEffectifMongoFilters()", () => {
it("Gère le filtre date uniquement", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
});
});

it("Gère le filtre organisme_departements", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
organisme_departements: ["56"],
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
"_computed.organisme.departement": {
$in: ["56"],
},
});
});

it("Gère le filtre organisme_regions", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
organisme_regions: ["25"],
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
"_computed.organisme.region": {
$in: ["25"],
},
});
});

it("Gère le filtre organisme_reseaux", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
organisme_reseaux: ["AGRI"],
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
"_computed.organisme.reseaux": {
$in: ["AGRI"],
},
});
});

it("Gère le filtre formation_cfds", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
formation_cfds: ["25021000"],
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
"formation.cfd": {
$in: ["25021000"],
},
});
});

it("Gère le filtre formation_niveaux", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
formation_niveaux: ["2"],
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
"formation.niveau": {
$in: ["2"],
},
});
});

it("Gère tous les filtres en même temps", () => {
const stages = buildEffectifMongoFilters({
date: currentDate,
organisme_regions: ["25"],
organisme_departements: ["56"],
organisme_reseaux: ["AGRI"],
formation_cfds: ["25021000"],
formation_niveaux: ["2"],
});
assert.deepStrictEqual(stages, {
annee_scolaire: {
$in: ["2023-2023", "2022-2023"],
},
"_computed.organisme.region": {
$in: ["25"],
},
"_computed.organisme.departement": {
$in: ["56"],
},
"_computed.organisme.reseaux": {
$in: ["AGRI"],
},
"formation.cfd": {
$in: ["25021000"],
},
"formation.niveau": {
$in: ["2"],
},
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { subYears } from "date-fns";
import { Filter } from "mongodb";
import { assertUnreachable, entries, getAnneesScolaireListFromDate } from "shared";

import { SIRET_REGEX } from "@/common/constants/validations";
import { Effectif } from "@/common/model/@types";
import { escapeRegExp } from "@/common/utils/regexUtils";
import { isValidUAI } from "@/common/utils/validationUtils";

import { FullEffectifsFilters } from "../../helpers/filters";

// [min, max[
const intervalParTrancheAge = {
"-18": [0, 18],
"18-20": [18, 21],
"21-25": [21, 26],
"26+": [26, 999],
};

function buildOrganismeSearchCondition(value: string) {
if (isValidUAI(value)) {
return [{ "_computed.organisme.uai": value }];
}
if (SIRET_REGEX.test(value)) {
return [{ "_computed.organisme.siret": value }];
}
if (/^\d{3,}$/.test(value)) {
return [{ "_computed.organisme.siret": new RegExp(escapeRegExp(value)) }];
}
return [{ "_computed.organisme.nom": new RegExp(escapeRegExp(value)) }]; // TODO probablement ajouter un champ nom (enseigne + raison_sociale) de l'organisme
}

export function buildEffectifMongoFilters(filters: FullEffectifsFilters): Filter<Effectif> {
return entries(filters).reduce((acc: Filter<Effectif>, [key, value]) => {
switch (key) {
case "date":
acc["annee_scolaire"] = { $in: getAnneesScolaireListFromDate(value) };
break;
case "organisme_regions":
acc["_computed.organisme.region"] = { $in: value };
break;
case "organisme_departements":
acc["_computed.organisme.departement"] = { $in: value };
break;
case "organisme_academies":
acc["_computed.organisme.academie"] = { $in: value };
break;
case "organisme_bassinsEmploi":
acc["_computed.organisme.bassinEmploi"] = { $in: value };
break;
case "organisme_search":
acc["$or"] = buildOrganismeSearchCondition(value);
break;
case "organisme_reseaux":
acc["_computed.organisme.reseaux"] = { $in: value };
break;
case "apprenant_tranchesAge":
acc["$or"] = value.map((key) => {
const [min, max] = intervalParTrancheAge[key];
return {
"apprenant.date_de_naissance": {
$lt: subYears(new Date(), min),
$gte: subYears(new Date(), max),
},
};
});
break;
case "formation_annees":
acc["formation.annee"] = { $in: value };
break;
case "formation_niveaux":
acc["formation.niveau"] = { $in: value };
break;
case "formation_cfds":
acc["formation.cfd"] = { $in: value };
break;
case "formation_secteursProfessionnels":
acc["_computed.formation.codes_rome"] = { $in: value };
break;
default:
assertUnreachable(key);
}

return acc;
}, {});
}
Loading

0 comments on commit 5f5cd06

Please sign in to comment.