• 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.
    zichun authored
     
    Browse Code »
  • 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.
    zichun authored
     
    Browse Code »
  • 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).
    zichun authored
     
    Browse Code »
  • 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.
    zichun authored
     
    Browse Code »
  • 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).
    zichun authored
     
    Browse Code »
  • 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.
    zichun authored
     
    Browse Code »
  • User flagged that searches for `BusinessBaseServiceImpl` and `MyBatis`
    were returning thousands of irrelevant matches. Cause: the search
    plugin's separator regex included `(?!\b)(?=[A-Z][a-z])`, which split
    every CamelCase boundary at INDEX time AND at QUERY time. So the
    indexed token stream for `BusinessBaseServiceImpl` was [Business, Base,
    Service, Impl] (each a common, low-relevance token), and the same
    4-token expansion happened on the query — every page that mentioned
    "service" matched.
    
    Removing the CamelCase splitter so identifiers stay whole. Verified
    via search_index.json: 18 docs now contain the intact
    `BusinessBaseServiceImpl` token (down from 119 spurious matches);
    `MyBatis` queries no longer collide with `MySQL` / `My...`. Lunr
    still supports wildcard suffixes (`Service*`) for partial-token
    search if a maintainer wants it.
    zichun authored
     
    Browse Code »
  • 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).
    zichun authored
     
    Browse Code »
  • 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.
    zichun authored
     
    Browse Code »
  • Second commit completing the verification plan after the first commit
    covered Pass A + most of Pass B P0/P1 + Pass C1/C2.
    
    P1 gaps:
    - slices/02-multi-tenancy.md: add the four-table sTableNameList
      exception (gdsformconst, gdsmodule, gdsconfigformmaster,
      gdsconfigformslave strip tenant cols at write); rewrite query-shape
      section to distinguish global framework metadata from tenant-scoped
      overlays + business state; flag dev DB has only 8S_001 in
      sisversionflow despite gdsmodule.sVersionFlowCode referencing
      EBC-SD/EBC-RD/EBC-MDM/etc.; add live row counts (1002 untagged,
      322 8S_001, 15 EBC-SD-002, …).
    - api-reference/internal.md, messaging.md, notifications.md verified
      as-is (Pass A surface fixes were sufficient, all file paths exist).
    
    P2:
    - slices/04-custom-field.md: close out the merge-code open item —
      merge is Java at BusinessBaseServiceImpl.java:246-248
      (getFormSlaveData + getFormCustomSlaveData); the two views supply
      the master⋈slave shape, the merge itself is in Java.
    - slices/06-hardware.md: PlcScheduledTasks uses Spring @Scheduled cron
      (every 30s + every 1s), not Quartz directly.
    - concepts/thesis.md: fix the "four-table read" framing — actual reads
      are from gdsconfigformmaster (with overlays), gdsformconst,
      sysjurisdiction, sysbillnosettings, sysreport. Soften slice-1
      reference to remove the "four-table" misframing.
    - slices/03-report.md, concepts/api-surface.md, customization-channels,
      customization-layers, semantic-fk verified clean (script/客户/
      customer dirs = 18, 0 FK / 0 triggers on xly tables, both overlay
      views exist).
    
    P3:
    - reference/builder/define-form.md: rewrite cache-invalidation section
      to match the corrected architecture (synchronous @CacheEvict, not the
      JMS path).
    - builder/define-vtable, builder/permissions, builder/index,
      builder/attach-workflow, slices/07-workflow, glossary/index,
      reference/maintainer/index, slices/index, contributing/index
      verified appropriately marked deferred / consistent.
    
    Pass D consistency sweep:
    - Ports (8080/8090/8000/8091/8597/8598) consistent across pages.
    - Schema names consistently use xlyweberp_saas_ai;
      running-locally.md correctly documents the xlyweberp_saas vs _ai
      divergence.
    - Counts (1358 gdsmodule rows, 311 views, 1687 procs, 177 functions)
      consistent.
    - Module/Modle/Models codebase quirk consistently surfaced.
    - xlyPlc plugin framing consistent across index.md, tech-stack.md,
      slice 06.
    - vtable / virtual table — single canonical form ("virtual table") used
      in narrative; URL-style filename `define-vtable` preserved.
    - proc / procedure / stored procedure usage clean (long form for
      emphasis, short for lists).
    
    Pass E live traces (partial):
    - Slice 1 read flow CORROBORATED end-to-end at BACK admin/123 edition
      基础版/8s. Both documented URLs captured exactly:
        GET  /xlyEntry/business/getModelBysId/13?sModelsId=13                                      → 200
        POST /xlyEntry/business/getBusinessDataByFormcustomId/19211681019715574676360040?sModelsId=13 → 200
      including the redundant ?sModelsId=13 alongside the path variable.
      Updated slice-01 open verification items to mark the read item closed.
    - Slice 1 save flow + slices 2-6 traces deferred (would mutate shared
      dev DB; FROUNT enumeration declined; monthly usage limit reached).
    
    Pass C3 frontend inventory (partial):
    - BACK admin sidebar = 10 framework-builder modules: 系统模块配置,
      数据表内容配置, 界面显示内容配置, 接口自定义配置, 系统常量配置,
      系统权限配置, 常用操作配置, 用户信息配置, Mysql脚本配置, 图表配置.
    - 8/10 covered by existing wiki pages; 2 silent (常用操作配置,
      图表配置 — admin BACK utilities, not framework runtime).
    - FROUNT enumeration declined by user.
    zichun authored
     
    Browse Code »
  • 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.
    zichun authored
     
    Browse Code »

  • Reflect xly-src cleanup branch:
    - xlyPlat* modules dropped (except xlyPlatConstant, kept as shared utility)
    - xlyTestService, xlyTestController dropped
    - xlyFile, xlyRxtx already excluded; now explicitly listed
    - Note xlyPlatConstant as misnamed shared-utility (xlyPersist imports MultiThreadServer + TimeContant)
    zichun authored
     
    Browse Code »
  • 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
    zichun authored
     
    Browse File »

  • 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.
    zichun authored
     
    Browse Code »
  • zichun authored
     
    Browse Code »
  • zichun authored
     
    Browse Code »