-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(formation): ajout de la page formation (#492)
feat(formation): ajout de la page formation
- Loading branch information
Showing
110 changed files
with
6,877 additions
and
157 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -176,3 +176,10 @@ seed.gz | |
|
||
tsconfig.tsbuildinfo | ||
.infra_ | ||
|
||
|
||
# Vs code config | ||
.vscode/terminals.json | ||
|
||
# Cursor | ||
.cursorrules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
server/src/modules/data/usecases/getDomaineDeFormation/dependencies/getFilters.dep.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { getKbdClient } from "@/db/db"; | ||
import { | ||
isInPerimetreIJAcademie, | ||
isInPerimetreIJDepartement, | ||
isInPerimetreIJRegion, | ||
} from "@/modules/data/utils/isInPerimetreIJ"; | ||
|
||
export const getFilters = async () => { | ||
const regions = await getKbdClient() | ||
.selectFrom("region") | ||
.select(["region.libelleRegion as label", "region.codeRegion as value"]) | ||
.where(isInPerimetreIJRegion) | ||
.orderBy("region.libelleRegion", "asc") | ||
.execute(); | ||
|
||
const academies = await getKbdClient() | ||
.selectFrom("academie") | ||
.select([ | ||
"academie.libelleAcademie as label", | ||
"academie.codeAcademie as value", | ||
"academie.codeRegion as codeRegion", | ||
]) | ||
.where(isInPerimetreIJAcademie) | ||
.orderBy("academie.libelleAcademie", "asc") | ||
.execute(); | ||
|
||
const departements = await getKbdClient() | ||
.selectFrom("departement") | ||
.select([ | ||
"departement.libelleDepartement as label", | ||
"departement.codeDepartement as value", | ||
"departement.codeAcademie as codeAcademie", | ||
"departement.codeRegion as codeRegion", | ||
]) | ||
.where(isInPerimetreIJDepartement) | ||
.orderBy("departement.libelleDepartement", "asc") | ||
.execute(); | ||
|
||
return { | ||
regions, | ||
academies, | ||
departements, | ||
}; | ||
}; |
105 changes: 105 additions & 0 deletions
105
server/src/modules/data/usecases/getDomaineDeFormation/dependencies/getFormations.dep.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { sql } from "kysely"; | ||
import { CURRENT_RENTREE } from "shared"; | ||
import type { formationSchema } from "shared/routes/schemas/get.domaine-de-formation.codeNsf.schema"; | ||
import { getDateRentreeScolaire } from "shared/utils/getRentreeScolaire"; | ||
import type { z } from "zod"; | ||
|
||
import { getKbdClient } from "@/db/db"; | ||
import { notHistoriqueUnlessCoExistant } from "@/modules/data/utils/notHistorique"; | ||
import { cleanNull } from "@/utils/noNull"; | ||
|
||
export const getFormations = async ({ | ||
codeNsf, | ||
codeRegion, | ||
codeDepartement, | ||
codeAcademie, | ||
}: { | ||
codeNsf: string; | ||
codeRegion?: string; | ||
codeDepartement?: string; | ||
codeAcademie?: string; | ||
}) => | ||
getKbdClient() | ||
.with("formations", (wb) => | ||
wb | ||
.selectFrom("formationView") | ||
.innerJoin("niveauDiplome", "niveauDiplome.codeNiveauDiplome", "formationView.codeNiveauDiplome") | ||
.where("formationView.codeNsf", "=", codeNsf) | ||
.where((w) => notHistoriqueUnlessCoExistant(w, CURRENT_RENTREE)) | ||
.select((sb) => [ | ||
sb.ref("formationView.codeNsf").as("codeNsf"), | ||
sb.ref("formationView.cfd").as("cfd"), | ||
sb.ref("formationView.libelleFormation").as("libelleFormation"), | ||
sb.ref("formationView.dateOuverture").as("dateOuverture"), | ||
sb.ref("niveauDiplome.libelleNiveauDiplome").as("libelleNiveauDiplome"), | ||
sb.ref("niveauDiplome.codeNiveauDiplome").as("codeNiveauDiplome"), | ||
sb.ref("formationView.typeFamille").as("typeFamille"), | ||
]) | ||
.orderBy("formationView.libelleFormation", "asc") | ||
.distinct() | ||
) | ||
.with("formation_renovee", (wb) => | ||
wb | ||
.selectFrom("formations") | ||
.leftJoin("formationHistorique", "formationHistorique.cfd", "formations.cfd") | ||
.where("formations.dateOuverture", "<=", sql<Date>`${getDateRentreeScolaire(CURRENT_RENTREE)}`) | ||
.where("formationHistorique.ancienCFD", "in", (eb) => eb.selectFrom("formationEtablissement").select("cfd")) | ||
.select("formationHistorique.cfd") | ||
.distinct() | ||
) | ||
.with("formation_etab", (wb) => | ||
wb | ||
.selectFrom("formations") | ||
.leftJoin("formationEtablissement", "formations.cfd", "formationEtablissement.cfd") | ||
.innerJoin("dataEtablissement", "dataEtablissement.uai", "formationEtablissement.uai") | ||
.selectAll("formations") | ||
.select((sb) => [ | ||
sb.ref("formationEtablissement.uai").as("uai"), | ||
sb.ref("formationEtablissement.voie").as("voie"), | ||
sb.ref("dataEtablissement.codeRegion").as("codeRegion"), | ||
sb.ref("dataEtablissement.codeAcademie").as("codeAcademie"), | ||
sb.ref("dataEtablissement.codeDepartement").as("codeDepartement"), | ||
]) | ||
.$call((q) => { | ||
if (codeRegion) { | ||
return q.where("codeRegion", "=", codeRegion); | ||
} | ||
return q; | ||
}) | ||
.$call((q) => { | ||
if (codeAcademie) { | ||
return q.where("codeAcademie", "=", codeAcademie); | ||
} | ||
return q; | ||
}) | ||
.$call((q) => { | ||
if (codeDepartement) { | ||
return q.where("codeDepartement", "=", codeDepartement); | ||
} | ||
return q; | ||
}) | ||
) | ||
.selectFrom("formations") | ||
.leftJoin("formation_etab", "formations.cfd", "formation_etab.cfd") | ||
.selectAll("formations") | ||
.select((sb) => [ | ||
sb.fn.count<number>("formation_etab.uai").as("nbEtab"), | ||
sql<boolean>`bool_or(voie = 'apprentissage' OR voie IS NULL)`.as("apprentissage"), | ||
sql<boolean>`bool_or(voie = 'scolaire' OR voie IS NULL)`.as("scolaire"), | ||
sb.fn | ||
.coalesce(sql<boolean>`formations.cfd IN (SELECT cfd FROM formation_renovee)`, sql<boolean>`false`) | ||
.as("isFormationRenovee"), | ||
]) | ||
.distinct() | ||
.groupBy([ | ||
"formations.cfd", | ||
"formations.libelleFormation", | ||
"formations.libelleNiveauDiplome", | ||
"formations.codeNiveauDiplome", | ||
"formations.typeFamille", | ||
"formations.codeNsf", | ||
"formations.dateOuverture", | ||
]) | ||
.$castTo<z.infer<typeof formationSchema>>() | ||
.execute() | ||
.then(cleanNull); |
4 changes: 4 additions & 0 deletions
4
server/src/modules/data/usecases/getDomaineDeFormation/dependencies/getNsf.dep.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { getKbdClient } from "@/db/db"; | ||
|
||
export const getNsf = async (codeNsf: string) => | ||
getKbdClient().selectFrom("nsf").where("codeNsf", "=", codeNsf).selectAll().executeTakeFirst(); |
3 changes: 3 additions & 0 deletions
3
server/src/modules/data/usecases/getDomaineDeFormation/dependencies/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { getFilters } from "./getFilters.dep"; | ||
export { getFormations } from "./getFormations.dep"; | ||
export { getNsf } from "./getNsf.dep"; |
24 changes: 24 additions & 0 deletions
24
server/src/modules/data/usecases/getDomaineDeFormation/getDomaineDeFormation.route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { createRoute } from "@http-wizard/core"; | ||
import { ROUTES } from "shared/routes/routes"; | ||
|
||
import type { Server } from "@/server/server"; | ||
|
||
import { getDomaineDeFormation } from "./getDomaineDeFormation.usecase"; | ||
|
||
const ROUTE = ROUTES["[GET]/domaine-de-formation/:codeNsf"]; | ||
|
||
export const getDomaineDeFormationRoute = (server: Server) => { | ||
return createRoute(ROUTE.url, { | ||
method: ROUTE.method, | ||
schema: ROUTE.schema, | ||
}).handle((props) => | ||
server.route({ | ||
...props, | ||
handler: async (request, response) => { | ||
const { codeNsf } = request.params; | ||
const result = await getDomaineDeFormation(codeNsf, request.query); | ||
response.status(200).send(result); | ||
}, | ||
}) | ||
); | ||
}; |
39 changes: 39 additions & 0 deletions
39
server/src/modules/data/usecases/getDomaineDeFormation/getDomaineDeFormation.usecase.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Boom from "@hapi/boom"; | ||
import type { QueryFilters } from "shared/routes/schemas/get.domaine-de-formation.codeNsf.schema"; | ||
|
||
import { getFilters, getFormations, getNsf } from "./dependencies"; | ||
|
||
const getDomaineDeFormationFactory = | ||
( | ||
deps = { | ||
getNsf, | ||
getFilters, | ||
getFormations, | ||
} | ||
) => | ||
async (codeNsf: string, queryFilters: QueryFilters) => { | ||
const { codeRegion, codeDepartement, codeAcademie } = queryFilters; | ||
const [nsf, filters, formations] = await Promise.all([ | ||
deps.getNsf(codeNsf), | ||
deps.getFilters(), | ||
deps.getFormations({ | ||
codeNsf, | ||
codeRegion, | ||
codeDepartement, | ||
codeAcademie, | ||
}), | ||
]); | ||
|
||
if (!nsf) { | ||
throw Boom.notFound(`Le domaine de formation avec le code ${codeNsf} est inconnue`); | ||
} | ||
|
||
return { | ||
codeNsf, | ||
libelleNsf: nsf.libelleNsf, | ||
filters, | ||
formations, | ||
}; | ||
}; | ||
|
||
export const getDomaineDeFormation = getDomaineDeFormationFactory(); |
65 changes: 65 additions & 0 deletions
65
server/src/modules/data/usecases/getDomainesDeFormation/dependencies/getNsfsAndFormations.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { sql } from "kysely"; | ||
import { CURRENT_RENTREE } from "shared"; | ||
import type { NsfOption } from "shared/routes/schemas/get.domaine-de-formation.schema"; | ||
|
||
import { getKbdClient } from "@/db/db"; | ||
import { openForRentreeScolaire } from "@/modules/data/utils/openForRentreeScolaire"; | ||
import { getNormalizedSearchArray } from "@/modules/utils/normalizeSearch"; | ||
import { cleanNull } from "@/utils/noNull"; | ||
|
||
export const getNsfsAndFormations = async (search?: string) => { | ||
let baseQuery = getKbdClient() | ||
.selectFrom("formationView") | ||
.leftJoin("nsf", "nsf.codeNsf", "formationView.codeNsf") | ||
.select((sb) => [ | ||
sb.ref("nsf.libelleNsf").as("label"), | ||
sb.ref("formationView.codeNsf").as("value"), | ||
sb.ref("nsf.codeNsf").as("nsf"), | ||
sb.val("nsf").as("type"), | ||
]) | ||
.where("nsf.libelleNsf", "is not", null) | ||
.where((eb) => openForRentreeScolaire(eb, CURRENT_RENTREE)); | ||
|
||
if (search) { | ||
const searchArray = getNormalizedSearchArray(search); | ||
|
||
baseQuery = baseQuery | ||
.where((w) => | ||
w.and( | ||
searchArray.map((search_word) => w(sql`unaccent(${w.ref("nsf.libelleNsf")})`, "ilike", `%${search_word}%`)) | ||
) | ||
) | ||
.union( | ||
getKbdClient() | ||
.selectFrom("formationView") | ||
.leftJoin("nsf", "nsf.codeNsf", "formationView.codeNsf") | ||
.leftJoin("niveauDiplome", "niveauDiplome.codeNiveauDiplome", "formationView.codeNiveauDiplome") | ||
.where("nsf.libelleNsf", "is not", null) | ||
.select((sb) => [ | ||
sql<string>`concat( ${sb.ref( | ||
"niveauDiplome.libelleNiveauDiplome" | ||
)}, ' - ', ${sb.ref("formationView.libelleFormation")})`.as("label"), | ||
sb.ref("formationView.cfd").as("value"), | ||
sb.ref("nsf.codeNsf").as("nsf"), | ||
sb.val("formation").as("type"), | ||
]) | ||
.where((w) => | ||
w.and( | ||
searchArray.map((search_word) => | ||
w( | ||
sql`concat( | ||
unaccent(${w.ref("formationView.libelleFormation")}), | ||
' ', | ||
unaccent(${w.ref("formationView.cfd")}) | ||
)`, | ||
"ilike", | ||
`%${search_word}%` | ||
) | ||
) | ||
) | ||
) | ||
); | ||
} | ||
|
||
return baseQuery.orderBy("label", "asc").distinct().$castTo<NsfOption>().execute().then(cleanNull); | ||
}; |
24 changes: 24 additions & 0 deletions
24
server/src/modules/data/usecases/getDomainesDeFormation/getDomainesDeFormation.route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { createRoute } from "@http-wizard/core"; | ||
import { ROUTES } from "shared/routes/routes"; | ||
|
||
import type { Server } from "@/server/server"; | ||
|
||
import { getDomainesDeFormation } from "./getDomainesDeFormation.usecase"; | ||
|
||
const ROUTE = ROUTES["[GET]/domaine-de-formation"]; | ||
|
||
export const getDomainesDeFormationRoute = (server: Server) => { | ||
return createRoute(ROUTE.url, { | ||
method: ROUTE.method, | ||
schema: ROUTE.schema, | ||
}).handle((props) => | ||
server.route({ | ||
...props, | ||
handler: async (request, response) => { | ||
const { search } = request.query; | ||
const result = await getDomainesDeFormation(search); | ||
response.status(200).send(result); | ||
}, | ||
}) | ||
); | ||
}; |
8 changes: 8 additions & 0 deletions
8
server/src/modules/data/usecases/getDomainesDeFormation/getDomainesDeFormation.usecase.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { getNsfsAndFormations } from "./dependencies/getNsfsAndFormations"; | ||
|
||
const getDomainesDeFormationFactory = | ||
(deps = { getNsfsAndFormations }) => | ||
async (search?: string) => | ||
deps.getNsfsAndFormations(search); | ||
|
||
export const getDomainesDeFormation = getDomainesDeFormationFactory(); |
Oops, something went wrong.