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
> **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
---
......@@ -135,19 +135,28 @@ 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
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
after the Cashier processes their addition fee), a subscription row for the **current financial
year** is automatically inserted for them.
When a member activates or a dependent is added, subscription rows are automatically inserted
for the **current financial year**. Two entry points in the service:
#### `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):
spouse.fee_paid → SubscriptionSyncService::syncForDependent('spouse', $spouseId, $memberId)
child.fee_paid → SubscriptionSyncService::syncForDependent('child', $childId, $memberId)
temporary.fee_paid→ SubscriptionSyncService::syncForDependent('temporary', $tempId, $memberId)
Triggers (all in Subscriptions/bootstrap.php):
member.activated → syncForMember(memberId)
— creates member row + all active dependents
spouse.fee_paid → syncForDependent('spouse', spouseId, memberId)
child.fee_paid → syncForDependent('child', childId, memberId)
temporary.fee_paid → syncForDependent('temporary', tempId, memberId)
Trigger B — zero-fee path (controller dispatches *.added with fee=0):
spouse.added (fee=0) → syncForDependent('spouse', ...)
child.added (fee=0) → syncForDependent('child', ...)
temporary.added(fee=0) → syncForDependent('temporary', ...)
......@@ -164,6 +173,10 @@ syncForDependent logic:
**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)
```
......
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