Kingdee Cloud Auxiliary Data Query Strategy: A Robust Single-Point Pull with Middle-Layer Landing Pattern
What This Strategy Solves (Scenario & Value)
In one retail engagement, the sales team kept hitting a wall: dropdowns like "industry type," "customer source," and "region" on new orders had to be cross-checked manually against the authoritative list living in Kingdee Cloud. After three months, the two dictionaries had drifted apart. We used the Qeasy data integration platform to own a small but critical strategy — Query Kingdee Auxiliary Data — that periodically pulls those dictionary records into the middle layer so every downstream write strategy consults the same source of truth. This strategy doesn't write business documents directly, but it determines whether the other nine sync strategies stay stable.
Data Flow & Field Mapping
The flow follows the classic Source → Middle Layer → Target pattern, except the "target" here is a no-op writeback whose job is to anchor the pulled data in the middle layer so other strategies can subscribe to it.
The source (Kingdee Cloud) exposes a WebAPI called executeBillQuery, and FNumber acts as the primary key for identification. The middle layer is the staging area inside Qeasy itself, where each field lands according to its declared metadata type. The target is configured as a "Write Empty Operation" — a POST with an empty body — whose purpose is to complete the standard pull-anchor-subscribe loop.
Key field mapping:
| Business Meaning | Source Field (Kingdee.Cloud) | Type | Middle-Layer Field | Notes |
|---|---|---|---|---|
| Code | FNumber | string | FNumber | Primary key, idempotency anchor |
| Name | FDataValue | string | FDataValue | Display label |
| Description | FDescription | string | FDescription | Nullable |
| Category | FId.FNumber | string | FId_FNumber | Composite field, child code only |
| Display Order | FSeq | string | FSeq | Frontend ordering |
Note that the source's dotted composite field FId.FNumber is flattened in the middle layer to FId_FNumber — a very common shape in Kingdee WebAPI responses.
How to Configure It in Qeasy
Open the strategy configuration page in Qeasy and create a new "Query" type strategy. Three points matter:
- Source platform: Pick Kingdee Cloud (Kingdee.Cloud). Select the
executeBillQueryAPI, method = POST, effect =QUERY. Make sureautoFillResponse: trueis set so the platform auto-maps response fields into the middle-layer schema — this saves manual table building. - Target platform: Pick Qeasy itself (datahub). Select the "Write Empty Operation" API; leave both request and response arrays empty. Set
idCheckto true so repeated pulls deduplicate by primary key and never bloat the dictionary. - Metadata declaration: Enter the full field table above. Set
is_requiredto false everywhere — auxiliary fields are generally nullable; missing this flag makes later troubleshooting painful.
One more detail: keep buildModel as false. Don't let the platform auto-model — the auxiliary data structure is owned by Kingdee; we just faithfully transport it.
Implementation Steps
We split this rollout into three phases; on the customer site the cadence ran roughly like this:
Step 1: Align the incremental starting point. Before going live, run one full pull as the baseline so every auxiliary record from Kingdee lands in the middle layer at once. Trigger it manually; no need to put it on a schedule.
Step 2: Set the schedule. Source crontab is 34 3 * * * (03:34 AM); target empty-write is 23 2 * * * (02:23 AM). The two windows are deliberately offset so the "target no-op write" completes before the "source pull" fires again — this is one of the common patterns we see among Qeasy customers: the "header / body staged" idea, repurposed here so the anchor action and the pull action live in separate time windows and never collide.
Step 3: Dependencies and observability. This strategy has no dependencies (depends_on: []), but every downstream strategy implicitly depends on it. Hang a run dashboard inside Qeasy and glance at it daily to confirm the target empty-write is succeeding — once it fails, the nine downstream strategies will be working with a stale dictionary.
Lessons from the Field
Lesson 1: Composite fields not flattened. On the first run, FId.FNumber landed in the middle layer verbatim; downstream strategies queried FId_FNumber and got all nulls. The safe move is to declare the flattened name in metadata up front — don't wait for downstream errors to remind you.
Lesson 2: idCheck left off. Once, Kingdee returned a dirty record with a duplicate code; without primary-key validation, the middle layer ended up with two rows and downstream joins picked one at random — a classic failure mode.
Lesson 3: Mixing autoFillResponse with a hand-written schema. In an earlier version we both ticked auto-fill and hand-edited fields, and the two drifted apart — runs reported success but every field was empty. Pick one: either fully automatic, or fully manual.
Lesson 4: Schedules colliding. When source and target trigger at the same moment, concurrent writes occasionally surface half-read dirty data in the middle layer. Offsetting by more than one hour reliably avoids this — an extension of the "incremental + full dual-track" pattern we commonly see among Qeasy customers.
Lesson 5: Misreading "empty write" as "skip." The empty write is actually a full transaction boundary; Qeasy uses it to fire subscription notifications and wake downstream strategies. If you misconfigure it as "skip," downstream never learns that the dictionary refreshed.
When It Fits and When It Doesn't
Fits: When master-data dictionaries need a single source of truth, when multiple downstream write strategies must reference the same lookup, or when source fields contain composites that must be flattened before distribution.
Doesn't fit: When the auxiliary data changes minute-by-minute (use a real-time event trigger instead), when the source system has no stable WebAPI query interface, or when the dictionary is so small that a dedicated strategy isn't worth it.