Commit 07f72f6c19b7a7c9a383a37ff8a9fb21d9347a22

Authored by zichun
1 parent 96573a81

docs: en wiki — Activiti is bypassed by xly's simple approval path

Critical correction in response to "no BPMN deployed means not used?":
yes, in this dev DB, Activiti's runtime is never invoked.

Findings:
- xly has TWO parallel approval mechanisms, only one of which uses
  Activiti.
- Path 1 (simple toggle): the "审核" button in the SPA POSTs to
  /business/doExamine → BusinessBaseController.java:384-391 →
  BusinessBaseServiceImpl.doExamine() → ExamineServiceImpl. Verified
  (grep -E 'runtimeService|taskService|processService|complete'
  against ExamineServiceImpl.java returns 0 hits) — this service
  flips bCheck=1 via direct SQL, never touching Activiti. This is
  the path actually used today.
- Path 2 (BPMN workflow): would only trigger when a gdsmodule has
  bCheck=1 AND a populated gdsmoduleflow row pointing at a deployed
  procdef. None of these exist in the dev DB.
- The bCheck flag is therefore xly's own approval boolean, owned by
  BusinessBaseServiceImpl, used widely as a list filter
  (SalesOrderServiceImpl etc. do WHERE bCheck=1 on every
  "show approved-only" query).
- /business/doExamine + /business/getProData added to internal.md
  endpoint table.
- activiti.md gets a "Two approval paths" section as the lead so a
  reader doesn't conflate the simple bCheck toggle with the workflow
  engine.
- The TL;DR is rewritten to make the "engine wired but not invoked"
  story explicit.
en/docs/api-reference/internal.md
@@ -26,6 +26,8 @@ page is the catalog of HTTP entry points. @@ -26,6 +26,8 @@ page is the catalog of HTTP entry points.
26 | `/business/getSelectDataBysControlId/{sId}` | POST | Dropdown population for a single control, by control `sId`. | 26 | `/business/getSelectDataBysControlId/{sId}` | POST | Dropdown population for a single control, by control `sId`. |
27 | `/business/getSelectLimit/{sId}` | POST | Paginated variant of the dropdown call. | 27 | `/business/getSelectLimit/{sId}` | POST | Paginated variant of the dropdown call. |
28 | `/business/addSysLocking` | POST | Optimistic-lock acquisition when a user starts editing a document — inserts a row in the system lock table keyed by `(sFormGuid, sUserId)`. The SPA fires this when entering edit mode so concurrent editors get a conflict warning. Handler: `BusinessBaseController.java:400-407`. | 28 | `/business/addSysLocking` | POST | Optimistic-lock acquisition when a user starts editing a document — inserts a row in the system lock table keyed by `(sFormGuid, sUserId)`. The SPA fires this when entering edit mode so concurrent editors get a conflict warning. Handler: `BusinessBaseController.java:400-407`. |
  29 +| `/business/doExamine` | POST | Simple "approve" — flips `bCheck = 1` on the named row via SQL. **Does NOT invoke Activiti**; this is xly's lightweight approval path used by every module that doesn't need multi-step workflow. Handler: `BusinessBaseController.java:384-391` → `BusinessBaseServiceImpl.doExamine` → `ExamineServiceImpl`. See [Two approval paths](../reference/maintainer/activiti.md#two-approval-paths) for when Activiti is used instead. |
  30 +| `/business/getProData` | POST | Generic stored-procedure invocation for a module — alternate path to `/procedureCall/doGenericProcedureCall`. Handler: `BusinessBaseController.java:350-358` → `BusinessBaseServiceImpl.getProData`. Used by FROUNT for module-level proc reads (the home dashboard `/getProData?sModelsId=...&sName=` pattern). |
29 31
30 These endpoints are documented in detail by [Slice 1](../slices/01-hello-world.md) 32 These endpoints are documented in detail by [Slice 1](../slices/01-hello-world.md)
31 (`getModelBysId` + grid load + save) and 33 (`getModelBysId` + grid load + save) and
en/docs/reference/maintainer/activiti.md
1 # Activiti integration 1 # Activiti integration
2 2
3 -> **State on this dev DB: engine wired, never used.** The Activiti  
4 -> engine is fully bootstrapped at runtime, the `act_*` schema is  
5 -> provisioned, the BPMN modeler UI is reachable — but **every  
6 -> workflow-related table is empty**. No BPMN deployed, no process  
7 -> instances ever started, no `gdsmodule` row currently has  
8 -> `bCheck = 1`. The plumbing is hot; nothing is flowing. 3 +> **TL;DR — Activiti is wired, the engine runs, no traffic flows
  4 +> through it.** Engine bootstrapped, `act_*` schema provisioned at
  5 +> 6.0.0.4, BPMN modeler reachable. But every workflow table is 0
  6 +> rows: no BPMN, no procdefs, no instances, no tasks. No
  7 +> `gdsmodule.bCheck=1`. No `gdsmoduleflow` link. **The approval
  8 +> button users see (`/business/doExamine`) bypasses Activiti
  9 +> entirely** and just UPDATEs `bCheck=1` via SQL — see
  10 +> [Two approval paths](#two-approval-paths) below.
9 11
10 This page documents what's actually wired (concrete classes, URLs, 12 This page documents what's actually wired (concrete classes, URLs,
11 engine state) and what would have to be true for it to do anything. 13 engine state) and what would have to be true for it to do anything.
12 14
  15 +## Two approval paths
  16 +
  17 +xly ships two parallel approval mechanisms. They look similar from
  18 +the UI but go through completely different code:
  19 +
  20 +| Path | Triggered by | Backend | Activiti involvement |
  21 +|---|---|---|---|
  22 +| **Simple "approve" toggle** | The "审核" button on a single-row form | `POST /business/doExamine` → `BusinessBaseController.java:384-391` → `BusinessBaseServiceImpl.doExamine()` → `ExamineServiceImpl` (xlyBusinessService). The service runs an UPDATE that flips `bCheck = 1` (and writes audit fields). | **None.** `grep` confirms `ExamineServiceImpl` calls neither `runtimeService`, `taskService`, `processService`, nor any other Activiti API. The `bCheck` flag is xly's own boolean, owned by `BusinessBaseServiceImpl`. Used widely as a list filter (`SalesOrderServiceImpl` and friends do `WHERE bCheck = 1` on every "show approved-only" query). |
  23 +| **Multi-step BPMN workflow** | A user submits a row whose module has `bCheck = 1` AND a populated `gdsmoduleflow` row pointing at a deployed `act_re_procdef` | `ProcessServiceImpl.submitApply()` → `runtimeService.startProcessInstanceByKey(...)`. Subsequent approvers act through `CurrencyFlowController.complete(...)` → `taskService.complete()`. xly mirrors state in `biz_flow` + `biz_todo_item`. | **Full Activiti.** Requires a deployed BPMN (in `act_re_procdef`), an active process instance (in `act_ru_*`), and an assigned task (`act_ru_task`). |
  24 +
  25 +In this dev DB, **path 1 is the only path that runs**. Path 2 has zero
  26 +configuration anywhere — no BPMN deployed, no `gdsmoduleflow` row, no
  27 +`gdsmodule.bCheck=1` modules. So when a user clicks 审核 today, the
  28 +record gets approved via the simple-toggle path and Activiti is not
  29 +involved.
  30 +
  31 +Why the second path even exists: a customer that *does* need a real
  32 +multi-step approval (warehouse → finance → GM, with reassignment and
  33 +delegation) gets it by deploying a BPMN through the modeler and
  34 +linking modules via `gdsmoduleflow`. That activates path 2 for those
  35 +modules; path 1 still handles everything else.
  36 +
13 ## Activiti is wired — engine ON 37 ## Activiti is wired — engine ON
14 38
15 Despite the dev DB being idle, the engine boots with `xlyEntry`: 39 Despite the dev DB being idle, the engine boots with `xlyEntry`: