@stalfh233/omc-cli 0.4.58 → 0.4.59

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/compute.js CHANGED
@@ -62,7 +62,27 @@ export async function cmdCompute(args) {
62
62
  catch (error) {
63
63
  return invalid(error instanceof Error ? error.message : String(error));
64
64
  }
65
- const { result, exitCode } = await runToolCall("datarule.create", { args: createArgs, requestId: request, environment });
65
+ // Live 2026-10-20 (purchase-request app): a child-table target
66
+ // (schemaCode = 子表 code) made datarule.create throw, and the uncaught error
67
+ // surfaced as `{"code":"internal","message":"command failed"}` — no way to tell
68
+ // whether the formula, the schema, or the tool was at fault. Catch it and hand
69
+ // back an actionable hint; the same shape succeeds via datarule.create.
70
+ let result;
71
+ let exitCode;
72
+ try {
73
+ ({ result, exitCode } = await runToolCall("datarule.create", { args: createArgs, requestId: request, environment }));
74
+ }
75
+ catch (error) {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ writeEnvelope(envelope("error", {}, request, {
78
+ code: "compute-write-failed",
79
+ message: `compute 调用 datarule.create 失败:${message}\n` +
80
+ "若 --schema 是**子表 code**(子表列计算),改用可跑样例直接发:omc describe datarule.create --example field-compute-child-column," +
81
+ "或 omc call datarule.create --args '<该样例 args>'(含 resultType/formulaType/expression 的嵌套 JSON)。",
82
+ retryable: false,
83
+ }));
84
+ return CLI_EXIT_CODES.internal;
85
+ }
66
86
  const classified = classifyResult(result);
67
87
  writeEnvelope(envelope(classified.status, result, request, classified.error));
68
88
  return exitCode;
@@ -45,7 +45,15 @@ const QUERY_FILTER_TYPES = new Set(QUERY_FILTER_TYPE);
45
45
  * (`QueryFilterType.getDefaultQueryFilterType`, QueryFilterType.java) — used
46
46
  * when a condition omits `filterType`, so the stored row names its comparison.
47
47
  */
48
- function defaultQueryFilterType(propertyType) {
48
+ function defaultQueryFilterType(propertyType, displayType) {
49
+ // Live 2026-10-20 (purchase-request app): a SHORT_TEXT field holding 是/否 was
50
+ // configured with `displayType:"SELECT"` but no `filterType`, and the property
51
+ // type table answered "Like" — a fuzzy match on an enum-valued column ("否"
52
+ // also matched text containing that character). An enumerated display control
53
+ // (SELECT/RADIO/CHECKBOX) is a closed value set, so its operator is Eq.
54
+ const display = typeof displayType === "string" ? displayType.toUpperCase() : undefined;
55
+ if (display === "SELECT" || display === "RADIO" || display === "CHECKBOX")
56
+ return "Eq";
49
57
  switch (propertyType) {
50
58
  case FIELD_PROPERTY_TYPES.LOGICAL:
51
59
  case FIELD_PROPERTY_TYPES.WORK_SHEET:
@@ -818,7 +826,7 @@ export function normalizeConditions(conditions, fieldRows, schemaCode) {
818
826
  value: requestedFilterType,
819
827
  message: `conditions 的 filterType "${String(requestedFilterType)}" 不是平台 QueryFilterType;可选:${QUERY_FILTER_TYPE.join(" / ")}`,
820
828
  });
821
- row.filterType = requestedFilterType !== undefined ? String(requestedFilterType) : defaultQueryFilterType(propertyType);
829
+ row.filterType = requestedFilterType !== undefined ? String(requestedFilterType) : defaultQueryFilterType(propertyType, condition.displayType);
822
830
  if (condition.displayType !== undefined)
823
831
  row.displayType = DISPLAY_TYPE.index[condition.displayType] ?? null;
824
832
  if (condition.defaultValue !== undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stalfh233/omc-cli",
3
- "version": "0.4.58",
3
+ "version": "0.4.59",
4
4
  "description": "CloudPivot 8.6 configuration capability CLI — governed, fail-closed, coverage-manifest bounded.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -50,9 +50,9 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "@stalfh233/omc-fake-platform": "0.4.58",
53
+ "@stalfh233/omc-fake-platform": "0.4.59",
54
54
  "commander": "14.0.3",
55
- "omc-core": "0.4.58",
55
+ "omc-core": "0.4.59",
56
56
  "proper-lockfile": "4.1.2",
57
57
  "write-file-atomic": "6.0.0",
58
58
  "zod": "^3.23.8",
@@ -89,6 +89,18 @@ omc call field.publish --env local --args '{"schemaCode":"expense"}'
89
89
 
90
90
  父 `CHILD_TABLE` 行不接受 `options/choices/subFields` 更新;子列直接走上面的 CRUD 面。
91
91
 
92
+ - **提交/审批都不要再回传子表数组**(真机 2026-10-19/20):`data.save` 建草稿后 `data.submit` 若带子表行(无 `id`),平台按新增追加(3→9);**审批提交同样**——`data.submit` 带 `workItemId`+`agree` 推进一步时回传子表,每级再 +1 行(1→2→3)。金额若显式传了合计不会翻倍,但行数与 SUM 口径已被污染,且没有报错。审批只回传标量字段(`agree`/意见/被改标量);确需改子行时带 `id`+`rowStatus:"Modified"`。验收加一条"审批后子表行数不变"。
93
+
94
+ ## 写调用纪律
95
+
96
+ - **同一 `<env>` 的写调用必须串行发起**:`write-lock-held` 不只在"并行重放失败请求"时出现,也会在**并行发起两个无关写**时触发(实测:并行两条 `dictionary.save`、并行 `field.update`+`field.publish` 各失败一次)。读可并行,写不要。
97
+
98
+ ## 计算规则(datarule)的取值时机
99
+
100
+ - **计算由门户前端执行,API 写入不回填**:`datarule.create` 接受 `IF({实际日期}>{需求日期},"是","否")` 这类比较式并落库,但 `data.save`/`data.submit` 不计算结果值,读回仍是 null。
101
+ - 所以"计算规则是否生效"**无法用 API 判定**,必须在门户录一条看结果;验收清单要写"计算类字段前台确认"。
102
+ - 需要服务端就有值(参与汇总、流程分流、超期判定)时不要依赖 datarule:改用二开接口在保存/审批时算好并回写标量。
103
+
92
104
  ## 规则与业务集成
93
105
 
94
106
  - 规则节点缺 `nodeName` 时 CLI 按平台 `RuleNodeType` 补默认名并给 warning;业务节点优先显式命名。