Other Goods Receipt Sync Strategy: Jky to Kingdee Cloud
What This Strategy Solves
A retail client's warehouse generates a steady stream of "other goods receipt" documents every day — stocktake surpluses, promotional gifts, status conversions, and similar edge cases. These originate in Jky but must land in Kingdee Cloud as the official record for inventory and accounting. On the surface it looks like moving one document; in practice it involves code mapping, organization resolution, date formats, and paged incremental reads. When mapping rules are scattered across ad-hoc code, the two sides drift apart within three to six months. We used the Qeasy data integration platform to handle this end-to-end, turning the sync into an observable, replayable, and auditable strategy.
Data Flow and Field Mapping
The end-to-end flow is Jky (A) → Qeasy middleware → Kingdee Cloud (B). The source side paginates qualifying receipt documents; the target side writes them into Kingdee's goods receipt model.
Key field mapping (extracted from the strategy metadata):
| Business Meaning | Source Field (Jky) | Target Field (Kingdee Cloud) | Handling |
|---|---|---|---|
| Receipt number | goodsdocNo | FBillNo | Passed through, used as idempotency key |
| Document type | inouttype | FBillTypeID | Constant: QTRKD01_SYS |
| Stock direction | Business context | FStockDirect | Constant: GENERAL |
| Receipt date | inOutDate | FDate | Unix timestamp → YYYY-MM-DD HH:MM:SS |
| Warehouse code | warehouseCode | FStockOrgId | Resolved via _findCollection lookup |
| Department | Business context | FDEPTID | Same lookup pattern as warehouse |
The source uses {{DAYS_AGO_2|datetime}} for startDate and {{CURRENT_TIME|datetime}} for endDate — a classic sliding-window incremental approach rather than relying on a modification timestamp.
How to Configure It on Qeasy
When configuring this strategy, we focus on three things.
First, source API configuration. Register erp.storage.goodsdocin in the Qeasy data integration platform with method POST, fixed pagination parameters pageIndex/pageSize of 0 and 50, goodsdocNo as the idempotency key, and template variables auto-injected for the time window.
Second, target write model. Call Kingdee's batchSave, with FBillTypeID fixed at QTRKD01_SYS and FStockDirect at GENERAL. The date field uses the built-in function _function FROM_UNIXTIME(({{inOutDate}}/1000),'%Y-%m-%d %T') to convert the millisecond timestamp into a string Kingdee accepts.
Third, centralized mapping management. For code-mapping rules, we recommend maintaining them in Qeasy's mapping table rather than scattering them into each field's value. When a warehouse or department is added later, only one place needs updating — a common pattern among Qeasy customers.
Implementation Steps
- Define the source starting point: during initial rollout, perform a one-off backfill by setting
startDateto the business go-live date andendDateto the current time, to pull historical documents in a single pass. - Switch to incremental mode: once backfill is complete, the scheduler runs at
*/25 * * * *(source query) and*/30 * * * *(target write), with the source ahead by one cycle so the target never waits on an empty payload. - Reconciliation check: deduplicate
FBillNoin Kingdee againstgoodsdocNoin Jky; trigger manual investigation when the delta exceeds the threshold. - Post-launch observation: monitor success rate, latency, and replay rate for about a week, then codify the dirty-data rules.
At customer sites we usually recommend a phased rollout — header first, line items second — so the document head stabilizes before the body items start flowing, avoiding large bursts of dirty data on day one.
Pitfalls and Lessons Learned
- Window only watches create time. Some Jky documents are edited after creation; filtering by
createTimealone misses updates. We later added a secondary filter on the source side. _findCollectionperformance. Both warehouse and department rely on lookups, which get slow at scale. The safer approach is caching resolved mappings in Qeasy's KV store and refreshing periodically.- Idempotency key overwritten. If someone manually edits
FBillNoon the Kingdee side, the next sync treats it as a new document. The fix is to write Jky'srecIdas a hidden idempotency field together with the visible key. - Pagination edges. The last page may contain fewer than 50 rows; some APIs also duplicate boundary rows, so the source must deduplicate by
recId. - Private-deployment time zone. The server's time zone is not always UTC+8 in private deployments, and
FROM_UNIXTIMEwithout an explicit zone can produce "yesterday or tomorrow" timestamps — always specify it.
When It Fits and When It Doesn't
Fit: multi-organization retail or distribution scenarios with moderate document volume that need near-real-time inventory and accounting sync. Don't fit: ultra-high-volume cases, deeply customized document fields, or strict real-time (sub-second) requirements — the latter should use message-queue direct push instead of polling.