diff --git a/src/data/Amende.ts b/src/data/Amende.ts new file mode 100644 index 0000000..499e609 --- /dev/null +++ b/src/data/Amende.ts @@ -0,0 +1,6 @@ +export type Amende = Readonly<{ + notionId: string; + notionIdEvenement: string; + Montant: number; + Type: "ferme" | "avec sursis"; +}>; diff --git a/src/data/EvenementFamille.ts b/src/data/EvenementFamille.ts index 1b8d97e..0689dac 100644 --- a/src/data/EvenementFamille.ts +++ b/src/data/EvenementFamille.ts @@ -1,5 +1,6 @@ import { Period } from "../period/Period"; import { isPeriodContaining } from "../period/isPeriodContaining"; +import { Amende } from "./Amende"; import { TypeEvenement } from "./TypeEvenement"; import { isEvtTypeProcedurePenale, @@ -14,6 +15,7 @@ export type EvenementFamille = Readonly<{ Évènement: string; Date: Date | null; Type: TypeEvenement; + Amendes: Amende[]; "Enfants concernés": string; }>; diff --git a/src/notion/fetch/dbIds.ts b/src/notion/fetch/dbIds.ts index 255d52e..3e917e7 100644 --- a/src/notion/fetch/dbIds.ts +++ b/src/notion/fetch/dbIds.ts @@ -3,3 +3,4 @@ export const departementsDbId: string = "787779be614544069f609bf9d2a7cd15"; export const contactsDbId: string = "be112427dd314c14b93dfd027323c908"; export const missionsDbId: string = "fa2ab021a5dc4e239b7e7201ae579162"; +export const amendesDbId: string = "1fd168be9f198019bb38c6ed4a90d00b"; diff --git a/src/notion/fetch/fetchAmendes.ts b/src/notion/fetch/fetchAmendes.ts new file mode 100644 index 0000000..84b3737 --- /dev/null +++ b/src/notion/fetch/fetchAmendes.ts @@ -0,0 +1,39 @@ +import { Client, isFullPage } from "@notionhq/client"; +import { Amende } from "../../data/Amende"; +import { relationPropertyToPageId } from "../utils/properties/relationPropertyToPageId"; +import { selectPropertyToText } from "../utils/properties/selectPropertyToText"; +import { titlePropertyToText } from "../utils/properties/titlePropertyToText"; +import { queryAllDbResults } from "../utils/queryAllDbResults"; +import { amendesDbId } from "./dbIds"; + +export async function fetchAmendes( + notionClient: Client, + cacheConfig: boolean | { ttl: number } +): Promise { + const amendesPages = ( + await queryAllDbResults( + notionClient, + { + database_id: amendesDbId, + }, + { cache: cacheConfig } + ) + ).filter(isFullPage); + + const amendes: Amende[] = amendesPages.map((page) => ({ + notionId: page.id, + notionIdEvenement: relationPropertyToPageId(page.properties, "Évènements")!, + Montant: amendeStringToNumber( + titlePropertyToText(page.properties, "Montant/parent") + )!, + Type: selectPropertyToText(page.properties, "Amendes")! as Amende["Type"], + })); + return amendes; +} + +function amendeStringToNumber(value: string | null): number { + if (value === null) { + return NaN; // or throw an error if you prefer + } + return parseFloat(value); +} diff --git a/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts b/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts index abbd968..0564dfc 100644 --- a/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts +++ b/src/notion/fetch/fetchFamiliesWithEventsFromNotion.ts @@ -31,6 +31,8 @@ import { Contact } from "../../data/Contact"; import { Mission } from "../../data/Mission"; import { relationPropertyToPageIds } from "../utils/properties/relationPropertyToPageIds"; import { checkboxPropertyToBoolean } from "../utils/properties/checkboxPropertyToBoolean"; +import { Amende } from "../../data/Amende"; +import { fetchAmendes } from "./fetchAmendes"; type Departement = { notionId: string; @@ -40,6 +42,76 @@ export async function fetchFamiliesWithEventsFromNotion( notionClient: Client, cacheConfig: CacheConfig = { ttl: 3600 * 1000 } ): Promise { + const departements: Departement[] = await fetchDepartements( + notionClient, + cacheConfig + ); + const missions: Mission[] = await fetchMissions(notionClient, cacheConfig); + const contacts: Contact[] = await fetchContacts( + notionClient, + cacheConfig, + missions + ); + const amendes: Amende[] = await fetchAmendes(notionClient, cacheConfig); + const evenements = await fetchEvenements(notionClient, cacheConfig, amendes); + const familles: Famille[] = await fetchFamilles( + notionClient, + cacheConfig, + evenements, + departements, + contacts + ); + return familles; +} + +async function fetchFamilles( + notionClient: Client, + cacheConfig: boolean | { ttl: number }, + familyEvents: Readonly<{ + notionId: string; + notionIdFamille: string; + Évènement: string; + Date: Date | null; + Type: TypeEvenement; + Amendes: Amende[]; + "Enfants concernés": string; + }>[], + departements: Departement[], + contacts: Readonly<{ + notionId: string; + notionIdFamille: string; + Nom: string; + Missions: Mission[]; + AExercéUneMission: boolean; + }>[] +) { + const familyPages = ( + await queryAllDbResults( + notionClient, + { + database_id: familiesDbId, + }, + { cache: cacheConfig } + ) + ).filter(isFullPage); + const familles: Famille[] = await Promise.all( + familyPages.map((pageObjectResponse) => { + return buildFamily( + pageObjectResponse, + familyEvents, + departements, + contacts + ); + }) + ); + return familles; +} + +async function fetchEvenements( + notionClient: Client, + cacheConfig: boolean | { ttl: number }, + amendes: Amende[] +) { const eventPages = ( await queryAllDbResults( notionClient, @@ -50,16 +122,22 @@ export async function fetchFamiliesWithEventsFromNotion( { cache: cacheConfig } ) ).filter(isFullPage); - const familyPages = ( - await queryAllDbResults( - notionClient, - { - database_id: familiesDbId, - }, - { cache: cacheConfig } - ) - ).filter(isFullPage); + const familyEvents = eventPages.map((pageObjectResponse) => { + return buildFamilyEvent(pageObjectResponse, amendes); + }); + return familyEvents; +} +async function fetchContacts( + notionClient: Client, + cacheConfig: boolean | { ttl: number }, + missions: Readonly<{ + notionId: string; + Nom: string; + Equipe: string; + ContactsNotionIds: string[]; + }>[] +) { const contactPages = ( await queryAllDbResults( notionClient, @@ -70,6 +148,23 @@ export async function fetchFamiliesWithEventsFromNotion( ) ).filter(isFullPage); + const contacts: Contact[] = contactPages.map((page) => ({ + notionId: page.id, + notionIdFamille: relationPropertyToPageId(page.properties, "Famille")!, + Nom: titlePropertyToText(page.properties, "Nom"), + AExercéUneMission: checkboxPropertyToBoolean( + page.properties, + "A exercé une mission" + ), + Missions: missions.filter((m) => m.ContactsNotionIds.includes(page.id)), + })); + return contacts; +} + +async function fetchMissions( + notionClient: Client, + cacheConfig: boolean | { ttl: number } +) { const missionsPages = ( await queryAllDbResults( notionClient, @@ -79,7 +174,22 @@ export async function fetchFamiliesWithEventsFromNotion( { cache: cacheConfig } ) ).filter(isFullPage); + const missions: Mission[] = missionsPages.map((page) => ({ + notionId: page.id, + Nom: titlePropertyToText(page.properties, "Nom"), + Equipe: selectPropertyToText(page.properties, "Équipe")!, + ContactsNotionIds: relationPropertyToPageIds( + page.properties, + "📔 Contacts" + ), + })); + return missions; +} +async function fetchDepartements( + notionClient: Client, + cacheConfig: boolean | { ttl: number } +) { const departementPages = ( await queryAllDbResults( notionClient, @@ -94,46 +204,13 @@ export async function fetchFamiliesWithEventsFromNotion( notionId: page.id, name: titlePropertyToText(page.properties, "Nom"), })); - - const missions: Mission[] = missionsPages.map((page) => ({ - notionId: page.id, - Nom: titlePropertyToText(page.properties, "Nom"), - Equipe: selectPropertyToText(page.properties, "Équipe")!, - ContactsNotionIds: relationPropertyToPageIds( - page.properties, - "📔 Contacts" - ), - })); - - const contacts: Contact[] = contactPages.map((page) => ({ - notionId: page.id, - notionIdFamille: relationPropertyToPageId(page.properties, "Famille")!, - Nom: titlePropertyToText(page.properties, "Nom"), - AExercéUneMission: checkboxPropertyToBoolean( - page.properties, - "A exercé une mission" - ), - Missions: missions.filter((m) => m.ContactsNotionIds.includes(page.id)), - })); - - const familyEvents = eventPages.map((pageObjectResponse) => { - return buildFamilyEvent(pageObjectResponse); - }); - - const familles: Famille[] = await Promise.all( - familyPages.map((pageObjectResponse) => { - return buildFamily( - pageObjectResponse, - familyEvents, - departements, - contacts - ); - }) - ); - return familles; + return departements; } -function buildFamilyEvent(page: PageObjectResponse): EvenementFamille { +function buildFamilyEvent( + page: PageObjectResponse, + amendes: Amende[] +): EvenementFamille { const pageProperties = page.properties; const familyEvent: EvenementFamille = { @@ -146,6 +223,7 @@ function buildFamilyEvent(page: PageObjectResponse): EvenementFamille { ), Date: datePropertyToDate(pageProperties, "Date"), notionIdFamille: relationPropertyToPageId(pageProperties, "Famille")!, + Amendes: amendes.filter((a) => a.notionIdEvenement === page.id), }; return familyEvent; } diff --git a/src/notion/utils/properties/numberPropertyToNumber.ts b/src/notion/utils/properties/numberPropertyToNumber.ts new file mode 100644 index 0000000..d7300fa --- /dev/null +++ b/src/notion/utils/properties/numberPropertyToNumber.ts @@ -0,0 +1,15 @@ +import { PageProperties } from "../types/PageProperties"; +import { extractPagePropertyValue } from "./extractPagePropertyValue"; + +export function numberPropertyToNumber( + pageProperties: PageProperties, + propName: string +): number | null { + const propValue = extractPagePropertyValue(pageProperties, propName); + if (propValue.type !== "number") { + throw new Error( + `Property ${propName} was expected to have type "number" but got "${propValue.type}".` + ); + } + return propValue.number; +}