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

# Billing Plans

> What a billing plan is, how charges are computed, and how plans turn usage into invoices.

A **billing plan** is a reusable rule set that turns a driver's raw usage
(currently toll tickets) into money on an [invoice](/documentation/driver-billing).
A plan is defined once; the system uses it to generate invoices as agreements
accumulate usage.

```
Billing Plan  ──assigned to──▶  Agreement (or Fleet default)
     │
     │ contains
     ▼
  Charges  ──computed against──▶  Driver's tickets  ──produces──▶  Invoice fees
```

Three layers:

1. **Plan** — the container plus global settings (grace periods, due dates).
2. **Charges** — the line-item rules inside a plan.
3. **Invoices** — the output (see [Driver Billing Overview](/documentation/driver-billing)).

## The plan

A plan belongs to a **fleet**. A fleet can have many plans. A plan applies to an
agreement in one of two ways:

* **Directly assigned** to an agreement, or
* **Fleet default** — used by any agreement without its own plan.

Which plan bills a driver = the agreement's own plan, else the fleet default. If
neither exists, no invoice can be generated.

### Plan settings

| Field                            | Type             | Controls                                                                                                                          |
| -------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `name`                           | text             | Display label.                                                                                                                    |
| `is_active`                      | boolean          | Inactive plans are soft-deleted.                                                                                                  |
| `effective_date`                 | date (optional)  | Agreements that **ended before** this date won't generate invoices. Blank = no cutoff; avoids back-billing historical agreements. |
| `progressive_billing_threshold`  | money (optional) | Amount of unbilled usage that triggers a mid-agreement invoice. Blank = only bill when the agreement ends.                        |
| `grace_period_hours`             | integer          | Hours after an invoice is created before it can be finalized (default/manual trigger).                                            |
| `progressive_grace_period_hours` | integer          | Same, for progressive invoices.                                                                                                   |
| `late_ticket_grace_period_hours` | integer          | How long a late-ticket draft stays open to batch in more late tickets before finalizing.                                          |
| `payment_due_hours`              | integer          | Hours after finalization until payment is due (drives the due date / overdue flag).                                               |
| `payment_instructions`           | rich text / HTML | Rendered in the "Payment Instructions" section of the invoice PDF.                                                                |

All `*_hours` values are **durations in hours**, not timestamps.

## Charges

A **charge** is one billable line. A plan has an ordered list of them. Each
charge selects some tickets, reduces them to a quantity, multiplies by a unit
rate, and produces one invoice line:

```
quantity  ×  unit rate  =  line total
   10     ×    $1.00     =    $10.00
```

### Charge fields

| Field                      | Meaning                                                                                                 |
| -------------------------- | ------------------------------------------------------------------------------------------------------- |
| `description`              | The label shown on the invoice line (e.g. "Toll pass-through").                                         |
| `source_type`              | What kind of record this charge bills. Currently only **`tolls`** is supported (citations are planned). |
| `aggregation_type`         | How to reduce matching records to a number: `count`, `sum`, or `count_unique`.                          |
| `aggregation_field`        | Which field to sum / count-unique on. Required for `sum` and `count_unique`; **not used** for `count`.  |
| `amount`                   | The per-unit rate (money), multiplied by the aggregated quantity.                                       |
| `filters`                  | Which records this charge applies to (see below). Empty = all of the driver's tickets.                  |
| `order`                    | Position of the line on the invoice.                                                                    |
| `display_aggregated_value` | If `false`, hide the quantity column on the PDF for this line.                                          |
| `display_rate_value`       | If `false`, hide the unit-rate column on the PDF for this line.                                         |

### Aggregation types

* **`count`** — number of matching tickets. Ignores `aggregation_field`.
  Example: "$2.00 per toll" → `count` × `$2.00\`.
* **`sum`** — add up `aggregation_field` across matching tickets. Example: pass
  through the raw toll cost → `sum` of `amount` × `$1.00`.
* **`count_unique`** — number of **distinct** values of `aggregation_field`.
  Example: charge per unique day driven → `count_unique` of `transaction_date`.

### Aggregation fields

The field that `sum` / `count_unique` operates on:

* **`amount`** — the toll's face amount.
* **`cash_cost`** — the fleet's negotiated cost (respects an amount-override
  setting); falls back to `amount` when no cash cost exists.
* **`transaction_date`** — mostly useful with `count_unique` (unique days).

When `aggregation_type` is `sum` or `count_unique`, `aggregation_field` is
required. For `count` it is not used.

### Filters

Filters narrow which tickets a charge applies to. A charge's `filters` is a
list; **all** filters must match (logical AND). Each filter is a triple:

```json theme={null}
{ "field": "agency", "op": "eq", "value": "MTA" }
```

Supported **fields**: `agency`, `transaction_date`, `exit_plaza`, `amount`.

Supported **operators** (`op`):

| op    | Meaning    | `value` shape |
| ----- | ---------- | ------------- |
| `eq`  | equals     | scalar        |
| `neq` | not equals | scalar        |
| `in`  | one of     | **list**      |
| `gte` | ≥          | scalar        |
| `lte` | ≤          | scalar        |

When `op` is `in`, `value` must be a list. Fields and operators outside the
supported sets are rejected by the backend.

### Examples

"Charge \$1.25 for every MTA toll":

```
description:       "MTA tolls"
source_type:       tolls
aggregation_type:  count
aggregation_field: (none)
amount:            1.25
filters:           [{ field: agency, op: eq, value: "MTA" }]
```

"Pass through the cash cost of all tolls over \$5":

```
aggregation_type:  sum
aggregation_field: cash_cost
amount:            1.00
filters:           [{ field: amount, op: gte, value: "5.00" }]
```

## From plan to invoice

Each invoice records **why** it was generated. The trigger maps to a plan
setting:

| Trigger           | When it fires                                                        | Related plan setting                                              |
| ----------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `PROGRESSIVE`     | Unbilled usage crosses `progressive_billing_threshold` mid-agreement | `progressive_billing_threshold`, `progressive_grace_period_hours` |
| `AGREEMENT_ENDED` | The agreement ends                                                   | `grace_period_hours`, `effective_date`                            |
| `LATE_TICKET`     | Tickets arrive after the agreement already ended/was billed          | `late_ticket_grace_period_hours`                                  |
| `MANUAL`          | A user generates one on demand                                       | `grace_period_hours`                                              |

The three grace-period settings exist because each maps to one automated
trigger. See the [invoice lifecycle](/documentation/driver-billing#invoice-lifecycle)
for how a draft becomes finalized.

### Plan snapshot

When an invoice is created, the plan and its charges are **frozen into the
invoice** as a snapshot. Editing the plan afterward does **not** change existing
invoices — only future ones. Plan details shown on an invoice come from its
snapshot, not the live plan. To correct an already-created invoice, use a fee
adjustment (draft) or a credit note (finalized).

## Corrections

Two distinct concepts:

* **Fee adjustment** — edits a line on a **DRAFT** invoice before it is
  finalized. Overrides the quantity and/or unit rate for one charge line, with a
  reason. Original values are preserved.
* **Credit note** — issued against a **FINALIZED** invoice to refund/reduce it
  after the fact. Has its own number, reason, line items, and PDF. The credit
  total can't exceed the invoice's remaining balance.

Rule of thumb: **draft → adjust the fee; finalized → issue a credit note.**
