@stalfh233/omc-cli 0.4.56 → 0.4.57
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.
|
@@ -499,8 +499,16 @@ export function registerRuntimeDataLane(tools) {
|
|
|
499
499
|
const selected = fields ?? Object.keys(data).filter((field) => !["id", "bizObjectId", "schemaCode", "sequenceStatus", "createdTime", "updatedTime", "creator", "updater"].includes(field));
|
|
500
500
|
return { id: row.bizObjectId ?? row.id ?? data.id, fields: Object.fromEntries(selected.map((field) => [field, data[field] ?? null])) };
|
|
501
501
|
});
|
|
502
|
+
// Live 2026-10-19: when a model has NO configured list view, the
|
|
503
|
+
// platform projects only system columns — every business field comes
|
|
504
|
+
// back null while `data.load` shows the real values. That reads as
|
|
505
|
+
// "the write failed". Detect an all-null business projection (items
|
|
506
|
+
// present, zero non-null business values) and say so.
|
|
507
|
+
const businessKeys = fields ?? Object.keys(items[0]?.fields ?? {}).filter((field) => !["id", "bizObjectId", "schemaCode", "sequenceStatus", "createdTime", "updatedTime", "creator", "updater", "name"].includes(field));
|
|
508
|
+
const projectionEmpty = items.length > 0 && businessKeys.length > 0 && items.every((item) => businessKeys.every((key) => item.fields[key] === null || item.fields[key] === undefined));
|
|
502
509
|
const readback = {
|
|
503
510
|
schemaCode: args.schemaCode,
|
|
511
|
+
...(projectionEmpty ? { projectionWarning: { reason: "business-columns-null", hint: "模型可能未配置列表视图:data.list 只投影列表列,业务列会全为 null;核对写入结果请用 data.load(或先建列表视图)" } } : {}),
|
|
504
512
|
...(args.queryCode !== undefined ? { queryCode: args.queryCode } : {}),
|
|
505
513
|
total: args.showTotal === false ? null : page.total,
|
|
506
514
|
// This branch is the non-`all` read: the platform's default filter
|
package/dist/lanes/workflow.js
CHANGED
|
@@ -914,7 +914,21 @@ async function childTableFieldsOf(session, schemaCode) {
|
|
|
914
914
|
};
|
|
915
915
|
const rows = (await read("false")).length > 0 ? await read("false") : await read("true");
|
|
916
916
|
return rows
|
|
917
|
-
.map((row) =>
|
|
917
|
+
.map((row) => {
|
|
918
|
+
const type = row.propertyType ?? row.type ?? 0;
|
|
919
|
+
// Live 2026-10-19: the list face carries `subSchema: null` on EVERY row,
|
|
920
|
+
// so `subSchema !== undefined` classified every scalar/relation field as
|
|
921
|
+
// a child table and refused `required` with a false reason. Only a
|
|
922
|
+
// NON-EMPTY subSchema marks a child table (plus the real type code:
|
|
923
|
+
// propertyType 8 = CHILD_TABLE / SHEET).
|
|
924
|
+
const subSchema = row.subSchema;
|
|
925
|
+
const hasSubSchema = subSchema !== undefined && subSchema !== null && String(subSchema).trim() !== "";
|
|
926
|
+
const isChild = Number(type) === 8 ||
|
|
927
|
+
String(type).toUpperCase() === "CHILD_TABLE" ||
|
|
928
|
+
String(type).toUpperCase() === "SHEET" ||
|
|
929
|
+
hasSubSchema;
|
|
930
|
+
return { code: String(row.code ?? row.propertyCode ?? ""), name: String(row.name ?? row.code ?? ""), isChild };
|
|
931
|
+
})
|
|
918
932
|
.filter((row) => row.isChild && row.code !== "");
|
|
919
933
|
}
|
|
920
934
|
const CHILD_TABLE_LIST_BUTTONS = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stalfh233/omc-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.57",
|
|
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.
|
|
53
|
+
"@stalfh233/omc-fake-platform": "0.4.57",
|
|
54
54
|
"commander": "14.0.3",
|
|
55
|
-
"omc-core": "0.4.
|
|
55
|
+
"omc-core": "0.4.57",
|
|
56
56
|
"proper-lockfile": "4.1.2",
|
|
57
57
|
"write-file-atomic": "6.0.0",
|
|
58
58
|
"zod": "^3.23.8",
|
|
@@ -38,6 +38,14 @@ omc help omc-write-hazards
|
|
|
38
38
|
- **运行时写值的最小形状**(组合出错只会得到一个不透明的 `50000`/NPE,逐一最小化再合):单选关联(9) → id 字符串 `"<id>"`;**人员/组织(50/51/60/61) → `[{"id":"<id>","type":3,"name":"<名>"}]`,`type` 必填且为整数**(缺/非整数 → `BizField.parseFromClient` 拆箱 NPE→50000;用户=3、部门=1);日期(3) → 字符串 `"2026-09-30 10:00:00"`;子表(8) → 行对象数组 `[{"<子列code>":<值>, ...}]`。先各写一条最小行通过,再组合。
|
|
39
39
|
- **DATE(3) 字段的 `options.format` 必须是平台大写枚举**(`YYYY-MM-DD`、`YYYY-MM-DD HH:mm:ss`、`YYYY年MM月DD日`…),**不是 Java 的 `yyyy-MM-dd`**:平台 `DateBizField` 按字面比较,Java 写法能创建字段但**首次运行时 save 稳定 `50000`(`不支持的format`)**(2026-09-30 R5 实测)。`field.create`/`intent` 会就地拒绝非枚举值。
|
|
40
40
|
|
|
41
|
+
## 业务规则与流程事件(源码实证,1.1.25)
|
|
42
|
+
|
|
43
|
+
- **`Create` 的触发判定是「旧状态→新状态」**:旧 `DRAFT` 且新 `PROCESSING` 或 `COMPLETED`(`DomainServiceImpl#getDefaultRuleCode`)。所以无流程模型一调 `data.submit`(→COMPLETED)**和流程表单提交(DRAFT→PROCESSING)都触发 Create**;`data.save` 存草稿不触发。不要因为"目标表没变化"就断言规则没触发。
|
|
44
|
+
- **副作用缺失归因三步**:先查执行记录(`h_log_biz_service` 按服务/方法/时间,或容器日志)→ ①无调用=规则/触发问题 ②有调用但失败=参数/权限/业务异常 ③调用成功但不可见=视图投影/事务未提交/查询条件。禁止只看目标表。
|
|
45
|
+
- **BIZ_ACTION 判成功只看传输**:REST 适配器解析响应后直接返回,**不校验 `errcode`**。扩展接口回 `{"errcode":50000}` + HTTP 200 会被当成节点成功(日志 `biz action node execute successful`)。要阻断必须走表单 `onValidate` 或数据规则,不能靠业务返回码。
|
|
46
|
+
- **流程事件处理器吞异常**:`start`/`end`/`cancel`/`activate` 中的 BIZ_ACTION 抛异常时,`InstanceContext#processingBusiness` 只记 `processingBusiness error.` 并返回失败结果,**流程继续**。事件处理器不能做"提交前拦截"。
|
|
47
|
+
- **禁写当前单据**:BIZ_ACTION 是 HTTP 自调用,外层事务已持行锁;同事务更新当前单据会等到 15s 超时并整条回滚。副作用写独立表;需要留痕用独立事务/异步重建 `RequestContext`。
|
|
48
|
+
|
|
41
49
|
## 运行数据读取的默认过滤
|
|
42
50
|
|
|
43
51
|
- `data.list` **默认不含 DRAFT**(`total` 也只算 COMPLETED):清测试数据时 `total:0` 不代表没有残留。核对/清理一律显式 `{"all":true,"showTotal":true}`,或读回体里的过滤标注。`data.load` 用于单行核对。
|