Commit 4ea83bcc5e672b7f85e2471e21535d07858338dc
1 parent
d21ed969
docs: en wiki — initiative pass to close open items
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.
Showing
6 changed files
with
199 additions
and
34 deletions
en/docs/api-reference/internal.md
| @@ -82,6 +82,25 @@ get past `@Authorization`; if it does (e.g., an unannotated method), | @@ -82,6 +82,25 @@ get past `@Authorization`; if it does (e.g., an unannotated method), | ||
| 82 | that method also bypasses the universal tenant injection in | 82 | that method also bypasses the universal tenant injection in |
| 83 | `RequestAddParamUtil` — and is therefore a multi-tenant bug. | 83 | `RequestAddParamUtil` — and is therefore a multi-tenant bug. |
| 84 | 84 | ||
| 85 | +## Coverage policy — what this catalog includes | ||
| 86 | + | ||
| 87 | +`xlyEntry` hosts **~71 controllers** in total. This page enumerates | ||
| 88 | +the ~19 that are part of the framework's universal runtime: | ||
| 89 | +`/business/*`, `/configform/*`, `/treegrid/*`, `/procedureCall/*`, | ||
| 90 | +`/panel/*`, `/checkflow/*`, `/gdsmodule/*`, `/gdsconfigform/*`, | ||
| 91 | +`/gdsconfigtb/*`, plus the print surface. Every form in the system | ||
| 92 | +flows through these. | ||
| 93 | + | ||
| 94 | +The remaining ~52 controllers are **business-domain modules** | ||
| 95 | +(`/sysworkorder`, `/salesorder`, `/productionPlan`, `/oee`, | ||
| 96 | +`/eleMaterialsStock`, etc.) — they implement specific industry-tier | ||
| 97 | +flows on top of the framework primitives above. The wiki treats those | ||
| 98 | +as *illustrations of the framework at work*, not as catalogued surface | ||
| 99 | +of their own. Maintainers who need to find a specific business | ||
| 100 | +controller should grep `xlyEntry/src/main/java/com/xly/web/` for the | ||
| 101 | +URL prefix; the framework primitives on this page are what's worth | ||
| 102 | +reading first. | ||
| 103 | + | ||
| 85 | ## What this API is *not* | 104 | ## What this API is *not* |
| 86 | 105 | ||
| 87 | - **Not stable** — endpoint shapes change with the framework. | 106 | - **Not stable** — endpoint shapes change with the framework. |
en/docs/reference/maintainer/cache-invalidation.md
| @@ -82,23 +82,32 @@ The same goes for the other 23 `ERP_JMS_ACTIVEMQ_*` queues in | @@ -82,23 +82,32 @@ The same goes for the other 23 `ERP_JMS_ACTIVEMQ_*` queues in | ||
| 82 | domain-specific base-data merge or fan-out work item, not cache | 82 | domain-specific base-data merge or fan-out work item, not cache |
| 83 | invalidation. | 83 | invalidation. |
| 84 | 84 | ||
| 85 | -## The cross-node coherence question (open) | 85 | +## Cross-node cache coherence — Redis-backed, confirmed |
| 86 | 86 | ||
| 87 | `@EnableCaching` is on `EntryApplicationBoot.java:22` and | 87 | `@EnableCaching` is on `EntryApplicationBoot.java:22` and |
| 88 | `ApiApplicationBoot.java:24`. **No custom `CacheManager` bean is | 88 | `ApiApplicationBoot.java:24`. **No custom `CacheManager` bean is |
| 89 | declared anywhere in the in-scope source** (no `RedisCacheManager`, | 89 | declared anywhere in the in-scope source** (no `RedisCacheManager`, |
| 90 | no `@Bean CacheManager`-returning method, no `implements CacheManager`, | 90 | no `@Bean CacheManager`-returning method, no `implements CacheManager`, |
| 91 | -no `spring.cache.*` property in any `application*.yml`). Spring Boot | ||
| 92 | -2.2.5 will then auto-pick a `CacheManager` based on what's on the | ||
| 93 | -classpath; the most likely outcome with `spring-boot-starter-data-redis` | ||
| 94 | -present is that Spring auto-configures Redis-backed caching, which | ||
| 95 | -would make `@CacheEvict` clear the shared Redis store and therefore | ||
| 96 | -fan out across nodes implicitly. **This has not been confirmed by live | ||
| 97 | -inspection of a running node** — it's the natural reading of the | ||
| 98 | -config but worth verifying when a deployment is available. If the | ||
| 99 | -auto-picked manager is in fact `ConcurrentMapCacheManager` (in-memory, | ||
| 100 | -per-JVM), the multi-node coherence story is broken under this code | ||
| 101 | -path and would need a separate fix. | 91 | +no `spring.cache.*` property in any `application*.yml`). With |
| 92 | +`spring-boot-starter-data-redis` present and no other cache provider | ||
| 93 | +on the classpath (no Caffeine, EhCache, Hazelcast, JCache; the | ||
| 94 | +`shiro-ehcache` jar in `xlyFlow` is for Shiro's own session cache, | ||
| 95 | +not Spring Cache), Spring Boot 2.2.5 auto-configures | ||
| 96 | +**`RedisCacheManager`**. | ||
| 97 | + | ||
| 98 | +**Empirically verified** against the live dev Redis at | ||
| 99 | +`118.178.19.35:16379` (database 0): 233 of 267 keys use Spring Cache's | ||
| 100 | +default `<cacheName>::<key>` separator. Sample key shape matching the | ||
| 101 | +`@Cacheable` SpEL spec from `BusinessGdsconfigformsServiceImpl.java:209-211`: | ||
| 102 | + | ||
| 103 | +``` | ||
| 104 | +businessGdsconfigformsServiceGetFormconstData::{sLanguage=sChinese, sModelsId=…, sSubsidiaryId=1111111111, sUserId=…, sBrandsId=1111111111} | ||
| 105 | +gdsmoduleById::gdsmoduleById_<sBrandsId>_<sSubsidiaryId>_<sLanguage> | ||
| 106 | +``` | ||
| 107 | + | ||
| 108 | +So `@CacheEvict` on any node clears the shared Redis store and the next | ||
| 109 | +read on every node sees the eviction. Cross-node coherence works | ||
| 110 | +through Redis, not through JMS. | ||
| 102 | 111 | ||
| 103 | ## When you change metadata directly via SQL | 112 | ## When you change metadata directly via SQL |
| 104 | 113 |
en/docs/reference/maintainer/management-services.md
0 → 100644
| 1 | +# Metadata-management services (`xlyManage`) | ||
| 2 | + | ||
| 3 | +The `xlyManage` module is the **service tier behind the BACK builder**. | ||
| 4 | +When a PM clicks 修改 / 新增 / 删除 in any of the 系统模块配置 / | ||
| 5 | +界面显示内容配置 / 数据表内容配置 / 系统权限配置 / 系统常量配置 / | ||
| 6 | +用户信息配置 / Mysql脚本配置 screens, the call lands on a | ||
| 7 | +`Gds*Controller` in `xlyEntry/.../web/systemweb/`, which then delegates | ||
| 8 | +to a `Gds*ServiceImpl` in `xlyManage/src/main/java/com/xly/service/systeminfo/impl/`. | ||
| 9 | + | ||
| 10 | +These services are the framework's **metadata-CRUD spine** — they own | ||
| 11 | +the read/write logic for every `gds*` table. The runtime | ||
| 12 | +([Slice 1](../../slices/01-hello-world.md), [runtime.md](runtime.md)) | ||
| 13 | +*reads* metadata; `xlyManage` *writes* it. | ||
| 14 | + | ||
| 15 | +## Services at a glance | ||
| 16 | + | ||
| 17 | +| Service | Lines | Owns | BACK page | | ||
| 18 | +|---|---:|---|---| | ||
| 19 | +| `GdsmoduleServiceImpl` | 729 | `gdsmodule` (modules), `gdsroute` (URL whitelist), module-tree CRUD, edition gating | 系统模块配置 | | ||
| 20 | +| `GdsconfigformServiceImpl` | 878 | `gdsconfigformmaster`, `gdsconfigformslave`, `gdsconfigformcustomslave`, `gdsconfigformpersonalize` (form definitions + per-tenant overlays) | 界面显示内容配置 | | ||
| 21 | +| `GdsconfigtbServiceImpl` | 555 | `gdsconfigtbmaster`, `gdsconfigtbslave` (virtual-table definitions) | 数据表内容配置 | | ||
| 22 | +| `SqlScriptsServiceImpl` | 489 | DDL / proc / view scripts authored in BACK; uses templates from [`templesql/`](sql-templates.md) | Mysql脚本配置 | | ||
| 23 | +| `GdsjurisdictionServiceImpl` | 362 | `gdsjurisdiction` (the action *catalogue* per module — see [permissions](../builder/permissions.md)) | (part of 系统权限配置 + builder flows) | | ||
| 24 | +| `GdsparameterServiceImpl` | 319 | `gdsparameter` (system-wide parameters) | (parameter screens) | | ||
| 25 | +| `GdsformconstServiceImpl` | 243 | `gdsformconst` (per-form constants — labels, default text). Slice 1 anchor table. | 系统常量配置 | | ||
| 26 | +| `GdslogininfoServiceImpl` | 221 | `sftlogininfo*` family (user / login / group catalogue) | 用户信息配置 | | ||
| 27 | +| `SysbrandsServiceImpl` | 125 | `sysbrands` (manufacturer / tenant master) | (tenant admin) | | ||
| 28 | +| `CommonServiceImpl` | 56 | shared helpers used across the rest | n/a | | ||
| 29 | + | ||
| 30 | +Total: ~4,000 lines of metadata-CRUD logic — a meaningful share of the | ||
| 31 | +framework runtime that this wiki had previously left undocumented. | ||
| 32 | + | ||
| 33 | +## Method-shape convention | ||
| 34 | + | ||
| 35 | +Every `Gds*Service` follows the same five-method shape: | ||
| 36 | + | ||
| 37 | +```java | ||
| 38 | +Feedback<Map<String,Object>> getXxx(Map<String, Object> params); // list / paged read | ||
| 39 | +Feedback<Map<String,Object>> getXxxBysId(Map<String, Object> params); // single-row read | ||
| 40 | +Feedback<Map<String,Object>> addXxx(Map<String, Object> params); // insert | ||
| 41 | +Feedback<Map<String,Object>> updateXxx(Map<String, Object> params); // update | ||
| 42 | +Feedback<Map<String,Object>> deleteXxx(Map<String, Object> params); // delete (often soft, via bInvalid) | ||
| 43 | +``` | ||
| 44 | + | ||
| 45 | +— mirrored exactly by the corresponding `Gds*Controller`'s endpoint | ||
| 46 | +methods. So the BACK admin surface is essentially a thin pass-through: | ||
| 47 | +controllers in `xlyEntry/.../systemweb/`, services in | ||
| 48 | +`xlyManage/.../systeminfo/impl/`. This is the inverse of the runtime | ||
| 49 | +side ([runtime.md](runtime.md)), where one universal | ||
| 50 | +`BusinessBaseController` handles every business-data CRUD against any | ||
| 51 | +table the metadata names — here, every framework-metadata CRUD has its | ||
| 52 | +own dedicated controller+service pair. | ||
| 53 | + | ||
| 54 | +## Notable specifics | ||
| 55 | + | ||
| 56 | +- **`GdsconfigformServiceImpl` is the largest** because it owns four | ||
| 57 | + closely-coupled tables (form-master, form-slave, customslave, | ||
| 58 | + personalize) plus the **DDL-script generation** flow. Methods like | ||
| 59 | + `getFormslaveScriptSqlPro` and `getMasterSlaveScriptSqlPro` produce | ||
| 60 | + SQL that an engineer can apply against the underlying physical | ||
| 61 | + tables when adding fields. This is what makes the | ||
| 62 | + customization-overlay model ([Slice 4](../../slices/04-custom-field.md)) | ||
| 63 | + end-to-end usable: the BACK builder can also generate the | ||
| 64 | + schema-migration SQL the overlay implies. | ||
| 65 | +- **`GdsmoduleServiceImpl` includes `getModuleTreePro`** — the | ||
| 66 | + per-edition / per-tenant module-tree resolution called by the SPA at | ||
| 67 | + login (the first `/gdsmodule/getModuleTreePro` request you see in | ||
| 68 | + the live trace). Edition gating | ||
| 69 | + ([Slice 2](../../slices/02-multi-tenancy.md)) happens here, as a | ||
| 70 | + filter on `gdsmodule.sVersionFlowId` against the user's | ||
| 71 | + `sisversionflow` row. | ||
| 72 | +- **`SqlScriptsServiceImpl`** glues the | ||
| 73 | + [`templesql/`](sql-templates.md) scaffolds into the BACK script | ||
| 74 | + authoring screen. Engineers fill in the placeholder spec; the | ||
| 75 | + service materialises a compilable proc/view body and runs it | ||
| 76 | + against the connected schema. | ||
| 77 | +- **`GdsjurisdictionServiceImpl` writes the action *catalogue***; | ||
| 78 | + `sysjurisdiction` (the per-user grant table) is written elsewhere | ||
| 79 | + (in `xlyBusinessService`'s permission-admin flow). See | ||
| 80 | + [How to set permissions](../builder/permissions.md) for the | ||
| 81 | + catalogue-vs-grant distinction. | ||
| 82 | +- **`SysbrandsServiceImpl`** writes the tenant master | ||
| 83 | + (`sysbrands` + `sBrandsId` rows); a fresh tenant onboarding flow | ||
| 84 | + is essentially a row insert here plus seed metadata. | ||
| 85 | + | ||
| 86 | +## Cache-invalidation hookpoints | ||
| 87 | + | ||
| 88 | +Every write through these services synchronously calls | ||
| 89 | +`BusinessCleanRedisData.delCleanRedisData*` on commit. This is why | ||
| 90 | +metadata edits in BACK take effect immediately on every node — the | ||
| 91 | +shared Redis cache (RedisCacheManager, see | ||
| 92 | +[cache-invalidation.md](cache-invalidation.md)) gets the relevant | ||
| 93 | +regions evicted in the same transaction the write commits. There is | ||
| 94 | +**no JMS fan-out here for cache-bust** — that's a common | ||
| 95 | +misconception, addressed in detail on the cache-invalidation page. | ||
| 96 | + | ||
| 97 | +## What's *not* in `xlyManage` | ||
| 98 | + | ||
| 99 | +- **Business-data CRUD.** That's the universal | ||
| 100 | + `BusinessBaseController` + `BusinessBaseServiceImpl` path | ||
| 101 | + ([runtime.md](runtime.md), [Slice 1](../../slices/01-hello-world.md)). | ||
| 102 | +- **API metadata** (`sysapi`). That's `xlyApi`'s own admin surface — | ||
| 103 | + see [external API](../../api-reference/external.md). | ||
| 104 | +- **Workflow metadata** (`gdsmoduleflow`, `act_*`, `biz_flow`). That's | ||
| 105 | + in `xlyFlow` — see [activiti.md](activiti.md). | ||
| 106 | + | ||
| 107 | +## Where to look first when something breaks | ||
| 108 | + | ||
| 109 | +| Symptom | First place to look | | ||
| 110 | +|---|---| | ||
| 111 | +| BACK 修改/新增 against `gdsconfigform*` returns "操作失败" | `GdsconfigformServiceImpl` — check field validation + the matching DDL-script generation path | | ||
| 112 | +| Edition gating shows wrong modules | `GdsmoduleServiceImpl.getModuleTreePro` — verify the user's `sVersionFlowId` resolution | | ||
| 113 | +| BACK script-authoring screen produces broken SQL | `SqlScriptsServiceImpl` + the [templesql scaffolds](sql-templates.md) | | ||
| 114 | +| Permission catalogue (BtnAdd / BtnUpd / …) missing for a module | `GdsjurisdictionServiceImpl` — check the rows under that `sParentId` | | ||
| 115 | +| User can log in to BACK but FROUNT is empty | `GdslogininfoServiceImpl` — check the `sftlogininfo*` link tables | |
en/docs/slices/04-custom-field.md
| @@ -53,10 +53,12 @@ implementer) does this without touching `gdsconfigformslave`. Instead: | @@ -53,10 +53,12 @@ implementer) does this without touching `gdsconfigformslave`. Instead: | ||
| 53 | The next time anyone in that tenant loads the form, they see the extra | 53 | The next time anyone in that tenant loads the form, they see the extra |
| 54 | column. Every other tenant continues to see the unmodified base form. | 54 | column. Every other tenant continues to see the unmodified base form. |
| 55 | 55 | ||
| 56 | -> **Caveat.** Whether `gdsconfigformcustomslave` is populated depends on | ||
| 57 | -> the deployment — the table is wired into the framework, but a deployment | ||
| 58 | -> with no tenant-level field overrides will see it empty. The trace below | ||
| 59 | -> is code-derived; observe a populated deployment to validate end-to-end. | 56 | +> **Confirmed against the dev DB:** `gdsconfigformcustomslave` is |
| 57 | +> currently **empty** in `xlyweberp_saas_ai` (0 rows). The table is | ||
| 58 | +> wired into the framework but no tenant on this dev DB has registered | ||
| 59 | +> any field-level override. The trace below is code-derived; the | ||
| 60 | +> end-to-end *observed* behaviour requires a tenant deployment that | ||
| 61 | +> actually populates the table. | ||
| 60 | 62 | ||
| 61 | ## How the runtime merges | 63 | ## How the runtime merges |
| 62 | 64 | ||
| @@ -157,3 +159,4 @@ forms never use. | @@ -157,3 +159,4 @@ forms never use. | ||
| 157 | itself? Likely the former, but worth confirming. | 159 | itself? Likely the former, but worth confirming. |
| 158 | 4. **A real example.** Find a tenant's actual `gdsconfigformcustomslave` | 160 | 4. **A real example.** Find a tenant's actual `gdsconfigformcustomslave` |
| 159 | rows in a populated deployment and use them as a worked example here. | 161 | rows in a populated deployment and use them as a worked example here. |
| 162 | + *(Dev DB confirmed empty — needs a tenant deployment with overlays.)* |
en/docs/slices/05-customer-sql-override.md
| @@ -106,24 +106,42 @@ The right rule of thumb: prefer Slice-4 metadata customization. Reach | @@ -106,24 +106,42 @@ The right rule of thumb: prefer Slice-4 metadata customization. Reach | ||
| 106 | for Slice-5 SQL overrides only when the metadata model genuinely cannot | 106 | for Slice-5 SQL overrides only when the metadata model genuinely cannot |
| 107 | express what the customer needs. | 107 | express what the customer needs. |
| 108 | 108 | ||
| 109 | -## Worked-example: what 重庆展印's `Sp_SalSalesCheck` does differently | ||
| 110 | - | ||
| 111 | -Skim of the file's top: | ||
| 112 | - | ||
| 113 | -- It reads a `'CbxSrcNoCheck'` row from `SysSystemSettings` to determine | ||
| 114 | - which billing types feed the sales-check report. This is a customer- | ||
| 115 | - specific switch the standard proc may not expose. | ||
| 116 | -- It calls the global `Fun_GetLookCustomer(sLoginId, sBrId, sSuId)` | ||
| 117 | - helper for permission scoping — same as the standard proc would. | ||
| 118 | -- It accepts the same parameter list as the standard | ||
| 119 | - (`sLoginId`/`sCustomerId`/`sBrId`/`sSuId`/`bFilter`/`pageNum`/`pageSize`/…) | ||
| 120 | - so the framework's call-site is unchanged. | ||
| 121 | - | ||
| 122 | -A future revision of this slice can do a side-by-side diff with the | ||
| 123 | -standard `Sp_SalSalesCheck` and explain *exactly* the business rule | ||
| 124 | -that diverges. For now, the structural fact is what matters: the proc | ||
| 125 | -shape and parameter list are identical to the standard; the body | ||
| 126 | -diverges. | 109 | +## Worked-example: 重庆展印's `Sp_SalSalesCheck` vs the standard |
| 110 | + | ||
| 111 | +Quantified diff against the live dev DB: | ||
| 112 | + | ||
| 113 | +| Aspect | Standard `Sp_SalSalesCheck` (in DB) | 重庆展印 override (`script/客户/重庆展印/Sp_SalSalesCheck.sql`) | | ||
| 114 | +|---|---|---| | ||
| 115 | +| Body length | 1,714 lines | 723 lines (≈42 % the size) | | ||
| 116 | +| Parameter signature | 14 params: `sLoginId, sCustomerId, sBrId, sSuId, bFilter, sUnTaskFormId, pageNum, pageSize, totalCount(OUT), countCloumn, countMapJson(OUT), sFilterOrderBy, sGroupby_select_sql, sGroupby_group_sql` | **Identical** — same 14 params in the same order | | ||
| 117 | +| `SysSystemSettings.CbxSrcNoCheck` lookup | **Not used** | **Used** (drives "未对账印件清单来源" — which billing-type sources feed the report) | | ||
| 118 | +| `Fun_GetLookCustomer(sLoginId, sBrId, sSuId)` permission scoping | Used | Used (same call) | | ||
| 119 | +| Temp-table-based aggregation flow (`B1`, `B2` etc., several `DROP TEMPORARY TABLE` + `INSERT INTO` blocks) | Heavy (the bulk of the 1,714 lines) | Removed / simplified | | ||
| 120 | + | ||
| 121 | +So 重庆展印's override: | ||
| 122 | +- Keeps the framework call-site unchanged (identical parameter | ||
| 123 | + signature so the metadata-driven dispatcher | ||
| 124 | + ([proc-dispatch.md](../reference/maintainer/proc-dispatch.md)) still | ||
| 125 | + invokes it correctly). | ||
| 126 | +- Adds a `CbxSrcNoCheck` system-setting branch that the standard | ||
| 127 | + doesn't expose. Twelve other `Sp_*` procs in the schema also use | ||
| 128 | + `CbxSrcNoCheck` (`Sp_Manufacture_MftWorkOrderAround`, | ||
| 129 | + `Sp_OverdueNoCheck`, `Sp_Receivables_*` family, plus sibling | ||
| 130 | + `Sp_SalSalesCheck1`/`_1227`/`_YanBao`/`_ded_copy1`); the override | ||
| 131 | + brings that pattern into the customer's main proc. | ||
| 132 | +- Strips the standard's heavy temp-table aggregation flow — a simpler | ||
| 133 | + query path, not a more complex one. The customer's check semantics | ||
| 134 | + evidently don't need the full standard aggregation. | ||
| 135 | + | ||
| 136 | +A maintainer wanting the *exact* business-rule difference should diff | ||
| 137 | +the two file bodies directly: | ||
| 138 | + | ||
| 139 | +```bash | ||
| 140 | +mysql --defaults-file=$HOME/.my.cnf xlyweberp_saas_ai \ | ||
| 141 | + -BNe "SELECT ROUTINE_DEFINITION FROM information_schema.routines \ | ||
| 142 | + WHERE ROUTINE_NAME='Sp_SalSalesCheck'" > /tmp/std.sql | ||
| 143 | +diff /tmp/std.sql script/客户/重庆展印/Sp_SalSalesCheck.sql | head -200 | ||
| 144 | +``` | ||
| 127 | 145 | ||
| 128 | The companion view `viw_salsaleschecking_pro.sql` exists for the same | 146 | The companion view `viw_salsaleschecking_pro.sql` exists for the same |
| 129 | reason — when the override needs a join shape the standard doesn't | 147 | reason — when the override needs a join shape the standard doesn't |
en/mkdocs.yml
| @@ -108,6 +108,7 @@ nav: | @@ -108,6 +108,7 @@ nav: | ||
| 108 | - "Cache invalidation on metadata change": reference/maintainer/cache-invalidation.md | 108 | - "Cache invalidation on metadata change": reference/maintainer/cache-invalidation.md |
| 109 | - "SQL templates (xlyEntry/templesql/)": reference/maintainer/sql-templates.md | 109 | - "SQL templates (xlyEntry/templesql/)": reference/maintainer/sql-templates.md |
| 110 | - "Multi-service deployment": reference/maintainer/deployment.md | 110 | - "Multi-service deployment": reference/maintainer/deployment.md |
| 111 | + - "Metadata-management services (xlyManage)": reference/maintainer/management-services.md | ||
| 111 | - "Activiti integration": reference/maintainer/activiti.md | 112 | - "Activiti integration": reference/maintainer/activiti.md |
| 112 | - 5. API Reference: | 113 | - 5. API Reference: |
| 113 | - api-reference/index.md | 114 | - api-reference/index.md |