> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myfundingmachine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 0010 revenue based estimates v1

# Revenue Based estimates V1: 8–12% of annual revenue

Status: accepted

Date: 2026-07-28

Fills the ADR-0008 follow-up ("MCA/BLOC funding range formulas") with the V1 product rule: the Revenue Based pre-approval estimate is **8–12% of exact annual business revenue**, applied identically to MCA and BLOC. SBA still never gets a pre-approval estimate (ADR-0003 / ADR-0008).

## Decision

1. **Input:** a new optional `annualRevenue` (exact dollars/year, operator-entered) flows through the canonical input factory (`assembleUnderwritingInput`) into `UnderwritingInput`, and is persisted on `underwritingResults.annualRevenue`. It is separate from the questionnaire's banded `avgRevenue`, which remains the eligibility input (ADR-0009). No GHL custom field in V1 — the value lives in Convex and re-underwrite carries it forward server-side (`getLatestAnnualRevenueByReportIdInternal`), so re-runs triggered by other field edits don't clear estimates.
2. **Formula:** `computeRevenueBasedEstimate` (convex/lib/revenueBasedEstimate.ts) returns `{ low: 8%, high: 12% }` of annual revenue, rounded to whole dollars; null when revenue is absent/non-positive.
3. **Attachment:** `deriveProductDecisions` attaches the identical estimate to the `mca` and `bloc` Product Decisions regardless of status — mirroring how `cardEstimate` rides on `card_stacking` — and never to `sba`.
4. **Count-once rule:** Total Estimated Funding = Cards + Term Loan + Revenue Based, where the RB contribution is counted **once** (never MCA + BLOC summed). `lib/funding/estimatedFundingTotals.ts` owns the derivation: the RB contribution comes from the first of MCA/BLOC that is `qualified`/`qualified_conditional` and carries an estimate.
5. **Term loan seam:** until the term-loan-estimates project ships, the TL contribution comes only from the operator override (`operatorOverrides.termLoanFundingRange`). The totals helper takes TL as an input, so engine-computed TL ranges will flow through with no shape change.

## Context

The client overview redesign shows a Total Estimated Funding strip and per-product ranges on the Product Decisions card. Product supplied the V1 RB rule (8–12% of annual revenue). Questionnaire revenue is banded ("$20,000 - $49,999"), too coarse for a dollar estimate, so operators enter an exact annual figure instead.

## Considered options

* **A — Derive from banded `avgRevenue` midpoints** — rejected; bands are too coarse and the top band is open-ended.
* **B — Exact annual revenue input + engine-computed estimate (accepted).**
* **C — GHL custom field as the source of truth** — rejected for V1; requires per-location field creation (ops burden). Can be added later as a discovery pattern without changing the engine seam.

## Consequences

* Golden persona snapshots: unchanged — personas provide no `annualRevenue`, so MCA/BLOC estimates stay null.
* UI must not sum MCA + BLOC into totals; use `resolveRevenueBasedContribution`.
* A fresh credit pull (new report) starts without annual revenue until the operator enters it again or a contact-level carry-forward ships; re-underwrites of the same report carry it forward automatically.
