Qeasy Cloud
Get Started

Practical Tutorial: Offline Return & Exchange Query to Sales Return Order Sync

· 许创贵· Integration Solutions· 17 views· 4 min read

What This Strategy Solves (Scenario & Value)

In a real retail supply-chain integration project, we kept hitting the same problem: offline store returns and exchanges were finalized in the retail/OMS side, but the back-office ERP's sales return orders lagged—or simply never showed up. Finance reconciliation, refund clearing, and stock return all stalled as a result.

This strategy focuses on pulling settled return/exchange records from the retail source system incrementally by "last update time," transforming them through the Qeasy data integration platform, and writing them into the target ERP as sales return orders. It is not about bulk backfill; it is about a stable, settlement-driven incremental flow.

Data Flow & Field Mapping (Source → Middle Layer → Target)

The chain splits into three segments: retail source pull → Qeasy mapping & transformation → ERP write.

Key Field Mapping Table

Business MeaningSource Field (Retail)Target Field (ERP)Handling Notes
Document numberrefund_noFBillNoIdempotency key, unique on source
Process statusprocess_status(filter condition)Only 90 (completed) is taken
Time windowstart_time / end_timeFDateIncremental by last update time
Time typetime_type—0 = last update time, 1 = settle time
Shop numbershop_noFSaleOrgIdResolved via customer/shop mapping
Warehouse numberwarehouse_noFStockOrgIdResolved via warehouse mapping
Document type(fixed)FBillTypeIDHardcoded XSTHD01_SYS on target
Return customer(source extension)FRetcustIdEncoding mapping in middle layer

Note that source start_time is typically written as {{LAST_SYNC_TIME|datetime}} and end_time as {{CURRENT_TIME|datetime}} in Qeasy—these are the hooks that make the incremental schedule work.

How to Configure in Qeasy

In the Qeasy data integration platform, this strategy is normally configured as a source-interface + write-interface pair.

  1. Source interface: type QUERY, method POST, API wdt.refund.query. Hardcode process_status to 90 so only completed returns are pulled—do not let half-finished documents pollute the ERP.
  2. Primary key & idempotency: set both number and id to refund_no, and enable idCheck so the same document is never written twice.
  3. Target interface: type EXECUTE, method POST, API batchSave. Hardcode FBillTypeID to XSTHD01_SYS.
  4. Organization field mapping: fields like FSaleOrgId and FStockOrgId should be resolved via _findCollection against the ERP's organization master, not hardcoded. This is a common Qeasy customer pattern—centralized encoding mapping: every external code to internal ID mapping lives in a visual mapping table, so when stores or warehouses change, only one place needs updating.
  5. Response & logging: enable autoFillResponse so the target's returned id is auto-written back to the middle layer for easier troubleshooting.

Implementation Steps (Phased Scheduling)

Across several similar projects, the safe pattern is three phases:

  • Incremental start point: before the first run, confirm with the business which timestamp serves as the historical starting point. Avoid dumping all history at once and overwhelming the ERP. A common choice is to set start_time to 00:00 on go-live day and let the incremental flow stabilize first.
  • Full-volume trigger: if historical data must be backfilled, run a separate full-volume task to write all settled historical documents once, then switch to incremental. Do not mix full and incremental in the same schedule—this is a trap we keep hitting.
  • Schedule frequency: source cron */3 * * * *, target cron */4 * * * *. The offsets are not arbitrary—source pulls every 3 minutes, target writes every 4 minutes; staggering prevents pulling and downstream writes from colliding. The incremental + full dual-track pattern common among Qeasy customers is exactly this kind of separation.

If the return document also contains line items (SKU, return qty, reason, etc.), go with header/body phased rollout: stabilize the header first, then configure a separate strategy for the body. It dramatically reduces debugging pain.

Pitfalls We Have Hit

  1. Forgot the status filter: without process_status=90, "pending review" and "pending receipt" documents flow into the ERP and trigger mass reversals. The safe move is to hardcode the filter in the source interface and not rely on downstream cleaning.
  2. Mixed time types: switching time_type between 0 (last update) and 1 (settle time) makes the same document get pulled again at settlement. Pick one time dimension at the source and document it in the config.
  3. Hardcoded organization mapping: writing FSaleOrgId as a fixed value works until store count grows. All organization-type fields must go through _findCollection.
  4. Overlapping cron rhythms: source and target firing at the same minute spike ERP interfaces. Staggering by 1–4 minutes is a low-cost, high-return tweak.
  5. Wrong idempotency key: choosing a business field as the idempotency key causes duplicates once that field changes later. The source system number refund_no is the safest key.

When It Applies and When It Doesn't

Applies: retailers with a standalone retail/OMS system, high return/exchange volume, and a back-office ERP that needs settled sales return orders for finance closing. Does not apply: pure online e-commerce returns (handled by online flows), very low document volume where automation is overkill, or scenarios requiring real-time return (this strategy is polling-based, minute-level latency, not seconds).

Original content. Please credit the source when reposting: https://www.qeasy.cloud/insights/solutions/strat-pc2ef6c-kingdee-cloud-0165-n37bcbdfa-e18e3425

Comments