-
Notifications
You must be signed in to change notification settings - Fork 6
money fields
A money field holds an amount. On its own it is a plain number, the same as decimal. Declare a
currency on it and every amount in the field is in that currency, held to that currency's decimal
places.
{ "name": "Total", "displayName": "Total", "type": "money", "currency": "USD" }-
currency is an ISO 4217 code, three capital letters.
usdis refused, not corrected. -
scale is the most decimal places an amount may carry, from 0 to 8. Leave it out and it is the
currency's own: 2 for USD, 0 for JPY, 3 for KWD. Set it to hold a unit price at 4 places, or to use
a code the built-in list does not have. The list is compiled in and nothing is looked up over the
network, so a code newer than the release needs its
scaledeclared. - A non-negative amount is the existing
minrule:"validationRules": { "min": 0 }. -
currencyandscaleon a field of any other type are refused, and so is ascalewith nocurrency.
A money field with no currency behaves exactly as it did before currencies existed. Nothing below
applies to it.
An entry stores, accepts and returns the amount as a plain JSON number, with or without a currency:
{ "Total": 1250.50 }The currency is on the field definition, from GET /api/content-types, and not in the entry. So a
filter (filter[Total][gte]=100), a sort, an export and an import read the same value they always
did, and declaring a currency rewrites no entry.
One currency per field. An entry cannot carry its own code, and nothing converts between codes.
There is none, on purpose: the API never rounds an amount, on write or on read.
| Field | Sent | Result |
|---|---|---|
| USD |
12.5, 12.50, 12
|
accepted |
| USD | 12.500 |
accepted, the extra zero is not a decimal place |
| USD | 12.345 |
400 naming the field, the currency and its decimal places |
| JPY | 100.5 |
400 |
| KWD | 1.234 |
accepted |
| USD |
"12.50" (text) |
400, send a JSON number |
| no currency | any of the above | accepted, as before |
Amounts are read as decimals and compared in PostgreSQL as numeric, never as binary floating
point. A decimal holds 28 significant digits. A number longer than that is outside what this rule
covers: the JSON reader has already shortened it, or handed it over as floating point, which a field
with a currency refuses.
The refusal never repeats the amount. On an update the stored value of a field the caller may not see is put back before validation, so repeating it would show that value to the caller.
Every path that writes an entry through the entry validator applies this: create, update, a status change that carries fields, a version restore, bulk import, a bundle import, a collection push and a form submission. A collection sync applies it too and skips an item that does not fit.
The API takes a JSON number. Three writers have nothing but text, and for a field that declares a currency each reads plain decimal text as the number it spells and stores a number:
- a spreadsheet import (
POST /api/import/content), where every cell is text - a form submission, where an input posts text
- the
UpdateFieldworkflow action, whoseValueparameter is text
Plain decimal text is an optional sign, digits, and at most one point with digits on both sides:
12.50, -3, 0.5. Space around it is ignored. 1,250.00, $12, 1e3 and 12. are not, and
neither is an amount with more decimal places than the scale. The import refuses that row naming the
field, the form answers 400, and the workflow action fails without retrying, with a message that
names the field and not the value. For a field with no currency all three store the text they were
given, as before.
PUT /api/content-types/{name}/fields/{field}/currency
{ "currency": "USD", "scale": null, "force": false }
No entry is rewritten. An amount that fits is now read in the declared currency.
- Entries of any status holding an amount with more decimal places than the scale, or a value that
is not a number, are counted. If there are any the answer is a 409 naming how many. With
"force": trueit goes ahead: those entries keep their value, and each is refused on its next save, or when a version holding it is restored, until the amount is corrected. - Changing from one code to another on a field that entries hold amounts in is a 409 the same way.
Nothing is converted, so with
forceevery stored amount is read under the new code. -
"currency": nullclears it and the field is a plain number again.
Each count reads every entry of the type, with no index to help, and a call makes up to two of them.
On a type with a very large number of entries the call is slow in proportion; run it outside busy
hours. The definition is read again after the counts and only currency and scale are changed on
that copy, so a field added or a sensitivity changed while the counts ran is kept. An entry written
while the counts run is not counted.
Needs manage_content_types. Recorded in the audit log as contenttype.field.currency.changed.
A bundle import does not change the currency or scale a stored field declares. A bundle that carries a different one, or none, is refused and points here.
Generated from docs/money-fields.md by scripts/wiki-sync.sh. Edit the doc in the repository, not this page.
Releases
Start here
- Approval by configuration
- Configuring email
- Delivering a client project on barakoCMS
- Deploying barakoCMS on a VM
- Deploying barakoCMS on a managed platform
- Upgrading from 3.x to 4.0
- Your first module
Content
- Content type blueprints
- Choice fields
- Pushing entries to a collection
- Collections filled from outside
- Public delivery API
- Event-sourced content types
- Field hints, sections and roles
- File fields
- Image variants
- Money fields
- Scheduling publish, unpublish and sensitivity
- SEO fields
- Site settings
- Token fields
- Uniqueness rules
- URL redirects
Security and access
- Security and compliance posture
- Scanning uploads for malware
- Where the admin keeps your session, and why
Tenancy
Operations
- Background jobs
- Backup and restore
- Connectors
- Inbound idempotency
- Migrations
- Reporting which modules an instance runs
- Webhooks
- Workflow runs and how long they are kept
Other