WanDianTong Sales Return Orders to Kingdee Cloud: Store-Level Integration Tutorial
What This Strategy Solves (Scenario & Value)
For a multi-store retail operation, WanDianTong accumulates large volumes of sales return orders at the front end, while Kingdee Cloud serves as the back-end finance & supply chain system that needs these refund vouchers organized by store for cost accounting and inventory reversal. If the integration strategy does not treat the store as a key dimension, the finance team will discover mismatched refund totals three months later during reconciliation. The core value of this strategy is to push WanDianTong completed (status 80) refund orders into Kingdee Cloud in a stable, store-granular way, keeping both sides consistent.
Data Flow & Field Mapping (Source → Middle Layer → Target)
The source is WanDianTong's wdt.stockin.order.query.refund endpoint, fetched incrementally using start_time/end_time, defaulting to status 80 (completed) only. The middle layer inside the Qeasy iPaaS platform handles the translation from store codes to Kingdee sales organizations and uses the source order number (order_no) as the idempotency key mapped to the target FBillNo. The target is Kingdee Cloud's batchSave API, persisting vouchers of type XSTHD01_SYS.
Key field mapping:
| Business Meaning | WanDianTong Source Field | Kingdee Target Field | Notes |
|---|---|---|---|
| Voucher number | order_no | FBillNo | Idempotency key |
| Return date | check_time | FDate | Format yyyy-MM-dd HH:mm:ss |
| Store code | shop_no | (organization lookup entry) | Used to find FCOUNTRY/FSaleOrgId |
| Sales org | (resolved via shop_name) | FSaleOrgId | Reverse lookup via _findCollection |
| Inventory org | warehouse_no | FStockOrgId | Direct mapping |
| Return customer | (resolved via customer) | FRetcustId | Customer code centrally maintained |
| Voucher type | (fixed value) | FBillTypeID | Hard-coded XSTHD01_SYS |
| Stock-in ID | stockin_id | id | Used for idCheck idempotency |
How to Configure It in Qeasy
Inside the Qeasy platform, register a QUERY-type API resource on the source side, fill in the endpoint and POST method, bind start_time to the built-in variable LAST_SYNC_TIME, end_time to CURRENT_TIME, hard-code status as 80, and leave shop_no empty to fetch all stores. The pagination parameter page_size directly references the PAGINATION_PAGE_SIZE system variable.
On the target side, register an EXECUTE-type batchSave, hard-code the voucher type as XSTHD01_SYS, reference the source order_no for FBillNo, check_time for FDate, and warehouse_no for FStockOrgId. The FSaleOrgId field is the trickiest part — use the _findCollection directive to look up the sales organization code (FCOUNTRY) by shop_name from the organization master. We typically recommend customers maintain this kind of code mapping centrally in Qeasy's data model layer rather than embedding it inside individual strategies.
Implementation Steps
We split the rollout into three phases:
- Confirm the incremental starting point. First, use a far-back
start_time(e.g., 30 days ago) for the initial historical backfill and verify both sides align; afterward, the scheduler continues usingLAST_SYNC_TIMEon each run. Qeasy's built-in schedule*/5 * * * *pulls data every five minutes. - Store-by-store triggering. If specific stores need a rerun, use
shop_noas an input whitelist and trial-run one store for 24 hours before opening up to the others. The safe approach is staged rollout per store rather than a full blast from day one. - Schedule frequency & monitoring. The target
batchSaveruns on*/10 * * * *, every ten minutes. Keep the source frequency higher than the target so you have execution headroom. Qeasy's run-monitoring dashboard shows success/failure/retry counts per strategy; if the row count stops growing, the first thing to check is whether the watermark has moved.
Pitfalls We Have Hit
- Default status 80 is a double-edged sword. The source defaults to completed only, but in practice finance sometimes manually flips status 60 (pending settlement) to completed, and those vouchers get missed. We later changed the source query to "60 or 80", or added a status-change listener strategy as compensation.
- Store-name-to-sales-org mapping hard-coded inside the strategy. A classic mistake is putting the
shop_name → FCOUNTRYmapping inside a single strategy's transformer, so adding a new store requires editing the strategy itself. The safe pattern is to build a dedicated store-mapping master in Qeasy and have every organization-touching strategy reference that one table. - Overlapping incremental windows cause duplicate vouchers. If
LAST_SYNC_TIMEis compared as a string and the two systems have mismatched time zones, the same voucher may be pushed twice. Always normalize timestamps to UTC+8 in Qeasy's global variables, or rely onFBillNoidempotency on the target side. batchSavebatch size not controlled. Stuffing 200 rows at once can trigger Kingdee-side transaction timeouts. Cap the batch size at around 50 rows in the Qeasy write component and roll back the whole batch on failure rather than partial commit.- Missing return customer code. If the customer master is not maintained in WanDianTong, Kingdee will reject the voucher with
FRetcustIdrequired. Run the customer master-data strategy first and usedepends_onto make it a precondition.
Where It Fits — and Where It Does Not
Fit: multi-store retail with a unified finance middle platform, refund businesses requiring cost reconciliation and inventory reversal in Kingdee. Not fit: single-store direct connections, B2B bulk returns, or returns that need workflow-based approval (this strategy only pushes completed vouchers).