Practical Guide: Syncing Kingdee Cloud Skylink Sales Outbound Orders to Wangdiantong Raw Orders via Qeasy
What This Strategy Solves (Scenario & Value)
In one multi-channel retail project, we ran into a classic pain point: store and e-commerce orders are fulfilled in Kingdee Cloud Skylink (sales outbound documents), but the Wangdiantong platform still needs a "raw order" record to drive shipping, after-sales, and settlement. Manual re-entry cannot keep up with the volume. So we used the Qeasy data integration platform to build a single strategy: every few minutes, push audited Kingdee sales outbound documents to Wangdiantong·QiMmen as raw orders. The pipeline only does one thing—move the document—and we keep return writes and status updates in separate strategies, so the boundaries stay clean.
Data Flow & Field Mapping (Source → Middle Layer → Target)
The source is Kingdee's SAL_OUTSTOCK (sales outbound document). The target is Wangdiantong's wdt.trade.push (raw order push). In Qeasy, data is pulled from the source, transformed through field mapping and scripts, then written to the target API.
Key field mapping (header):
| Source (Kingdee) | Target (Wangdiantong) | Type | Notes |
|---|---|---|---|
F_VTRK_Text + FEntity_FENTRYID + FID | tid | TRANSFORM | Raw order number: contract-line_FID, unique within a shop |
| Constant 30 | trade_status | CONSTANT | Platform status: shipped |
| Constant 2 | pay_status | CONSTANT | Payment status: paid |
| Constant 1 | delivery_term | CONSTANT | Delivery term: pay-before-ship |
FDate | trade_time / pay_time | DIRECT | Order/payment time |
FCustomerID_FName | buyer_nick | DIRECT | Buyer nickname |
F_VTRK_Text1/2/3/11/12/13 | receiver_name/mobile/address/province/city/district | DIRECT | Receiver info |
F_VTRK_Assistant | shop_no | DIRECT | Shop number, passed via otherRequest |
details_list.FStockID_FNumber | warehouse_no | DIRECT | Warehouse number |
Key field mapping (line items):
| Source | Target | Type | Notes |
|---|---|---|---|
F_VTRK_Text8 | spec_no | DIRECT | Wangdiantong spec code |
FRealQty | num | DIRECT | Actual shipped quantity |
F_VTRK_Text | trade_memo | DIRECT | Per-item memo (contract number) |
| Constant 0 | price/discount/... | CONSTANT | Pricing fields resolved by Wangdiantong from spec_no |
Source filter (configured directly in Qeasy's source query):
FCreateDate>='{{LAST_SYNC_TIME|datetime}}'
AND FDocumentStatus='A'
AND F_VTRK_Assistant <> ''
AND F_VTRK_Text11 <> ''
AND F_VTRK_Text12 <> ''
AND F_VTRK_Text13 <> ''
AND F_VTRK_Text10 =''
The common pitfalls are already blocked here: only audited docs, with a shop, with complete province/city/district, and not previously pushed.
How to Configure It in Qeasy
On the Qeasy strategy canvas, this strategy is split into three segments: source query → script processing → target write.
- Source config: Business object
SAL_OUTSTOCK, APIexecuteBillQuery, pagination via{{PAGINATION_PAGE_SIZE}}and{{PAGINATION_START_ROW}}, primary keyFBillNo, line IDFEntity_FENTRYID. - AfterSourceInvoke script: A PHP script handles the indoor/outdoor unit split for air-conditioner products. If
F_VTRK_Text9(outer-unit material code) exists, it becomes the main material; ifF_VTRK_Text6(Wangdiantong name) orF_VTRK_Text9is non-empty, additional line items are appended, all usingFRealQtyfor quantity. This is the "soul" of the strategy—validate the split in a test environment with a few real air-conditioner outbound documents before going live. - Target write: API
wdt.trade.push, request body built from the header mapping above. Constants are written directly in Qeasy field config.shop_nois passed viaotherRequest.switch=0(non-strict mode) so a single bad field doesn't fail the entire document.
We also applied several patterns we often see in Qeasy customer projects: centralized code mapping (shop and material mappings live in one table, so adding a new shop does not require touching the strategy); header/line staged processing (header fields mapped first, line items processed by script afterward, so failures stay row-scoped); dual-track incremental + full sync (5-minute incremental in normal operation, with manual full-range replays by FCreateDate when something goes wrong).
Implementation Steps
- First go-live: full baseline. Set
LAST_SYNC_TIMEto a past timestamp (e.g., midnight of the project kickoff day), trigger a manual run to push all existing audited sales outbound documents. Immediately write backF_VTRK_Text10 = 'synced'to prevent re-pushing in the next cycle. - Daily schedule: 5-minute incremental. Configure the schedule as
*/5 6-23 * * *(every 5 minutes between 06:00 and 23:00). TheFCreateDate>=LAST_SYNC_TIMEfilter automatically picks up only deltas. After each successful run, Qeasy advancesLAST_SYNC_TIMEto the latest timestamp seen. - Retry & alerting. Qeasy retries by default, but we recommend surfacing business errors from Wangdiantong (e.g., "shop not found", "spec not found") to a manual queue—fix the mapping table, then replay. Avoid infinite retries on business errors.
- Return writes live in another strategy. This strategy only pushes outbound → raw order in one direction. Logistics numbers and sign-off status coming back from Wangdiantong to Kingdee should be handled by a separate strategy to keep concerns separated.
Pitfalls We Hit in the Field
tiduniqueness. Wangdiantong requirestidto be unique within asid. We initially used onlyFBillNo, and two documents with the same contract number in the same shop got rejected. The reliable pattern is the three-partcontract-line_FIDconcatenation shown in the spec—non-duplicate and traceable back to the source.- Empty province/city/district. Without a strong address-completeness check upstream, Wangdiantong simply errors out. Adding
F_VTRK_Text11/12/13to the filter means incomplete-address docs are skipped until business fills them in. - Indoor/outdoor units becoming two orders. Before adding the
AfterSourceInvokescript, indoor and outdoor units generated two separate raw orders, and reconciliation broke. With the script, a single sales outbound line is split into main-material + outer-unit + Wangdiantong-name lines, all under the sametid. - Hard-coding monetary fields to 0 is intentional. A common reflex is to map unit price and discount across, but Wangdiantong treats them as "specified price" and rejects. Per the spec, leave monetary fields at 0 and let the platform resolve them from the product master via
spec_no. - Forgetting to write back
F_VTRK_Text10. If the "synced" flag is not written back, the next incremental run pushes the same documents again. Always add a writeback step (either inline or as a downstream strategy); otherwise the two sides will drift within a quarter.
When This Strategy Fits (and When It Doesn't)
Fits: Mid-volume multi-channel retail/manufacturing where 5-minute latency is acceptable, source is Kingdee Cloud Skylink sales outbound, target is Wangdiantong raw order, and shop/material/address mappings are relatively stable. Doesn't fit: Sub-second real-time needs (use message queues or event-driven triggers instead); multiple target platforms (split into multiple strategies instead of stuffing fields); scenarios requiring heavy business validation before push (this strategy is a pure carrier—validation belongs upstream).