Sales Order Delivery Notice to WMS Outbound Sync: A Practical Strategy from Kingdee Cloud Cosmos to WMS
What This Strategy Solves (Scenario & Value)
In a private deployment for a pharmaceutical distribution enterprise, after a sales order is approved in the ERP, the "delivery notice" must be synchronized to the WMS in near real time to trigger warehouse picking, outbound processing, and logistics handover. It looks like just pushing a single document across, but in practice, code mapping, order-type routing, incremental baseline design, and foreign-key validation can each become a landmine. Our approach on the customer site is to use the Qeasy Data Integration Platform as the middle layer: query delivery notices from Kingdee Cloud Cosmos using an incremental window, then push them to the WMS in the required field structure.
Data Flow & Field Mapping
The overall chain is Kingdee Cloud Cosmos → Qeasy → YiWeiMeng WMS. The source side queries delivery notices by document number through executeBillQuery (WebAPI, POST), while the target side writes or updates outbound orders through pushOutboundOrder (RESTful, POST).
Key field mapping:
| Business Meaning | Source (Kingdee Cloud Cosmos) | Target (WMS) | Notes |
|---|---|---|---|
| External system unique ID | FBillNo | bh | Filled via {{FBillNo}} template, serves as idempotency key |
| WMS internal ID | — | wmsbh | Default 0; passing an existing ID triggers an update |
| Order type | — | ddlx | Fixed as "Sales" |
| Warehouse | F_UVQS_Base | ck | WMS foreign key, requires mapping |
| Customer | FCustomerID_Fnumber | kh | Foreign key, mapped against customer master |
| Sales order number | FORDERNO | xsdh | Links back to the upstream sales order |
The source request needs FEntity_FEntryID, FID, FORDERNO, FBillNo, FDate, FApproveDate, and other fields. The target-side bh is the primary key for later data matching and must remain stable and unique.
How to Configure on Qeasy
When we configure this strategy in Qeasy, we usually split it into three parts:
- Source metadata: Declare
api=executeBillQuery, POST method, enableidCheckandbuildModel, setFBillNoas the document number field, FEntry_FEntryID as the line ID, and disableautoFillResponsesince we assemble the payload on the platform side. - Target metadata: Declare
api=pushOutboundOrder, RESTful POST, map bothnumberandidto the WMSidfield, disablebuildModel, and let Qeasy write the payload based on the field template. - Script layer: Handles code mapping, customer foreign-key lookup, and order type normalization. A common pattern we see among Qeasy customers is centralized code mapping management: maintain a separate mapping table for warehouses, customers, and materials, and have strategy scripts only read from it. Changes go through a unified entry point instead of being scattered across multiple strategies.
Implementation Steps
We split the rollout into three phases to avoid the regression risk of a single cutover:
- Phase 1: Confirm the incremental baseline. First use
FApproveDateas the time window, replay a span of historical data to load the full baseline, and record the starting timestamp. Once the incremental start point is confirmed, the strategy rolls forward on approval time and never goes back to query the full set again. - Phase 2: Full trigger and verification. Manually trigger a full push in Qeasy, and verify line by line on the WMS side: inbound status, inventory reservation, and whether picking tasks are generated. A typical mistake is checking only the document header while ignoring whether line items fully landed.
- Phase 3: Steady-state scheduling. Set the source
crontabto*/5 7-22 * * *(every 5 minutes during working hours), and the targetcrontabto3-59/5 7-22 * * *(staggered by 2 minutes to avoid same-frame contention). Nighttime pauses help reduce pressure on the private deployment database.
Additionally, the dual-track incremental + full approach is common among Qeasy customers: run incremental on a daily basis, and trigger a full reconciliation at a fixed time each month to detect missing documents and drift.
Lessons from the Trenches
- Unstable idempotency key: Early on we used the WMS auto-increment
idas the idempotency key, which caused retries to create new documents. The safe approach is to usebh={{FBillNo}}as the external unique ID and let the WMS deduplicate onbh. - Missing order type: Sales, purchase returns, samples, transfers, and damaged-goods outbound all share the same outbound interface, so the type field must be explicitly passed per scenario or the WMS will route to the wrong workflow. This is a common pitfall; we once saw a batch where "Sales" was accidentally transmitted as "Purchase Return".
- Foreign keys pushed without mapping: Passing warehouse and customer codes directly without lookup causes the WMS to reject the document when the master record is missing. The safe approach is to query the mapping table in the script first; if not found, branch into an alert path instead of aborting the entire batch.
- Header and body not split by phase: Pushing header and body in a single request makes it difficult to determine whether the failure is in the header or the body. We recommend pushing the header first (no line items) on the Qeasy side; once the WMS accepts it, push the body. Troubleshooting becomes much faster.
- Nighttime schedules overloading the database: Replaying full loads during off-hours with high concurrency can spike private deployment database I/O. We later changed to staggered runs during working hours and incremental only at night.
Applicable & Non-applicable Scenarios
Applicable: Real-time or near-real-time push of sales order delivery notices from ERP to WMS in a private deployment, with clear order types and established customer and warehouse master data. Not applicable: Scenarios requiring two-way coordination of picking strategy, inventory reservation feedback to ERP, or complex multi-org and multi-book distribution. These require separate dedicated strategies rather than reusing this design.