Two customization channels
xly customers customize the system through two distinct paths. Understanding the difference is essential — they have different powers, different costs, and different operational consequences.
Channel 1 — Metadata edits via BACK
The supported, PM-driven path. A customer's implementer (or the customer themselves) opens the BACK builder, navigates to a module, and inserts / updates / deletes rows in metadata tables:
-
gdsmoduleto register a new module -
gdsconfigformmaster+gdsconfigformslaveto define a form -
gdsconfigformcustomslaveto add a per-tenant field overlay (Slice 4) -
gdsconfigformpersonalizeto override a form's SQL/where/order per tenant -
gdsjurisdictionto grant or restrict permissions -
gdsroute,gdsformconst,sysbillnosettings, … as needed
These edits are data. They travel with the customer's database. They are visible in the BACK UI so a PM can audit them. The framework's runtime reads them on every request (with caching). The Java code is unchanged; the application's behaviour is what those rows say it is.
This is the default path. 90%+ of customer customizations should live here.
Channel 2 — Per-customer SQL overrides
The escape hatch. When metadata cannot express what a customer needs —
typically because the customer needs different procedural logic, not
just different fields or labels — engineers commit a hand-written SQL
file to script/客户/<customer>/<file>.sql in the codebase. The file
typically contains a DROP PROCEDURE … CREATE PROCEDURE pair (or a
DROP VIEW … CREATE VIEW for view replacements).
The file is then manually applied to the target customer's MySQL schema by a DBA or engineer. From that moment, that customer's database has a literally-different stored procedure with the same name as the standard.
Documented in detail in Slice 5.
This channel is real and used in production — eighteen customers have override directories in the codebase today. It is also significantly more expensive to maintain than Channel 1.
How to choose
Use Channel 1 when:
- The customization is structural (new field, new module, different label).
- The behaviour can be expressed by changing SQL fragments
(
sSqlStr/sWhere/sOrder). - The customization should be visible in BACK and editable by a PM.
- You want it to travel with the database backup.
Use Channel 2 when:
- The customer needs procedural logic the framework's Add/Update/Calc procs don't express.
- You need to replace a stored procedure body, not just inject SQL fragments around it.
- A maintainer reviewing the customer's runtime would benefit from seeing the difference in source-controlled SQL files.
Channel 2 is almost always a last resort. Reach for it only after confirming Channel 1 cannot do the job.
Cost comparison
| Property | Channel 1 (metadata) | Channel 2 (SQL override) |
|---|---|---|
| Travels with DB backup | yes | only if the customer's schema is the backup target |
| Visible in BACK | yes | no |
| Editable by a PM | yes | no — engineer-only |
| Cross-tenant impact | none — rows are scoped by sBrandsId
|
none — applied per-customer schema |
| Re-applies after schema rebuild | yes (rows in DB) | no — must be manually re-run |
| Auditable from a single source | yes (DB rows + their sMakePerson) |
partial — file is in repo but the apply step has no log |
| Discovery by reading codebase | requires connecting to DB | yes — file lives in script/客户/
|
What this means for slice readers
When a slice describes "the standard behaviour", it means the behaviour seen by a tenant whose customizations are entirely in Channel 1. A customer with Channel 2 overrides may experience different runtime behaviour for the procs that have been replaced — the framework's controller code can't tell the difference. Reasoning about runtime behaviour for such customers requires looking at the deployed schema, not just the codebase.