# Cross-Module Dependency Graph

## Purpose

This graph maps how modules interact with each other — events, shared tables, data flows, and cascading changes. It answers: "If I change X, what else breaks?"

---

## Core Entity: `members` Table

The `members` table is the central hub. Nearly every module in the ERP references it.

### Direct Foreign Keys TO members
| Table | FK Column | Module |
|-------|-----------|--------|
| spouses | member_id | Spouses |
| children | member_id | Children |
| temporary_members | member_id | Temporary |
| subscriptions | member_id | Subscriptions |
| payments | member_id | Payments |
| payment_requests | member_id | Cashier |
| installment_plans | member_id | Installments |
| fines | member_id | Fines |
| violations | member_id | Fines |
| transfer_requests | source_member_id, target_member_id | Transfers |
| waiver_requests | source_member_id, target_member_id | Waiver |
| death_cases | member_id, transferred_to_member_id | Death |
| divorce_cases | member_id, spouse_new_member_id | Divorce |
| carnets | member_id | Carnets |
| receipts | member_id | Receipts |
| member_notes | member_id | Members |
| seasonal_memberships | member_id | Seasonal |
| honorary_members | member_id | Honorary |
| foreign_member_details | member_id | Foreign |

---

## Module → Module Dependencies

### Members Module
| Depends On | How |
|------------|-----|
| Rules (RuleEngine) | All fee calculations, limits, rates |
| Pricing (pricing_configs) | Membership value resolution |
| ServiceCatalog | Form fee price (SVC_NEW_FORM) |
| Branches | Branch selection, branch-specific pricing |
| Qualifications | Pricing tier determination |
| Workflow | New membership workflow instance |
| Forms | Form submission tracking |
| Cashier (PaymentRequestService) | Payment request creation |

### Subscriptions Module
| Depends On | How |
|------------|-----|
| Members | member_id FK, status checks, membership_type for exemptions |
| Spouses | person_type='spouse', active spouses list |
| Children | person_type='child', active children list |
| Temporary | person_type='temporary', active temps list |
| ServiceCatalog | Rate lookup (SVC_ANNUAL_MEMBER, SVC_ANNUAL_CHILD, etc.) |
| Rules (RuleEngine) | Discount percentages, fine rates, grace months, drop years |
| Payments | payment_id FK on paid subscriptions |

### Payments Module
| Depends On | How |
|------------|-----|
| Members | member_id FK |
| Receipts | receipt_id FK |
| Cashier (PaymentRequestService) | Payment request lifecycle |
| Installments | Plan creation on down_payment |
| MembershipPaymentGuard | Activation/deactivation on payment events |
| Workflow | Workflow state transitions on payment |

### Installments Module
| Depends On | How |
|------------|-----|
| Members | member_id, status transitions |
| Payments | payment_id per schedule item |
| Pricing (BoardOffer) | Offer-based terms (grace, interest override) |
| Rules (RuleEngine) | Default rates, min down, max months |

### Fines Module
| Depends On | How |
|------------|-----|
| Members | member_id, status changes (suspended/terminated) |
| Payments | Fine payment via payment_id |
| Cashier | Auto-queue monetary fines |
| Subscriptions | Overdue fine calculation |

### Children Module
| Depends On | How |
|------------|-----|
| Members | member_id FK, membership_value for fee calc |
| Pricing | Current price lookup for fee calculation |
| Rules (RuleEngine) | Fee percentages, age limits, included count |
| Cashier | Addition fee payment requests |

### Spouses Module
| Depends On | How |
|------------|-----|
| Members | member_id FK, membership_value, acquired_member flags |
| Pricing | Current price lookup for fee calculation |
| Rules (RuleEngine) | Fee percentages per order, annual fee, max spouse count |
| Cashier | Addition fee payment requests |

### Temporary Module
| Depends On | How |
|------------|-----|
| Members | member_id FK, membership_value |
| Rules (RuleEngine) | Fee percentages, category validation, age limits |
| Cashier | Addition fee payment requests |

### Waiver Module
| Depends On | How |
|------------|-----|
| Members | Source + target member records |
| Spouses/Children/Temporary | Dependent counts and comparison |
| Archive | Snapshot creation |
| Subscriptions | Cancel source subs, create target subs |
| Cashier | Waiver fee payment request |
| MembershipPaymentGuard | Target activation |

### Death Module
| Depends On | How |
|------------|-----|
| Members | Deceased member + new member creation |
| Spouses | Primary spouse becomes new member |
| Children | Child assignment to new member |
| Temporary | Temp assignment to new member |
| Archive | Snapshot, document transfer |
| Subscriptions | Transfer/create subscriptions for new member |
| Cashier | Death fee payment request |
| MembershipPaymentGuard | New member activation |

### Divorce Module
| Depends On | How |
|------------|-----|
| Members | Original member + new member creation |
| Spouses | Divorced spouse data → new member |
| Children | Child transfer to divorced spouse's new membership |
| Archive | Snapshot creation |
| Subscriptions | New member subscription creation |
| Cashier | Divorce fee payment |
| MemberNumberGenerator | New number for divorced spouse |

### Transfers Module
| Depends On | How |
|------------|-----|
| Members | Source + target member records |
| Children | Child being separated |
| Spouses | Spouse being transferred |
| Pricing | Separation fee = % of current pricing_configs price |
| Archive | Snapshot creation, number chain recording |
| Subscriptions | Sync after transfer completion |
| Cashier | Separation fee payment request |
| MemberNumberGenerator | New number assignment |

---

## Event Dependencies

### Events Dispatched → Listeners

| Event | Dispatched By | Listened By |
|-------|--------------|-------------|
| `member.created` | Members | — |
| `member.activated` | MembershipPaymentGuard | Subscriptions (syncForMember), Pricing (applyFreeSubscriptionBonus) |
| `member.dropped` | InstallmentDefaultJob, OverdueFineJob | — |
| `payment.completed` | PaymentService, RetroactiveMembershipService | Payments bootstrap (workflow transition) |
| `payment_request.completed` | Cashier | PaymentLifecycleService (activation logic) |
| `child.added` | Children | Subscriptions (syncForDependent if fee=0) |
| `child.fee_paid` | Cashier | Subscriptions (syncForDependent) |
| `spouse.added` | Spouses | Subscriptions (syncForDependent if fee=0) |
| `spouse.fee_paid` | Cashier | Subscriptions (syncForDependent) |
| `temporary.added` | Temporary | Subscriptions (syncForDependent if fee=0) |
| `temporary.fee_paid` | Cashier | Subscriptions (syncForDependent) |
| `transfer.completed` | TransferProcessor | Subscriptions (sync target, refresh source) |
| `death.completed` | DeathController | Subscriptions (refresh new member) |
| `divorce.completed` | DivorceController | — |
| `waiver.fee_paid` | Cashier | WaiverAutoCompleteJob (cron) |

---

## Database Dependencies (Shared Entities)

### `pricing_configs` (read by multiple modules)
- Members (fill-form: resolves membership_value)
- BillingService (working/sports bill calculation)
- Children/Spouses/Temporary (fee calculators use current price, NOT stored membership_value)
- Transfers (separation fee base amount)
- Divorce (fee base amount)
- Waiver (waiver fee base)

### `service_catalog` (rate lookup)
- Members (SVC_NEW_FORM for form fee)
- Subscriptions (SVC_ANNUAL_MEMBER, SVC_ANNUAL_SPOUSE, SVC_ANNUAL_CHILD, SVC_ANNUAL_TEMP, + year-specific variants)
- Transfers (FORM_TRANSFER_FEE)

### `system_config` (configuration store)
- MemberNumberGenerator (form_start_number, membership.number_start)

### `board_offers` (promotional pricing)
- Members/BillingService (show bill with offer)
- MemberController (payment request creation with offer snapshot)
- Installments (plan creation uses offer terms)

### `special_discounts`
- Members (assigned per member)
- BillingService (discount line item)
- Pricing/SpecialDiscountService (bonus free subscription years)

---

## Workflow Dependencies

### New Membership Workflow (workflow_definition: 'new_membership')
```
potential → under_review → [interview_scheduled] → accepted → payment_pending → active
```
- Created in MemberController::store()
- Transitions driven by PaymentLifecycleService on payment completion
- workflow_instance_id stored on members table

---

## Financial Year Dependencies

All modules that reference `financial_year`:
- Subscriptions (primary consumer)
- Members/MembershipRulesService (rate lookup)
- Members/MembershipValidationService (current FY subscription check)
- AutoFreezeService (subscription block check)
- OverdueFineApplicator (fine progression by year)
- SubscriptionGenerator (batch generation per year)
- MemberController::show() (current FY display)

**Critical**: FY starts July 1. Format: "2025/2026". Determined by `financial_year()` helper in `app/Core/Helpers.php`.

---

## Cascading Impact Analysis

### If `members.status` changes:
- Subscriptions: exempt types skip generation; active status required for dependent sync
- Payments: PaymentGuard validates status for activation
- Carnets: canPrintCarnet() checks status
- AccessMatrix: facility access gated by active status
- Installments: dropped status on default

### If `members.membership_value` changes:
- BillingService: recalculates bill
- Spouses/Children/Temporary fee calculators: use pricing_configs (NOT stored value), so impact is limited to display
- NOTE: Fee calculators use `pricing_configs` current price, not `members.membership_value`

### If `pricing_configs` changes:
- ALL new fee calculations use new prices (separation, waiver, divorce, child addition, spouse addition)
- Existing members' stored `membership_value` does NOT auto-update
- Impact: new members get new prices; existing member fees remain as calculated at time of creation

### If a dependent is added/removed:
- Subscriptions: syncForDependent creates/removes subscription rows
- BillingService: recalculates totals
- Transfers: dependent counts affect separation eligibility
- Waiver: dependent comparison between source and target

### If a payment is voided:
- MembershipPaymentGuard: may deactivate member + all dependents
- Installments: if down_payment voided, plan affected
- Subscriptions: if annual_subscription voided, status reverts
- Fines: if fine payment voided, fine status reverts to imposed

### If subscription rates change (RuleEngine/ServiceCatalog):
- Only affects NEXT year's generation (existing rows are immutable)
- SubscriptionDataMigration can retroactively fix amounts

### If an installment plan defaults:
- Member dropped immediately
- All pending schedule items marked overdue
- Carnet blocked, subscription generation skipped

---

## National ID Deduplication (Cross-Table Constraint)

National ID uniqueness is enforced ACROSS tables:
- `members.national_id` (unique index)
- `spouses.national_id` (checked against members + children)
- `children.national_id` (checked against members + spouses)
- `temporary_members.national_id` (checked against all above)

This is application-level validation, NOT database-level cross-table constraints.

---

## Permission Dependencies

### Shared Permission Patterns
- `member.*` → Members module
- `subscription.*` → Subscriptions module
- `installment.*` → Installments module
- `fine.*` → Fines module
- `transfer.*` / `separation.*` → Transfers module
- `waiver.*` → Waiver module
- `child.*` → Children module
- `spouse.*` → Spouses module
- `temp.*` → Temporary module
- `carnet.*` → Carnets module
- `payment.*` → Payments module

Super admin check: `employee_roles JOIN roles WHERE role_code = 'super_admin'`
