Sync Jushuitan After-sales Return-to-Warehouse Orders to Kingdee QJB Return Orders: A Qeasy Hands-on Tutorial
What This Strategy Solves
In one retailer's after-sales flow, Jushuitan runs the e-commerce front end while Kingdee QJB runs back-office finance and inventory. When a Douyin offline order is returned and physically received at the warehouse, the after-sales record must be logged in both systems—double entry by hand is slow and error-prone. We use Qeasy to pull Jushuitan 'sales return-to-warehouse / actual receipt' records on an incremental time window and write them as Kingdee return bills, so inventory and receivables reversals have a clear source.
Data Flow and Field Mapping
End-to-end flow: Jushuitan (after-sales query) → Qeasy middle layer → Kingdee QJB (return bill write).
The source endpoint is /open/aftersale/received/query, POST, paginated. Key inputs:
modified_begin/modified_end: incremental window, auto-filled by the Qeasy scheduler from the last sync time to now.date_type: fixed as4(by modification time) in this scenario.page_index/page_size: pagination, typically1and50, looped by Qeasy.shop_id: shop id used as a filter.
In the source response, io_id acts as both the business number and the idempotency key; combined with idCheck=true it deduplicates.
The target endpoint is /kapi/v2/.../im_saloutbill/batchAddV2. Key target fields:
| Target field | Meaning | Source / Handling |
|---|---|---|
| org_number | Inventory org code | Constant 100 |
| customer_number | Customer code | {{shop_id}} mapped via Qeasy mapping table |
| billtype_number | Bill type code | Constant im_SalOutBill_STD_BT_S_R (return outbound) |
| settlecurrency_number | Settlement currency | Constant CNY |
| billno | Bill number | {{io_id}}, same as source idempotency key |
| bizorg_number | Sales org code | Constant |
The middle layer handles three things: page aggregation, time-window advancement, and code mapping.
How to Configure in Qeasy
Step 1: create the source data source with the Jushuitan adapter and fill in the app credentials (omitted here for security). Step 2: create the target data source with the Kingdee QJB adapter and the tenant info (omitted). Step 3: create an integration strategy and paste the two JSON metadata files—Qeasy will render the request/response field panels automatically.
Three points deserve attention:
- Incremental watermark: source
modified_beginuses the variable{{LAST_SYNC_TIME|datetime}},modified_enduses{{CURRENT_TIME|datetime}}. The scheduler pushes these forward every run. - Idempotency: enable
idCheckon the target, with the sourceio_idas the key; duplicates are skipped automatically. - Code mapping: customer, org, and bill-type codes live in Qeasy's centralized mapping table, not scattered across scripts. This is one of the most common patterns Qeasy customers adopt—adding a new shop or changing an org only requires editing one place.
Implementation Steps
On-site we typically proceed in three phases:
- Full initialization: temporarily set
modified_beginto a fixed historical start point, run once for a full pull, and verify that Kingdee return bills are created correctly and inventory reversals are clean. - Switch to incremental: once the full pull passes, restore the time-window variables and run 3–5 scheduler cycles (every 30 minutes), checking that bill numbers are continuous with no duplicates or gaps.
- Steady-state scheduling: set the source cron to
05,35 * * * *and the target cron to20,50 * * * *, staggered to give the target time to write and write back.
We recommend a daily reconciliation sample: pick 5 bills and compare amount, customer, and warehouse across both sides.
Pitfalls from Real Projects
- Time window not advancing: in early versions someone hard-coded
modified_beginas a constant, so every run pulled the same batch. The safe move is to check thatLAST_SYNC_TIMEis actually moving forward in the Qeasy scheduler logs. - Duplicate
io_idwrites: Jushuitan after-sales records get re-pushed on edits. You must rely onidCheckplus the idempotency key; do not trust bill status alone. - Missing customer code: a shop goes live but no customer code is added in the Qeasy mapping table, and the whole target batch fails. Centralized mapping exists exactly for this reason.
- Mixing inventory org and sales org: in a Kingdee return outbound,
org_number(inventory org) andbizorg_number(sales org) are two separate fields. The source does not supply them directly, so during configuration confirm which constant maps to which. - Target rate limits: a single large
batchAddV2call can be throttled. On the Qeasy side, split bills into batches of around 50 or fewer.
When to Use and When Not
Use this pattern when e-commerce returns must generate back-office return bills for inventory and receivables reversals in a multi-store retail setup. Do not use it for pure offline returns without a source record, for after-sales work orders that require complex approval flows, or for cross-legal-entity scenarios that need secondary splitting—those need dedicated multi-org distribution strategies, not a reuse of this one.