mirror of
https://framagit.org/enfance-libre/statistiques
synced 2025-12-07 07:33:46 +00:00
chore: remove stats v1
This commit is contained in:
parent
f8109fe524
commit
b35a479c49
12 changed files with 45 additions and 612 deletions
|
|
@ -1,9 +1,7 @@
|
|||
import { Client } from "@notionhq/client";
|
||||
import { writeFileSync } from "fs";
|
||||
import { fetchFamiliesWithEventsFromNotion } from "./notion/fetch/fetchFamiliesWithEventsFromNotion";
|
||||
import { publishStatisticsToNotion } from "./notion/publish/v1/publishStatisticsToNotion";
|
||||
import { publishStatsToPage } from "./notion/publish/v2/publishStatsToPage";
|
||||
import { computeELStats } from "./statistiques/v1/computeELStats";
|
||||
import { computeStatsPenales } from "./statistiques/v2/penales/computeStatsPenales";
|
||||
import { statsPenalesDesc } from "./statistiques/v2/penales/StatsPenales";
|
||||
import { computeStatsGenerales } from "./statistiques/v2/generales/computeStatsGenerales";
|
||||
|
|
@ -20,6 +18,7 @@ import { typeEvenementsProcedurePenale } from "./data/TypeEvenementsPenal";
|
|||
import { nettoyerDonneesFamilles } from "./data/nettoyage/familles/preparerDonneesFamilles";
|
||||
import { statsAutresDesc } from "./statistiques/v2/autres/StatsAutres";
|
||||
import { computeStatsAutres } from "./statistiques/v2/autres/computeStatsAutres";
|
||||
import { updateUpdateDate as updateRootPageUpdateDate } from "./notion/publish/updateUpdateDate";
|
||||
|
||||
type ProcessOptions = {
|
||||
dryRun: boolean;
|
||||
|
|
@ -105,10 +104,7 @@ function buildProcessOptions(): ProcessOptions {
|
|||
const currentDate = new Date(Date.now());
|
||||
|
||||
console.log("Calcul des statistiques...");
|
||||
const elStats = computeELStats(familles, currentDate);
|
||||
|
||||
const statsGenerales = computeStatsGenerales(familles);
|
||||
|
||||
const statsPenales = computeStatsPenales(familles);
|
||||
const statsSociales = computeStatsSociales(familles);
|
||||
const statsAutres = computeStatsAutres(familles);
|
||||
|
|
@ -127,7 +123,6 @@ function buildProcessOptions(): ProcessOptions {
|
|||
console.log(
|
||||
"Dry run => Pas de publication. Les stats sont écrite localement dans el-stats-xxx"
|
||||
);
|
||||
writeFileSync("./el-stats-v1.json", JSON.stringify(elStats, null, " "));
|
||||
|
||||
writeFileSync(
|
||||
"./el-stats-v2.json",
|
||||
|
|
@ -145,7 +140,7 @@ function buildProcessOptions(): ProcessOptions {
|
|||
);
|
||||
} else {
|
||||
console.log("Publishing statistics...");
|
||||
await publishStatisticsToNotion(elStats, currentDate, notionClient);
|
||||
await updateRootPageUpdateDate(notionClient, currentDate);
|
||||
|
||||
const header = `Notes:
|
||||
- Dernière mise à jour le ${formatDate(currentDate, "dd/MM/yyyy à HH:mm")}
|
||||
|
|
|
|||
43
src/notion/publish/updateUpdateDate.ts
Normal file
43
src/notion/publish/updateUpdateDate.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { Client, isFullBlock } from "@notionhq/client";
|
||||
import { listAllChildrenBlocks } from "../utils/listAllChildrenBlocks";
|
||||
import { richTextToPlainText } from "../utils/text/richTextToPlainText";
|
||||
|
||||
export const statsRootPageId = "2b91cd90e3694e96bb196d69aeca59b1";
|
||||
|
||||
export async function updateUpdateDate(notionClient: Client, updateDate: Date) {
|
||||
const childrenBlocks = (
|
||||
await listAllChildrenBlocks(notionClient, {
|
||||
block_id: statsRootPageId,
|
||||
})
|
||||
).filter(isFullBlock);
|
||||
|
||||
const blockTextPrefix = "Dernière mise à jour des statistiques : ";
|
||||
const block = childrenBlocks.find(
|
||||
(b) => b.type === "paragraph" &&
|
||||
richTextToPlainText(b.paragraph.rich_text).startsWith(blockTextPrefix)
|
||||
);
|
||||
if (!block) {
|
||||
console.log(`Could not find block starting with "${blockTextPrefix}"`);
|
||||
return;
|
||||
}
|
||||
|
||||
await notionClient.blocks.update({
|
||||
block_id: block?.id,
|
||||
paragraph: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: blockTextPrefix,
|
||||
},
|
||||
},
|
||||
{
|
||||
mention: {
|
||||
date: {
|
||||
start: updateDate.toISOString(),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
import { Client, isFullPage } from "@notionhq/client";
|
||||
import {
|
||||
PageObjectResponse,
|
||||
UpdateDatabaseParameters,
|
||||
} from "@notionhq/client/build/src/api-endpoints";
|
||||
import { formatValueWithEvol } from "../../../format/formatValueWithEvol";
|
||||
import {
|
||||
ELStatsPeriod,
|
||||
PeriodStatsValues,
|
||||
ValueWithEvol,
|
||||
} from "../../../statistiques/v1/ELStats";
|
||||
import { titlePropertyToText } from "../../utils/properties/titlePropertyToText";
|
||||
import { queryAllDbResults } from "../../utils/queryAllDbResults";
|
||||
import { removeBlocks } from "../../utils/removeBlocks";
|
||||
import { CreatePageProperties } from "../../utils/types/CreatePageProperties";
|
||||
import { StatPublishOptions, statPublishOptions } from "./statPublishOptions";
|
||||
|
||||
const periodeDbPropertyName = "Période";
|
||||
|
||||
export async function publishPeriodStats(
|
||||
notionClient: Client,
|
||||
periodStatsDbId: string,
|
||||
statsPeriods: ELStatsPeriod[]
|
||||
) {
|
||||
if (statsPeriods.length > 0) {
|
||||
await updateDbProps(notionClient, periodStatsDbId, statsPeriods[0].stats);
|
||||
}
|
||||
const periodRows = (
|
||||
await queryAllDbResults(notionClient, {
|
||||
database_id: periodStatsDbId,
|
||||
})
|
||||
).filter(isFullPage);
|
||||
|
||||
const indexedPeriodRows: { [period: string]: PageObjectResponse } =
|
||||
Object.fromEntries(
|
||||
periodRows.map((r) => [
|
||||
titlePropertyToText(r.properties, periodeDbPropertyName),
|
||||
r,
|
||||
])
|
||||
);
|
||||
|
||||
const indexedPeriodStats = Object.fromEntries(
|
||||
statsPeriods.map((stat) => [stat.periodId, stat])
|
||||
);
|
||||
|
||||
const rowIdsToDelete = Object.entries(indexedPeriodRows)
|
||||
.filter(
|
||||
([periodId]) =>
|
||||
!Object.prototype.hasOwnProperty.call(indexedPeriodStats, periodId)
|
||||
)
|
||||
.map(([, row]) => row.id);
|
||||
|
||||
const periodIdsToUpdate = Object.entries(indexedPeriodRows)
|
||||
.filter(([periodId]) =>
|
||||
Object.prototype.hasOwnProperty.call(indexedPeriodStats, periodId)
|
||||
)
|
||||
.map(([periodId]) => periodId);
|
||||
|
||||
const periodIdsToCreate = Object.entries(indexedPeriodStats)
|
||||
.filter(
|
||||
([periodId]) =>
|
||||
!Object.prototype.hasOwnProperty.call(indexedPeriodRows, periodId)
|
||||
)
|
||||
.map(([periodId]) => periodId);
|
||||
|
||||
// Delete rows to delte
|
||||
await removeBlocks(notionClient, rowIdsToDelete);
|
||||
|
||||
// Create rows to create
|
||||
for (const periodId of periodIdsToCreate) {
|
||||
const periodStats = indexedPeriodStats[periodId];
|
||||
await notionClient.pages.create({
|
||||
parent: {
|
||||
database_id: periodStatsDbId,
|
||||
},
|
||||
properties: buildRowPropertiesForUpsert(periodId, periodStats.stats),
|
||||
});
|
||||
}
|
||||
|
||||
// Update rows
|
||||
for (const periodId of periodIdsToUpdate) {
|
||||
const periodStats = indexedPeriodStats[periodId];
|
||||
const row = indexedPeriodRows[periodId];
|
||||
await notionClient.pages.update({
|
||||
page_id: row.id,
|
||||
properties: buildRowPropertiesForUpsert(periodId, periodStats.stats),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function updateDbProps(
|
||||
notionClient: Client,
|
||||
periodStatsDbId: string,
|
||||
stats: PeriodStatsValues<ValueWithEvol>
|
||||
) {
|
||||
const db = await notionClient.databases.retrieve({
|
||||
database_id: periodStatsDbId,
|
||||
});
|
||||
const statsNotionProps: UpdateDatabaseParameters["properties"] =
|
||||
Object.fromEntries(
|
||||
(Object.keys(stats) as Array<keyof PeriodStatsValues<ValueWithEvol>>).map(
|
||||
(jsProp) => {
|
||||
const publishOptions = statPublishOptions(jsProp);
|
||||
return [
|
||||
publishOptions.notionPropName,
|
||||
{
|
||||
rich_text: {},
|
||||
},
|
||||
];
|
||||
}
|
||||
)
|
||||
);
|
||||
const propsToRemove = Object.fromEntries(
|
||||
Object.keys(db.properties)
|
||||
.filter(
|
||||
(k) =>
|
||||
!Object.prototype.hasOwnProperty.call(statsNotionProps, k) &&
|
||||
k !== periodeDbPropertyName
|
||||
)
|
||||
.map((k) => [k, null])
|
||||
);
|
||||
|
||||
await notionClient.databases.update({
|
||||
database_id: periodStatsDbId,
|
||||
properties: {
|
||||
[periodeDbPropertyName]: {
|
||||
title: {},
|
||||
},
|
||||
...statsNotionProps,
|
||||
...propsToRemove,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function buildRowPropertiesForUpsert(
|
||||
periodId: string,
|
||||
stats: PeriodStatsValues<ValueWithEvol>
|
||||
): CreatePageProperties {
|
||||
const statsNotionProps: CreatePageProperties = Object.fromEntries(
|
||||
(Object.keys(stats) as Array<keyof PeriodStatsValues<ValueWithEvol>>).map(
|
||||
(jsProp) => {
|
||||
const value: ValueWithEvol = stats[jsProp];
|
||||
const publishOptions = statPublishOptions(jsProp);
|
||||
return [
|
||||
publishOptions.notionPropName,
|
||||
valueWithEvolProp(value, publishOptions),
|
||||
];
|
||||
}
|
||||
)
|
||||
);
|
||||
return {
|
||||
[periodeDbPropertyName]: {
|
||||
title: [
|
||||
{
|
||||
text: {
|
||||
content: periodId,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
...statsNotionProps,
|
||||
};
|
||||
}
|
||||
|
||||
function valueWithEvolProp(
|
||||
n: ValueWithEvol,
|
||||
publishOptions: StatPublishOptions
|
||||
) {
|
||||
const formatted = formatValueWithEvol(n, publishOptions);
|
||||
return {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: formatted,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
import { Client, isFullBlock } from "@notionhq/client";
|
||||
import { ELStats } from "../../../statistiques/v1/ELStats";
|
||||
import { listAllChildrenBlocks } from "../../utils/listAllChildrenBlocks";
|
||||
import { richTextToPlainText } from "../../utils/text/richTextToPlainText";
|
||||
import { publishPeriodStats } from "./publishPeriodStats";
|
||||
import { publishStatsActuelles } from "./publishStatsActuelles";
|
||||
|
||||
export const statsPageId = "2b91cd90e3694e96bb196d69aeca59b1";
|
||||
export const currentStatsHeading = "Statistiques v1";
|
||||
|
||||
const yearStatsDb = "4b19a72aa07840eab948525ea41878ee";
|
||||
const monthStatsDb = "8418a8a4a7544f6a8c54e6003be7efe5";
|
||||
export async function publishStatisticsToNotion(
|
||||
stats: ELStats,
|
||||
currentDate: Date,
|
||||
notionClient: Client
|
||||
) {
|
||||
await updateUpdateDate(notionClient, currentDate);
|
||||
await publishStatsActuelles(notionClient, stats.actuelles);
|
||||
|
||||
await publishPeriodStats(notionClient, yearStatsDb, stats.annees);
|
||||
|
||||
await publishPeriodStats(notionClient, monthStatsDb, stats.mois);
|
||||
}
|
||||
|
||||
async function updateUpdateDate(notionClient: Client, updateDate: Date) {
|
||||
const childrenBlocks = (
|
||||
await listAllChildrenBlocks(notionClient, {
|
||||
block_id: statsPageId,
|
||||
})
|
||||
).filter(isFullBlock);
|
||||
|
||||
const blockTextPrefix = "Dernière mise à jour des statistiques : ";
|
||||
const block = childrenBlocks.find(
|
||||
(b) =>
|
||||
b.type === "paragraph" &&
|
||||
richTextToPlainText(b.paragraph.rich_text).startsWith(blockTextPrefix)
|
||||
);
|
||||
if (!block) {
|
||||
console.log(`Could not find block starting with "${blockTextPrefix}"`);
|
||||
return;
|
||||
}
|
||||
|
||||
await notionClient.blocks.update({
|
||||
block_id: block?.id,
|
||||
paragraph: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: blockTextPrefix,
|
||||
},
|
||||
},
|
||||
{
|
||||
mention: {
|
||||
date: {
|
||||
start: updateDate.toISOString(),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
import { Client, isFullBlock } from "@notionhq/client";
|
||||
import { BlockObjectRequest } from "@notionhq/client/build/src/api-endpoints";
|
||||
import { formatValue } from "../../../format/formatValue";
|
||||
import { ELStatsAtDate } from "../../../statistiques/v1/ELStats";
|
||||
import { listAllChildrenBlocks } from "../../utils/listAllChildrenBlocks";
|
||||
import { removeBlocks } from "../../utils/removeBlocks";
|
||||
import { richTextToPlainText } from "../../utils/text/richTextToPlainText";
|
||||
import { currentStatsHeading, statsPageId } from "./publishStatisticsToNotion";
|
||||
import { StatPublishOptions, statPublishOptions } from "./statPublishOptions";
|
||||
|
||||
export async function publishStatsActuelles(
|
||||
notionClient: Client,
|
||||
statsActuelles: ELStatsAtDate<number>
|
||||
) {
|
||||
const newBlocks = (
|
||||
Object.keys(statsActuelles) as Array<keyof typeof statsActuelles>
|
||||
).map((jsProp) => {
|
||||
const value: number = statsActuelles[jsProp];
|
||||
const publishOptions = statPublishOptions(jsProp);
|
||||
return currentStatBlock(value, publishOptions);
|
||||
});
|
||||
await updateStatsActuellesBlocks(notionClient, newBlocks);
|
||||
}
|
||||
|
||||
function currentStatBlock(
|
||||
value: number,
|
||||
publishOptions: StatPublishOptions
|
||||
): BlockObjectRequest {
|
||||
const formattedValue = formatValue(value, publishOptions);
|
||||
|
||||
const content = `${publishOptions.notionPropName} : ${formattedValue}`;
|
||||
return {
|
||||
paragraph: {
|
||||
rich_text: [
|
||||
{
|
||||
text: {
|
||||
content: content,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function updateStatsActuellesBlocks(
|
||||
notionClient: Client,
|
||||
blocks: BlockObjectRequest[]
|
||||
) {
|
||||
const childrenBlocks = (
|
||||
await listAllChildrenBlocks(notionClient, {
|
||||
block_id: statsPageId,
|
||||
})
|
||||
).filter(isFullBlock);
|
||||
|
||||
const currentStatsHeadingBlockIndex = childrenBlocks.findIndex(
|
||||
(block) =>
|
||||
block.type === "heading_1" &&
|
||||
richTextToPlainText(block.heading_1.rich_text) === currentStatsHeading
|
||||
);
|
||||
const endOfCurrentStats = childrenBlocks.findIndex(
|
||||
(block, index) =>
|
||||
index > currentStatsHeadingBlockIndex && block.type === "heading_1"
|
||||
);
|
||||
if (currentStatsHeadingBlockIndex === -1 || endOfCurrentStats === -1) {
|
||||
throw new Error("Cannot find expected headings in statistics page");
|
||||
}
|
||||
|
||||
const currentStatsHeadingBlock =
|
||||
childrenBlocks[currentStatsHeadingBlockIndex];
|
||||
|
||||
const blocksIdsToRemove = childrenBlocks
|
||||
.slice(currentStatsHeadingBlockIndex + 1, endOfCurrentStats)
|
||||
.map((b) => b.id);
|
||||
await removeBlocks(notionClient, blocksIdsToRemove);
|
||||
|
||||
await notionClient.blocks.children.append({
|
||||
block_id: statsPageId,
|
||||
after: currentStatsHeadingBlock.id,
|
||||
children: [...blocks],
|
||||
});
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import { EvolFormatOptions } from "../../../format/EvolFormatOptions";
|
||||
import { ValueFormatOptions } from "../../../format/ValueFormatOptions";
|
||||
import { AllStatsPropNames } from "../../../statistiques/v1/ELStats";
|
||||
|
||||
export function statPublishOptions(
|
||||
statJsPropName: AllStatsPropNames
|
||||
): StatPublishOptions {
|
||||
return statPropsPublishOptions[statJsPropName];
|
||||
}
|
||||
const statPropsPublishOptions: {
|
||||
[jsPropName in AllStatsPropNames]: StatPublishOptions;
|
||||
} = {
|
||||
// Autre
|
||||
|
||||
nbFamillesAvecContrôleFiscal: {
|
||||
notionPropName: "Nb familles ayant eu un contrôle fiscal",
|
||||
},
|
||||
pourcentageFamillesAvecContrôleFiscal: {
|
||||
notionPropName: "% familles ayant eu un contrôle fiscal",
|
||||
unit: "%",
|
||||
},
|
||||
nbFamillesAvecContrôleURSSAF: {
|
||||
notionPropName: "Nb familles ayant eu un contrôle URSAFF",
|
||||
},
|
||||
pourcentageFamillesAvecContrôleURSSAF: {
|
||||
notionPropName: "% familles ayant eu un contrôle URSAFF",
|
||||
unit: "%",
|
||||
},
|
||||
};
|
||||
export type StatPublishOptions = {
|
||||
notionPropName: string;
|
||||
} & ValueFormatOptions &
|
||||
EvolFormatOptions;
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
export type ELStats = {
|
||||
actuelles: ELStatsAtDate<number>;
|
||||
annees: ELStatsPeriod[];
|
||||
|
||||
mois: ELStatsPeriod[];
|
||||
};
|
||||
|
||||
export type ELStatsAtDate<V> = {
|
||||
// Autre
|
||||
nbFamillesAvecContrôleFiscal: V;
|
||||
pourcentageFamillesAvecContrôleFiscal: V;
|
||||
nbFamillesAvecContrôleURSSAF: V;
|
||||
pourcentageFamillesAvecContrôleURSSAF: V;
|
||||
};
|
||||
|
||||
export type ELStatsPeriod = {
|
||||
periodId: string;
|
||||
stats: PeriodStatsValues<ValueWithEvol>;
|
||||
};
|
||||
|
||||
export type PeriodStatsValues<V> = ELStatsAtDate<V>;
|
||||
|
||||
export type ValueWithEvol = {
|
||||
value: number;
|
||||
evol: number;
|
||||
evolPercent: number;
|
||||
};
|
||||
|
||||
export type AllStatsPropNames = keyof ELStatsAtDate<number>;
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
import { Famille } from "../../data/Famille";
|
||||
import { IdentifiedPeriod } from "../../period/IdentifiedPeriod";
|
||||
import { Period } from "../../period/Period";
|
||||
import { ELStatsPeriod, PeriodStatsValues, ValueWithEvol } from "./ELStats";
|
||||
import { computeELStatsAtDate } from "./computeELStatsAtDate";
|
||||
|
||||
export function computeELPeriodStats(
|
||||
familles: Famille[],
|
||||
periods: IdentifiedPeriod[]
|
||||
): ELStatsPeriod[] {
|
||||
let previousPeriodStatNumberValues: PeriodStatsValues<number> | null = null;
|
||||
return periods.map((period) => {
|
||||
const periodStatNumberValues: PeriodStatsValues<number> =
|
||||
computePeriodStatsNumberValues(familles, period);
|
||||
|
||||
// Compute evol
|
||||
const statsWithEvol = computeStatsEvol(
|
||||
periodStatNumberValues,
|
||||
previousPeriodStatNumberValues
|
||||
);
|
||||
previousPeriodStatNumberValues = periodStatNumberValues;
|
||||
const periodStats: ELStatsPeriod = {
|
||||
periodId: period.id,
|
||||
stats: statsWithEvol,
|
||||
};
|
||||
return periodStats;
|
||||
});
|
||||
}
|
||||
|
||||
function computePeriodStatsNumberValues(
|
||||
familles: Famille[],
|
||||
period: Period
|
||||
): PeriodStatsValues<number> {
|
||||
return computeELStatsAtDate(familles, period.end);
|
||||
}
|
||||
|
||||
function computeStatsEvol(
|
||||
periodStatNumberValues: PeriodStatsValues<number>,
|
||||
previousPeriodStatNumberValues: PeriodStatsValues<number> | null | undefined
|
||||
): PeriodStatsValues<ValueWithEvol> {
|
||||
return Object.fromEntries(
|
||||
(
|
||||
Object.entries(periodStatNumberValues) as Array<
|
||||
[prop: keyof PeriodStatsValues<number>, number]
|
||||
>
|
||||
).map(([k, v]) => [
|
||||
k,
|
||||
valueWithEvol(v, previousPeriodStatNumberValues?.[k]),
|
||||
])
|
||||
) as PeriodStatsValues<ValueWithEvol>;
|
||||
}
|
||||
|
||||
function valueWithEvol(
|
||||
value: number,
|
||||
previous: number | undefined
|
||||
): ValueWithEvol {
|
||||
return {
|
||||
value: value,
|
||||
evol: evol(value, previous),
|
||||
evolPercent: evolPercent(value, previous),
|
||||
};
|
||||
}
|
||||
|
||||
function evolPercent(current: number, previous: number | undefined): number {
|
||||
if (previous === undefined) return NaN;
|
||||
const evolValue = evol(current, previous);
|
||||
if (evolValue === 0) return 0;
|
||||
return (100 * evolValue) / previous;
|
||||
}
|
||||
|
||||
function evol(current: number, previous: number | undefined): number {
|
||||
if (previous === undefined) return NaN;
|
||||
return current - previous;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import { Famille } from "../../data/Famille";
|
||||
import { computeELPeriodStats } from "./computeELPeriodStats";
|
||||
import { computeELStatsAtDate } from "./computeELStatsAtDate";
|
||||
import { ELStats } from "./ELStats";
|
||||
import { generateELMonths } from "../../period/generateELMonths";
|
||||
import { generateELYears } from "../../period/generateELYears";
|
||||
|
||||
export function computeELStats(
|
||||
families: Famille[],
|
||||
currentDate: Date
|
||||
): ELStats {
|
||||
const actuelles = computeELStatsAtDate(families, currentDate);
|
||||
|
||||
const yearsStats = computeELPeriodStats(families, generateELYears());
|
||||
|
||||
const monthsStats = computeELPeriodStats(families, generateELMonths());
|
||||
|
||||
return {
|
||||
actuelles: actuelles,
|
||||
annees: yearsStats,
|
||||
mois: monthsStats,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
import { Famille, isExResistant, isResistant } from "../../data/Famille";
|
||||
import { percent } from "../../utils/math/percent";
|
||||
import { ELStatsAtDate } from "./ELStats";
|
||||
|
||||
export function computeELStatsAtDate(
|
||||
familles: Famille[],
|
||||
asOfDate: Date
|
||||
): ELStatsAtDate<number> {
|
||||
const familleResistantesOrEx = familles.filter(
|
||||
(famille) =>
|
||||
isResistant(famille, asOfDate) || isExResistant(famille, asOfDate)
|
||||
);
|
||||
|
||||
const famillesAvecContrôleFiscal = familleResistantesOrEx.filter((f) =>
|
||||
f.EvenementsEL.find((e) => e.Type === "Contrôle fiscal")
|
||||
);
|
||||
|
||||
const famillesAvecContrôleURSAFF = familleResistantesOrEx.filter((f) =>
|
||||
f.EvenementsEL.find((e) => e.Type === "Contrôle URSSAF")
|
||||
);
|
||||
const elStats: ELStatsAtDate<number> = {
|
||||
// Autre
|
||||
nbFamillesAvecContrôleFiscal: famillesAvecContrôleFiscal.length,
|
||||
pourcentageFamillesAvecContrôleFiscal: percent(
|
||||
famillesAvecContrôleFiscal.length,
|
||||
familleResistantesOrEx.length
|
||||
),
|
||||
nbFamillesAvecContrôleURSSAF: famillesAvecContrôleURSAFF.length,
|
||||
pourcentageFamillesAvecContrôleURSSAF: percent(
|
||||
famillesAvecContrôleURSAFF.length,
|
||||
familleResistantesOrEx.length
|
||||
),
|
||||
};
|
||||
return elStats;
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
import { addMonths } from "date-fns";
|
||||
import {
|
||||
EvenementFamille,
|
||||
isEvenementBefore,
|
||||
} from "../../data/EvenementFamille";
|
||||
import { Famille } from "../../data/Famille";
|
||||
import { percent } from "../../utils/math/percent";
|
||||
import { statutExResistant, statutResistant } from "../../data/StatutFamille";
|
||||
|
||||
type FamillesWithEventsConditionInEarlyPeriod = {
|
||||
[name: string]: {
|
||||
nbFamillesWithAtLeastDuration: number;
|
||||
nbFamillesWithEventPredicate: number;
|
||||
percentage: number;
|
||||
};
|
||||
};
|
||||
|
||||
export const computeFamillesWithEventsConditionInEarlyPeriod = (
|
||||
familles: Famille[],
|
||||
eventsPredicate: (events: EvenementFamille[]) => boolean,
|
||||
durations: {
|
||||
[name: string]: number;
|
||||
} = {
|
||||
"0 mois": 0,
|
||||
"3 mois": 3,
|
||||
"6 mois": 6,
|
||||
"12 mois": 12,
|
||||
"24 mois": 24,
|
||||
}
|
||||
): FamillesWithEventsConditionInEarlyPeriod => {
|
||||
const evalDate = new Date(Date.now());
|
||||
return Object.fromEntries(
|
||||
Object.entries(durations).map(([name, months]) => {
|
||||
const famillesWithAtLeastDurationOfDc = familles
|
||||
.filter(
|
||||
(f) => f.Statut === statutResistant || f.Statut === statutExResistant
|
||||
)
|
||||
.filter(
|
||||
(f) =>
|
||||
dcStartDate(f) !== null &&
|
||||
addMonths(dcStartDate(f)!, months) < evalDate
|
||||
);
|
||||
|
||||
const famillesWithEventPredicate = famillesWithAtLeastDurationOfDc.filter(
|
||||
(f) => {
|
||||
const dcDate = dcStartDate(f)!;
|
||||
const dcPeriodEnd = addMonths(dcDate, months);
|
||||
const eventsBeforeDate = f.EvenementsEL.filter((e) =>
|
||||
isEvenementBefore(e, dcPeriodEnd)
|
||||
);
|
||||
return eventsPredicate(eventsBeforeDate);
|
||||
}
|
||||
);
|
||||
return [
|
||||
name,
|
||||
{
|
||||
nbFamillesWithAtLeastDuration: famillesWithAtLeastDurationOfDc.length,
|
||||
nbFamillesWithEventPredicate: famillesWithEventPredicate.length,
|
||||
percentage: percent(
|
||||
famillesWithEventPredicate.length,
|
||||
famillesWithAtLeastDurationOfDc.length
|
||||
),
|
||||
},
|
||||
];
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const dcStartDate = (famille: Famille): Date | null => {
|
||||
return famille.Integration;
|
||||
};
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import { Famille } from "../../data/Famille";
|
||||
import { percent } from "../../utils/math/percent";
|
||||
|
||||
export function computePourcentageEntreeApresMiseEnDemeure(
|
||||
familles: Famille[]
|
||||
) {
|
||||
const entreeApresMiseEnDemeure = familles.filter(
|
||||
(f) =>
|
||||
f.ContexteEntree === "Après mise en demeure" ||
|
||||
f.ContexteEntree === "Après poursuite procureur"
|
||||
);
|
||||
const pourcentageEntreeApresMiseEnDemeure = percent(
|
||||
entreeApresMiseEnDemeure.length,
|
||||
familles.length
|
||||
);
|
||||
return pourcentageEntreeApresMiseEnDemeure;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue