-
User asked "Is there a BI engine?" Investigation found a substantial metadata-driven BI layer that the wiki had no dedicated coverage for. New page reference/maintainer/bi-engine.md: - Charts: gdsconfigcharmaster (3,006 rows) + slave (1,951) + CharServiceImpl (2,219 lines, one of the heaviest in xlyBusinessService). 11 chart types catalogued by sCharType distribution: Div(1558)/sLabel(1143)/Progress(137)/sPie(52)/ commonList(45)/sColumnarGroup(30)/sColumnar(28)/sBrokenLine(5)/ sBar(3)/ColorBlock(3)/sGauge(2). - 20 Sp_chart_* aggregation procs catalogued by domain (homepage cards, today/month sales, financial, equipment/shop-floor). - 6 /indexPage/commonChar dashboard modules listed by sId+name. - KPI subsystem: 6 kpi* tables (kpimaster=124,524 rows live), KpiServiceImpl (833 lines), BusinessModelKpiServiceImpl (901), FlushModleKpiThread, 2 Sp_KPI_* procs + spKPImodule. - Render flow end-to-end (SPA → getModelBysId → CharServiceImpl → generic proc dispatch → ECharts). - Customer-override KPI examples under script/客户/ noted. - Explicit "what this is not": not self-service BI, not real-time analytics, not OLAP-cube-backed. - Added to mkdocs nav under Reference (Maintainer). Tech-stack.md correction: - The OLAP4J row previously claimed "1 file in xlyPersist imports org.olap4j.*". Empirical re-grep returns ZERO Java imports of org.olap4j anywhere in source. The jars are classpath dead weight (the xmlaserver line is even commented out in build.gradle). Updated row to reflect the actual state and link to bi-engine.md.
-
Plan: /Users/reporkey/.claude/plans/noble-tumbling-sparkle.md Inventory: 33 hedge entries / open verification items across 12 hand- written pages, clustered into 5 groups by why-they're-not-verified. Cluster A — closed inline by reading source / running DB queries: - slices/02-multi-tenancy item 1: edition gating is **not** sVersionFlowId → sisversionflow. Verified: `grep sVersionFlowId xly-src --include='*.java' --include='*.xml'` returns ZERO mapper hits. The actual filter is `MenuChildServiceImpl.getBuMenuSql` line 64: `AND m.sId in (#{sVersionFlowId... wait sVerifyLicense})`. sVerifyLicense is sourced from the TrueLicense-bound `VerifyLicense.getModelAllList()` and injected via xlyApi RequestAddParamUtil:50 or controller-level param assembly. sVersionFlowId/Code are catalogue tags, NOT runtime gates. Wiki body of "How modules are filtered per edition" rewritten. - slices/02 item 2: closed; cross-link to the activiti.md rewrite that documents Activiti is wired-but-idle. - slices/02 item 3: session→tenant chain mapped: AuthorizationInterceptor.preHandle → RedisTokenManager.getToken (AES-decrypts bearer, checkToken validates Redis at <sLoginType><userId>) → @CurrentUser via CurrentUserMethodArgumentResolver → RequestAddParamUtil.addParams injects 16 keys. - slices/04 item 3: bVisible semantics closed. BusinessGdsconfigformsServiceImpl.java:413-433 — customslave row matches base by sControlName/sName, REPLACES base. Lines 446-468 — user-overlay then explicitly sets bVisible=false at line 464 when user-row hides the field. Hides at either layer; scope differs (per-tenant vs per-user). - slices/05 item 1: DbToDbServiceImpl is inter-DB sync (getData/ getDataDetail/etc. over Druid+JDBC), NOT a script-applier. `grep "script/客户" xly-src --include='*.java'` returns zero. Manual application via mysql CLI confirmed. - slices/06 item 2: PlcScheduledTasks ships two @Scheduled cron methods (`0/30 * * * * ?` line 74, `0/1 * * * * ?` line 105). Per-profile tuning is parameter-side, not cron-side. - slices/06 item 3: xlyRxtx git history — added in commit daf581311 ("1、添加串口功能"), commented out in cleanup branch for builds where serial isn't needed. xlyPlc runs without RXTX on TCP/Ethernet press models; serial-only models would re-enable. - builder/define-vtable item 1: 11 of 307 sTbName values (3.6 %) don't resolve to a base table. Breakdown: 4 point at views (viw_*), 3 at procs (Sp_*), 4 at case-drift / dropped tables. Audit query embedded. - builder/define-vtable hedge: real worked example added — `包装方式 / SisPacking` with 10 slave columns mapped to physical columns. Cluster B — closed via live BACK browser session: - slices/04 item 1: 界面显示内容配置 (gdsmodule.sId=11, /jmnrpz) renders three form-master panels. Third panel (sId=19211681019715596285250620, sTbName=gdsconfigformcustomslave) is the customslave editor. Verified live via clicking the menu and inspecting the GET /business/getBusinessDataByFormcustomId call. Cluster D — left in place with "Deferred (needs populated DB)" admonition: - slices/03 item 1 (view-with-print-template): no view-backed forms with a sysreport row — DB query returns 0. - slices/04 item 4 (real customslave example): COUNT(*) = 0. - slices/07 stub (active workflow): act_re_procdef = 0; bCheckflowCheck hard-disabled regardless. - builder/attach-workflow stub: same — recipe is code-derived hypothesis, not live-verified. Cluster E — left in place with "Deferred (outside repository)" admonition: - slices/06 item 1 (wire protocols): vendor docs, not source. - deployment.md "Open: production URL routing": nginx config in deployment ops, not the codebase. Cluster F — converted to "Future-work backlog" callouts: - slices/03 hedge "future revision should pick a module with print template": demoted to a future-work callout adjacent to the open item. - slices/05 items 2 & 3: re-cast as "Future-work backlog item — not a verification claim" with the workable command/mitigation noted. - concepts/customization-channels line 66: rephrased — the choice is about *runtime divergence visibility in source control*, not maintainer opinion. Bonus closure: - slices/03 item 3 (tenant-leaky views): DB audit returns 19 of 305 viw_* lacking sBrandsId (~6.2 %). Embedded the SQL + the count. - slices/04 line-41 hedge ("needs verification by clicking through BACK"): replaced with the verified mapping from item 1. After-state: of the original 33 entries: - 19 newly closed with evidence, - 4 left as deferred-because-DB-state with concrete blocker query, - 2 left as deferred-because-outside-repo with concrete blocker note, - 4 demoted to "Future-work backlog" callouts, - 4 already closed in earlier passes. Build verified `mkdocs --strict` green. -
User asked: are there examples of customising workflow other than the standard hardcoded one? Investigated and found a substantial customer example. Findings: - script/客户/万昌/计件工资/日报审核/领班驳回.sql is a 185-line customer-side workflow customisation defining Sp_mftproductionreportmaster_check1_0 ("Foreman Rejection", state 1 → state 0 transition). - Naming convention: Sp_<table>_check<currentState>_<nextState>. No procs in standard DB use this pattern; it's 万昌's own convention. - The proc resets SIX approval flags simultaneously (bManager, bIPQC, bDeputy, bSubmit, bWorkshopManager, bCheck) — 万昌 has ALTER TABLEd mftproductionreportmaster to add 5 columns that don't exist in the standard schema. - Adds sRejectMemo rejection-reason history (also custom column), appends each rejection's reason + timestamp + foreman name. - Calls sp_add_flow_log — a custom audit-log proc that doesn't exist in the standard DB. - Includes customer-specific business rules (e.g., block rejection if any slave row has bSAPCheck=1 — SAP-sync guard). So the answer to "any examples of customising workflow": - Yes — 万昌 has built their OWN multi-level approval workflow on top of xly's button-dispatch primitive: schema extension + custom transition procs + custom audit log. The framework provides only the button-press dispatch (via /business/ genericProcedureCall* or sButtonParam); everything else is customer-defined. - This is fundamentally different from Activiti — no BPMN, no FSM library, no engine. Just SQL + ALTER TABLE. - Other customer dirs (千彩, 重庆展印, 朝阳, etc.) mostly customise *calculations and reports*, not workflow. 万昌's pattern is rare but real. Slice 5 gets a "Worked-example 2" section walking through 领班驳回.sql in detail, plus a customisation-patterns-at-a-glance breakdown of what each of the 18 customer dirs actually contains. Activiti.md gets a back-reference: "A real Path-1 customisation example" pointing at the new slice 5 worked example, with the empirical observation that Activiti deployment is NOT seen in any script/客户/ directory. -
User asked: if Activiti isn't used, what implements workflow? Investigated and replaced the original two-path table with a proper three-path explainer. Findings: - Path 1 (single-step approval via stored proc + bCheck flag) is the dominant pattern. Each business table carries bCheck (426 tables), tCheckDate (400), sCheckPerson (398) — virtually universal. The 审核 button POSTs to /business/doExamine which calls the proc named in gdsmodule.sProcName; the proc owns the business validation and flips bCheck=1 directly. No engine, no state machine, no queue. - Path 2 (document chaining) is how multi-document business processes work: separate gdsmodule entries arranged as parent + ordered children, each with its own form and approval button. A "convert-to-next-doc" proc on form A creates the document for form B. The "01/04, 02/04…" KPI Work Center step numbering is just iOrder of children under a parent gdsmodule. No state machine; the workflow is the chain of procs wired by buttons. - Path 3 (Activiti BPMN) is GATED by ConstantUtils.bCheckflowCheck which is hard-coded false. So even if a tenant configured gdsmoduleflow rows and deployed BPMN, the gate in ExamineServiceImpl.doExcuExamine would short-circuit. To activate Path 3 a maintainer would have to recompile xly with the constant flipped, OR runtime-patch it. The page now leads with all three paths and a comparison table covering state storage, step transitions, reassignment/delegation, parallel branches, current activation status, and tooling. Concluding section explains why this design fits xly's audience (printing-industry ERP, where each business step is naturally its own document) and the trade-off (workflow logic scattered across stored procs rather than visualised in BPMN).
-
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.
-
Re-investigated Activiti's actual integration after the user asked how it's used. Substantive findings: State on this dev DB: engine wired, never used. - The Activiti 6.0 engine bootstraps with xlyEntry. activiti-spring- boot-starter-rest-api:6.0.0 declared in xlyFlow/build.gradle pulls ProcessEngineAutoConfiguration. xlyEntry's EntryApplicationBoot only excludes Activiti's REST-security autoconfig, not the engine. xlyFlow is consumed as api project(':xlyFlow') in xlyEntry, so all xlyFlow controllers serve at xlyEntry's context-path. - ActivitiConfig.java is a real @Configuration that wires Chinese fonts and a custom ICustomProcessDiagramGenerator into the engine. - Real call sites confirmed: * runtimeService.startProcessInstanceByKey(...) at ProcessServiceImpl.java:107 * taskService / repositoryService used across CurrencyFlowController, ModelerController, ProcessDefinitionController, ProcessActController, BizTodoItemServiceImpl, etc. * Modeler endpoints: /modeler/model/{id}/save, /modeler/editor/ stencilset, /modeler/create, /modeler/deploy/{id}. - Empirical state: every workflow table is 0 rows in this dev DB — act_re_model, act_re_procdef, act_ru_task, act_hi_procinst, gdsmoduleflow, biz_flow, biz_todo_item, plus 0 gdsmodule rows with bCheck=1. Engine running, plumbing hot, no traffic. CheckFlowController correction: - The class file is 22 lines with ZERO handler methods. Just @RestController @RequestMapping("/checkflow") shell. The wiki previously described it as "Activiti workflow surface (approve/ reject/view)" — this was wrong. /checkflow/* returns 404. - Real workflow URLs live in xlyFlow's CurrencyFlowController: /complete/{taskId}/{sBrandsId}/{sSubsidiaryId}/{sUserId}, /completeerp/{...}, plus /modeler/* for BPMN authoring. - Fixed in runtime.md (load-bearing-controllers row), internal.md (specialised-runtime row), with cross-link to activiti.md. activiti.md rewritten: - Reframed from "deferred for full coverage" to "engine wired, never used in this dev DB" — the engine state is concrete and documentable; only the flow content is empty. - Added "Activiti is wired — engine ON" section with the bootstrap chain. - Added a concrete table of Activiti API call sites (file:line + which Activiti service is invoked). - Added URLs-the-modeler-exposes section listing the real workflow URLs served via xlyEntry. - Added the act_* schema state table with the live 0-row counts. - Added "What would make it move" — the 6-step path from drawing a BPMN to seeing a flowing approval. - Added "Why xly bothered with Activiti at all" — the architectural rationale. - Documented xlyApi/xlyPersist 5.17 declarations as vestigial (only IdGen.java's User import; type signature works under 6.0 too — safe to remove). -
Investigated the FROUNT home-page card titled `KPI监控` to determine whether it's Activiti-driven (it isn't). Findings: - Endpoint: POST /xlyEntry/modelCenter/getModelCenter → BusinessModelCenterController.getModelCenter (xlyEntry, web/businessweb/) → BusinessModelCenterServiceImpl.getKPIModelList (thin wrapper) → BusinessModelKpiServiceImpl.getKPIModelList (xlyBusinessService). - Internal name: "KPI Work Center" (Javadoc 初次获取KPI工作中心). - Data source: gdsmodule rows where bUnTask=1, partitioned by sUnType ∈ {Pending, PendingCheck, MyWarning}. No KPI math; just open-task aggregation. - Categorisation in UI: by role (sftlogininfojurisdictiongroup ⋈ sisjurisdictionclassify) and by business flow (gdsmodule parent- child tree; "01/04, 02/04…" is the iOrder within a flow parent). - Cache: @Cacheable(value="getKpiModelByUser") evicted by getModelCenterCalculation and gdsmodule-changing paths. - Empirical proof of independence from Activiti: in this dev DB, biz_todo_item and biz_flow are both 0 rows, yet the KPI Work Center still shows non-zero counts. Activiti's task surface flows through CheckFlowController instead. Updates: - runtime.md: add BusinessModelCenterController row to the load- bearing-controllers table; new "The KPI Work Center" subsection with full architecture, data source, cache behaviour, and the why-not-Activiti contrast. - internal.md: add /modelCenter/* row to the runtime endpoints table with cross-link. -
Live findings from BACK + FROUNT browser session: - /business/addSysLocking: undocumented optimistic-lock endpoint (POST, called when entering edit mode; handler at BusinessBaseController.java:400-407). Added to internal.md universal-CRUD table. - BACK admin sidebar fully enumerated (10 modules) and mapped to backing form-master sTbName + owning service. 8/10 are framework primitives covered elsewhere; 常用操作配置 has no gdsconfigformmaster row in this dev DB (SPA-side admin special-case); 图表配置 is gdsconfigcharmaster/slave (added to the gds prefix entry in modules-forms-vtables.md). - FROUNT login confirmed; this dev DB exposes only 4 sidebar modules (2 are AI/LLM out-of-scope). Production tenants would carry the full business-module catalog. - Slice 1 save endpoint live-corroborated: clicking 新增 → 保存 fired POST /xlyEntry/business/addUpdateDelBusinessData?sModelsId=13 → 200 OK. (Audit-tag mutation didn't actually land because the Vue model didn't pick up our scripted input change — endpoint flowed but with original row state.) Updated slice-01 open- verification item with the partial verification. Dead-source flag (sql-templates.md): - Two `FileSqlUtil` classes coexist. xlyFlow's loader points at the 8 templates that exist on disk. xlyApi's loader names 7 templates (sInSqlStrTemple, sOutSqlStrTemple, sDataSqlTmp[Def], sJsonSqlTmp[Out], sDbPro) — NONE of them exist as files. Documented as broken-by-default; either restore templates or remove the loader. Auto-catalog regen verified accurate (gdsmodule.md columns match live DB).
-
Third commit closing high-value gaps the user flagged in the verification plan. Cross-node cache coherence — LOCKED EMPIRICALLY: - Connected to live Redis at 118.178.19.35:16379 db=0. - 233 of 267 keys use Spring's `<cacheName>::<key>` separator. - Confirmed key shapes match @Cacheable SpEL specs: businessGdsconfigformsServiceGetFormconstData::{...} (37 entries) gdsmoduleById::gdsmoduleById_<sBrandsId>_<sSubsidiaryId>_<sLanguage> (2 entries) - Conclusion: Spring's RedisCacheManager IS the active CacheManager. @CacheEvict on any node clears the shared Redis store; cross-node coherence works without any JMS involvement. Removed the "open question" hedge in cache-invalidation.md. New page — Metadata-management services (xlyManage): - Closes the biggest documentation gap surfaced by Pass C2. - Catalogs the 8 large Gds*ServiceImpl classes (878+729+555+489+ 362+319+243+221 = ~3,800 lines of metadata-CRUD logic) plus CommonServiceImpl (56) and SysbrandsServiceImpl (125). - Documents the universal five-method shape every Gds*Service follows (get/getBysId/add/update/delete) and how it pairs with the corresponding Gds*Controller in xlyEntry/.../systemweb/. - Maps each service to its BACK admin screen. - Notes the cache-invalidation hookpoint (synchronous BusinessCleanRedisData.delCleanRedisData* on commit). - Added to mkdocs nav under Reference (Maintainer). Worked examples: - Slice 04: gdsconfigformcustomslave is empty in the dev DB (0 rows). Updated the open verification item to confirm this rather than leave the framing "depends on the deployment". - Slice 05: side-by-side diff of 重庆展印's Sp_SalSalesCheck vs the standard. Quantified differences (1714 vs 723 lines, same 14-param signature, override adds CbxSrcNoCheck branch and strips temp-table aggregation, 12 sibling procs use the same CbxSrcNoCheck pattern). Added a copy-pasteable diff command. Honest scope acknowledgement: - api-reference/internal.md: explicit "what this catalog includes vs treats as illustrative" paragraph. ~19 framework- primitive controllers documented; ~52 business-domain controllers (workorder/salesorder/productionPlan/etc.) treated as illustrations of the framework at work, with grep guidance for maintainers who need to find them. Auto-catalog regenerated: - Ran scripts/gen_catalog.py against live DB. No changes (catalog was already current); 3081 generated pages. Pass E save trace: - Tried multiple angles (UI flow, hand-crafted POST with token in Authorization header, fetch interception). Edit-mode UI didn't yield a save fire under our setup (Ant Design grid + Vue SPA edit-mode peculiarity). Read trace remains fully verified end-to-end. Save body shape is documented in the Javadoc on BusinessBaseController.java:161-163 and reflected in the wiki; live save corroboration deferred again. -
Audit every concrete claim in the 41 hand-written en pages against the three primary sources (DB, source on cleanup branch, source-tree inventory). Fix divergent claims in place; preserve framing where verified. Substantive corrections: - request-lifecycle / runtime / slice 01: the metadata read sources from five tables/families (gdsconfigformmaster + overlays, gdsformconst, sysjurisdiction, sysbillnosettings, sysreport), not four. The map key `gdsjurisdiction` is misleading — the per-user grant read queries `sysjurisdiction`; `gdsjurisdiction` is the builder-side action catalogue. `gdsformconst`, `gdsconfigformmaster`, `gdsconfigformslave` are NOT tenant-scoped; they filter by form-id only. - multi-tenancy: four metadata tables (gdsformconst, gdsmodule, gdsconfigformmaster, gdsconfigformslave) are an explicit exception to the "every table tenant-scoped" promise — `sTableNameList` strips sBrandsId/sSubsidiaryId from writes against them. - sSaveProName / sSaveProNameBefore are pre/post-save HOOKS on top of the always-running base path (BusinessBaseServiceImpl.add/update), not either/or branches. Default add/update path is in BusinessBaseServiceImpl, not AddDelUpdCommonServiceImpl. - cache-invalidation: redis cache is cleared synchronously in BACK via @CacheEvict on CleanRedisServiceImpl during save. The JMS CHANGE_GDS_MODULE queue triggers PRO_ERPMERGEBASEGDSMODULE (base-data merge), NOT cache invalidation despite the name. Cross-node coherence open question (no custom CacheManager bean configured). - messaging: enumerate all 24 P2pQueue destinations grouped by intent; fix CHANGE_GDS_MODULE description; clarify single Consumer.java with 24 @JmsListener methods (not 24 listener classes). - API paths: /checkflow lowercase (mapping value, not class name); /procedureCall/doGenericProcedureCall (not /business/genericProcedureCall*). - tech-stack: Druid 6 java imports + 16 yml mentions (was 25 conflated); fastjson per-module xlyInterface 9 (was 10); commons-lang3 39 (was 41); @Document classes 20 PLAT_* + 2 DIKE_TEST* (was "all PLAT_*"); xlyPersist activiti hit is IdGen.java (was BaseDao.java); add Springfox to declared-but-no-imports table; reconcile module list to 11 framework core + xlyPlc plugin + xlyPlatConstant utility. - index.md: clarify xlyFace as "in build, not documented"; add xlyErpTask / xlyPlatTask scheduler bullet; correct MongoDB framing (caller is in xlyPersist with no consumers, not xlyPlat*); add xlyPlc note; extend backup-table OOS to cover *_copy1 / *_history / *YYYYMMDD[HHMMSS]. - deployment.md: split deployable Boot apps from library modules; enumerate 12 commented-out includes (was 3); remove xlyPlatConstant from out-of-scope Plat* list; split profile permutations by service. - activiti.md: add xlyApi to 5.17 dependency list; replace speculative BPMN path hint with verified state; name actual ActivitiConfig.java; note act_id_* are views projecting xly users into Activiti shapes. - api-reference/external.md: fix bearer-token validation flow (sysapibrand via AES-decrypted corpid, not sysapithirdtoken); /online/* are page renders not API execution; /pro/* mostly returns Thymeleaf views; mark sysapidbtodb as xlyFlow-owned; /token/getToken accepts GET and POST. - api-reference/webhooks.md: add Swagger Docket caveat (UI shell ships but no Docket bean → /v2/api-docs effectively empty); flag /send/sendQw as stub (returns "ok"). - slices/03-report.md: fix dir path xlyEntry/com/xly/report/ → xlyEntry/com/xly/web/report/; reframe PrintReportControllerOld as dead source (file body fully commented out). - concepts/modules-forms-vtables.md: add 22-prefix glossary table (gds/sys/sis/sft/ele/mft/sal/quo/acc/pur/ops/cah/sgd/ept/mit/pit/qly/ kpi/udf/viw_/plat_/ai_/act_/qrtz_) so a maintainer can enumerate business-data domains at a glance. - concepts/master-slave.md: disambiguate document-row pattern from DataSource master/slave (different concept, name overlap). - proc-dispatch.md: add proc-name molds (Sp_*_BeforeSave/AfterSave/ SaveReturn, sp_btn_*, PRO_ERPMERGE*) + function-layer paragraph (Fun_*/Fn_*/get_*; SQL-called, not Java-dispatched). - concepts/index.md: schema label MySQL\nxlyweberp → xlyweberp_*. Pass E (live behavioural traces) deferred — source/DB-side audit was thorough; live traces best done as a follow-up sweep against a running instance.
-
en: - new: api-reference/notifications.md, reference/maintainer/running-locally.md, reference/maintainer/tech-stack.md - concepts/index.md: add Mermaid architecture diagram - index.md: scope-note MongoDB store as plat-tier - concepts/api-surface.md: point "the four-table read" link at the reference/maintainer/runtime.md anchor that actually contains the section - maintainer/index.md, api-reference/index.md, mkdocs.yml: nav + cross-links zh: - mirror translations of the new en pages, plus zh api-reference/* section
-
Verified every factual claim in the hand-written prose against the codebase under ../xly/ and the live xlyweberp_saas_ai schema, and fixed the drift: - semantic-fk: clarified — zero FKs on xly tables; the ones that exist are all on bundled Activiti / Quartz schemas, which the runtime doesn't join through. - multi-tenancy / runtime / slice 2: corrected RequestAddParamUtil shape (16 keys, 56 lines), noted the parallel xlyApi copy. - slice 1: corrected line ranges for addUpdateDelBusinessData; clarified that sTableNameList is a cache-invalidation gate, not an authorisation gate; corrected the gdsroute claim — unregistered paths are NOT 404'd server-side, the SPA uses gdsroute as a client-side whitelist (web-verified). - runtime: fixed controller package paths (Gdsmodule/Gdsconfigform/Gdsconfigtb live in systemweb/, not businessweb/); added CheckFlowController. - sql-templates / proc-dispatch: 8 scaffolds, not 7 (sSqlStr.sql). - master-slave: removed table names that don't exist (accOrderCostAnalysisMaster, quoQuotationCalc, mftWorkOrderCalc, mftWorkOrderSlaveMoney); added the *_tmp family that does. - permissions: full rewrite. The original page described gdsjurisdiction as a per-(module, role, button) rule table backed by empty plat_base_authority_* lookups; reality is gdsjurisdiction is a per-module catalog of buttons/actions, with sysjurisdiction carrying the actual role/user grants. - Removed environment-specific facts (row counts, sizes, timestamps, per-DB enumerations) so the wiki documents the framework, not one particular DB snapshot. Auto-catalog generator (en/scripts/gen_catalog.py): - Rewritten to query MySQL directly via ~/.my.cnf (replaces the recon/*.tsv pipeline). - Stripped ephemeral fields from output (Rows, Data size, Created, Updated on tables; Created, Last altered on routines; Definer on views). - Strips the schema-name prefix from VIEW_DEFINITION so view bodies are portable across deployments. - Wipes and rewrites docs/auto-catalog/{tables,views,procedures,functions}/ on each run. - Auto-catalog regenerated. New API Reference chapter (5): - concepts/api-surface.md introduces the three-tier design (xlyEntry internal, xlyApi external, xlyInterface webhooks). - api-reference/{index,internal,external,webhooks,messaging}.md cover each surface, with the data-driven /api/invoke{sApiCode} pattern, sysapi schema, token flow, and the SpringFox Swagger UI location on xlyInterface. - mkdocs nav: chapters renumbered (Auto-Catalog → 6, Glossary → 7, Contributing → 8); glossary/contributing wrapped as section indexes to render correctly under navigation.sections. Other: - Bilingual top-level README (Chinese + English). - requirements.txt: pymysql added for the new generator. -
Documents the xly (小羚羊) printing-industry ERP framework. Built with MkDocs Material; CJK search via jieba; 3,076 auto-generated catalog pages from recon/*.tsv plus hand-written prose for the framework's core mental model and end-to-end vertical slices. Phase 0 recon: stack, schema shape, framework metadata layer, scope. Phase 1 wiki: scaffold + auto-catalog + Slices 1-6 (Slice 7 deferred). Slice coverage: 1. CRUD module (Hello World) — observed network + cited source 2. Multi-tenancy & product editions — sBrandsId/sSubsidiaryId/sVersionFlowId 3. View-backed module (read-only report) 4. Custom field overlay (gdsconfigformcustomslave) 5. Per-customer SQL override (script/客户/<customer>/) 6. Hardware integration (xlyPlc, optional) 7. Workflow (deferred — Activiti tables empty in dev DB) Concepts: thesis, modules-forms-vtables, master/slave, semantic-FK, customization channels & layers, multi-tenancy, request lifecycle. Reference (Builder): define-form, define-vtable, permissions, attach-workflow (deferred). Reference (Maintainer): runtime, proc-dispatch, cache-invalidation, sql-templates, deployment, activiti.