Sales Order Sync in Practice: JKY to Kingdee Cloud Integration Strategy
What This Strategy Solves
A retail client running multi-channel operations was using JKY as the front-end order system and Kingdee Cloud as the back-end finance and inventory backbone. Several hundred to a few thousand shipped sales orders had to flow from JKY into Kingdee every day. Manual reconciliation caused inventory drift within three days, and direct database extraction failed in bulk whenever customer or organization codes did not align. The approach we used was to put the Qeasy data integration platform in the middle: incremental pulls by consign-time window, code mapping in the middle layer, and batch writes into Kingdee Cloud sales- delivery orders.
Data Flow and Field Mapping (Source → Middle → Target)
The overall pipeline is JKY (QM) → Qeasy middle layer → Kingdee Cloud. The source pulls orders through jackyun.tradenotsensitiveinfos.list.get, and the target writes them via batchSave. The middle layer focuses on code translation and time-window control.
| Business Meaning | JKY Source Field | Middle Layer | Kingdee Target Field | Notes |
|---|---|---|---|---|
| Document Number | tradeNo | Pass-through, used as idempotency key | FBillNo / FJKYNo | FJKYNo for reverse lookup |
| Consign Date | consignTime | Extract date portion | FDate | Key filter field |
| Shop Code | shopCode | _mongoQuery lookup | FSaleOrgId / FCustomerID | One shop → one org + one customer |
| Warehouse Code | warehouseCode | Centralized code mapping | FStockOrgId / FStockID | Warehouse → org + stock |
| SKU | goodsDetail.goodsNo | Shared mapping with item sync | FMaterialID / FNumber | Depends on prior item sync |
| Quantity | goodsDetail.sellCount | Pass-through | FQty | Mind unit conversion |
| Price / Allocated Fee | goodsDetail.shareFavourableFee | Optional, write to price list | FPrice / FAmount | Usually write qty only |
The key point is that the document header and body are assembled in two phases. A common Qeasy customer pattern is to resolve header-side organization and customer first, then fill line items with material codes and quantities, so dirty data never reaches Kingdee.
How to Configure in Qeasy
- Register both connectors: JKY-QM on the source side, Kingdee Cloud on the target side. Route credentials through the private gateway and store them in the platform credential vault rather than embedding tokens in the strategy.
- Configure source metadata: Use API
jackyun.tradenotsensitiveinfos.list.get, setpageSize=200, and trim thefieldslist to only what is needed. GeneratestartConsignTime/endConsignTimedynamically with_function, defaulting to "yesterday 00:00 to today 00:00" on a rolling basis. - Configure target metadata: Use API
batchSave, document typeXSCKD01_SYS(sales delivery), withFBillNoas the uniqueness check andidCheckenabled. - Centralize code mapping: All shop→sales org/customer, warehouse→inventory org, and SKU→material mappings should live in a single mapping table in Qeasy. Source fields resolve via
_mongoQuery. Do not duplicate mapping logic across strategies. - Configure the write strategy: Set
buildModel=falseso the source payload drives the target structure. LeaveautoFillResponse=falseso failed writes land in an error queue for re-processing.
Implementation Steps
We split this strategy into three scheduling phases, running incremental and full loads on parallel tracks:
- Phase 1: Incremental start. On go-live day, run a full load to backfill historical shipped orders using absolute date windows rather than relative functions. After the first pass, switch to incremental.
- Phase 2: Full load trigger. Run a full load only in two cases: initial go-live, or after source-side organization adjustments or mapping changes. Avoid full loads during normal operations because they tend to cause document number collisions in Kingdee.
- Phase 3: Scheduling cadence. Incremental should run once daily in the early hours, covering the "previous full day" window. For high-volume scenarios, an hourly run with a "previous 1 hour" window also works. The
crontabin the source material reads1 1 1 1 1(Jan 1 every year), which is intended for the annual full-load fallback; set a separate cron for the daily incremental.
Lessons from the Field
- Wrong field chosen for the time window. A typical mistake is using
gmtCreate(creation time) instead ofconsignTime, which causes orders that are audited early but shipped late to be missed. The safe approach is to useconsignTimestrictly and normalize the time zone to UTC+8 in the source_function. - Mapping scattered across strategies. A common error is each sales strategy maintaining its own shop→organization mapping. When a new shop opens, only some strategies get updated, and Kingdee starts reporting errors. Centralized mapping management is the most common Qeasy customer pattern: change once, and every downstream strategy picks it up.
- Header and line items written in a single batch. Header-side organization and customer resolution depends on the shop mapping. If that is submitted together with line-item material codes, and one material is not yet activated in Kingdee, the whole batch rolls back. A safer approach is to submit header and body in separate phases.
- Unit conversion overlooked. JKY's
unitmay be "box", while Kingdee's base unit is "piece". The middle layer must perform unit conversion or quantities will diverge. - Idempotency key uses tradeNo alone. The safer pattern is
FBillNo = tradeNo + channel tagto prevent collisions across channels.
When to Use and When Not to
Use when: Multi-channel retail or distribution in a hybrid architecture where JKY handles front-end transactions and Kingdee Cloud handles back-end accounting, with daily volumes from hundreds to tens of thousands of shipments and a need to sync by consign-time window rather than creation-time window. Do not use when: Real-time requirements down to the minute (use message push or change streams instead), return and exchange orders (which need a separate strategy), or when JKY and Kingdee organizations are 1:1 mirrored with no mapping needed (direct database ETL is more cost-effective).