Commit e93d166b authored by Mahmoud Aglan's avatar Mahmoud Aglan

docs(subscriptions): update architecture map for member.activated sync

Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
parent 724a37ca
# Subscriptions Module — Architecture Map # Subscriptions Module — Architecture Map
> **Last updated:** 2026-07-18 (added SubscriptionSyncService — real-time dependent sync on activation events) > **Last updated:** 2026-07-18 (added syncForMember + member.activated listener; production backfill of missing 2026/2027 rows)
> **Status:** Living document — incrementally updated as new information is discovered > **Status:** Living document — incrementally updated as new information is discovered
--- ---
...@@ -135,22 +135,31 @@ service codes. All 204 initially generated subscriptions had `base_amount=0.00`. ...@@ -135,22 +135,31 @@ service codes. All 204 initially generated subscriptions had `base_amount=0.00`.
2. Hard-coded fallback rates as last resort: member/spouse=492, child/temporary=222 2. Hard-coded fallback rates as last resort: member/spouse=492, child/temporary=222
3. All 204 bad rows manually corrected via UPDATE on production DB. 3. All 204 bad rows manually corrected via UPDATE on production DB.
### 5.1b Real-Time Dependent Sync (SubscriptionSyncService) — Added 2026-07-18 ### 5.1b Real-Time Member + Dependent Sync (SubscriptionSyncService) — Added 2026-07-18
When a spouse, child, or temporary member is activated (either immediately because fee=0, or When a member activates or a dependent is added, subscription rows are automatically inserted
after the Cashier processes their addition fee), a subscription row for the **current financial for the **current financial year**. Two entry points in the service:
year** is automatically inserted for them.
#### `syncForMember(memberId)` — called on `member.activated`
Creates the member's own FY subscription row plus all currently-active dependents.
Used when a brand-new member activates mid-year (after the July batch already ran).
#### `syncForDependent(personType, personId, memberId)` — called on dependent activation
Adds a single dependent's FY row. Used when a dependent is added to an already-active member.
``` ```
Trigger A — fee paid path (Cashier dispatches): Triggers (all in Subscriptions/bootstrap.php):
spouse.fee_paid → SubscriptionSyncService::syncForDependent('spouse', $spouseId, $memberId)
child.fee_paid → SubscriptionSyncService::syncForDependent('child', $childId, $memberId) member.activated → syncForMember(memberId)
temporary.fee_paid→ SubscriptionSyncService::syncForDependent('temporary', $tempId, $memberId) — creates member row + all active dependents
Trigger B — zero-fee path (controller dispatches *.added with fee=0): spouse.fee_paid → syncForDependent('spouse', spouseId, memberId)
spouse.added (fee=0) → syncForDependent('spouse', ...) child.fee_paid → syncForDependent('child', childId, memberId)
child.added (fee=0) → syncForDependent('child', ...) temporary.fee_paid → syncForDependent('temporary', tempId, memberId)
temporary.added(fee=0) → syncForDependent('temporary', ...)
spouse.added (fee=0) → syncForDependent('spouse', ...)
child.added (fee=0) → syncForDependent('child', ...)
temporary.added(fee=0) → syncForDependent('temporary', ...)
syncForDependent logic: syncForDependent logic:
1. Guard: member must be active + not an exempt membership type (honorary/seasonal) 1. Guard: member must be active + not an exempt membership type (honorary/seasonal)
...@@ -164,6 +173,10 @@ syncForDependent logic: ...@@ -164,6 +173,10 @@ syncForDependent logic:
**Idempotent:** safe to re-fire; the dedup guard prevents double rows. **Idempotent:** safe to re-fire; the dedup guard prevents double rows.
**Production backfill (2026-07-18):** 5 rows were created manually via targeted script
(2 member rows + 2 child rows + 1 temp row). Remaining gaps in audit were all explained
by ineligible members (archived, deceased, waived, not yet active).
### 5.2 Subscription Payment (with FIFO enforcement) ### 5.2 Subscription Payment (with FIFO enforcement)
``` ```
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment