# BNI Accounting — Development Log

Tracks implementation tasks, decisions, and deferred items.

---

## Task Status

| # | Task | Status |
|---|---|---|
| 01 | Project scaffold (Laravel, Sanctum, base migrations) | DONE |
| 02 | Role system (treasurer / president / member) | DONE |
| 03 | Chapter model + isolation middleware | DONE |
| 04 | User provisioning (Treasurer creates users, no invite flow) | DONE |
| 05 | Member model (independent of User) | DONE |
| 06 | Chapter leadership FKs (president_id, treasurer_id) | DONE |
| 07 | Authentication (login, logout, token refresh) | DONE |
| 08 | Password management (set, reset by Treasurer) | DONE |
| 09 | Meeting model + state machine (draft → open → closed) | DONE |
| 10 | Member dues generation on meeting open | DONE |
| 11 | Visitor entry (Screen 11 flow) | DONE |
| 12 | Visitor fee defaults (chapters.standard_visitor_fee) | DONE |
| 13 | Member payment recording | DONE |
| 14 | FIFO payment allocation (PaymentAllocationService) | DONE |
| 15 | Ledger transaction recording with concurrency lock | DONE |
| 16 | Meeting close + reconciliation snapshot | DONE |
| 17 | Expense recording | DONE |
| 18 | Financial reversal architecture (no hard delete) | DONE |
| 19 | Dashboard — cash in hand + bank balance computation | DONE |
| 20 | Open Questions Resolution — approved decisions implemented | DONE |
| 21 | Role / status management (self-mutation guards, token revocation) | DONE |

---

## Task 20 — Open Questions Resolution

All open product questions from `docs/open-questions.md` have been resolved. That file is now superseded by `docs/decision-log.md`, which records all 24 decisions with rationale, implementation impact, and status.

### Major schema changes implemented as part of this task

| Table | Column Added | Purpose |
|---|---|---|
| `chapters` | `standard_visitor_fee` decimal(10,2) nullable | Default visitor fee pre-populated on meeting open |
| `chapters` | `weekly_meeting_fee` decimal(10,2) | Per-chapter configurable meeting due amount |
| `chapters` | `timezone` varchar(50) | IANA timezone string for date display |
| `chapter_terms` | `start_date` date | Term start (6-month window) |
| `chapter_terms` | `end_date` date | Term end (start_date + 6 months - 1 day) |
| `chapter_terms` | `opening_cash` decimal(10,2) | Opening cash balance for the term |
| `member_dues` | `status` enum(unpaid, partial, paid) | Denormalised status updated by PaymentAllocationService |
| `member_payments` | `unallocated_amount` decimal(10,2) | Excess payment not yet applied to any due |
| `member_payments` | `reversed_at` timestamp nullable | Set when payment is reversed |
| `member_payments` | `reversal_of` unsignedBigInt nullable | FK to the original payment this reverses |
| `expenses` | `reversed_at` timestamp nullable | Set when expense is reversed |
| `expenses` | `reversal_of` unsignedBigInt nullable | FK to the original expense this reverses |
| `ledger_transactions` | `running_balance` decimal(12,2) | Cumulative balance at time of entry |
| `ledger_transactions` | `reversed_at` timestamp nullable | Set when ledger line is reversed |
| `meetings` | `closing_cash_in_hand` decimal(10,2) nullable | Snapshot of cash in hand at meeting close |
| `visitors` | `is_first_visit` boolean | Server-derived; true if no prior visit for same mobile |
| `visitors` | `fee_waived` boolean | Derived server-side when `amount == 0` |

### Key service classes introduced

- `PaymentAllocationService` — FIFO allocation, deallocation on reversal
- `ReversalService` — compensating entry creation, audit chain maintenance
- `LedgerService` — ledger write with `lockForUpdate` concurrency guard
- `CashInHandService` — cash and bank balance computation from ledger
- `TermService` — chapter term creation and validation

---

## Deferred Items (Phase 2)

The following decisions were made and documented but implementation is deferred past the initial launch:

| Item | Decision Ref | Notes |
|---|---|---|
| Dark mode | Q15 | Requires full design token audit and QA pass |
| Biometric authentication | Q16 | Face ID / fingerprint; backend auth is already token-based and ready |
| Push notifications | Q17 | Requires FCM/APNs integration and device token management |
| Offline visitor entry | Q4 | Online-only for Phase 1; offline queue design TBD |

---

## Architectural Invariants (do not break)

These decisions are load-bearing. Changing them requires a full decision-log update and migration plan.

1. **No hard deletes on financial records.** Use reversal entries. See Q18.
2. **Chapter-level `lockForUpdate` for ledger writes.** Do not remove without replacing with an equivalent serialisation mechanism. See Q19.
3. **FIFO allocation.** Any change to allocation order invalidates existing `PaymentAllocation` records and historical reports. See Q12.
4. **Server derives `is_first_visit` and `is_partial`.** Clients do not set these. See Q6 and Q22.
5. **One open meeting per chapter at a time.** Enforced at service layer. See Q5.
6. **6-month terms.** `TermService::create()` hardcodes the 6-month window. Do not make this configurable without a full reporting review. See Q8.
