# Secure Finance System Architecture

This document is the long-term build plan for the Examism finance management system. It is intentionally not a patch list. The goal is to replace loose finance entry with a secure, controlled, auditable ledger that supports your Pakistan, USA, and Australia voucher business flow.

## Core Principles

- Use one permanent accounting engine for every country, bank, wallet, payment gateway, vendor, loan, and expense.
- Store money movement as immutable ledger postings. Posted financial records are not edited or deleted; corrections are made by reversal entries.
- Keep all banks, wallets, gateways, vendors, exchangers, and "other" options configurable in the database, not hard-coded in PHP.
- Track business flow levels for reporting, but do not create separate transaction systems for each level.
- Keep category and subcategory data normalized so expense reports remain clean as the business grows.
- Require authorization, approval, audit logging, and reconciliation for sensitive finance actions.
- Never store money as floating point. Use fixed precision decimals and ISO currency codes.

## Business Flow Model

### Level 1: Pakistan Customer Receipts And First Distribution

Money is received into Pakistan receiving accounts and gateways:

- Examism Faysal Bank
- FlyFreedom Faysal Bank
- Other Pakistan receiving banks
- KuchikPay
- PayFast
- Manual/other deposits

Funds can then move to:

- Pakistan Tifwa Group
- AR Commission
- Other Pakistan clearing or partner accounts

System treatment:

- Customer receipt creates a posted ledger transaction.
- The receiving bank or gateway balance increases.
- Source channel is recorded separately from the actual money account.
- Transfer from receiving account to Tifwa/AR/other is recorded as a controlled transfer, not as a fresh income record.

### Level 2: Pakistan Clearing To Expenses, USA, And Australia

Tifwa, AR Commission, and other Pakistan clearing accounts receive funds from Level 1, then send funds to:

- Pakistan bank accounts for operating expenses such as salary, rent, utilities, marketing, tax, refunds, and other categories.
- USA funding paths for voucher invoice payment.
- Australia funding paths for invoice and operating payment.

System treatment:

- Pakistan expenses are posted against category and subcategory.
- USA and Australia funding are transfers with country, currency, exchange rate, fee, and reference proof.
- Every movement preserves the original source trail.

### Australia Flow

Australia resources include:

- Tifwa Group AUS
- Commbank CC AUS
- Other future Australia bank/card resources

Money can be added from Pakistan banks or other resources, then used to pay:

- Vendor invoices
- Card payments
- Australia operating expenses
- Other approved business payments

System treatment:

- Australia resources are money accounts with country `AU` and currency such as `AUD`.
- Card payments are tracked as card liability or card resource depending on the real business meaning.
- Vendor invoice payment links directly to vendor, invoice, voucher product, and payment account.

### USA Payment Flow

USA resources include:

- Ahad Wallet
- Tayyab Wallet
- Opal BOFA
- Examism BOFA
- Other future USA banks and wallets
- Lent/borrowed amounts

System treatment:

- Wallets and BOFA accounts are separate money accounts.
- Lent/borrowed money is tracked through loan records and ledger entries, not hidden in notes.
- Each wallet-to-bank movement is a transfer with reference, fee, and status.

### Level 3: Exchanger/Vendor To Wallet To Bank

Money can move through exchange vendors/methods:

- Speed Global
- Phenom Exchange
- Other exchange method

Flow:

1. Pakistan or clearing account sends money to exchanger.
2. Exchanger credits Ahad Wallet or Tayyab Wallet.
3. Wallet sends money to Opal BOFA or Examism BOFA.

System treatment:

- Exchange order is recorded with source currency, destination currency, expected amount, actual amount, rate, fee, and proof.
- Transfers can stay pending until destination wallet/bank confirms receipt.
- FX gain/loss and exchange fees are explicit ledger entries.

### Level 4: Voucher Vendor Invoice Payment

Vendor list:

- Pearson
- ETS
- Duolingo
- Oxford
- LanguageCert
- APEUni
- ApplyBoard
- AlphaPTE
- Other vendor

Payment resources:

- Australia: Tifwa Group AUS, Commbank CC AUS, other future Australia resources.
- USA: Opal BOFA, Examism BOFA, other future USA resources.

System treatment:

- Vendor invoice is entered first.
- Payment is linked to the invoice and payment account.
- Voucher stock/inventory can be linked to the invoice when vouchers are purchased.
- Partial payments, overpayments, refunds, and credits are tracked cleanly.

## Proposed Database Structure

### Reference Tables

`countries`

- `id`
- `code` unique, for example `PK`, `US`, `AU`
- `name`
- `is_active`
- timestamps

`currencies`

- `id`
- `code` unique, for example `PKR`, `USD`, `AUD`
- `name`
- `decimal_places`
- `is_active`
- timestamps

`business_entities`

- `id`
- `name`, for example Examism, FlyFreedom
- `country_id`
- `base_currency_id`
- `is_active`
- timestamps

`parties`

- `id`
- `party_type`: customer, vendor, exchanger, staff, partner, bank, gateway, owner, other
- `name`
- `country_id` nullable
- `email` nullable
- `phone` nullable
- `notes` nullable
- `is_active`
- timestamps

Use `parties` for Pearson, ETS, Speed Global, Phenom Exchange, staff members, customers, and "other" counterparties.

### Money Accounts

`money_accounts`

- `id`
- `business_entity_id` nullable
- `party_id` nullable
- `name`, for example Examism Faysal, Ahad Wallet, Opal BOFA
- `account_kind`: bank, wallet, gateway, cash, credit_card, clearing, loan, owner_equity, income, expense, payable, receivable, suspense
- `flow_group`: level_1_receiving, level_2_clearing, pakistan_expense, usa_wallet, usa_bank, australia_bank, australia_card, vendor_payable, lending_borrowing, system
- `country_id`
- `currency_id`
- `bank_name` nullable
- `account_number_encrypted` nullable
- `last_four` nullable
- `opening_balance`
- `opening_balance_date`
- `is_active`
- `requires_reconciliation`
- `notes` nullable
- timestamps

This replaces the current loose `bank_accounts` concept with a future-safe account/resource table.

`payment_channels`

- `id`
- `name`, for example KuchikPay, PayFast, Bank Transfer, Manual Deposit
- `channel_type`: bank_transfer, gateway, wallet, cash, manual, other
- `default_money_account_id` nullable
- `is_active`
- timestamps

The channel records how payment arrived; the money account records where the money sits.

### Category Structure

`expense_categories`

- `id`
- `parent_id` nullable, references `expense_categories`
- `name`, for example Payroll, Salary, Rent, Vendor Fee
- `code` unique nullable
- `country_id` nullable
- `is_active`
- timestamps

Example category tree:

- Payroll
- Salary
- Contractor Payment
- Office
- Rent
- Utilities
- Internet
- Marketing
- Ads
- Agency Commission
- Voucher Purchase
- Pearson
- ETS
- Duolingo
- Bank And Gateway Charges
- Exchange Fee
- PayFast Fee
- KuchikPay Fee
- Travel
- Tax And Compliance
- Refunds
- Other Expense

`income_categories`

- `id`
- `parent_id` nullable
- `name`
- `code` unique nullable
- `is_active`
- timestamps

Example income category tree:

- Voucher Sales
- Pearson Voucher Sale
- ETS Voucher Sale
- Duolingo Voucher Sale
- Manual Bank Deposit
- Refund Received
- Other Income

### Ledger

`ledger_transactions`

- `id`
- `transaction_no` unique
- `business_date`
- `posting_status`: draft, submitted, approved, posted, void
- `transaction_type`: customer_receipt, internal_transfer, expense, vendor_invoice, vendor_payment, exchange_order, wallet_transfer, loan_issued, loan_received, loan_repayment, adjustment, reversal
- `flow_level`: level_1, level_2, level_3, level_4, general
- `business_entity_id` nullable
- `country_id` nullable
- `reference` nullable
- `description` nullable
- `created_by`
- `submitted_by` nullable
- `approved_by` nullable
- `posted_by` nullable
- `reversed_by` nullable
- `reversal_of_id` nullable
- `posted_at` nullable
- `voided_at` nullable
- timestamps

`ledger_entries`

- `id`
- `ledger_transaction_id`
- `money_account_id`
- `entry_side`: debit, credit
- `amount`
- `currency_id`
- `base_amount` nullable
- `base_currency_id` nullable
- `exchange_rate` nullable
- `expense_category_id` nullable
- `income_category_id` nullable
- `party_id` nullable
- `vendor_invoice_id` nullable
- `voucher_product_id` nullable
- `notes` nullable
- timestamps

Rules:

- Each posted ledger transaction must balance: total debits equal total credits per currency or base currency policy.
- Drafts can be edited; posted entries cannot be edited.
- Reversals create new entries linked to the original transaction.

### Workflow Tables

`account_transfers`

- `id`
- `ledger_transaction_id`
- `from_money_account_id`
- `to_money_account_id`
- `amount`
- `currency_id`
- `fee_amount` default 0
- `fee_expense_category_id` nullable
- `exchange_rate` nullable
- `expected_receive_amount` nullable
- `actual_receive_amount` nullable
- `status`: draft, pending, completed, cancelled
- `sent_at` nullable
- `received_at` nullable
- timestamps

`exchange_orders`

- `id`
- `ledger_transaction_id`
- `exchanger_party_id`
- `source_money_account_id`
- `destination_money_account_id`
- `source_amount`
- `source_currency_id`
- `destination_amount`
- `destination_currency_id`
- `exchange_rate`
- `fee_amount` default 0
- `status`: draft, sent, received, completed, cancelled
- `reference` nullable
- timestamps

`vendor_invoices`

- `id`
- `vendor_party_id`
- `invoice_no`
- `invoice_date`
- `due_date` nullable
- `country_id`
- `currency_id`
- `subtotal_amount`
- `fee_amount` default 0
- `tax_amount` default 0
- `total_amount`
- `status`: draft, approved, partially_paid, paid, cancelled
- `notes` nullable
- timestamps

`vendor_invoice_items`

- `id`
- `vendor_invoice_id`
- `voucher_product_id` nullable
- `description`
- `quantity`
- `unit_cost`
- `total_amount`
- timestamps

`vendor_payments`

- `id`
- `ledger_transaction_id`
- `vendor_invoice_id`
- `payment_money_account_id`
- `amount`
- `currency_id`
- `payment_date`
- `reference` nullable
- timestamps

`loans`

- `id`
- `counterparty_id`
- `direction`: lent, borrowed
- `currency_id`
- `principal_amount`
- `open_date`
- `due_date` nullable
- `status`: open, settled, written_off
- `notes` nullable
- timestamps

`loan_movements`

- `id`
- `loan_id`
- `ledger_transaction_id`
- `movement_type`: disbursement, repayment, adjustment, write_off
- `amount`
- `currency_id`
- `movement_date`
- timestamps

### Voucher Tables

Keep `voucher_products`, but evolve it:

- Add `vendor_party_id`
- Add `country_id`
- Add `currency_id`
- Add stronger SKU uniqueness
- Keep active/inactive state

Keep inventory movements, but link them to invoices and ledger transactions:

- `ledger_transaction_id` nullable
- `vendor_invoice_item_id` nullable
- `movement_no` unique
- no hard delete after posting

### Evidence And Reconciliation

`attachments`

- `id`
- `attachable_type`
- `attachable_id`
- `file_name`
- `disk`
- `path`
- `mime_type`
- `size`
- `sha256_hash`
- `uploaded_by`
- timestamps

Use this for bank screenshots, invoices, receipts, exchange proofs, and vendor documents.

`reconciliations`

- `id`
- `money_account_id`
- `statement_start_date`
- `statement_end_date`
- `statement_balance`
- `system_balance`
- `status`: draft, reconciled, reopened
- `reconciled_by` nullable
- `reconciled_at` nullable
- timestamps

`reconciliation_items`

- `id`
- `reconciliation_id`
- `ledger_entry_id`
- `matched_amount`
- `notes` nullable
- timestamps

### Imports

`import_batches`

- `id`
- `source_type`: csv, google_sheets, bank_statement, manual
- `source_name` nullable
- `status`: pending, processing, completed, failed
- `created_by`
- timestamps

`import_rows`

- `id`
- `import_batch_id`
- `row_number`
- `raw_payload` json
- `validation_status`: pending, valid, invalid, imported, skipped
- `error_message` nullable
- `ledger_transaction_id` nullable
- timestamps

Imports must validate first, then post only approved clean records.

### Security And Audit Tables

`roles`

- `id`
- `name`: owner, admin, finance_manager, data_entry, viewer, auditor
- timestamps

`permissions`

- `id`
- `name`, for example `transactions.post`, `accounts.manage`, `reports.view`
- timestamps

`role_user`

- `role_id`
- `user_id`

`permission_role`

- `permission_id`
- `role_id`

`audit_logs`

- Keep current table but strengthen it:
- Add `event_uuid`
- Add `request_id`
- Add `before_hash`
- Add `record_hash`
- Add `metadata`
- Add indexes on action, user, date, auditable target

Audit logs should be append-only.

## Required Security Controls

### Authentication

- Disable public registration before production.
- Require email verification.
- Require 2FA for owner, admin, finance manager, and any user who can post/approve money movement.
- Keep login throttling and two-factor throttling.
- Use strong password validation and hashed passwords only.
- Use database sessions with secure, HttpOnly, SameSite cookies.

### Authorization

- Add roles and permissions.
- Protect every finance route with policies, not only route middleware.
- Sensitive actions require permission checks:
- Create/edit draft transaction
- Submit transaction
- Approve transaction
- Post transaction
- Reverse transaction
- Manage money accounts
- Manage vendors
- Export reports
- View audit logs

### Finance Integrity

- Use database transactions for every posting.
- Lock affected accounts during posting where needed.
- Validate that posted ledger transactions balance.
- Prevent negative balances only where the business rule requires it. Some accounts, such as credit cards or loans, may intentionally go negative.
- Never hard-delete posted finance records.
- Use reversal workflow for mistakes.
- Require approval before posting high-value transfers, vendor payments, and account changes.
- Store references and proof attachments for transfers, exchanges, and invoices.

### Data Protection

- Encrypt sensitive account numbers.
- Display masked account numbers only.
- Store attachments on private storage, not public web paths.
- Hash uploaded files to detect tampering.
- Do not store bank passwords, OTPs, card CVV, or secret payment credentials in this application.
- Keep API keys and Google credentials outside Git, under `.env` or private storage.

### Application Security

- Use Laravel Form Requests or equivalent validation classes.
- Use enums/constants for transaction types and account kinds.
- Avoid raw SQL unless parameterized and reviewed.
- Keep mass assignment limited with explicit fillable fields.
- Escape all output in Blade.
- Keep CSRF protection on every form.
- Keep security headers, but later tighten CSP by removing inline script/style needs from the frontend build.

### Production Security

- `APP_ENV=production`
- `APP_DEBUG=false`
- HTTPS only
- `SESSION_SECURE_COOKIE=true`
- Least-privilege database user
- Daily encrypted database backups
- Backup restore tests
- Dependency updates and vulnerability checks
- Server firewall with only required ports open
- Error logs monitored without exposing sensitive data to users

## Migration Strategy

Because this system is still early, the cleanest path is:

1. Confirm whether current local demo data can be discarded.
2. If yes, replace the Phase 1 finance tables with the new ledger schema before real usage.
3. If no, write explicit forward migrations and a one-time data conversion command from old `bank_accounts` and `transactions` into `money_accounts`, `ledger_transactions`, and `ledger_entries`.
4. Add seeders for default countries, currencies, roles, permissions, account groups, vendors, payment channels, and expense categories.
5. Build workflows on top of the ledger tables only.

No temporary compatibility layer should be used for new finance operations.

## Initial Seed Data

Countries:

- Pakistan
- United States
- Australia

Currencies:

- PKR
- USD
- AUD

Payment channels:

- KuchikPay
- PayFast
- Bank Transfer
- Manual Deposit
- Other

Pakistan accounts/resources:

- Examism Faysal Bank
- FlyFreedom Faysal Bank
- Pakistan Tifwa Group
- AR Commission
- Other Pakistan Bank/Resource

USA accounts/resources:

- Ahad Wallet
- Tayyab Wallet
- Opal BOFA
- Examism BOFA
- Other USA Bank/Wallet

Australia accounts/resources:

- Tifwa Group AUS
- Commbank CC AUS
- Other Australia Bank/Card

Exchange parties:

- Speed Global
- Phenom Exchange
- Other Exchange Method

Voucher vendors:

- Pearson
- ETS
- Duolingo
- Oxford
- LanguageCert
- APEUni
- ApplyBoard
- AlphaPTE
- Other Vendor

## Build Phases

### Phase 1: Security And Ledger Foundation

- Disable public registration.
- Add roles, permissions, and policies.
- Create countries, currencies, parties, money accounts, payment channels, categories.
- Create ledger transactions and ledger entries.
- Add posting service with balance validation.
- Add immutable audit logging.

### Phase 2: Level 1 And Level 2 Workflows

- Customer receipt form.
- Internal transfer form.
- Pakistan expense form with category and subcategory.
- Account balance reports by country, business entity, and flow level.

### Phase 3: USA/Australia Funding And Exchange

- Exchange order workflow.
- Wallet-to-bank transfer workflow.
- Australia resource funding workflow.
- Lent/borrowed workflow.

### Phase 4: Vendor Invoice And Voucher Inventory

- Vendor invoice entry.
- Invoice approval and payment.
- Vendor-wise balance.
- Voucher inventory linked to invoice items.
- Vendor payment reports.

### Phase 5: Reconciliation, Imports, And Reports

- Bank/wallet/card reconciliation.
- CSV and Google Sheets import staging.
- Profit/loss report.
- Cash flow report.
- Vendor invoice report.
- Expense category report.
- Audit report.

## Approval Points Before Coding

Before implementation, confirm these points:

- Should old demo records be discarded, or must they be migrated?
- Should every transaction require approval, or only transactions above a limit?
- What approval limit should be used for Pakistan, USA, and Australia?
- Should data-entry users be allowed to create drafts only, with owner/admin posting?
- Should account balances be allowed to go negative for wallets and banks, or only for credit cards/loans?
- What is the business base currency for consolidated reports: PKR, USD, or both?
- Should voucher inventory quantity be mandatory on every vendor invoice item, or optional?
