@stalfh233/omc-cli 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +4 -0
- package/dist/field-families.js +26 -2
- package/dist/graph.js +19 -1
- package/dist/recipes/field.js +1 -1
- package/package.json +3 -3
- package/skills/omc-business-configuration.md +1 -0
package/dist/cli.js
CHANGED
|
@@ -1073,6 +1073,10 @@ async function cmdGraphPull(environment, concurrency, transport) {
|
|
|
1073
1073
|
status: "ok",
|
|
1074
1074
|
environment: data.meta.environmentName,
|
|
1075
1075
|
applicationCode: data.meta.applicationCode,
|
|
1076
|
+
// The index covers ONE application. Echo where it came from, so a
|
|
1077
|
+
// zero-hit query against a 1-of-N slice cannot read as tenant-wide
|
|
1078
|
+
// absence (same contract as model.list / rule.references).
|
|
1079
|
+
...(data.meta.applicationResolution ? { applicationResolution: data.meta.applicationResolution } : {}),
|
|
1076
1080
|
identityFingerprint: data.meta.identityFingerprint,
|
|
1077
1081
|
pulledAtIso: data.meta.pulledAtIso,
|
|
1078
1082
|
scope: data.meta.scope,
|
package/dist/field-families.js
CHANGED
|
@@ -341,6 +341,12 @@ function orgSelectorControlOptions(base, deptVisible, multi) {
|
|
|
341
341
|
* previous behaviour) left the control with an unrecognised format, so the
|
|
342
342
|
* portal rendered the raw decimal. Derive the constant from the field's
|
|
343
343
|
* `scale` (0-based decimal places) and `format` family.
|
|
344
|
+
*
|
|
345
|
+
* NAMING TRAP (2026-10-30 field report "数值怎么变成百分比了"): `percentile`
|
|
346
|
+
* here is 百分位 = TWO DECIMALS (`2,000.00`), NOT percentage. The platform's
|
|
347
|
+
* own control API documents the scale as none / integer(200) / tenths(2,000.0)
|
|
348
|
+
* / percentile(2,000.00) / ratio(20%) / ratio.tenths(20.0%) /
|
|
349
|
+
* ratio.percentile(20.00). Percentage is spelled with the `ratio` word.
|
|
344
350
|
*/
|
|
345
351
|
const NUMERICAL_DECIMALS_FORMAT = Object.freeze({
|
|
346
352
|
0: "integer",
|
|
@@ -353,6 +359,16 @@ const NUMERICAL_DECIMALS_FORMAT = Object.freeze({
|
|
|
353
359
|
7: "tenMillionDecimals",
|
|
354
360
|
8: "billionDecimals",
|
|
355
361
|
});
|
|
362
|
+
/**
|
|
363
|
+
* Ratio formats only exist as bare `ratio`, `ratio.tenths`, `ratio.percentile`
|
|
364
|
+
* (platform control API); `ratio.integer` / `ratio.Millimeter` are not
|
|
365
|
+
* documented values, so a percent field clamps to the closest documented one.
|
|
366
|
+
*/
|
|
367
|
+
const RATIO_DECIMALS_FORMAT = Object.freeze({
|
|
368
|
+
0: "ratio",
|
|
369
|
+
1: "ratio.tenths",
|
|
370
|
+
2: "ratio.percentile",
|
|
371
|
+
});
|
|
356
372
|
function numericalFormatPrefix(format) {
|
|
357
373
|
const value = String(format ?? "").toLowerCase();
|
|
358
374
|
if (value === "currency" || value === "rmb" || value === "¥")
|
|
@@ -369,8 +385,16 @@ function numericalFormatPrefix(format) {
|
|
|
369
385
|
}
|
|
370
386
|
export function numericalControlFormat(fieldOptions) {
|
|
371
387
|
const scale = fieldOptions?.scale;
|
|
372
|
-
|
|
373
|
-
|
|
388
|
+
// Absent/invalid scale: the platform default is `integer` — every native
|
|
389
|
+
// numeric control sampled in a live tenant carries it (2026-10-30: 10 models,
|
|
390
|
+
// 20+ controls, all `integer`). Defaulting to 2 (`percentile`) made a form
|
|
391
|
+
// rebuild silently turn existing integer money fields into "2,000.00".
|
|
392
|
+
const valid = isNumericalScale(scale);
|
|
393
|
+
const decimals = valid ? scale : 0;
|
|
394
|
+
const prefix = numericalFormatPrefix(fieldOptions?.format);
|
|
395
|
+
if (prefix === "ratio.")
|
|
396
|
+
return RATIO_DECIMALS_FORMAT[Math.min(decimals, 2)];
|
|
397
|
+
return `${prefix}${NUMERICAL_DECIMALS_FORMAT[decimals]}`;
|
|
374
398
|
}
|
|
375
399
|
export function fieldControlOptions(type, name, relativeCode, relationMappings, relationDisplayField = "name", fieldOptions) {
|
|
376
400
|
const base = { name, name_i18n: { "zh-CN": name, en: name }, visible: true, labelVisible: true, span: 24 };
|
package/dist/graph.js
CHANGED
|
@@ -380,6 +380,18 @@ export async function pullRuleGraph(session, concurrency = DEFAULT_PULL_CONCURRE
|
|
|
380
380
|
timings: { listMs, readMs, totalMs: Date.now() - totalStart },
|
|
381
381
|
};
|
|
382
382
|
}
|
|
383
|
+
/** Parse the persisted `applicationResolution` meta row; a malformed row degrades to undefined. */
|
|
384
|
+
function parseApplicationResolution(raw) {
|
|
385
|
+
try {
|
|
386
|
+
const parsed = JSON.parse(raw);
|
|
387
|
+
if (typeof parsed.code !== "string" || typeof parsed.source !== "string")
|
|
388
|
+
return undefined;
|
|
389
|
+
return parsed;
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
383
395
|
function ensureGraphDir() {
|
|
384
396
|
const dir = dirname(graphDbPath());
|
|
385
397
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
@@ -480,8 +492,11 @@ export async function publishGraphPull(session, concurrency = DEFAULT_PULL_CONCU
|
|
|
480
492
|
CREATE TABLE gaps (kind TEXT NOT NULL, ref TEXT NOT NULL, note TEXT);
|
|
481
493
|
`);
|
|
482
494
|
const insertMeta = db.prepare("INSERT INTO meta (key, value) VALUES (?, ?)");
|
|
495
|
+
// `applicationResolution` is an object; String(value) would persist
|
|
496
|
+
// "[object Object]" (2026-10-30: the field was written and unreadable).
|
|
497
|
+
// JSON-encode structured values, keep scalars verbatim.
|
|
483
498
|
for (const [key, value] of Object.entries(data.meta))
|
|
484
|
-
insertMeta.run(key, String(value));
|
|
499
|
+
insertMeta.run(key, typeof value === "object" && value !== null ? JSON.stringify(value) : String(value));
|
|
485
500
|
const insertRule = db.prepare("INSERT INTO rules (schema_code, rule_code, name, enabled, status, default_rule, row_id, graph_sha256) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
|
486
501
|
for (const rule of data.rules)
|
|
487
502
|
insertRule.run(rule.schemaCode, rule.ruleCode, rule.name, rule.enabled === null ? null : rule.enabled ? 1 : 0, rule.status, rule.defaultRule === null ? null : rule.defaultRule ? 1 : 0, rule.rowId, rule.graphSha256);
|
|
@@ -545,6 +560,9 @@ function openGraphIndex() {
|
|
|
545
560
|
summary: {
|
|
546
561
|
environmentName: meta.environmentName ?? "",
|
|
547
562
|
applicationCode: meta.applicationCode ?? "",
|
|
563
|
+
// Persisted as JSON by the writer; a legacy index (pre-0.5.4) has no
|
|
564
|
+
// such key, so this stays optional rather than failing the read.
|
|
565
|
+
...(meta.applicationResolution ? { applicationResolution: parseApplicationResolution(meta.applicationResolution) } : {}),
|
|
548
566
|
identityFingerprint: meta.identityFingerprint ?? "",
|
|
549
567
|
pulledAtIso: meta.pulledAtIso ?? "",
|
|
550
568
|
freshness: gapCount === 0 ? "complete" : "partial",
|
package/dist/recipes/field.js
CHANGED
|
@@ -101,7 +101,7 @@ const numericTwoDecimals = Object.freeze({
|
|
|
101
101
|
title: "数值字段(金额,两位小数 / 整数)— scale 必填",
|
|
102
102
|
status: "offline-valid",
|
|
103
103
|
tool: "field.create",
|
|
104
|
-
args: { environment, schemaCode: model, code: "applyAmount", name: "申请金额", propertyType: "NUMERICAL", options: { scale:
|
|
104
|
+
args: { environment, schemaCode: model, code: "applyAmount", name: "申请金额", propertyType: "NUMERICAL", options: { scale: 2 } },
|
|
105
105
|
preconditions: ["模型已存在"],
|
|
106
106
|
conditionalRequirements: ["NUMERICAL 必须显式 options.scale:scale = 小数位数(0=整数, 1=1位, 2=2位 … 8=8位);缺 scale 门户显示裸 decimal 且工具会拒绝。"],
|
|
107
107
|
priorToolReferences: [{ tool: "discover_environment", args: { environment }, purpose: "确认目标模型已存在" }],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stalfh233/omc-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "CloudPivot 8.6 configuration capability CLI — governed, fail-closed, coverage-manifest bounded.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@stalfh233/omc-fake-platform": "0.5.
|
|
55
|
+
"@stalfh233/omc-fake-platform": "0.5.6",
|
|
56
56
|
"commander": "14.0.3",
|
|
57
|
-
"omc-core": "0.5.
|
|
57
|
+
"omc-core": "0.5.6",
|
|
58
58
|
"proper-lockfile": "4.1.2",
|
|
59
59
|
"write-file-atomic": "6.0.0",
|
|
60
60
|
"zod": "^3.23.8",
|
|
@@ -141,6 +141,7 @@ rules:
|
|
|
141
141
|
- rebuild 会保留已识别的关系映射、显示和布局 options;Sheet201 columns 按最新子表字段刷新。
|
|
142
142
|
- **配置列表视图用 `listview.configure`(省略 `code` 即平台自动生成的默认视图 code=schemaCode),不要先 `listview.create`——那会多出一个视图。** 只有确实要第二个视图才 create;两者职责分开。
|
|
143
143
|
- 数值控件:`scale` 是小数位数(0=整数,1=1位,2=2位…);「金额两位小数」用 `scale:2`。列表列 displayFormat 由 scale 推导。
|
|
144
|
+
- **`percentile` 不是百分比**(高频误读,2026-10-30 现场反馈):表单控件的 `format` 里 `integer`(200) / `tenths`(2,000.0) / `percentile`(2,000.00) 都是小数位;**百分比要带 `ratio` 词**——`ratio`(20%) / `ratio.tenths`(20.0%) / `ratio.percentile`(20.00),货币用 `RMB.*`/`dollar.*`。字段行 `options.format` 缺 `scale` 时控件按平台默认 `integer` 生成(不是两位小数),所以「金额」务必显式 `scale:2`。
|
|
144
145
|
- **列表列只放业务字段**:平台 `listview.create` 会预置系统列(`name/creater/createdTime/sequenceNo`)和一条 `createdTime` 默认筛选;intent 的 `fieldCodes` 是权威集合,编译器用 `replaceColumns:true + hideDefaultSystemFields:true + conditions:[]` 清掉预置项。要展示某系统列/筛选就显式点名。
|
|
145
146
|
- 筛选条件默认显示:`conditions[].visible` 不传也应为 true。
|
|
146
147
|
- 配置默认视图后即可用 `data.list`;否则部分 8.6.26 读面业务列可能为 null,单行用 `data.load` 核对。
|