You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 0c2c5ba
Browse filesBrowse the repository at this point in the historyBrowse files
feat(objectql): a record-currency amount is refused without its code, refused in an ungrouped raw aggregate, and refused under a summary roll-up
8
+
9
+
Clause-②: yes (widening)
10
+
Metadata-protocol: none
11
+
12
+
-**A `record`-mode amount is stored with its currency code (ADR-0144 D8 rule 4).** An insert or update that would store a value in a `currency` field declaring `currencyConfig: { currencyMode: 'record', currencyField }` while that code field is blank (absent, `null` or white space) is refused `ERR_CURRENCY_CODE_REQUIRED` / 400, with `field` naming the code field and `amountField` the amount. The server never fills a currency in. On an update, only a write that carries the amount or its code is judged, against the stored row with the payload laid over it, so an edit of another field never meets it. The `validate()` preview (`validateData`) answers the same refusal as the row's finding for an insert and for a by-id update, so a dry run does not pass a row the write refuses. The code is registered under `@objectstack/objectql` in the ADR-0112 error-code ledger.
13
+
-**A raw aggregate over a `record`-mode amount groups by its code field (ADR-0144 D6).**`sum`, `avg`, `min` and `max` over such a field through `engine.aggregate` are refused `INVALID_FIELD` / 400 unless `groupBy` names the code field; grouped, each currency totals on its own. `count` and `count_distinct` are not judged. Before, USD 100 and EUR 100 summed to 200 under one label.
14
+
-**A `summary` roll-up over a `record`-mode amount is refused at registration (ADR-0144 D6).**`sum` / `avg` / `min` / `max` of such a child field is refused `INVALID_METADATA` / 422 (`RecordCurrencySummaryRefusedError`) at whichever object's registration completes the pair. Before, child rows of USD 100 and JPY 15000 rolled up to 15100. Use `count`, or roll up a stored home-currency amount.
15
+
-**`inferFormulaReturn` carries a record currency (`@objectstack/formula`).** A formula over a `record`-mode amount now declares `returnType: 'currency'` with `currencyConfig: { currencyMode: 'record', currencyField }`, the code field its sources name, instead of a tenant-default (`dynamic`) amount. Two record-mode amounts naming different code fields, or a record-mode amount meeting a `fixed` or `dynamic` one, are not one currency and are not stamped as money.
16
+
-**Nothing to migrate.**`currencyMode: 'record'` is new; no field declared before it meets any of these refusals.
feat(spec,service-analytics): analytics over a record-currency amount — grouped answers name a per-row currency, an ungrouped amount aggregate is refused, and two compile-time guards on record-mode measures (ADR-0144 D2, D6)
7
+
8
+
Clause-②: yes (widening)
9
+
Metadata-protocol: added
10
+
11
+
A measure column over a `currencyMode: 'record'` amount now carries `fields[].currencyField` on a `queryDataset` answer: the name of the dimension column that groups by the amount's code field. Each row's currency is that row's value of it, and the column carries no `currency`. Before, a breakdown by currency labelled every group with one code.
12
+
13
+
-`AnalyticsResult.fields[].currencyField` (`@objectstack/spec/contracts`) and the same key on `AnalyticsResultResponseSchema` (`@objectstack/spec/api`).
14
+
- The cube door refuses a `sum`, `avg`, `min` or `max` over a record-mode amount whose query does not group by the code field, with `INVALID_FIELD` / 400 naming the measure, the field and its object. It judges every path: a dataset or registered cube, an ad-hoc `query` over the object (`amount_sum`), and a draft preview. A `totals` grouping that drops the code, the grand total included, is refused the same way. `count` reads no amount and is served, and its column carries neither currency key.
15
+
16
+
Two compile-time refusals, `DATASET_INVALID` / 400, on the record mode alone, so nothing that compiled before is refused:
17
+
18
+
- a measure `currency` over a record-mode amount, whose currency is per row, including on a derived measure that resolves to one;
19
+
- a derived measure that combines a record-mode amount with an operand in another currency (another code field, a `fixed` code, an explicit code or the tenant's), for every op. A count operand is not compared, so an amount-per-invoice ratio still compiles.
20
+
21
+
The same two shapes over `fixed` fields only are not judged here; ADR-0144 open item 12 refuses them on a card of its own after this release.
22
+
23
+
⛔ Not released alone: this ships in the same release as the record currency mode, its write refusals and the per-row display.
0 commit comments