# SPECIFICATIONS/05_ALGORITHMS/02_CONTRACT_MATH_VALIDATION.md

**PURPOSE:** Defines the step-by-step mathematical validation that the backend performs on financial figures received from the client. The system validates — it does not calculate. This file answers "what exact math checks must pass?" — it contains zero business workflow logic.

> **Business rules enforced by this algorithm:** `../01_BUSINESS_CONTEXT/03_BUSINESS_RULES.md` → BR-002-1, BR-002-2, BR-003-2, BR-006-1 through BR-006-4

**Precision Rule:** All decimal comparisons in this algorithm MUST use arbitrary-precision arithmetic. Floating-point math is strictly prohibited.

---

## Inputs

| Parameter | Type | Description |
|:---|:---|:---|
| `purchase_amount` | decimal | Product purchase price |
| `initial_payment` | decimal | Down payment (can be 0) |
| `profit_percentage` | decimal | Profit margin percentage |
| `total_after_profit` | decimal | Total with profit |
| `months` | integer | Number of installments |
| `monthly_installment_amount` | decimal | Monthly payment amount |

---

## Validation Steps

### Step 1: Initial Payment Bounds
Reject if `initial_payment < 0` or `initial_payment > purchase_amount`.
**Error:** Validation failure (422)

### Step 2: Calculate Expected Profit
```
expected_profit = purchase_amount × (profit_percentage / 100)
```
**Critical:** Profit percentage applies to the TOTAL `purchase_amount`, not the remaining amount.

### Step 3: Verify Total After Profit
```
expected_total = purchase_amount + expected_profit
```
Reject if `total_after_profit ≠ expected_total`.
**Error Key:** `errors/contract.total_mismatch` (422)

### Step 4: Calculate Remaining Amount
```
remaining = total_after_profit - initial_payment
```

### Step 5: Verify Monthly Installment Amount
**If `months = 1`:** Reject if `monthly_installment_amount ≠ remaining`

**If `months > 1`:**
```
expected_monthly = remaining / months
```
Reject if `monthly_installment_amount ≠ expected_monthly` (rounded to 2 decimal places, half-up).
**Error Key:** `errors/contract.math_validation_failed` (422)

### Step 6: Fraction Prevention
```
verification = monthly_installment_amount × months
```
Reject if `verification ≠ remaining`. This catches cases where the division in Step 5 produces a recurring decimal that was rounded away.
**Error Key:** `errors/contract.fractional_payment` (422) — the caller must absorb the fractional remainder into the initial payment and resubmit.

---

## Error Summary

| Condition | Error Key | HTTP |
|:---|:---|:---|
| Initial payment out of bounds | Validation failure | 422 |
| Total after profit mismatch | `errors/contract.total_mismatch` | 422 |
| Monthly amount mismatch | `errors/contract.math_validation_failed` | 422 |
| Fraction detected | `errors/contract.fractional_payment` | 422 |