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

# Proration

> Fair math for mid-cycle plan changes — charge for the upgrade you used, credit the downgrade you didn't.

When a customer changes plan in the middle of a billing period, somebody owes somebody money for the unused fraction. `Proration` (a pure class in `@duro/billing`) computes the fair number.

## The intuition

A period is a span of time the customer already paid for. Halfway through a month on a ₦5,000 plan, they've *consumed* ₦2,500 of value and have ₦2,500 of *unused credit*. If they switch to a ₦10,000 plan, the new plan's unused portion costs ₦5,000. The difference is what changes hands.

```mermaid theme={null}
flowchart LR
    subgraph period["One billing period"]
        USED["used so far<br/>(days elapsed)"] --- LEFT["unused<br/>(days remaining)"]
    end
    LEFT --> OLDCREDIT["credit: unused × old daily rate"]
    LEFT --> NEWCHARGE["charge: unused × new daily rate"]
    OLDCREDIT & NEWCHARGE --> DELTA{"new charge −<br/>old credit"}
    DELTA -->|"> 0"| CH["charge the difference<br/>(upgrade)"]
    DELTA -->|"< 0"| CR["credit the balance<br/>(downgrade)"]
    DELTA -->|"= 0"| NO["no movement"]
```

## The computation

`Proration.changePlan` works in daily rates so any interval behaves consistently:

* `dailyRate(amount, periodDays) = amount / periodDays`
* `unusedCredit = daysRemaining × oldDailyRate`
* `newCharge = daysRemaining × newDailyRate`
* `result = newCharge − unusedCredit`

It returns a tagged result — `{ amount, kind }` where `kind` is `'charge'`, `'credit'`, or `'none'` — so the caller never has to interpret a sign.

| Change                        | `daysRemaining` | Result            |
| ----------------------------- | --------------- | ----------------- |
| ₦5k → ₦10k, half a month left | 15 / 30         | **charge ₦2,500** |
| ₦10k → ₦5k, half a month left | 15 / 30         | **credit ₦2,500** |
| same price                    | any             | **none**          |

## Where the credit goes

An upgrade's charge can be collected immediately or rolled into the next invoice; a downgrade's credit lands on the subscription's `balance` field (integer kobo), which is netted against the next renewal. Money owed *to* the customer never disappears into a rounding gap — it's a real balance carried on the row.

<Note>
  Proration is pure and unit-tested with the exact figures above (₦400k charge / ₦600k credit cases verified live during the build). Like the rest of `@duro/billing`, it touches no database — the `SubscriptionService` feeds it amounts and periods and stores what it returns.
</Note>

Next, the heart of the system: [recovery & dunning](/billing/dunning).
