# `Money`

An amount of money: a whole number of its currency's minor units and its `Currency`, written `GBP 10.50`.

[Money and banking](types.md#money-and-banking); ordered; since Jadpo 0.1.0.

## Make one

`text.parse(raw, as: Money)` reads one from its text; text that isn't one at all fails `malformed`, such as `10.50`, `GBP 10.505` or `GBP 10.5`.

These operations give one: `money.allocate`, `money.convert`, `money.from_minor`, `money.of`, `money.split` and `money.sum`.

## Text, JSON and storage

`text.from` writes its canonical text, the one form `text.parse` reads back. JSON sends an object of its parts.

| Text | JSON |
|---|---|
| `GBP -5.00` | `{"amount":-500,"currency":"GBP"}` |
| `GBP 0.05` | `{"amount":5,"currency":"GBP"}` |
| `GBP 10.50` | `{"amount":1050,"currency":"GBP"}` |
| `GBP 1234.50` | `{"amount":123450,"currency":"GBP"}` |

It is stored in 2 columns, each named for the field, `_` and its suffix. This is `GBP 10.50`:

| Column | Type | Holds |
|---|---|---|
| `<field>_amount` | `bigint` | `1050` |
| `<field>_currency` | `char(3)` | `'GBP'` |

## Shown to people

`text.format(value, locale:)` shows it to people in their locale. A call may also give `precision:`, `display:` or `sign:`.

With `locale: Locale.en_gb`:

| Value | Shown |
|---|---|
| `GBP -5.00` | `-£5.00` |
| `GBP 0.05` | `£0.05` |
| `GBP 10.50` | `£10.50` |
| `GBP 1234.50` | `£1,234.50` |

## Operations

- `money.allocate(total: Money, ratios: List<Int>) -> List<Money>`: `total` shared in proportion to `ratios`, whole numbers never below 0, at least one of them; a share of ratio 0 is nothing.
- `money.convert(value: Money, rate: ExchangeRate) -> Money`: `value` in `rate`'s `to` currency, from its `from` one: the major units times `rate.rate`, rounded half to even to a minor unit, so £10.50 at a `GBP/EUR` rate of 1.17 is €12.28. It fails with `currency_mismatch` when `value` isn't in `rate.from`, unless that is known: an inverted rate is then a compile error. The rate is one the app holds; nothing here fetches one.
- `money.currency(value: Money) -> Currency`: The currency `value` is in.
- `money.from_minor(amount: Int, currency: Currency) -> Money`: `amount` minor units of `currency`: `money.from_minor(1050, Currency.gbp)` is £10.50.
- `money.minor(value: Money) -> Int`: `value`'s minor units: 1050 for £10.50.
- `money.of(amount: Decimal, currency: Currency) -> Money`: `amount` major units of `currency`, a `Decimal`: `money.of(10.50, Currency.gbp)` is £10.50. It fails with `too_many_places` for more places than the currency has (10.505 in pounds), unless the currency is written out and the amount proved to have no more.
- `money.split(total: Money, parts: Int) -> List<Money>`: `total` in `parts` near-equal shares, `parts` at least 1: £10.00 in 3 is £3.34, £3.33 and £3.33.
- `money.sum(items: List<Money>, currency: Currency) -> Money`: The items added up in `currency`, the zero an empty list gives. It fails with `currency_mismatch` for an item in another currency, unless the items' type fixes `currency`.

Like every standard type, it also has the contract's own operations: `text.parse`, `text.from`, `text.format`, `json.read`, `json.write` and `==`. It is ordered, so `<` and sorting take it. [Every standard type meets one contract](../topics/every-standard-type-meets-one-contract.md) says how they work.
