Practical Tutorial: Syncing Jushuitan After-Sales Rejection Refunds to Kingdee Cloud Return Orders
What This Strategy Solves
In e-commerce operations, "rejection refunds" are a very common after-sales scenario: a parcel is rejected by the customer upon delivery, or the courier returns it to the pickup point. The upstream e-commerce system then creates a pending after-sales order, which needs to drive refund, inbound put-away, and inventory reversal processes. The problem is that the e-commerce after-sales order and the Kingdee return order live in two separate systems with two separate document models. If teams rely on manual daily import/export, error rates are extremely high, and within three months inventory and receivables will no longer reconcile.
What we need to do is take upstream "pending confirmation" rejection-refund after-sales orders, pull them incrementally on a schedule, transform them through a middleware layer, and write them into Kingdee Cloud as sales return orders to close the after-sales loop. The whole pipeline is carried by the Qeasy data integration platform.
Data Flow and Field Mapping
The overall flow is: Jushuitan (WebAPI query) → Qeasy middleware (transform / validate / code mapping) → Kingdee Cloud (RESTful write).
Key field mapping:
| Business Meaning | Jushuitan (Source) | Middleware Handling | Kingdee (Target) |
|---|---|---|---|
| Document unique ID | as_id | Pass-through | billno |
| Shop / customer | shop_id | Centralized code mapping | customer_number |
| Modification time window | modified_begin / modified_end | Dynamically composed from LAST_SYNC_TIME and CURRENT_TIME | — |
| After-sales status | status = WaitConfirm | Filter condition, only pending records | — |
| Document type | type (refund / return) | Route by type to matching document type | billtype_number |
| Inventory org | Derived from shop mapping | Default org or shop-based mapping | org_number |
| Settlement currency | — | Default CNY | settlecurrency_number |
| Pagination | page_index / page_size | Loop until empty | — |
One critical engineering practice: code mapping must be managed centrally. The most common pitfall at customer sites is having customer codes, shop codes, and organization codes scattered across multiple strategies, where one business change updates one place and forgets the rest. We recommend creating a dedicated "mapping dictionary" asset in Qeasy, referenced by every return / order strategy so changes are consistent.
How to Configure in Qeasy
In the Qeasy integration platform, this strategy is typically configured as a pair of integration scenarios:
- Source scenario (Jushuitan side): WebAPI type,
effectset to QUERY, calling/open/refund/single/queryvia POST to paginate and pull after-sales orders betweenmodified_beginandmodified_endwith statusWaitConfirm. EnableidCheckto support incremental deduplication. - Target scenario (Kingdee side): RESTful type,
effectset to EXECUTE, calling/kapi/v2/null/im/im_saloutbill/batchAddV2, with document numbernameand primary keyidfor idempotency to avoid duplicate writes.
Several configuration points worth highlighting:
- Parameterized time window:
modified_beginuses{{LAST_SYNC_TIME|datetime}},modified_enduses{{CURRENT_TIME|datetime}}, with the watermark managed automatically by Qeasy — no manual intervention. - Idempotency and replay: On the Kingdee side, enable
idCheckplusbillnoso a successfully written after-sales order will not generate duplicate return orders even on rerun. - Batch write: Kingdee's
batchAddV2supports batches. The middleware aggregates multiple records pulled from Jushuitan pagination into a batch, reducing API call count. - Routing branch: Use Jushuitan's
typefield to route "rejection refunds" and "normal returns" to different Kingdee document types, preventing mixed documents.
Implementation Steps
At customer sites we typically proceed in three phases:
Phase 1: Full initialization
On first go-live, backfill historical rejection refunds over a chosen window. Trigger it manually in Qeasy in "full mode", fixing modified_begin to a sufficiently early timestamp, then record the current time as the watermark. Run this only once.
Phase 2: Incremental sync go-live
Switch to normal scheduling. The Jushuitan side pulls pending after-sales orders every 30 minutes during business hours (05,35 8-22 * * *); the Kingdee side writes every hour twice (20,50 * * * *). The two schedules are offset to avoid resource contention at the same instant.
Phase 3: Exception compensation and reconciliation For records that fail to write, have missing fields, or cannot be mapped, Qeasy routes them into a retry queue and exception log. During the daily off-peak window, ops reviews these and compensates manually or automatically. We also recommend exporting a weekly return-order list from Kingdee by document number and reconciling it against the Jushuitan after-sales order list.
Lessons Learned
- Filter conditions only half-defined: An early version filtered only on
status=WaitConfirmbut did not constraintype, which caused "refund-only" after-sales orders to be written into Kingdee as return orders, inflating inventory. The safer approach is to filter on bothstatusandtype, and add an assertion in the middleware. - Hard-coded customer codes: The first version hard-coded shop IDs in the target request; later shop changes required updates scattered everywhere. We then centralized all shop→customer mappings into a single Qeasy mapping dictionary, so a single update propagates globally.
- Pagination stopped before empty: With page_size=50, if the source side happens to have 40 records left, some engineers forget to keep paging until empty. The safe pattern is a while loop, terminating when "returned records < page_size".
- Time zone and format: Jushuitan returns local-time strings. Without normalization, the same instant can be interpreted twice when passed to Kingdee. Apply a unified
datetimeconversion in the Qeasy field-processing script. - Idempotency key using only the document number: On the Kingdee side, use both
billnoandidas idempotency keys. In edge cases (e.g., upstream document number reset), this adds an extra safeguard.
Suitable and Unsuitable Scenarios
Suitable: E-commerce retail enterprises that use Jushuitan as the front-end OMS/ERP and Kingdee Cloud as the back-end finance and supply chain core, and need rejection-refund after-sales orders to automatically generate return inbound orders.
Not suitable: Pure offline retail, cross-border bonded returns (significant differences in document type and tax handling), or scenarios where the after-sales process is fully closed-loop inside Kingdee.