# What you can do

> Loyalty points, warehouse stock with batches and expiry, mutual settlements, budget limits - four things companies usually build four times, on one register

Source: https://aipril.dev/docs/ledger/what-you-can-do

## One engine, four familiar problems

This is a platform block, not a feature of an application, because these look like different
problems and are the same one.

| What the business calls it | What it actually is |
|---|---|
| Loyalty points, bonuses, internal currency | A balance per person, earned and spent |
| Warehouse stock | A balance per item per location, received and shipped |
| Mutual settlements with a counterparty | A balance per counterparty, invoiced and paid |
| A budget or a limit | A balance per cost centre, allocated and committed |

Build them separately and you write the same concurrency bugs four times. Here they are the same
register with different assets on it.

## Points and internal currency

The complete loyalty mechanic, without a loyalty product:

- **Earn and spend**, with every movement carrying its reason, so a customer asking "where did these
  come from" gets an answer instead of an apology.
- **Batches with an expiry.** Points earned in March expire before points earned in June, and
  spending draws down the right ones in the right order - which is the part home-made
  implementations get wrong first.
- **Clawback.** A cancelled order takes back exactly the points it granted, including when they have
  been partially spent since.
- **A shop to spend them in**, with the cart holding a reservation and not a deduction, so an
  abandoned basket costs nobody anything.

## Stock

Stock is the same primitive with a different key: a balance per item, per warehouse, per whatever
else you need to split it by.

- **Receipts, shipments, transfers and write-offs** as movements, so the current quantity is derived
  from them instead of typed in after a count.
- **Batches** - by delivery, by production date, by expiry - so "what do we have" and "what expires
  first" are the same question asked differently.
- **Reservations against orders**, which is what makes "40 in stock, 30 already promised" an honest
  answer instead of a promise you cannot keep.
- **A discrepancy is visible.** When a physical count disagrees with the register, the register can
  say exactly which movements produced its figure.

## Settlements and limits

- **What a counterparty owes**, moved by invoices and payments instead of recalculated, so an aged
  balance is explainable line by line.
- **Budgets and limits**, where the useful number is not what was spent but what is still available:
  allocated, minus committed to approvals that have not completed, minus actually spent.

## Documents: carts, orders, bookings

A reservation on its own is a held amount on one account. Real work groups them: a cart is several
reservations that succeed or fail together, an order is a set that converts to movements at the
moment it is confirmed, a booking holds a thing for a while and then either happens or does not.

That grouping lives in a **document** layer above the register, declared as part of an application
instead of built into the ledger. The separation keeps the register usable for the next case: the
ledger knows about balances and holds, and it does not need to learn what a cart is in order for you
to have one.

## How it reaches the rest of the platform

- **A process moves it.** An approval that completes, a shipment that is confirmed, a return that
  is accepted - a [transition](https://aipril.dev/docs/processes.md) can post the movement, so the balance changes as
  part of the work, not as a separate act of data entry somebody has to remember.
- **Reports read it.** Movements and balances reach [analytics](https://aipril.dev/docs/analytics.md) through a dataset
  bridge, so "points issued by month" or "stock turnover by warehouse" are ordinary questions, not
  an export.
- **Pages show it.** A balance on a portal page or an app screen is a widget bound to the same data,
  not a bespoke screen written per application.

## Next

[Under the hood](https://aipril.dev/docs/ledger/under-the-hood.md) - what makes this correct when two people act at the
same time, which is the only interesting question about a register of balances.
