Practical Tutorial: Syncing Jushuitan After-Sales Orders to Kingdee Return Orders
What This Strategy Solves
In a Douyin/Kuaishou e-commerce setup, the after-sales return chain for a retail business typically looks like this: a buyer initiates a return in the Douyin store → Jushuitan generates a "sales return-to-warehouse / actual receipt" document → the warehouse physically receives the goods. Once this document lands in Jushuitan, the inventory and receivables in Kingdee Cloud · Stellar flagship must reflect it in sync; otherwise there will be a discrepancy where "the goods are physically in, but finance has not caught up."
The scope of this strategy is narrow and specific: push Jushuitan's after-sales return documents (anchored on the "actual receipt" status) through the Qeasy Data Integration Platform into Kingdee Cloud · Stellar flagship return-outbound orders, achieving hourly-level reconciliation on both sides.
Data Flow and Field Mapping
Data flow: Jushuitan (source) → Qeasy Integration Platform (middleware) → Kingdee Cloud · Stellar flagship (target).
Key field mapping:
| Dimension | Jushuitan source field | Kingdee target field | Notes |
|---|---|---|---|
| Document number | io_id | billno | Idempotency key, must not be lost |
| Shop | shop_id | customer_number | Customer code mapping |
| Document type | Sales return-to-warehouse / actual receipt | billtype_number = im_SalOutBill_STD_BT_S_R | Return outbound order |
| Inventory org | (not in source) | org_number = 100 | Fixed value on target |
| Settlement currency | (not in source) | settlecurrency_number = CNY | Fixed value on target |
| Receipt time | received_at | Derived document date | Determines same-day inventory |
The middleware's value lies right in this table: Jushuitan does not carry inventory org or currency fields, but Kingdee requires them—who fills them in? The encoding mappings are managed centrally in Qeasy's field-mapping table, not hard-coded in scripts.
How to Configure on Qeasy
In the Qeasy Data Integration Platform, this strategy is a standard "source QUERY + target EXECUTE" combination.
-
Source (Jushuitan):
- API:
/open/aftersale/received/query, POST; - Query window:
modified_beginpicks up the last sync time,modified_endpicks up the current time, achieving an incremental window; - Paging:
page_size=50, Qeasy auto-paginates; date_type=4filters by modification time, consistent with the incremental-window semantics.
- API:
-
Target (Kingdee Cloud · Stellar flagship):
- API:
/kapi/v2/.../im_saloutbill/batchAddV2, POST; idCheck=true+number=io_id, ensuring the same after-sales document is never pushed twice;- Header and body are written in phases: the header lands first, then the line items are appended as a sub-table, so a single failure does not bring down the entire batch.
- API:
-
Middleware configuration essentials:
- Centralized encoding mapping: put
shop_id → customer_number, organization, and currency in Qeasy's mapping table; - Idempotency-key strategy: use
io_idas the unique number, withidCheckenabled on the target—reruns will not create duplicate documents; - Header and body in phases: do not throw everything into one transaction; the header goes first, the body follows, and failures can retry per segment.
- Centralized encoding mapping: put
Implementation Steps
We recommend a three-phase rollout, which we have found stable at customer sites:
-
Phase 1 · Incremental starting point (cold start) Run a full pull of historical data once and anchor
LAST_SYNC_TIMEto the current moment; from then on, switch to incremental. This is the standard "incremental and full dual-track" approach, which avoids crushing the target database on go-live by consuming all history at once. -
Phase 2 · Incremental scheduling The source triggers at minutes 5 and 35 of every hour via
05,35 * * * *; the target runs at minutes 20 and 50 via20,50 * * * *, queuing 15 minutes later. This gives the middleware conversion time after the source pulls data, and the target writes in order. -
Phase 3 · Exception loop closure Qeasy's failure queue should be manually or automatically re-injected; when
idCheckhits an existing document, skip it instead of raising an error, to avoid false positives clogging the queue.
Pitfalls Revisited
- Treating
received_atasmodified: after the "actual receipt" status changes in Jushuitan, the document can still be edited (e.g., remarks, attachments), so pulling only byreceived_atwill miss documents. The safe approach is to usedate_type=4and pull by modification time, while using the receipt action as a filter condition. - Pushing
shop_iddirectly ascustomer_number: the Douyin/Kuaishou shop code and Kingdee customer code are two separate systems; pushing without mapping will cause Kingdee to reject the order or mix accounts. We build a shop→customer mapping table in Qeasy and maintain it centrally. - Hard-coding the inventory organization in the script: every time the organization changes, code must be modified—a textbook anti-pattern. Move it to a Qeasy mapping-table configuration item that the business can switch on their own.
- Reruns causing duplicate return orders: when
idCheckis off or the idempotency key uses the wrong column, supplemental pushes create phantom return-outbound orders, and inventory is deducted twice. Usingio_idas thenumberis the baseline. - Oversized batchAdd calls: 50 records per page is fine, but Qeasy defaults to merging the entire window into one push, which times out on the target side. The safe practice is to batch in 20–50 records, so failures can retry per segment.
Applicable and Non-Applicable Scenarios
Applicable: enterprises with high after-sales return volume on Douyin/Kuaishou e-commerce, Jushuitan as the order middle platform, and Kingdee handling finance and inventory in a private-deployment environment. Not applicable: "refund-only" scenarios without an actual-receipt step; environments where Jushuitan and Kingdee have not aligned on organization/customer master data; and scenarios requiring sub-second real-time performance that must rely on message queues rather than scheduled polling.