@stalfh233/omc-fake-platform 0.4.87 → 0.4.90
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/state.d.ts +8 -0
- package/dist/state.js +1 -0
- package/dist/workflow.js +62 -17
- package/package.json +2 -2
package/dist/state.d.ts
CHANGED
|
@@ -380,6 +380,14 @@ export interface FakeState {
|
|
|
380
380
|
roleIds: string[];
|
|
381
381
|
deptIds?: string[];
|
|
382
382
|
}>;
|
|
383
|
+
/** Workflow instances (biz_workflow_instance), keyed by instance id. */
|
|
384
|
+
workflowInstances: Map<string, {
|
|
385
|
+
id: string;
|
|
386
|
+
workflowCode: string;
|
|
387
|
+
schemaCode: string;
|
|
388
|
+
bizObjectId: string;
|
|
389
|
+
status: string;
|
|
390
|
+
}>;
|
|
383
391
|
/** Workflow start permissions (h_workflow_permission): who may originate. */
|
|
384
392
|
workflowPermissions: Map<string, {
|
|
385
393
|
id: string;
|
package/dist/state.js
CHANGED
package/dist/workflow.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { businessRefusal, malformedEnvelope, NOT_HANDLED } from "./state.js";
|
|
2
|
-
|
|
2
|
+
// DRAFT: a portal draft-save start item is state DRAFT (live r15 readback) and
|
|
3
|
+
// still appears in the caller's todo face until submitted.
|
|
4
|
+
const PENDING_STATES = new Set(["NOTSTARTED", "INPROGRESS", "DRAFT"]);
|
|
3
5
|
const ACTIVITY_TYPES = new Set(["START", "END", "CONNECTION", "PARTICIPANT", "SUB_INSTANCE", "CIRCULATE", "SYSTEM_ACTIVITY", "AGENT_ACTIVITY"]);
|
|
4
6
|
const POINT = /^-?\d+(?:\.\d+)?,\s-?\d+(?:\.\d+)?$/;
|
|
5
7
|
/**
|
|
@@ -102,13 +104,25 @@ export function startWorkflowDraft(state, input) {
|
|
|
102
104
|
const sequence = state.workItems.size + 1;
|
|
103
105
|
const instanceId = `wf-${sequence}`;
|
|
104
106
|
const startId = `wi-${sequence}`;
|
|
107
|
+
// Live 1.1.25: saveWorkflow creates a DRAFT instance row plus a DRAFT start
|
|
108
|
+
// work item (read back from biz_workflow_instance/biz_workitem on the r15
|
|
109
|
+
// scratch model). The DRAFT state is load-bearing: the instance-list endpoint
|
|
110
|
+
// hides DRAFT rows (see the route above), so a purge that only reads that list
|
|
111
|
+
// misses exactly this case.
|
|
112
|
+
state.workflowInstances.set(instanceId, {
|
|
113
|
+
id: instanceId,
|
|
114
|
+
workflowCode: input.workflowCode,
|
|
115
|
+
schemaCode: input.schemaCode,
|
|
116
|
+
bizObjectId: input.bizObjectId,
|
|
117
|
+
status: "DRAFT",
|
|
118
|
+
});
|
|
105
119
|
state.workItems.set(startId, {
|
|
106
120
|
id: startId,
|
|
107
121
|
instanceId,
|
|
108
122
|
activityCode: "fill",
|
|
109
123
|
activityName: "填写申请单",
|
|
110
124
|
participant: "tester",
|
|
111
|
-
state: "
|
|
125
|
+
state: "DRAFT",
|
|
112
126
|
workflowCode: input.workflowCode,
|
|
113
127
|
schemaCode: input.schemaCode,
|
|
114
128
|
bizObjectId: input.bizObjectId,
|
|
@@ -372,6 +386,44 @@ export const workflowRoute = (ctx, input) => {
|
|
|
372
386
|
content: rows.slice(start, start + size).map(toWorkItemVO),
|
|
373
387
|
};
|
|
374
388
|
}
|
|
389
|
+
case "/api/api/runtime/workflow/list_instances": {
|
|
390
|
+
// WorkflowInstanceController.list_instances — the instance list a purge
|
|
391
|
+
// must empty before the model cascade can run (r14: a surviving instance's
|
|
392
|
+
// work item outlives its template and NPEs the global todo search).
|
|
393
|
+
//
|
|
394
|
+
// Live-faithful detail (r15, decompiled 8.6.26): the controller always
|
|
395
|
+
// sets currentUserId, and BizWorkflowinstanceServiceImpl adds
|
|
396
|
+
// `state != DRAFT` for any non-empty user — so DRAFT instances are NEVER
|
|
397
|
+
// in this list. A purge must find them through their work items.
|
|
398
|
+
let rows = [...ctx.state.workflowInstances.values()].filter((row) => String(row.status ?? "").toUpperCase() !== "DRAFT");
|
|
399
|
+
if (q.workflowCode)
|
|
400
|
+
rows = rows.filter((row) => row.workflowCode === q.workflowCode);
|
|
401
|
+
const size = Number(q.size ?? 10);
|
|
402
|
+
const page = Number(q.page ?? 0);
|
|
403
|
+
const start = page * size;
|
|
404
|
+
return {
|
|
405
|
+
totalElements: rows.length,
|
|
406
|
+
totalPages: size > 0 ? Math.ceil(rows.length / size) : 0,
|
|
407
|
+
content: rows.slice(start, start + size),
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
case "/api/api/runtime/workflow/delete_instance": {
|
|
411
|
+
// WorkflowInstanceController.delete_instance: only the instance id is
|
|
412
|
+
// required (the user comes from the session), so an admin session can erase
|
|
413
|
+
// an instance started by someone else.
|
|
414
|
+
const id = String(q.workflowInstanceId ?? "");
|
|
415
|
+
if (!id)
|
|
416
|
+
return businessRefusal(40000, "流程实例id为空");
|
|
417
|
+
const instance = ctx.state.workflowInstances.get(id);
|
|
418
|
+
// Live 1.1.25 (r15): deleting an instance whose business row is already
|
|
419
|
+
// gone makes the engine NPE while rendering the "workflow removed"
|
|
420
|
+
// notice (`bizObject should not be null`) → 50000, and the instance row
|
|
421
|
+
// stays. Mirror it so purge's stale-instance path is exercised offline.
|
|
422
|
+
if (instance && !ctx.state.dataRows.has(String(instance.bizObjectId ?? "")))
|
|
423
|
+
return businessRefusal(50000, "服务异常");
|
|
424
|
+
const existed = ctx.state.workflowInstances.delete(id);
|
|
425
|
+
return existed;
|
|
426
|
+
}
|
|
375
427
|
case "/api/api/runtime/workflow/list_workitems": {
|
|
376
428
|
// The JPA-spec face (WorkflowInstanceController.listWorkItems): it queri
|
|
377
429
|
// the work-item table directly instead of resolving each hit's template,
|
|
@@ -406,8 +458,9 @@ export const workflowRoute = (ctx, input) => {
|
|
|
406
458
|
{ id: "role-finance", name: "财务负责人", code: "SYS260515031207258", roleType: "SYS", corpId: "corp-1" },
|
|
407
459
|
];
|
|
408
460
|
case "/api/api/organization/department/tree": {
|
|
409
|
-
// Platform semantics (1.1.25): no deptIds → roots;
|
|
410
|
-
//
|
|
461
|
+
// Platform semantics (re-verified r15, 1.1.25): no deptIds → roots ONLY;
|
|
462
|
+
// deptIds=<id> → DIRECT CHILDREN only. The old "whole subtree" fake made
|
|
463
|
+
// the one-level walker look correct, hiding third-level departments.
|
|
411
464
|
const all = [
|
|
412
465
|
{ id: "dept-1", name: "总所", code: "1", corpId: "corp-1", parentId: null },
|
|
413
466
|
{ id: "dept-2", name: "业务部", code: "1_1", corpId: "corp-1", parentId: "dept-1" },
|
|
@@ -416,18 +469,7 @@ export const workflowRoute = (ctx, input) => {
|
|
|
416
469
|
const requested = String(q.deptIds ?? "");
|
|
417
470
|
if (requested === "")
|
|
418
471
|
return { departmentList: all.filter((dept) => dept.parentId === null) };
|
|
419
|
-
|
|
420
|
-
const queue = [requested];
|
|
421
|
-
while (queue.length > 0) {
|
|
422
|
-
const current = queue.shift();
|
|
423
|
-
for (const dept of all) {
|
|
424
|
-
if (dept.parentId !== current || subtree.some((seen) => seen.id === dept.id))
|
|
425
|
-
continue;
|
|
426
|
-
subtree.push(dept);
|
|
427
|
-
queue.push(dept.id);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return { departmentList: subtree };
|
|
472
|
+
return { departmentList: all.filter((dept) => dept.parentId === requested) };
|
|
431
473
|
}
|
|
432
474
|
case "/api/api/organization/user/search": {
|
|
433
475
|
// UserController.search: @RequestBody {wd,page,size} → PageVO<UserVO>.
|
|
@@ -645,7 +687,10 @@ export const workflowRoute = (ctx, input) => {
|
|
|
645
687
|
const members = [...ctx.state.orgMembers.values()].filter((member) => member.roleId === roleId);
|
|
646
688
|
const page = Number(q.page ?? 0);
|
|
647
689
|
const size = Number(q.size ?? 500);
|
|
648
|
-
|
|
690
|
+
// Live 1.1.25 row: departmentId is null, the department rides
|
|
691
|
+
// parentDepartmentName[0].deptId, and ouScope is what role-participant
|
|
692
|
+
// resolution filters on (r15).
|
|
693
|
+
return { totalElements: members.length, totalPages: size > 0 ? Math.ceil(members.length / size) : 0, content: members.slice(page * size, page * size + size).map((member) => ({ id: member.userId, name: member.name, unitType: member.unitType, departmentId: null, departmentName: "总所", parentDepartmentName: [{ deptId: "dept-1", deptPath: "总所", deptName: "总所" }], ouScope: member.ouScope })) };
|
|
649
694
|
}
|
|
650
695
|
case "/api/api/organization/role/get_ouscope": {
|
|
651
696
|
const member = ctx.state.orgMembers.get(`${String(q.roleId ?? "")}#${String(q.userId ?? "")}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stalfh233/omc-fake-platform",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.90",
|
|
4
4
|
"description": "OMC 的内存假 CloudPivot 平台(wire 接缝的第二个适配器)+ HTTP 假服务器——@stalfh233/omc-cli 的测试与 bench 基准基座",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"build": "tsc --project tsconfig.build.json"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"omc-core": "0.4.
|
|
21
|
+
"omc-core": "0.4.90"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
24
|
"node": ">=22.13"
|