Sync Purchase Orders from LingXing ERP to Kingdee Cloud: A Single-Strategy Hands-On Guide
What This Strategy Solves
In the supply chain of a cross-border retail business, buyers create purchase orders in LingXing ERP, while finance and cost accounting run on Kingdee Cloud. Without integration, the two sides drift apart: goods-in-transit and accrual accounts simply do not match.
The goal is to pull purchase orders from LingXing incrementally by creation time and write them into Kingdee Cloud's purchase order module — automatically and re-runnably. The strategy looks like a simple document move, but it depends on two foundation-data strategies (product and supplier) being in place first, so the rollout sequence matters.
Data Flow and Field Mapping
The overall flow is LingXing ERP (source) → Qeasy middleware → Kingdee Cloud (target). The middleware handles time-window filtering, code mapping, field enrichment, and the payload assembly required by Kingdee's batchSave.
Source key fields (from the LingXing endpoint /erp/sc/routing/data/local_inventory/purchaseOrderList):
| Source field | Meaning | How it is set |
|---|---|---|
order_sn | Purchase order number, used as the unique key | Returned by the API |
start_date / end_date | Incremental window | {{DAYS_AGO_s10|datetime}} / {{CURRENT_TIME|datetime}} |
search_field_time | Time dimension for the window | Fixed as create_time |
length / offset | Pagination parameters | 100 / 0 initially, offset accumulates |
Target key fields (written via batchSave into Kingdee):
| Target field | Meaning | Value / mapping |
|---|---|---|
FBillTypeID | Document type | Fixed CGDD01_SYS (standard purchase order) |
FBillNo | Document number | {{order_sn}} |
FDate | Purchase date | {{order_time}} |
FPurchaseOrgId | Purchase organization | {{purchaser_id}} |
FSupplierId | Supplier | A Mongo query maps supplier name → Kingdee FNumber |
FBusinessType | Business type | Mapped as needed |
Code mapping is the part most likely to break this strategy. LingXing hands you a supplier name, but Kingdee wants a code. We keep a single Mongo collection holding FName → FNumber mappings, and a Mongo-query action resolves it centrally — instead of scattering the mapping logic across every strategy. This is a common pattern among Qeasy customers: centralized code mapping. New suppliers are added by inserting a row into Mongo, with no changes to the strategy itself.
How to Configure It on Qeasy
In the Qeasy data integration platform's strategy editor, load the source and target metadata into the source reader and target writer respectively, and place a transformer in between.
Key configuration points: ① The source reader is a WebAPI/POST call. Paste in the LingXing endpoint and fill the request body per the table above. Note that start_date should use a relative-time expression like DAYS_AGO_s10 so the window rolls forward on every run. ② The target writer is batchSave. Assemble each purchase order's header and lines into the JSON shape Kingdee expects. ③ In the transformer, use a Mongo-query action for the supplier-name → FSupplierId mapping rather than hard-coding it.
On the source side, enable idCheck=true and use order_sn as the unique key so re-runs are idempotent and downstream document numbers never collide.
Implementation Steps
Stage 1 — Foundation data first. Before going live, make sure the two upstream strategies ("LingXing product → Kingdee material" and "LingXing supplier → Kingdee supplier") have run cleanly at least once. Otherwise the purchase orders arrive with no resolvable material or supplier code.
Stage 2 — Incremental starting point. On first go-live, perform a historical backfill with an explicit anchor (e.g. start_date set to the start of the month, end_date set to "now") to catch up the backlog. Then switch to daily increments.
Stage 3 — Scheduling cadence. Source crontab 1 1 * * * (01:01) and target crontab 1 2 * * * (02:01), leaving a one-hour buffer between them. The incremental window defaults to "10 days ago → now" to provide enough slack for missed runs.
Stage 4 — Exception re-runs. If a run fails because of a transient network issue, widen the window and re-run instead of tweaking start_date by hand. Qeasy supports parameterized windows, so a single config change covers every retry.
Lessons from the Field
Pitfall 1 — Wrong time dimension. The LingXing endpoint supports create_time, update_time, and expect_arrive_time. You must pick create_time here, otherwise any change to an order will keep re-pulling it.
Pitfall 2 — Missing records at the pagination edge. length is capped at 500; we use 100 for safety. Each page must be advanced by accumulating offset, and the loop must stop when "returned rows < length". The typical bug is to stop after a fixed number of pages, which silently drops the tail of the last page.
Pitfall 3 — Null supplier code. If a new supplier is not yet in the Mongo mapping table, FSupplierId will be empty and batchSave will reject the whole batch. A safer pattern is to add a null-check in the transformer and divert the affected order into a "needs manual entry" queue instead of failing the entire batch.
Pitfall 4 — Idempotency bypassed. If idCheck is not enabled, a re-run will cause Kingdee to generate duplicate FBillNo values. Source-side idCheck=true with order_sn as the unique key is mandatory.
Pitfall 5 — Headers and lines stuffed into one payload. A purchase order has both a header and line items. Stuffing them into a single JSON makes debugging miserable. A common pattern among Qeasy customers is headers and lines in separate stages: write the header first, verify, then add the line items.
When It Fits — and When It Doesn't
It fits cross-border e-commerce, retail, and trading businesses where purchasing execution lives in LingXing ERP but finance and costing run on Kingdee Cloud, and where finance needs daily purchase orders to drive accounts payable and goods receipt.
It does not fit scenarios where purchasing execution already runs inside Kingdee Cloud, or where two-way real-time sync is required (for example, edits made in Kingdee need to flow back into LingXing). The one-way incremental model here is not enough for those cases; a dedicated reverse-sync strategy is required.