Repository navigation
service-analytics: refuse fixed-versus-fixed cross-currency measures at dataset compile (multi-currency, epic #8345) #27579
Description
epic:#8345#1 · os-bill · session_01Utp6CbTZrFqRYNgjSaSbN5
Filed by the epic PM under maintainer ruling 6486427200 on #8345 (ADR-0144 Open item 12, letter A, 2026-10-29T02:42Z, 「A 拒收,R1 之后单独立卡」). Part of #8345. ⛔ Not a claim. R1 has landed (#27268, #27339, #27338, #27340), so this card is free to go. It pairs with no PR and ships in whichever Version Packages release it is ready for.
Ruling-ref: 6486427200
维护者速读
- 改了什么: 数据集编译时新增两条只针对
fixed币种的拒收:度量上写的currency和被汇总字段的fixed币种不同 ⇒ 拒收;派生度量的金额操作数落在两个不同的fixed币种 ⇒ 拒收。两条都返回DATASET_INVALID/ 400,并给出改法。 - 为什么改: 这两种写法今天会算出不报错的错数(比如 USD 字段标成 EUR,或 USD 减 EUR)。record 模式的同类护栏已随 feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338 上线,这张卡把 fixed 模式拉平。
- 风险与回滚: 这是收窄:以前能编译的这两种写法会被拒。仓内实测预计 0 处;已部署租户存的数据集无法从仓库里调查,PR 正文会写明。回滚即撤 PR。
- 先看:
packages/services/service-analytics/src/measure-currency-coherence.ts;起点是 PR feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338 的初稿提交fea128ce(后在507ed8f9撤掉)。 - 两分钟验证: 写一个 USD
fixed字段配度量currency: 'EUR'的数据集:注册与请求都返回 400 并给出改法;写currency: 'USD'照常通过。 - 需要您做的: 无,已裁 A。
Task
- Shape 1: a measure
currencywhose code differs from the aggregated field'sfixedcode →DATASET_INVALID/ 400, naming the fix (delete the measure'scurrency; the column takes the field's code). A measurecurrencythat restates thefixedcode stays accepted. - Shape 2: a derived measure (any op) whose monetary operands resolve to two different
fixedcodes →DATASET_INVALID/ 400, naming the fix (derive from measures in one currency, or drop the operand in the other). A non-monetary operand (acount) is not compared. - Not judged, unchanged: a
fixedcode against the tenant's currency (not known at compile: cannot answer, so do not block); a measurecurrencyover adynamicfield (the explicit code tops the [Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,fixed's CNY, the example's USD) #27119 Q2 X chain and stays legal). The record-mode arms are already on main from feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338. - Both doors compile through the same
compileDatasetcall, so the refusal reaches boot registration,queryDatasetand the Studio draft preview. Test all three. - Starting point: PR feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338's first-draft commit
fea128ce(the fixed arms ofmeasure-currency-coherence.ts, the two moved pins incurrency-mode-relay.test.tsandquery-dataset.test.ts, the guard tests). It was dropped at507ed8f9and is not on main (squash merge); fetch it withgit fetch origin pull/27338/head, since it is an ancestor of that head. Re-apply onto main, not onto the old branch. - Narrowing kit as on spec(field):
fixed-modecurrencyConfigwith nodefaultCurrencymaterialises'CNY'— require the code, drop the default (narrowing; #27119 Q2 X, G3) #27157 / PR fix(spec)!: a fixed currency config needs its code — currencyConfig.defaultCurrency loses its CNY default #27218: the full dogfood battery on the final head, and a survey of in-tree dataset metadata for both shapes (0 expected inexamples/**). A deployed tenant's stored datasets cannot be surveyed from the repository, and the PR body says so.
Declarations (fixed in the ruling): Clause-②: yes (narrowing) · Metadata-protocol: narrowed · @objectstack/service-analytics minor with a BREAKING paragraph (the fixed group refuses major before GA, per check-changeset-no-major) · ADR-0087 marker not-required (no-migration-prescription): the prescription is the refusal message, and no stored shape converts. The ADR-0144 Open item 12 dated note (Tier H) stays with the epic PM, apart from this code PR.
Lane: server (service-analytics) · Size: S–M · Review: CONTRACT_REVIEW_TIER (the published refusal face narrows). Epic: #8345. Dedupe: #8345 thread, ruling 6486427200, PR #27338 (record arms only); no open card carries this slice.
Activity