# TANRAIL ONE — Phase 3.3 Financial Core Architecture

## 1. Objective
Design the generic financial infrastructure for the TANRAIL ONE platform. This establishes a foundational double-entry ledger capable of recording the financial consequences of business operations (Sales, Procurement, Inventory) without coupling to any industry-specific terminology.

## 2. Answers to Mandatory Architectural Questions

### 1. Chart of Accounts Architecture
The Chart of Accounts (CoA) is defined at the **Organization** level to ensure consistent consolidated reporting. It consists of generic nominal accounts (e.g., Cash, Accounts Receivable, Inventory Asset, Cost of Goods Sold, Sales Revenue, Accounts Payable).

### 2. Account Hierarchy
Flat for now, categorized by generic type: Asset, Liability, Equity, Revenue, Expense. Parent-child relationships (e.g., Current Assets -> Bank) can be added as a nullable `parent_id` on the Account model, but transactions always post to the leaf account.

### 3. Organization-level vs Business Unit-level boundaries
Accounts belong to the Organization. However, every financial transaction (Journal Entry) must specify a `business_unit_id`. This allows an Organization-level CoA while ensuring every single financial value is ring-fenced to the exact Business Unit that generated it.

### 4. Fiscal Periods
To keep the Core generic but compliant, we introduce `FiscalPeriod` (e.g., "2026-09"). A period belongs to an Organization. It has statuses: `OPEN`, `CLOSED`. Posting into a closed period is strictly forbidden.

### 5. Journal / Journal Entry Architecture
- **Journal**: A collection of entries representing a single business event (e.g., a Sale).
- **JournalEntry**: A single line (Debit or Credit) hitting a specific Account.

### 6. Debit and Credit Representation
We use two separate decimal columns on the `JournalEntry`: `debit` and `credit`. A row must have a value > 0 in exactly one of these columns, and 0 in the other. (Alternatively, a single `amount` where positive=debit, negative=credit, but separate columns are more standard in traditional ERP tables for clarity and reporting). We will use separate `debit` and `credit` columns.

### 7. Double-entry Accounting Invariants
`SUM(debit) == SUM(credit)` within a single Journal. This is a non-negotiable mathematical invariant enforced at the Service layer before persisting to the database.

### 8. Transaction Posting Lifecycle
Journals are instantiated in memory, their lines are accumulated, and then they are POSTED in a single atomic database transaction. There is no concept of a "saved but unposted" Journal in the Core ledger. It is either completely posted or it does not exist.

### 9. Draft vs Posted vs Reversed states
- `POSTED`: Normal state.
- `REVERSED`: Indicates this journal was cancelled via a reversing journal.
There is no `DRAFT` state for journals; drafts belong to operational documents (like Orders), not the final ledger.

### 10. Financial Transaction Immutability
Once a Journal is `POSTED`, it is strictly immutable. Model observers will block any `update()` or `delete()` calls.

### 11. Reversal Strategy
To correct a mistake, a new Journal is created with the exact inverse debits and credits of the original, linking back to the original via `reverses_journal_id`. Both remain in the database.

### 12. Relationship between Sales Payments and accounting entries
When an `Order` generates a `Payment` in the Sales Engine, an Event (`PaymentReceived`) is dispatched. The Financial Core listens to this and posts a Journal (Debit Cash, Credit Accounts Receivable/Revenue).

### 13. Relationship between Supplier Payments and accounting entries
When a `SupplierPayment` is recorded in Procurement, an Event is dispatched. The Financial Core listens and posts a Journal (Debit Accounts Payable, Credit Cash).

### 14. Relationship between Inventory movements and accounting entries
*Deferred Decision:* Currently, Inventory operates on physical quantities only, not valuation (FIFO/LIFO). Therefore, Inventory Movements will NOT generate financial Journals in Phase 3.3. Inventory valuation is deferred to a future Advanced Procurement/Finance extension.

### 15. Currency Architecture
For Phase 3.3, the system assumes a single base currency defined at the Organization level. Multi-currency (FX rates, realized gains/losses) is out of scope for the foundational core to avoid scope creep.

### 16. Tax Architecture
We use the existing `TaxCategory` (if any, or simply the `tax_amount` values calculated by the Sales/Procurement engines). The operational engines calculate tax; the Financial Core merely books the `tax_total` to a dedicated "Tax Payable/Receivable" Account.

### 17. Financial Period Locking
The `JournalService` will validate the Journal's `posting_date` against the Organization's `FiscalPeriod`. If `CLOSED`, it throws an exception.

### 18. Audit Trail
Journals record `created_by` (User ID), `business_unit_id`, `reference_type` (e.g., 'Payment'), and `reference_id`, ensuring full traceability to the operational source.

### 19. Cross-BU financial isolation
Journals are strictly filtered by `business_unit_id` globally. A user in BU A cannot query Journals belonging to BU B.

### 20. Organization-level consolidated reporting
Since Accounts are Organization-wide and Journals share a schema, an Organization Admin can query `SUM(debit) - SUM(credit)` grouped by `account_id` across ALL Business Units to generate a consolidated trial balance.
