Salesperson Master Sync in Practice: A Deep Dive into the Single Strategy of Querying Kingdee Cloud Sky and Writing to Qeasy
What This Strategy Solves
Salesperson master records are the human-side primary key for orders, shipments, and collections. Once the codes drift, every downstream document goes wrong. In one real project, a retail enterprise treats Kingdee Cloud Sky as the ERP master data source and XiaoMan OKKI CRM as the front-end sales tool. Salesperson records are maintained only in Kingdee and must be pulled into a middle layer every day for the CRM and BI to consume. This strategy only pulls salesperson data out of Kingdee and does not persist it on Qeasy. It is a typical QUERY_ONLY shape.
Data Flow and Field Mapping
The flow is one-way: Kingdee Cloud Sky → Qeasy Data Integration Platform (middle layer), and the platform then dispatches the data to subscribers. The source side calls executeBillQuery (POST) to query salesperson documents. The target side is a Write No-Op (WebAPI, POST), with FNumber as the number field, FEntity_FEntryId as the ID field, idCheck off, and autoFillResponse on.
Key field mapping (source → middle layer semantics):
| Source Field | Meaning | Type |
|---|---|---|
| FNumber | Salesperson code | string |
| FName | Salesperson name | string |
| FOperatorId | Operator ID | string |
| FOperatorType | Salesperson type | string |
| FBillNo | Document number | string |
| FDescription | Description | string |
| FCreateDate | Creation date | string |
| FModifyDate | Last modified date | string |
Note that the target Write No-Op does not really persist data. It just gives the strategy a landing point, and the real persistence is done by downstream subscriber strategies. This is exactly the "staged header/body processing" pattern at the platform level.
How to Configure on Qeasy
On the Qeasy data integration platform, the configuration is intentionally lightweight:
- Source side: choose the Kingdee Cloud Sky connector, pick
executeBillQueryas the API, and select all fields above as return values in the request body. - Target side: choose the built-in
Write No-Opadapter, which acts as a placeholder that drives the schedule forward. - Schedule:
crontabis set to25 3 * * *, running at 03:25 a.m. to avoid peak business hours in the source system. - Dependencies:
depends_onis empty. It runs as an independent "base data collection" strategy and does not block other jobs. - Response:
autoFillResponse=true. The platform automatically maps source fields into the standard response, avoiding manual assembly.
We recommend that code mappings be centralized in the platform's Mapping Center. Enum values of FOperatorType, such as "Internal Sales", "Part-Time", and "Agent", should be maintained in one place and reused by every downstream strategy. This is the classic "centralized code mapping" pattern we often use at customer sites.
Implementation Steps
We suggest a three-stage rollout, which is much safer:
Stage 1: full trigger, baseline check. Before going live, disable the schedule and trigger it manually once to pull all salesperson records from Kingdee into the middle layer. Compare them row by row against a manual ledger exported from Kingdee reports, and confirm that FNumber matches one-to-one. The focus here is "the counts match and the names match".
Stage 2: enable the incremental start point. Use the maximum FModifyDate from the first full pull as the incremental start point. Add FModifyDate >= last successful time to the filter condition of executeBillQuery, so that from then on only the salespeople who changed that day are pulled at 03:25 a.m. Keep idCheck off to avoid batch failures caused by tiny historical differences.
Stage 3: schedule frequency and alerting. Fix the cron at 03:25 a.m. to avoid clashing with the source system's nightly batch and backup windows. Configure two retries with a 5-minute interval on Qeasy, and route alerts for "row count below threshold" and "API timeout" into the alerting channel. Once the flow is stable, let the downstream CRM and BI subscribe to the middle layer's results, completing a stable "incremental plus full" dual-track operation.
Pitfalls and Lessons Learned
-
A typical mistake is treating QUERY_ONLY as a "real sync". Many engineers see
Write No-Opon the target side and panic, thinking the configuration is wrong. This is a common trap. The safe way is to understand that it is a placeholder adapter specifically reserved on the platform for "collect only, do not persist" strategies, while real downstream persistence is handled by other strategies. -
FModifyDatetime zone and format. The modification timestamp returned by Kingdee does not carry a time zone. If the middle layer does not explicitly parse it using the source system's time zone, you will see weird phenomena such as "no data today" or "duplicate pulls". We have been bitten by this. The safe way is to add explicit time-zone conversion in the source filter. -
Be careful with the
idCheckswitch. Once it is turned on, the middle layer de-duplicates byFEntity_FEntryId. If the source side has ID drift (a common issue after historical Kingdee data migration), the whole batch will be discarded as conflicts. Leaving it off by default is safer; turn it on in batches after the data has stabilized. -
Do not let cron collide with source-side backup. The salesperson master is small in volume, but Kingdee runs index rebuilds and pre-closing jobs at night. Putting cron in the same window often leads to timeouts. We finally settled on 03:25, which is the quietest window on the source side.
-
Salesperson type enums scattered across strategies. The first time around we did not centralize the mapping, so the CRM showed "Internal Sales" as "Type A" while BI showed it as "Internal", and the reports no longer matched. We later moved all enums into the platform's Mapping Center and fixed the issue once and for all.
Applicable and Non-applicable Scenarios
Applicable: Kingdee Cloud Sky is the ERP master data source and you need to extract salesperson records (or other lightweight master data) into a middle layer on a schedule so that multiple downstream systems can subscribe, with a daily-level freshness requirement.
Not applicable: scenarios that require second-level real-time salesperson change push, strong historical ID validation, or direct persistence in the middle layer with external query services. Those should use a separate write-oriented strategy rather than a QUERY_ONLY placeholder.