# TANRAIL ONE — Phase 3.3 Financial Workflows

## 1. Posting a Journal
1. **Initiation**: The `FinancialService::postJournal()` is called with an array of entry lines (Account ID, Debit, Credit) and context (BU, Date, Reference).
2. **Validation**:
   - Verify `SUM(debit) == SUM(credit)`. Reject if unequal.
   - Verify no line has both Debit > 0 and Credit > 0.
   - Verify `FiscalPeriod` for the `posting_date` is not `is_closed`.
   - Verify all `Account`s belong to the same Organization as the Business Unit.
3. **Execution**:
   - Begin DB Transaction.
   - Insert `Journal` header.
   - Insert `JournalEntry` lines.
   - Commit DB Transaction.

## 2. Reversing a Journal
1. **Initiation**: The `FinancialService::reverseJournal(Journal $original)` is called.
2. **Validation**:
   - Ensure original Journal is not already `REVERSED`.
   - Check `FiscalPeriod` for the current date (reversals post today, they don't alter the past if closed).
3. **Execution**:
   - Begin DB Transaction.
   - Mark original Journal as `REVERSED`.
   - Create new `Journal` indicating it reverses the original.
   - Create inverted `JournalEntry` lines (Original Debits become Credits, Credits become Debits).
   - Commit DB Transaction.

## 3. Operational Integration (Event-Driven)
The Financial Core does not reach into Sales or Procurement. Instead:
- Sales Engine emits `PaymentReceived`.
- Financial Core listener `ProcessSalesPayment` catches it, structures the debits and credits, and calls `FinancialService::postJournal()`.

This guarantees the Financial Core remains generic.
