Sync Rejection-Return After-Sales Orders from Jushuitan to Kingdee Refund Bills: A Single-Strategy Implementation Guide
What This Strategy Solves
Refund documents look simple but are full of traps. A retail enterprise selling on a short-video commerce channel generates a large volume of "rejection-return" after-sales orders every day: once a buyer rejects a parcel, a WaitConfirm after-sales record appears in Jushuitan, and finance and warehouse teams need to see the matching refund bill in Kingdee Cloud · Stellar flagship in order to reverse the outbound shipment and adjust receivables. Manual export cannot keep up during peak season, when hundreds of records land in a single day. This strategy does exactly one thing: incrementally pull rejection-return after-sales orders from Jushuitan by modification time and land them as refund bills in Kingdee.
Data Flow and Field Mapping
The overall flow is: Jushuitan (source, WebAPI) → Qeasy data integration platform (middleware, responsible for cleansing, mapping and code conversion) → Kingdee Cloud · Stellar flagship (target, RESTful). We typically centralize code mapping inside the platform — Jushuitan shop IDs and Kingdee customer codes live in different systems and must be aligned via a mapping table, otherwise within three months the two sides will not reconcile and the finance close will collapse.
Key field mapping:
| Meaning | Jushuitan Source Field | Middleware Handling | Kingdee Target Field |
|---|---|---|---|
| Bill number | as_id | Passed through | billno |
| Customer code | shop_id | Translated via shop mapping table | customer_number |
| Bill type | type=WaitConfirm | Fixed mapping | billtype_number=im_SalOutBill_STD_BT_S_R |
| Inventory org | — | Constant 100 | org_number |
| Settlement currency | — | Constant CNY | settlecurrency_number |
| Modification window | modified_begin / modified_end | Incremental cursor | — |
| Line items | items[] | Split lines → Kingdee entries | FEntity (multiple) |
Landing the header first and pushing line items in phases is one of the common patterns we see in Qeasy deployments: get the document header right first, verify the bill number, status, and org code, and only then open up line-level writes.
How to Configure It on Qeasy
Inside the Qeasy data integration platform this strategy is composed of a source integration solution plus a target integration solution, deployed in a private environment. There are four configuration essentials:
- Source solution: WebAPI / POST against
/open/refund/single/query, paginationpage_size=50, status hard-pinned toWaitConfirm, time window uses platform variables{{LAST_SYNC_TIME}}and{{CURRENT_TIME}}. - Target solution: RESTful / POST into Kingdee's
/kapi/v2/.../im_saloutbill/batchAddV2, withidCheck=trueandautoFillResponse=trueso the platform auto-fills the id from the response. - Build code mapping as a separate resource table (shop → customer code, SKU → material code) and reference it through expressions instead of hard-coding inside scripts.
- Failure retry and idempotency: the same
as_idmay be pulled again on retry; setbillnoas the idempotency key in the target solution and let Kingdee deduplicate on its side.
Implementation Steps
- Incremental starting point: at first go-live, run a one-shot full backfill script to push all historical WaitConfirm records, then move the cursor to
CURRENT_TIMEand switch to incremental from the next scheduled run. - Full trigger: create a one-shot "full backfill" task in Qeasy that has no cron and exits when done.
- Scheduling: source runs at
05,35 8-22 * * *, every 30 minutes, covering the daytime peak; target runs at20,50 * * * *, twice per hour, offset from the source so there is no gap where records are pulled but not yet written. - Monitoring and alerts: alert when failure rate crosses a threshold; manually intervene when a record stays in "pulled but not pushed" for too long.
Pitfalls and Lessons Learned
- Writing
created_begininstead ofmodified_begin— a classic mistake. After-sales records are repeatedly modified by status, so the cursor must use modification time; creation time will miss records. The safe pattern is to default the platform to modification time and manually verify the last seven-day window at first go-live. - Not filtering WaitConfirm — Jushuitan after-sales has many statuses; for rejection-returns only, hard-code
status=WaitConfirm. A common miss on-site is leaving status blank and pulling already-refunded records, which causes duplicate reversals on the Kingdee side. - Pushing the shop ID directly as the customer code into Kingdee — this is where things blow up most often. Jushuitan shops and Kingdee customers are entirely different code systems; you must go through a mapping table and never shortcut with an
if-elseinside a script. - Too many line items in one batch — Kingdee's batchAddV2 caps line count per document; going over fails the whole bill. Split by
as_idat the middleware layer and keep line count per document within a reasonable range. - Timezone mismatch in private deployment — Jushuitan servers use UTC, while the privately deployed Kingdee host may use UTC+8. Using
LAST_SYNC_TIMEdirectly will be off by 8 hours. The safe approach is to do explicit timezone conversion inside the platform.
Where This Applies and Where It Does Not
Applies: retail enterprises with high rejection-return volume from e-commerce channels that need day-level settlement, where Kingdee is the ERP of record in a private deployment. Does not apply: buyer-initiated returns (non-rejection), refund-required after-sales records (which should go to a refund document instead), or cross-org transfer scenarios. Running incremental and full tracks in parallel is one of the most common patterns Qeasy customers adopt for after-sales documents.