From 37fa636713b34ecdee4ceb13971d1fb3d59c20ea Mon Sep 17 00:00:00 2001 From: Anthonius Munthi Date: Sun, 12 Apr 2026 20:39:34 +0800 Subject: [PATCH 01/13] docs: define ordo feature and database schema in PRD and ERD - [docs/prd]: add Ordo (Liturgical Calendar) as MVP feature - [docs/prd]: define user stories, ranks, and liturgical colors - [docs/erd]: add sync_staging.liturgi table definition - [docs/erd]: add ordo sync transform flowchart --- docs/erd.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++---- docs/prd.md | 51 +++++++++++++++++++++++--- 2 files changed, 141 insertions(+), 11 deletions(-) diff --git a/docs/erd.md b/docs/erd.md index 4dc5f22..3f24649 100644 --- a/docs/erd.md +++ b/docs/erd.md @@ -4,9 +4,9 @@ --- -**Document Version:** 1.2.0 +**Document Version:** 1.3.0 **Status:** In Progress -**Last Updated:** 11 April 2026 +**Last Updated:** 12 April 2026 --- @@ -131,6 +131,32 @@ export const NotificationStatus = { } as const ``` +### Ordo (Liturgical Calendar) + +```typescript +export const CelebrationRank = { + Solemnity: 'solemnity', + Feast: 'feast', + Memorial: 'memorial', + Commemoration: 'commemoration', + Feria: 'feria', +} as const + +export const LiturgicalColor = { + Purple: 'purple', + White: 'white', + Red: 'red', + Green: 'green', + Rose: 'rose', + Black: 'black', +} as const + +export const OrdoSource = { + Lagumisa: 'lagumisa', + Manual: 'manual', +} as const +``` + --- ## 2. Entities & Table Schemas @@ -422,7 +448,35 @@ Represents kelurahan/desa level. --- -### 2.5 Events & Attendance +### 2.5 Ordo (Liturgical Calendar) + +#### `ordo` + +Master liturgical calendar. One record per celebration per day. For days with multiple masses (e.g., Christmas: Midnight, Dawn, Day), each mass is a separate record distinguished by `massLabel`. + +| Field | Type | Description | +|---|---|---| +| `id` | uuid v7 | Primary key | +| `date` | date | Liturgical date. Required. | +| `name` | string | Celebration name. e.g. `"HARI MINGGU ADVEN IV"`. Required. | +| `rank` | CelebrationRank | `solemnity` \| `feast` \| `memorial` \| `commemoration` \| `feria`. Required. | +| `color` | LiturgicalColor | `purple` \| `white` \| `red` \| `green` \| `rose` \| `black`. Required. | +| `massLabel` | string? | Mass label for days with multiple masses. e.g. `"Misa Malam"`, `"Misa Fajar"`, `"Misa Siang"`. Null if only one mass. | +| `readings` | text[] | Array of scripture reading references. e.g. `["Yes. 9:1-6", "Mzm. 96:1-2a", "Tit. 2:11-14", "Luk. 2:1-14"]` | +| `songs` | string? | Raw Puji Syukur song number suggestions. e.g. `"PS 451, 452, 453, 454"` | +| `source` | OrdoSource | `lagumisa` \| `manual`. Default: `manual`. | +| `createdBy` | text? | FK → `users.id`. Null if seeded from scraper. | +| `createdAt` | datetime | | +| `updatedAt` | datetime | | +| `deletedAt` | datetime? | Soft delete | + +**Constraint:** `UNIQUE (date, massLabel)` — prevents duplicate entries for the same mass on the same day. `massLabel` uses `NULLS NOT DISTINCT` so null is treated as a unique value per date. + +> **Note:** `songs` is stored as raw text to preserve the original Puji Syukur numbering format from lagumisa.web.id, including range notations (e.g., `"464 (1, 2, 4)"`). Parsing into structured data is deferred to a future iteration. + +--- + +### 2.6 Events & Attendance #### `events` @@ -430,6 +484,7 @@ Represents kelurahan/desa level. |---|---|---| | `id` | uuid v7 | Primary key | | `organizationId` | uuid v7? | FK → `organizations.id`. Nullable for public events | +| `ordoId` | uuid v7? | FK → `ordo.id`. Optional link to the liturgical celebration this event corresponds to. | | `name` | string | Required | | `description` | string? | | | `location` | string | Required | @@ -484,7 +539,7 @@ Represents kelurahan/desa level. --- -### 2.6 Finance +### 2.7 Finance #### `financial_periods` @@ -533,7 +588,7 @@ Represents kelurahan/desa level. --- -### 2.7 Attachments +### 2.8 Attachments #### `attachments` @@ -553,7 +608,7 @@ Represents kelurahan/desa level. --- -### 2.8 Notifications +### 2.9 Notifications #### `notifications` @@ -595,6 +650,7 @@ erDiagram users ||--o{ attendances : "verifies" users ||--o{ events : "creates" users ||--o{ attachments : "uploads" + users ||--o{ ordo : "creates" parishioners ||--o{ org_enrollments : "enrolled in" parishioners ||--o{ rsvp : "submits" @@ -614,6 +670,8 @@ erDiagram org_terms ||--o{ org_placements : "linked to" org_enrollments ||--o{ org_placements : "has" + ordo ||--o{ events : "linked to" + events ||--o{ rsvp : "receives" events ||--o{ attendances : "records" @@ -713,6 +771,17 @@ flowchart TD E --> F[Return viewerUrl to client] ``` +### 4.6 Ordo Seeding Flow + +```mermaid +flowchart TD + A[Cron / manual trigger] --> B[SyncClient scrapes lagumisa.web.id/saranps.php] + B --> C[Write raw data to sync_staging.liturgi] + C --> D[Transform: map color & rank to English enums] + D --> E[Upsert into ordo\nON CONFLICT date + massLabel DO UPDATE] + E --> F[source = lagumisa\ncreatedBy = null] +``` + --- ## 5. Soft Delete Strategy @@ -774,6 +843,26 @@ Stores raw sacrament data scraped from DUK. Imported as-is — not transformed i | `rawData` | jsonb | Full raw sacrament data | | `scrapedAt` | timestamptz | Default: `NOW()` | +#### `sync_staging.liturgi` + +Stores raw liturgical calendar data scraped from lagumisa.web.id. Transformed into the `ordo` table. + +| Field | Type | Description | +|---|---|---| +| `id` | serial | Primary key | +| `celebrationName` | text | Raw celebration name from HTML | +| `month` | text | Month name (e.g., `"Desember"`) | +| `dayName` | text | Day name (e.g., `"Minggu"`) | +| `dateNumber` | integer | Date number (e.g., `25`) | +| `isSunday` | boolean | `true` if `class="iconminggu"` on `