Incremental Warehouse Master Data Sync from Kingdee to MES: An Audit-Date-Driven Update Strategy
What This Strategy Solves
In a manufacturing enterprise, warehouse master data is owned by Kingdee Cloud while the MES shop floor needs the same authoritative list. Whenever a warehouse is renamed, renumbered, or reassigned to a different org, MES must reflect the change—otherwise receiving, shipping, inventory counts, and transfers all break. This strategy is not about initial load; it is an update-by-key path that pulls Kingdee records modified since the last sync and idempotently updates the matching MES rows.
Data Flow and Field Mapping
Flow: Kingdee Cloud (source, executeBillQuery / BD_STOCK) → Qeasy integration platform (middleware: filter, map, schedule) → MES (target, /api/updateWarehouse).
The middleware is responsible for applying the FAuditDate filter, populating target fields from source fields, and passing FStockId through as the lookup key.
Key Field Mapping
| Target field (MES) | Source field (Kingdee) | Map type | Notes |
|---|---|---|---|
| warehouseUuid | FStockId | DIRECT | Kingdee warehouse primary key; used for update-by-key and cross-system identity |
| warehouseCode | FNumber | DIRECT | Warehouse code, passed through |
| warehouseName | FName | DIRECT | Warehouse name, passed through |
| companyCode | Fixed constant | CONSTANT | MES tenant / org identifier, sample value fdd8dc88 (use the actual tenant value) |
Source fields FGroup (warehouse group), FUseOrgId (using org), and FIsOpenLocation (location-enabled flag) have no counterpart on the current MES interface and are therefore not mapped—they are extension points, not part of this strategy.
How to Configure It on Qeasy
We build the pipeline on Qeasy around a three-segment pattern: source QUERY → middleware → target EXECUTE.
Source configuration
- Data source: Kingdee Cloud. API:
executeBillQuery. Business object:BD_STOCK. Method: POST. - Declare
FStockId / FNumber / FName / FGroup / FUseOrgId / FIsOpenLocationas return fields. Even if you don't map them today, fetching them now means future extensions don't require changing the source. - Incremental filter:
FAuditDate>='{{LAST_SYNC_TIME|dateTime}}'. Qeasy automatically injects the last successful sync timestamp. - Set
idChecktofalse—we don't dedupe on the source side; the middleware handles it.
Target configuration
- Data source: MES. API:
/api/updateWarehouse. Method: POST. - Set
idCheckto true. This is the heart of update-by-key behavior: MES locates the existing row bywarehouseUuidand UPDATEs rather than INSERTs, which gives natural idempotency. request[0].valueis a constant (company code); the remaining three fields use{{source field}}interpolation.numberandidare both0because the lookup key lives in the body, not the URL.
Scheduling and triggers
crontabis* 7-22 * * *, covering the daytime operation window and leaving nights for full reconciliation or maintenance.- In the strategy detail page on Qeasy, enable the "last sync time" option—the platform persists
LAST_SYNC_TIMEautomatically, so resume-after-failure needs no manual intervention.
Implementation Steps
We split the rollout into three phases—it's the rhythm we use most often in customer projects because it's the safest.
Step 1: Set the incremental starting point. Before go-live, confirm with the customer what timestamp to use as the baseline—usually the last manual sync timestamp, or midnight of the go-live date. Seed this as the initial LAST_SYNC_TIME in the Qeasy config; the platform rolls it forward automatically thereafter.
Step 2: Trigger a full backfill. On the first run, do not apply the time filter—or use the platform's "backfill" feature to force a historical pull. The goal is to make sure every existing MES warehouse has already been created upstream; only then does "update" mode make sense. Skip this step and the first update calls will hit 404 or empty rows.
Step 3: Switch to incremental scheduling. Trigger hourly between 07:00 and 22:00. Each run pulls only warehouses whose FAuditDate is greater than or equal to the last sync time. Heads up: FAuditDate is not the modification date. We've been bitten by this on customer sites—someone edits a master record in Kingdee but forgets to audit it, and the change never arrives. Negotiate a "edit-then-audit-same-day" rule with the business team.
Phased rollout pattern (common at customer sites): first stand up header-level master data on the hourly cadence, get alerting in place, stabilize the pipeline; only later add body-level entities (e.g., locations, bins) as separate strategies. This is the header-then-body phased approach.
Pitfalls We Have Hit
-
Incremental starting point misconfigured, three months later numbers no longer reconcile. Classic mistake: forgetting to enable the "last sync time" option, so the platform falls back to pulling from the earliest record. Fix: seed
LAST_SYNC_TIMEmanually before go-live, and add a monitor that alerts when a single run pulls an unusually high volume. -
Confusing audit date with modification date. A record edited in Kingdee but not audited does not move
FAuditDateand therefore never gets pushed. We eventually required business owners to audit same-day whenever they change warehouse info. -
idCheckleft atfalseon the target. The most damaging misconfiguration—the platform then treats each call as INSERT, so every Kingdee change duplicates the MES row. Within weeks the data doubles. For warehouse update scenarios,idCheckmust betrue. -
Treating unmapped fields as non-existent.
FGroupandFIsOpenLocationaren't mapped today, but six months later the customer will ask for them. Always pull all source fields upfront, even ones you don't map yet—future expansion then requires no source-side change, only a new mapping rule in the middleware. -
Reusing the
companyCodeconstant in multi-org scenarios. A fixed constant only works for single-org deployments. As soon as multi-org is in play, switchcompanyCodeto a COLLECTION lookup or a TRANSFORM expression based onFUseOrgId.FNumber—do not copy-paste the constant.
When to Use and When Not to Use
Use when: Kingdee and MES belong to the same org, warehouse codes are stable, change volume is low (single to dozens per day), and a separate create strategy already exists for backfill.
Don't use when: this is the first load (use the create strategy instead), the deployment is multi-tenant / multi-org (the constant breaks), or you need to sync warehouse groups or location-level details (this strategy does not cover body data—build a separate one).