## Overview

The **unified revenue ledger** is the native record of **every** paid sale — regardless of source. A
charge paid in the conversation, a WhatsApp catalog order, a Hotmart sale, a manual order or an API
order all converge to **one canonical order** (the CRM orders registry). The moment that order is paid,
Conversa Labs credits the **seller (the order owner) exactly once**: gamification points, commission and
the revenue shown in the report.

Before this, each money path credited differently (or not at all): a catalog or Hotmart sale might earn
nobody points or commission, while a charge credited its author. The unified ledger fixes that with
**one revenue axis** and **exactly-once counting** — the same sale is never counted twice.

## Prerequisites

- The **Sales & Gamification** module enabled on the account.
- The **`unified_revenue_ledger`** feature enabled on the account (it is dark-shipped, default **off** —
  the operator enables it). With it off, behavior is identical to before.
- The **CRM orders registry** (`orders_registry`) enabled so charges and commerce orders also converge
  to the single order — this is what suppresses the legacy crediting and guarantees a single count.
- The **sales-management** permission (`sales_manage`) — or an admin — to read the ledger and export.
- **Real paid sales flowing** (charges, catalog, Hotmart, manual orders) so there is something to count.

## Step by step

1. **Enable the feature** `unified_revenue_ledger` (and `orders_registry`) on the account.
2. **Ensure sales are flowing** from any source — convergence is automatic through the order feeders.
3. **Open the Revenue view** in the Sales dashboard/wallboard.
4. **Pick a period** (defaults to the last 30 days).
5. **Read the groupings** — total per currency, by source, by gateway, by seller and by affiliate.
6. **Export to CSV** to reconcile revenue outside the platform.

## Settings & options

### What the ledger groups

Over the **paid** orders in the period (by `paid_at`), revenue is summed and grouped:

| Grouping | What it brings |
|---|---|
| Total per currency | Total revenue per currency — it **never sums across currencies** |
| By source | Revenue by the order `source`: `manual`, `webhook`, `api`, `payments`, `commerce` |
| By gateway | Revenue by the money gateway (asaas, mercado_pago, hotmart, native, catalog…) |
| By seller | Revenue by the order owner (the credited seller) |
| By affiliate | Revenue by the attributed affiliate (dual attribution) |

### Exactly-once counting (no double count)

Crediting happens **on the order axis** when an order exists, and on the legacy path only when no order
is produced:

| `unified_revenue_ledger` | `orders_registry` | Who credits | Result |
|---|---|---|---|
| Off | any | Legacy path (charge/commerce) | identical to before |
| On | On | `order.paid` (the order) — legacy suppressed | once, on the order |
| On | Off | Legacy (no order is produced) | once, on the charge/commerce |

### Seller attribution (fallback)

The order owner is resolved in a cascade: **deal → contact → assignee → creator**. A charge without a
deal still attributes to the user who created it (the charge's creator field), so no paid sale ends up
"ownerless".

### External-sale attribution

**External** sales (catalog, Hotmart, Kiwify and other gateways) arrive from the gateway and often reach
a buyer contact who is **not in anyone's portfolio**. Without a rule, that paid sale would be
"seller-less". The per-account **`external_attribution_mode`** setting decides how the seller is
auto-resolved in that case:

| Mode | What it does |
|---|---|
| `off` (default) | No automatic credit — the external sale stays seller-less until a manual attribution |
| `last_conversation` | Credits the agent who last handled the buyer (the contact's last conversation) |
| `distribution` | Credits according to the active distribution rules (the same as lead distribution) |

When the mode resolves a seller, the **buyer's portfolio is durably claimed** for that seller — so the
contact's next sales already arrive with an owner. The default is **`off`**: no automatic credit until
you explicitly choose `last_conversation` or `distribution`.

**Manual seller (re)attribution.** A **manager** (sales-management permission) can, from the order,
**link an external sale to a seller** or **move the credit between agents**. The switch **reverses the
previous owner's points and commission** and credits the new owner; the **affiliate credit is
untouched**. Leaving the seller blank **unassigns** the order. Every change is **audited** (the
`order_reattributed` event), preserving the record of who was credited and why.

### Refund (clawback)

When an order is refunded, the credit is **reversed on the order source** — for the seller **and** the
affiliate — keeping the ledger true to the money actually received.

### CSV export

One row per paid order, with the columns: `order_id`, `paid_at`, `source`, `gateway`, `owner_id`,
`affiliate_id`, `amount`, `currency`. Amounts are in **major units** (e.g. `4970.50` = R$ 4,970.50).

### Permissions and visibility

- Reading the ledger and exporting require the **sales-management** permission.
- The read honors **per-seller isolation**: under portfolio/privacy, a manager sees only their cascade;
  a rep sees only their own portfolio.

## Use cases

- The manager reads revenue by seller to recognize who sold the most in the period.
- Finance exports the CSV to reconcile paid revenue against the commission statement.
- Leadership compares revenue by **source** (Hotmart × catalog × charge) and by **gateway**.
- Revenue by **affiliate** feeds the affiliate program tracking (dual attribution).

## Tips, limits & best practices

- Money is in **major units** (decimal), the same convention as Payments/Catalog — never divide by 100.
- The ledger **never sums across currencies**: each currency is its own row.
- Enabling the feature credits sales **going forward** — there is no automatic retroactive re-credit. To
  reprocess Hotmart history, use the operator backfill.
- Enable **both** features (`unified_revenue_ledger` + `orders_registry`): that combination is what
  suppresses the legacy path and prevents double counting.

## Troubleshooting

- **Empty ledger**: there are no paid orders in the period, or the feature is off. Confirm the feature is
  enabled and that paid sales exist.
- **Double numbers**: `orders_registry` is probably **off**, so the legacy path and the order path credit
  together. Enable the orders registry.
- **Seller shows as null**: the order had no resolvable owner (no deal, contact, assignee or creator).
  Check attribution at the source.
- **External sale seller-less or credited to the wrong seller**: if `external_attribution_mode` is `off`,
  external sales stay ownerless — choose `last_conversation` or `distribution`, or do a manual
  re-attribution (sales-management) from the order.
- **Refund not reflected**: the order refund event did not fire. Confirm the refund flow in the
  gateway/Payments.
- **Export blocked**: you lack the **sales-management** permission. Ask an admin.

## See also

- [Affiliate program: dual attribution, commission and portal](/hc/ajuda/articles/sales-gamification-affiliate-program-en)
- [Sales dashboards and reports](/hc/ajuda/articles/sales-gamification-paineis-e-relatorios-de-vendas-en)
- [Sales and Gamification overview](/hc/ajuda/articles/sales-gamification-overview-en)