diff --git a/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts b/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts index 8879196..bd2e50d 100644 --- a/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts +++ b/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts @@ -2,7 +2,7 @@ import { Client, isFullPage } from "@notionhq/client"; import { PageObjectResponse } from "@notionhq/client/build/src/api-endpoints"; import { Family, FamilyEvent, StatutFamille } from "../../data/Family"; import { datePropertyToDate } from "../utils/properties/datePropertyToDate"; -import { relationPropertyToPageId } from "../utils/properties/relationPropertyToPAgeId"; +import { relationPropertyToPageId } from "../utils/properties/relationPropertyToPageId"; import { selectPropertyToText } from "../utils/properties/selectPropertyToText"; import { statusPropertyToText } from "../utils/properties/statusPropertyToText"; import { titlePropertyToText } from "../utils/properties/titlePropertyToText"; diff --git a/src/notion/publish/publishStatisticsToNotion.ts b/src/notion/publish/publishStatisticsToNotion.ts index cc1083b..52fabca 100644 --- a/src/notion/publish/publishStatisticsToNotion.ts +++ b/src/notion/publish/publishStatisticsToNotion.ts @@ -1,5 +1,11 @@ import { Client, isFullPage } from "@notionhq/client"; -import { ELPeriodStats, ELStats } from "../../statistiques/ELStats"; +import { PageObjectResponse } from "@notionhq/client/build/src/api-endpoints"; +import { + ELPeriodStats, + ELStats, + ValueWithEvol, +} from "../../statistiques/ELStats"; +import { titlePropertyToText } from "../utils/properties/titlePropertyToText"; import { queryAllDbResults } from "../utils/queryAllDbResults"; import { removeBlocks } from "../utils/removeBlocks"; import { publishCurrentStats } from "./publishCurrentStats"; @@ -30,42 +36,106 @@ async function publishPeriodStats( database_id: periodStatsDbId, }) ).filter(isFullPage); - await removeBlocks( - notionClient, - periodRows.map((r) => r.id) + + const indexedPeriodRows: { [period: string]: PageObjectResponse } = + Object.fromEntries( + periodRows.map((r) => [titlePropertyToText(r.properties, "Période"), r]) + ); + + const indexedPeriodStats = Object.fromEntries( + stats.map((stat) => [stat.periodId, stat]) ); - for (const stat of stats) { + 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 stat = indexedPeriodStats[periodId]; await notionClient.pages.create({ parent: { database_id: periodStatsDbId, }, - properties: { - Période: { - title: [ - { - text: { - content: stat.periodId, - }, - }, - ], - }, - "Nb Famille Résistante": numberProp(stat.nbFamilleResistantes), - "Nb Famille Résistante - Evol": numberProp( - stat.nbFamilleResistantesEvol - ), - "Nb Famille Résistante - Evol %": numberProp( - stat.nbFamilleResistantesEvolPercent - ), - }, + properties: buildRowPropertiesForUpsert(stat), + }); + } + + // Update rows + for (const periodId of periodIdsToUpdate) { + const stat = indexedPeriodStats[periodId]; + const row = indexedPeriodRows[periodId]; + await notionClient.pages.update({ + page_id: row.id, + properties: buildRowPropertiesForUpsert(stat), }); } } -function numberProp(n: number): { - number: number; -} { +function buildRowPropertiesForUpsert(stat: ELPeriodStats) { return { - number: n, + Période: { + title: [ + { + text: { + content: stat.periodId, + }, + }, + ], + }, + "Nb Famille Résistante": valueWithEvolProp(stat.nbFamilleResistantes), }; } + +function valueWithEvolProp(n: ValueWithEvol) { + const formatted = formatValueWithEvol(n); + return { + rich_text: [ + { + text: { + content: formatted, + }, + }, + ], + }; +} +function formatValueWithEvol(n: ValueWithEvol): string { + const value = n.value.toLocaleString("fr-FR", { + useGrouping: false, + maximumFractionDigits: 2, + }); + if (isNaN(n.evol)) { + return value; + } else { + const evol = n.evol.toLocaleString("fr-FR", { + useGrouping: false, + maximumFractionDigits: 2, + signDisplay: "always", + }); + const evolPercent = Math.round(n.evolPercent).toLocaleString("fr-FR", { + useGrouping: false, + signDisplay: "always", + }); + + return `${value} (${evol} | ${evolPercent}%)`; + } +} diff --git a/src/statistiques/ELStats.ts b/src/statistiques/ELStats.ts index 15861b2..5f3ee95 100644 --- a/src/statistiques/ELStats.ts +++ b/src/statistiques/ELStats.ts @@ -13,7 +13,11 @@ export type ELStats = { export type ELPeriodStats = { periodId: string; - nbFamilleResistantes: number; - nbFamilleResistantesEvol: number; - nbFamilleResistantesEvolPercent: number; + nbFamilleResistantes: ValueWithEvol; +}; + +export type ValueWithEvol = { + value: number; + evol: number; + evolPercent: number; }; diff --git a/src/statistiques/computeELPeriodStats.ts b/src/statistiques/computeELPeriodStats.ts index ad2572d..b0c1d5e 100644 --- a/src/statistiques/computeELPeriodStats.ts +++ b/src/statistiques/computeELPeriodStats.ts @@ -1,6 +1,6 @@ import { Family, isResistantOverPeriod } from "../data/Family"; import { IdentifiedPeriod } from "../period/IdentifiedPeriod"; -import { ELPeriodStats } from "./ELStats"; +import { ELPeriodStats, ValueWithEvol } from "./ELStats"; export function computeELPeriodStats( familles: Family[], @@ -15,14 +15,9 @@ export function computeELPeriodStats( const stats: ELPeriodStats = { periodId: period.id, - nbFamilleResistantes: resistantsCount, - nbFamilleResistantesEvol: evol( + nbFamilleResistantes: valueWithEvol( resistantsCount, - previousELPeriodStats?.nbFamilleResistantes - ), - nbFamilleResistantesEvolPercent: evolPercent( - resistantsCount, - previousELPeriodStats?.nbFamilleResistantes + previousELPeriodStats?.nbFamilleResistantes.value ), }; periodStats.push(stats); @@ -31,10 +26,22 @@ export function computeELPeriodStats( return periodStats; } +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; return (100 * evol(current, previous)) / previous; } + function evol(current: number, previous: number | undefined): number { if (previous === undefined) return NaN; return current - previous;