# SPECIFICATIONS/05_ALGORITHMS/04_COMPUTED_FIELDS.md

**PURPOSE:** Defines the formulas for all dynamically calculated fields in the system. This file answers "how is this number calculated?" — it contains zero database query implementations.

> **Business rules behind these formulas:** `../01_BUSINESS_CONTEXT/03_BUSINESS_RULES.md` → BR-005-3 (investor profit), BR-005-4 (shares balance)
> **Where these fields appear in API responses:** `../06_API/06_0X_*.md`

**Precision Rule:** All financial calculations MUST use arbitrary-precision arithmetic. All monetary results rounded to 2 decimal places, half up.

---

## 5.1: Investor Profit (Per Investor)

> **Rule definition:** `../01_BUSINESS_CONTEXT/03_BUSINESS_RULES.md` → BR-005-3

**Formula:**
```
contract_margin = total_after_profit - purchase_amount

total_contract_margin = SUM(contract_margin)
    FROM contracts
    WHERE agent_id = {investor_id}
      AND status IN ('active', 'completed')

investor_profit = total_contract_margin × 0.05
```

**Filters:**
- Only `active` or `completed` contracts
- Draft contracts excluded
- If investor has no active/completed contracts where they are the agent: profit = 0.00

---

## 5.2: Shares Balance

> **Rule definition:** `../01_BUSINESS_CONTEXT/03_BUSINESS_RULES.md` → BR-005-4

**Formula:**
```
balance = SUM(
    CASE WHEN transaction_type = 'deposit' THEN +shares_count
         WHEN transaction_type = 'withdraw' THEN -shares_count
    END
)
FROM client_shares_logs
WHERE client_id = {investor_id}
  AND status = 'active'
```

**Examples:**

| Operation | Type | Count | Status | Effect on Balance |
|:---|:---|:---|:---|
| Deposit 10 | deposit | 10 | active | +10 |
| Deposit 5 | deposit | 5 | active | +5 |
| Withdraw 3 | withdraw | 3 | active | -3 |
| **Result** | | | | **+12** |

| Operation | Type | Count | Status | Effect on Balance |
|:---|:---|:---|:---|:---|
| Withdraw 3 | withdraw | 3 | **deleted** | **Excluded** |

---

## 5.3: Customer Financial Summary

**Used in:** Customer detail endpoint (`GET /api/v1/customers/{id}`), customer update endpoint

**Data source:** Live query (not Materialized View)

**Scope:** Only contracts with status `active` or `completed`.

| Field | Formula |
|:---|:---|
| `total_installment_amount` | `SUM(installments.amount)` from active/completed contracts |
| `total_collected_amount` | `SUM(installments.amount) WHERE installments.status = 'paid'` |
| `total_remaining_amount` | `SUM(installments.amount) WHERE installments.status IN ('pending', 'overdue')` |
| `total_pending_installments` | `COUNT(*) WHERE installments.status = 'pending'` |
| `total_overdue_installments` | `COUNT(*) WHERE installments.status = 'overdue'` |
| `total_received_payments` | `COUNT(*) WHERE installments.status = 'paid'` |
| `total_number_installments` | `COUNT(*)` — all installments regardless of status |

---

## 5.4: Agent Financial Summary

**Used in:** Agent list and agent detail endpoints

**Scope:** Only contracts with status `active` or `completed` where this person is the `agent_id`.

| Field | Formula |
|:---|:---|
| `total_installments_via_agent` | `SUM(monthly_installment_amount × months)` from agent's contracts |
| `total_collected_via_agent` | `SUM(paid installment amounts)` from agent's contracts |
| `total_remaining_via_agent` | `SUM(pending/overdue installment amounts)` from agent's contracts |

---

## 5.5: Customer List Summary (via Materialized View)

**Used in:** Customer list endpoint (`GET /api/v1/customers`)

**Data source:** `customer_listing_mv` — these fields come pre-computed.

| Field | MV Column |
|:---|:---|
| `total_remaining_amount` | `total_remaining_amount` |
| `next_due_date` | `next_due_date` |
| `next_due_product_name` | `next_due_product_name` |
| Status flags | `has_overdue`, `has_due_this_month`, `paid_this_month` |

> **MV definition:** `../04_DATABASE/02_MATERIALIZED_VIEWS.md`

---

## 5.6: Customer Total Remaining in Contract Detail

**Used in:** Contract detail endpoint (`GET /api/v1/contracts/{id}`) — inside the `customer` object

**Rule:** This is the customer's TOTAL remaining amount across ALL their active/completed contracts — not just the viewed contract.

**Formula:** Same as Section 5.3 `total_remaining_amount`, computed at the customer level regardless of which contract is being viewed.

**Rationale:** The mobile client needs to show the customer's overall financial standing without a separate API call.

**Boundary:** This field appears ONLY in the contract detail response (assembled by a Response Builder). It does NOT appear in the contract create/sign response (assembled by a Resource).

---

## 5.7: Investor Profit Per Referred Customer

**Used in:** Investor detail endpoint (`GET /api/v1/investors/{id}`) — inside `referred_customers` array

**Rule:** For each customer whose contracts were referred by this investor (where `contracts.agent_id = {investor_id}`), calculate the contract margin and investor profit from that specific customer's contracts.

**Formula:**
```
per_customer_contract_margin = SUM(total_after_profit - purchase_amount)
    FROM contracts
    WHERE agent_id = {investor_id}
      AND customer_id = {referred_customer_id}
      AND status IN ('active', 'completed')

per_customer_investor_profit = per_customer_contract_margin × 0.05
```

**Rules:**
- Shown for all investors who have contracts where they are the `agent_id`, regardless of whether they hold the `agent` flag
- `contract_margin` can be zero (if all referred customer's contracts are draft) — profit would be "0.00"
- Uses the same 5% formula as overall investor profit (Section 5.1), scoped to a single customer