# Sprint D4 Assumptions Log

Generated automatically during AI-assisted implementation. These are decisions made during D4-01–D4-18 where the sprint plan was ambiguous, incomplete, or the referenced user story did not match the task title.

---

## D4-07 — Invoice List

- **Auth test pattern**: No named `login` route exists. Changed `assertRedirect('/login')` to `getJson()->assertUnauthorized()` in auth tests. Applied to all subsequent auth tests in D4.
- **ComingSoonTest**: `/invoices` was in the placeholder routes test — removed it when the real InvoiceList page was wired in.

---

## D4-08 — Purchase Bill Schema + Form

- **Bill table naming**: ARCHITECTURE.md uses `creditor_invoices` but all prior sprint work used `bills` (consistent with our Invoice/Bill naming in D4-06). Kept `bills`.
- **Bill number**: Supplier's reference (`bill_no`) is nullable — it's what the supplier prints on their invoice. Our internal reference (`PBIL-YYYYMM-NNNN`) is generated on posting, not stored in `bill_no`. This mirrors how invoice_no works on the debtor side.
- **MyInvois UIN**: Validated as UUID regex (standard UIN format). `e_invoice_inbound` flag set automatically if UIN is present.
- **TransactionType.Bill**: D4-06 migration already allowed `'bill'` in the CHECK constraint. Only needed to add the enum case, no new migration.
- **`account_type = 'expense'`** used for expense accounts in bill lines (matches AccountType::Expense->value = 'expense').

---

## D4-09 — Bill Post Action

- **Double-entry for posted bill**: Dr Expense (each line's coa_account_id), Cr AP (party.default_account_id). Mirrors the invoice posting but on the payables side.
- **Reference format**: `PBIL-YYYYMM-NNNN` — count of already-posted bills + existence check to avoid collisions (no separate sequence table for bills).
- **Status transition on post**: draft → received (not posted). "Received" means "we've received the bill and it's in our books as payable".

---

## D4-10 — Bill List Page

- **account_type filter**: Bills are creditor-side; filtered parties use PartyType::Creditor. Consistent with CreateBillController.
- **eInvoice badge**: Shows when `e_invoice_inbound = true` (bill came in via MyInvois). Orange badge to distinguish from domestic bills.
- **Quick "Rekod" action**: Links to `/bills/{id}/pay` for draft bills — should be "Post" not "Rekod". Labelled "Hantar" (Post) in UI for draft bills. Assumption: "Rekod" means record/post the bill to AP.

---

## D4-11 — Pay Invoice Action

- **amount_paid_cents on invoices**: Added via a separate migration (not in the original bills table schema). D4-11 adds it to invoices, D4-12 adds it to bills.
- **Transaction type for invoice receipt**: `type = 'receipt'` (cash received from debtor).
- **Status logic**: `amount_paid >= total` → `paid`; `0 < amount_paid < total` → `partial`. Over-payment rejected with DomainException.
- **Bank accounts**: Filtered from CoaAccounts as `account_type = 'asset'` and `is_active = true`. No separate bank party type needed for the payment form.

---

## D4-12 — Pay Bill Action

- **Transaction type for bill payment**: `type = 'payment'` (cash paid to creditor). Mirrors invoice receipt on the AP side.
- **Double-entry for payment**: Dr AP (reduce liability), Cr Bank (reduce asset). Correct accounting direction.
- **Bill status check**: Only `received` and `partial` statuses can be paid. Draft bills rejected.

---

## D4-13 — Payment Allocations

- **Table name**: `payment_allocations` (from ARCHITECTURE.md). Uses polymorphic `target_type IN ('invoice', 'bill')` instead of the original ARCHITECTURE.md `('invoice', 'creditor_invoice', 'credit_note', 'debit_note')` — adapted to match our actual model names.
- **No multi-invoice allocation form**: The task description mentions "allocation defaults to oldest-invoice-first but TU can manually allocate" (from TXN-TU-08). For demo sprint, the allocation table is written as a schema + single-payment row. The multi-invoice allocation form (UI to pick which invoices to pay against one payment) is deferred to a future task.
- **Allocation created per payment**: Each `PayInvoice`/`PayBill` action call writes one allocation row. If a future multi-invoice payment form is built, it will write multiple allocation rows per transaction.

---

## D4-14 — Trial Balance Polish

- **"Export to Excel"**: Implemented as CSV (Excel-compatible). No `maatwebsite/excel` or `phpoffice/phpspreadsheet` package installed. CSV opens natively in Excel. Added note in PR.
- **Drill-down link**: Uses raw `<a href>` (not Inertia `Link`) since the target is Buku Tunai with query params — full page load is acceptable.
- **account_id filter validation**: UUID format regex validated before query to prevent PostgreSQL type errors on invalid input.

---

## D4-15 — P&L Statement

- **User story mismatch**: The sprint plan references RPT-TA-02 (Notes to Accounts) in the acceptance criteria, but the task title says "P&L statement". Implemented per the title. Notes to Accounts is a separate, much larger feature not appropriate for demo sprint.
- **No cost-of-sales section**: The current CoA doesn't classify accounts into COGS vs operating expenses. All expense accounts appear in one "Perbelanjaan" section. A future task could add a `is_cogs` flag to CoA accounts.
- **Normal balance logic**: Income = net credit (revenue recognised when credited); Expense = net debit (cost recognised when debited).

---

## D4-16 — Balance Sheet

- **User story mismatch**: The sprint plan references RPT-TA-03 (full Penyata Kewangan PDF) in the acceptance criteria. Implemented the Balance Sheet data report only, per the task title.
- **Cumulative computation**: Balance Sheet is computed from ALL posted periods with `period_start <= selected period_end`. This is the correct accounting approach — the BS reflects balances from inception, not just one period.
- **Retained earnings**: Net income from P&L is computed inline and added as a retained earnings line in equity. This ensures BS.assets = BS.liabilities + BS.equity always.
- **Opening balances**: Not yet imported (no data migration feature). BS figures represent only AMIR-entered transactions from day one. Future task: opening balance import wizard.

---

## D4-17 — Cash Flow Statement

- **User story mismatch**: Sprint plan references RPT-TA-03 in AC. Implemented Cash Flow per the task title.
- **Indirect method approximation**: AR movement computed from receipt-type transactions crediting asset accounts; AP movement from payment-type transactions debiting liability accounts. This is an approximation — a full indirect CF would need to compare opening/closing AR/AP balances, which requires opening balances (not yet implemented).
- **Investing/Financing sections**: Show zero for demo — no fixed assets or equity transactions yet. Structurally present so the page layout is complete.
- **Opening cash balance**: Shows 0 (no opening balance import). Closing cash = net change in cash for the period.

---

## D4-18 — Numbers Tie-Out Integration Test

- **Cash Flow not included in tie-out**: The tie-out asserts TB, P&L→BS retained, and BS equation. Cash Flow's AR/AP movement logic depends on `transaction.type` being set to 'receipt'/'payment', which the generic Transaction factory doesn't set. Separate CashFlowTest.php covers cash flow. Added note in PR.
- **10 transactions chosen to cover**: capital injection, loan received, 2 invoices raised, 1 receipt, 2 expenses (one on credit, two cash), 1 creditor payment, 1 loan repayment. All balanced entries.
- **Specific asset assertion**: Bank + AR totals manually traced to 770,000 to verify the action produces correct figures (not just "balanced").

---

*End of D4 Assumptions Log. Next sprint: D5-01 through D5-22.*
