feat: stats sociales v2

wip-related-pages
Sébastien Arod 2024-09-07 22:11:20 +02:00
parent 49d76832d5
commit 16cc607b9c
8 changed files with 157 additions and 99 deletions

View File

@ -1,6 +1,10 @@
import { Period } from "../period/Period";
import { isPeriodContaining } from "../period/isPeriodContaining";
import { TypeEvenement } from "./TypeEvenement";
import { typesEvenementsPenal } from "./TypeEvenementsPenal";
import { TypeEvenementsPenal } from "./TypeEvenementsPenal";
import { typesEvenementsSocial as typesEvenementsCivil } from "./TypeEvenementsSocial";
import { TypesEvenementsSocial as TypesEvenementsCivil } from "./TypeEvenementsSocial";
export type EvenementFamille = Readonly<{
notionId: string;
@ -12,8 +16,10 @@ export type EvenementFamille = Readonly<{
}>;
export function isProcedurePenale(evenement: EvenementFamille): boolean {
return categorieEvenement[evenement.Type] === "Procédure Pénale" && evenement.Type !== "Validation désobéissance"
&& evenement.Type !== "Mise en demeure de scolarisation";
return (
typesEvenementsPenal.includes(evenement.Type as TypeEvenementsPenal) &&
evenement.Type !== "Mise en demeure de scolarisation"
);
}
export function isCompositionPenale(evenement: EvenementFamille): boolean {
@ -32,56 +38,9 @@ export function isCRPC(evenement: EvenementFamille): boolean {
}
export function isProcedureCivile(evenement: EvenementFamille): boolean {
return categorieEvenement[evenement.Type] === "Procédure Civile";
return typesEvenementsCivil.includes(evenement.Type as TypesEvenementsCivil);
}
const categorieEvenement: {
[evt in TypeEvenement]: CategorieEvenement;
} = {
// Procédure civile/social
["Signalement au procureur"]: "Procédure Civile",
["Classement social sans suite"]: "Procédure Civile",
["Enquête sociale"]: "Procédure Civile",
["Information préoccupante"]: "Procédure Civile",
["Juge pour enfants"]: "Procédure Civile",
["Audition des enfants"]: "Procédure Civile",
["Assistance éducative"]: "Procédure Civile",
["Contrôle forcé"]: "Procédure Civile",
// Procédure pénale
["Récidive gendarmerie"]: "Procédure Pénale",
["Appel du jugement"]: "Procédure Pénale",
["Tribunal de police judiciaire"]: "Procédure Pénale",
["Mise en demeure de scolarisation"]: "Procédure Pénale",
["Audition gendarmerie / police"]: "Procédure Pénale",
["Gendarmerie/Forces de l'ordre"]: "Procédure Pénale",
["Passage police municipale"]: "Procédure Pénale",
["Convocation procureur"]: "Procédure Pénale",
["Audition procureur"]: "Procédure Pénale",
["Composition pénale refusée"]: "Procédure Pénale",
["Composition pénale acceptée"]: "Procédure Pénale",
["Classement pénal sans suite"]: "Procédure Pénale",
["Tribunal correctionnel"]: "Procédure Pénale",
["Convocation CRPC"]: "Procédure Pénale",
["Audience CRPC"]: "Procédure Pénale",
["Refus CRPC"]: "Procédure Pénale",
["Acceptation CRPC"]: "Procédure Pénale",
["Rappel à la loi"]: "Procédure Pénale",
["Validation désobéissance"]: "Procédure Pénale",
// Autre
["Plaidoirie"]: "Autre",
["Refus de contrôle"]: "Autre",
["Administrateur AD'HOC"]: "Autre",
["Signalement"]: "Autre",
["Contrôle URSSAF"]: "Autre",
["Contrôle fiscal"]: "Autre",
};
export type CategorieEvenement =
| "Procédure Pénale"
| "Procédure Civile"
| "Autre";
export function isEvenementInPeriod(
evt: EvenementFamille,
period: Period
@ -97,12 +56,6 @@ export function isEvenementBefore(evt: EvenementFamille, date: Date): boolean {
return evt.Date < date;
}
export function isValidEvenementFamille(str: string | null): boolean {
return (
str === null ||
Object.prototype.hasOwnProperty.call(categorieEvenement, str)
);
}
export function isGendarmerie(e: EvenementFamille): boolean {
return (
e.Type === "Audition gendarmerie / police" ||
@ -112,8 +65,13 @@ export function isGendarmerie(e: EvenementFamille): boolean {
);
}
export function isAuditionProcureurOuCRPC(e: EvenementFamille): boolean {
return e.Type === "Audition procureur" || e.Type === "Audience CRPC";
}
export function isInformationPreoccupante(e: EvenementFamille): boolean {
return (
e.Type === "Audition procureur" ||
e.Type === "Audience CRPC"
e.Type === "Information préoccupante 1" ||
e.Type === "Information préoccupante 2" ||
e.Type === "Information préoccupante 3"
);
}

View File

@ -1,37 +1,6 @@
export const typesEvenementsPenal = [
"Récidive gendarmerie",
"Appel du jugement",
"Tribunal de police judiciaire",
"Mise en demeure de scolarisation",
"Audition gendarmerie / police",
"Convocation procureur",
"Audition procureur",
"Composition pénale refusée",
"Composition pénale acceptée",
"Classement pénal sans suite",
"Tribunal correctionnel",
"Convocation CRPC",
"Plaidoirie",
"Audience CRPC",
"Refus CRPC",
"Acceptation CRPC", // PLaceholder see does not exist in Notion yet // See https://discord.com/channels/990921361121746984/1245360366322585691/1248260713634336839
"Rappel à la loi",
"Passage police municipale",
"Administrateur AD'HOC",
"Gendarmerie/Forces de l'ordre",
] as const;
import { typesEvenementsPenal } from "./TypeEvenementsPenal";
import { typesEvenementsSocial } from "./TypeEvenementsSocial";
export const typesEvenementsSocial = [
"Information préoccupante 1",
"Information préoccupante 2",
"Information préoccupante 3",
"Classement social sans suite",
"Enquête sociale",
"Juge pour enfants",
"Audition des enfants",
"Assistance éducative",
"Signalement",
];
export const typesEvenements = [
...typesEvenementsPenal,
...typesEvenementsSocial,

View File

@ -0,0 +1,23 @@
export type TypeEvenementsPenal = (typeof typesEvenementsPenal)[number];
export const typesEvenementsPenal = [
"Récidive gendarmerie",
"Appel du jugement",
"Tribunal de police judiciaire",
"Mise en demeure de scolarisation",
"Audition gendarmerie / police",
"Convocation procureur",
"Audition procureur",
"Composition pénale refusée",
"Composition pénale acceptée",
"Classement pénal sans suite",
"Tribunal correctionnel",
"Convocation CRPC",
"Plaidoirie",
"Audience CRPC",
"Refus CRPC",
"Acceptation CRPC", // PLaceholder see does not exist in Notion yet // See https://discord.com/channels/990921361121746984/1245360366322585691/1248260713634336839
"Rappel à la loi",
"Passage police municipale",
"Administrateur AD'HOC",
"Gendarmerie/Forces de l'ordre",
] as const;

View File

@ -0,0 +1,12 @@
export type TypesEvenementsSocial = (typeof typesEvenementsSocial)[number];
export const typesEvenementsSocial = [
"Information préoccupante 1",
"Information préoccupante 2",
"Information préoccupante 3",
"Classement social sans suite",
"Enquête sociale",
"Juge pour enfants",
"Audition des enfants",
"Assistance éducative",
"Signalement",
] as const;

View File

@ -1,4 +1,3 @@
import { isValidEvenementFamille } from "./EvenementFamille";
import { Famille, isExResistant, isResistant } from "./Famille";
export function checkDataConsistency(families: Famille[]): ConsistencyReport {

View File

@ -10,6 +10,8 @@ import { computeStatsPenales } from "./statistiques/v2/penales/computeStatsPenal
import { statsPenalesDesc } from "./statistiques/v2/penales/StatsPenales";
import { computeStatsGenerales } from "./statistiques/v2/generales/computeStatsGenerales";
import { statsGeneralesDesc } from "./statistiques/v2/generales/StatsGenerales";
import { computeStatsSociales } from "./statistiques/v2/sociales/computeStatsSociales";
import { statsSocialesDesc } from "./statistiques/v2/sociales/StatsSociales";
type ProcessOptions = {
dryRun: boolean;
@ -71,8 +73,9 @@ function buildProcessOptions(): ProcessOptions {
JSON.stringify(statsParAnciennete, null, " ")
);
const statsPenales = computeStatsPenales(familles);
const statsGenerales = computeStatsGenerales(familles);
const statsPenales = computeStatsPenales(familles);
const statsSociales = computeStatsSociales(familles);
if (options.dryRun) {
console.log(
@ -83,7 +86,11 @@ function buildProcessOptions(): ProcessOptions {
writeFileSync(
"./el-stats-v2.json",
JSON.stringify(
{ generales: statsGenerales, penales: statsPenales },
{
generales: statsGenerales,
penales: statsPenales,
sociales: statsSociales,
},
null,
" "
)
@ -92,19 +99,23 @@ function buildProcessOptions(): ProcessOptions {
console.log("Publishing statistics...");
await publishStatisticsToNotion(elStats, currentDate, notionClient);
await publishStatsToPage(
notionClient,
"313751fb-daed-4b33-992f-c86d7ac2de37",
statsGeneralesDesc,
statsGenerales
);
await publishStatsToPage(
notionClient,
"969eac5c-a4eb-49d4-b4ad-c341c9c4c785",
statsPenalesDesc,
statsPenales
);
await publishStatsToPage(
notionClient,
"313751fb-daed-4b33-992f-c86d7ac2de37",
statsGeneralesDesc,
statsGenerales
"68a8c03a-a4a2-4ff3-b044-7c8dbbdc28ce",
statsSocialesDesc,
statsSociales
);
}
})();

View File

@ -0,0 +1,38 @@
import { StatsType } from "../StatsDesc";
export const statsSocialesDesc = {
label: "Stats Sociales",
stats: {
nbFamillesProcedureCivile: {
label: "Nb Familles avec une procedure sociale",
},
nbFamilleAvecClassementSansSuite: {
label: "Nb Familles avec un classement sans suite",
},
nbFamilleAvecIP: {
label: "Nb Familles avec une Information Préoccupante",
},
nbFamilleAvecAssistanceEducative: {
label: "Nb Familles avec une Assistance educative",
},
nbFamilleAvecAuditionDesEnfants: {
label: "Nb Familles avec audition des enfants",
},
jugePourEnfant: {
label: "Juge pour enfant",
stats: {
nbFamillesPassees: {
label: "Nb familles passées",
},
nbFamillesConvoquées: {
label: "Nb familles convoquées",
},
},
},
},
} as const;
export type StatsSociales = StatsType<typeof statsSocialesDesc>;

View File

@ -0,0 +1,48 @@
import {
isEvenementBefore,
isInformationPreoccupante,
isProcedureCivile,
} from "../../../data/EvenementFamille";
import { Famille } from "../../../data/Famille";
import { filterFamillesWithOneOfEvenements } from "../filterFamillesWithOneOfEvenements";
import { filterFamillesWithOneOfEvenementsOfType } from "../filterFamillesWithOneOfEvenementsOfType";
import { StatsSociales } from "./StatsSociales";
export function computeStatsSociales(familles: Famille[]): StatsSociales {
const now = new Date();
const statsCiviles: StatsSociales = {
nbFamillesProcedureCivile: filterFamillesWithOneOfEvenements(
familles,
(e) => isProcedureCivile(e)
).length,
nbFamilleAvecIP: filterFamillesWithOneOfEvenements(
familles,
isInformationPreoccupante
).length,
nbFamilleAvecAssistanceEducative: filterFamillesWithOneOfEvenementsOfType(
familles,
"Assistance éducative"
).length,
nbFamilleAvecAuditionDesEnfants: filterFamillesWithOneOfEvenementsOfType(
familles,
"Audition des enfants"
).length,
jugePourEnfant: {
nbFamillesPassees: filterFamillesWithOneOfEvenements(
familles,
(e) => e.Type === "Juge pour enfants" && isEvenementBefore(e, now)
).length,
nbFamillesConvoquées: filterFamillesWithOneOfEvenements(
familles,
(e) => e.Type === "Juge pour enfants" && !isEvenementBefore(e, now)
).length,
},
nbFamilleAvecClassementSansSuite: filterFamillesWithOneOfEvenementsOfType(
familles,
"Classement social sans suite"
).length,
};
return statsCiviles;
}