# `MaskedCardNumber`

What you may keep of a card once its number is gone: the brand and the last four digits.

Use it to show "Visa ending 4242" on an account page. To charge a card, your payment provider's own token does that, not this.

## Shape

| Field | Type | Required? |
|---|---|---|
| `brand` | [`CardBrand`](/docs/types/type-card-brand.md) | No |
| `last_four` | `Text` | Yes |

Write every field when you build one, and give a field that isn't required as `none`.

## Example

```jadpo
MaskedCardNumber { brand: CardBrand.visa last_four: "4242" }
```

This operation gives one: `money.mask`.

## Good to know

- `money.mask` makes one from a [`PaymentCardNumber`](/docs/types/type-payment-card-number.md) and fills in the brand.
- `brand` is `none` when no listed card scheme issued the card.
- `==` tells you whether two are the same. `<` and `list.sort_by` don't take it, so sort by one of its parts instead.
- A field that holds one counts as personal data (`financial`), so you don't mark it yourself.

## In JSON

An object of its parts, in a request, a response or `json.write`:

```json
{"brand":"visa","last_four":"4242"}
{"brand":"american_express","last_four":"0005"}
{"brand":null,"last_four":"1234"}
```

When you read one, a field that isn't required may be left out, or sent as `null`.

## Details

<details>
<summary>Text form, storage, how it is shown, and operations</summary>

`MaskedCardNumber` is in the group Money and banking, and has been in Jadpo since 0.1.0.

### Text form

It has no single text form, so `text.from` and `text.parse` don't take it.

### How it is stored

It is stored in 2 columns, each named for the field, `_` and its suffix. This is `{"brand":"american_express","last_four":"0005"}`:

| Column | Type | Holds |
|---|---|---|
| `<field>_brand` | `text` | `'american_express'` |
| `<field>_last_four` | `text` | `'0005'` |

### How it is shown to people

`text.format(value, locale:)` shows it to people in their locale.

With `locale: Locale.en_gb`:

| Value | Shown |
|---|---|
| `{"brand":"visa","last_four":"4242"}` | `Visa •••• 4242` |
| `{"brand":"american_express","last_four":"0005"}` | `American Express •••• 0005` |
| `{"brand":null,"last_four":"1234"}` | `•••• 1234` |

### Operations

- `money.mask(card: PaymentCardNumber) -> MaskedCardNumber`: What may be kept of `card` once its number is gone: its brand, told by its first digits from the ranges each scheme publishes (`none` for a range no listed scheme issues), and its last four digits.

It also takes `text.format`, `json.read`, `json.write` and `==`. [How every standard type behaves](/docs/every-standard-type-meets-one-contract.md) says how they work.

</details>
