• Cross-verified every load-bearing claim against current src/db. Two
    real defects found and fixed; everything else holds.
    
    Fixes:
    
    - tech-stack.md HikariCP row: claim was "8 files reference
      com.zaxxer.hikari (xlyApi=6, xlyInterface=2)". Empirical recount on
      the cleanup branch: only 3 files import HikariDataSource (xlyApi=2:
      MasterDataSourceConfig + SlaveDataSourceConfig; xlyInterface=1:
      MasterDataSourceConfig). Updated the cell to match.
    - slices/01-hello-world.md "Open verification items" had two items
      numbered 3 (a copy/paste artefact from the Pass-E live-trace
      edit). Renumbered the second to 4, fixed the cross-ref to point at
      the actual section anchor (#4-user-edits-a-row-clicks-save), and
      rewrote the closing one-liner so it names the items that are still
      open (2 + 3) rather than the original v1 framing.
    
    Re-verified (no change needed):
    
    - All cited line numbers in BusinessBaseController.java (63, 65, 105,
      107, 165, 167) and BusinessBaseServiceImpl.java (162, 165, 181, 196,
      246, 325-327, 1014, 1078, 1250, 1738, 1824) still accurate.
    - BusinessGdsconfigformsServiceImpl.java:209 @Cacheable still reads
      the documented value/key pair.
    - RequestAddParamUtil line counts: 56 (xlyPersist), 57 (xlyApi).
    - DB count claims: 1358 gdsmodule, 124,524 kpimaster, 2986 gdsformconst,
      0 gdsconfigformcustomslave, 311 views, 901 tables, 1687 procs,
      177 functions, 18 customer override dirs, 305 viw_* views, 19 leaky.
    - BI/management line counts: CharServiceImpl 2219, KpiServiceImpl 833,
      BusinessModelKpiServiceImpl 901, all 10 Gds*ServiceImpl line counts.
    - Cache regions: 17 in CleanRedisServiceImpl matches the wiki.
    - xlyPlc: 5 java files + 9 yml profiles. xlyEntity: 22 @Document.
    - EntryApplicationBoot.java:22 @EnableCaching, :23-24 SecurityAutoConfig
      exclude — both still where the wiki says.
    - act_*/biz_flow/biz_todo_item/gdsmoduleflow all still 0 rows
      (Activiti is wired-but-idle as the activiti.md page says).
    - gdsconfigtbmaster drift: 11 of 307 sTbName values unresolved (3.6 %).
    - All 6 BACK framework-builder admin pages (系统模块配置, 数据表内容
      配置, 界面显示内容配置, 接口自定义配置, 系统常量配置, 系统权限
      配置, etc.) referenced consistently across wiki.
    - Cross-page consistency on all key facts: gdsjurisdiction-as-key vs
      sysjurisdiction-as-table; sTableNameList 4-table tenant-bypass
      exception; Spring RedisCacheManager (NOT JMS) is the cross-node
      cache mechanism; xlyPlc as plugin; xlyFace in-build-out-of-doc-
      scope; the 5-key composite (formData, gdsformconst, gdsjurisdiction,
      billnosetting, report).
    - mkdocs --strict green.
    - nav matches filesystem (no orphans).
    zichun authored
     
    Browse Code »
  • Editorial pass per user direction: stop justifying the architecture.
    For every "why this design works" passage, name the costs the design
    imposes — not as a parenthetical aside but as substantive critical
    analysis. Each major architectural-claim page now carries an explicit
    drawbacks/costs section.
    
    Pages revised:
    
    concepts/thesis.md
    - "The reward" → "What the design enables (and what each enabler still costs)":
      for each promised benefit (single codebase, PMs evolve without
      engineering, customisations layered cleanly), name the limit. Added
      closing observation that data-driven design redistributes complexity
      to people and tools the framework can't compile-check.
    - "When it breaks down": rewrote to call out that "bypassing the
      framework" via 18 customer dirs makes the data-driven thesis
      partial, not complete.
    
    concepts/semantic-fk.md
    - "Why xly disabled FKs": added critical analysis. Both reasons
      could be addressed surgically; the chosen "no FKs anywhere" is the
      trade for DB-enforced integrity, paid every day the system runs.
    
    concepts/master-slave.md
    - "Slave naming caveat": stop framing retention as wise pragmatism.
      The naming was a poor choice; preservation has a real ongoing cost.
    
    concepts/modules-forms-vtables.md
    - "Three nouns, one engine": the universal dispatch path concentrates
      3,500+ lines + edge cases + special-case hardcodes in one class.
      Naming the trade.
    
    concepts/multi-tenancy.md
    - "How the design scales" → "How the design scales — and where it
      doesn't": shared schema = shared contention; tenant-filter index
      discipline; no physical hard-delete; rigid (sBrandsId,
      sSubsidiaryId) tenancy unit.
    
    concepts/customization-channels.md
    - Soften "90%+ should live here" claim — that's an aspirational
      target, not a measured fact. The 18 customer override directories
      are evidence the channel-2 demand is non-trivial.
    
    concepts/api-surface.md
    - "Why three tiers, not one" → "Why three tiers (and what splitting
      them costs)": three WARs to deploy, duplicate code, no shared
      session, three reverse-proxy entries. Note the alternative
      (single-WAR with package boundaries) and what that would cost
      vs gain.
    
    reference/maintainer/proc-dispatch.md
    - "Why dynamic proc dispatch matters": added five concrete costs
      (no compile-time check, no type safety, no call-site discoverability,
      no static analysis, broken stack traces). Reframed: dynamic
      dispatch made it cheap to keep adding procs, which made the pile
      grow, which made the pile harder to audit.
    
    reference/maintainer/cache-invalidation.md
    - New "Drawbacks of this design" section: confusing co-named systems,
      eviction in same transaction as write (silent corruption on
      Redis outage), allEntries=true blunt eviction, no batching,
      direct DB writes bypass everything. Also fixed the "if cache is
      local" hedge in section 3 (we've now empirically confirmed Redis-
      backed, so cache is shared).
    
    reference/maintainer/bi-engine.md
    - New "Drawbacks of the homebrewed approach" section: every chart
      needs a SQL author, charts run heavy SQL on OLTP DB, no semantic
      consistency between charts, no drill-down, customer-divergent KPI
      logic. Also dedup'd the duplicated "What this is not" section.
    
    reference/maintainer/sql-templates.md
    - "Why this is a 'template' library and not a code generator" →
      added costs: no enforcement, no regeneration, no template-origin
      tracking, customer overrides drift from scaffold. The 1,687 procs
      the schema carries are the evidence that "discipline rather than
      enforcement" doesn't fully hold.
    
    reference/maintainer/activiti.md
    - "Why this design works for xly's audience" → "Why xly avoided
      Activiti — and what that costs": scattered workflow logic, no
      central audit trail, no parallel-branch/reassignment, invisible
      flow-graph evolution, idle Activiti engine paying boot cost
      anyway.
    - "Why xly bothered with Activiti at all" → "Why xly bothered with
      Activiti — and whether it was worth it": named the costs (second
      engine, second schema, second auth surface, modeler UI to learn)
      and the damning fact that on this dev DB the engine is idle. A
      future cleanup could plausibly remove Activiti entirely.
    
    reference/maintainer/runtime.md
    - New "What 'universal CRUD' means in practice" section: 3,500-line
      single-point-of-failure class, no type system on Map<String,Object>,
      poor discoverability ("what endpoints write to table X" is
      unanswerable). The trade: adding a module is essentially free,
      touching the runtime essentially never is.
    - Updated cache-invalidation cross-link to drop the "open question"
      hedge (now empirically resolved).
    
    slices/04-custom-field.md
    - "Why it works without code changes" → "Why it works without code
      changes — and what that costs": merge runs on every request,
      three near-empty tables on every schema, display-only extension
      (real persisted fields still need ALTER TABLE), debuggability
      requires diffing 3 overlay tables.
    
    slices/05-customer-sql-override.md
    - Added drawbacks: no version control on the deployed body, no
      type-safety bridge, compounds the BI problem. Reframed the
      "right rule of thumb": 18 customer override directories suggest
      the channel-2 demand is structural, not exceptional — that's
      evidence the metadata model isn't expressive enough, not a
      celebration of the escape hatch.
    
    slices/06-hardware.md
    - "The cleanest story xly tells about an awkward problem" →
      removed the "cleanest" framing. Added costs of "DB as the only
      contract": no backpressure, no request/response, bridge-side
      state invisible to the framework, three layers of polling
      multiply latency, hardest code (byte protocols) gets least CI.
      A real-time-aware architecture would use streaming end-to-end;
      xly's choice trades latency, observability, flow control for
      operational simplicity. Liveable for press tempo, not for
      faster shop-floor signals.
    zichun authored
     
    Browse Code »
  • The FROUNT home card "KPI监控" is open-task aggregation
    (BusinessModelCenterController), not analytics — already covered in
    runtime.md from the parallel session. Added a callout at the top of
    the KPI subsystem section so readers don't conflate the two.
    zichun authored
     
    Browse Code »
  • 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.
    zichun authored
     
    Browse Code »

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