Inter-Org Demand Order Sync in Practice: A Single-Strategy Pipeline from Kingdee Cloud to MySQL OMS
What This Strategy Solves
In multi-org groups, demand orders constantly flow from the issuing org to the receiving org. Direct point-to-point links quickly break down when BOM, customer codes, or status write-backs change. We use the Qeasy data integration platform to consolidate this path into a single strategy: the source pulls approved documents incrementally from Kingdee Cloud, the field mapping cleans and translates them, and the result lands in MySQL's OMS order and order-BOM tables. All code conversions, status mappings, and date translations are maintained centrally inside the strategy—observable and replayable.
Data Flow and Field Mapping
Flow: Kingdee Cloud (executeBillQuery, POST) → Qeasy middleware → MySQL (execute, POST, writing oms_order / oms_order_bom).
Source-side key fields: FID (entity primary key), FDocumentStatus (document status), FIsClosed (close status), FBillNo (document number), FApproveDate (approval date), FMaterialId_FNumber (material code), FDemandDate (demand date), and others. These standard Kingdee fields serve as the query conditions for both the header and the body.
On the MySQL side, two tables are involved:
| Target Table | Key Fields | Meaning |
|---|---|---|
| oms_order | order_uuid, order_no, order_date, order_status, company_code, is_distribute, is_soa_finish, customer_uuid, order_type, leader, customer_order_no, order_delivery_date, create_by | Document header: order-level status and ownership |
| oms_order_bom | bom_uuid, bom_no, order_uuid, order_no, company_code, part_no, grade_name, pic_no, pic_version, order_num, delivery_date, completed_num, change_status, bom_status, price, eng_bom_id, serial, material_source, if_material | Document body: line-item materials and delivery details |
Typical mappings: FBillNo → order_no, FDemandDate → order_delivery_date, FMaterialId_FNumber → part_no. Header and body are linked through order_uuid. A common Qeasy pattern is "header-then-body in stages": generate the header UUID first, then reuse the same UUID when writing the body, so line items never become orphans.
How to Configure on Qeasy
Source: API = executeBillQuery, method = POST, primary-key field = FID. Enable autoFillResponse so the platform unfolds the response structure automatically. Pass the incremental cursor field (e.g., FApproveDate) as a filter in the request body.
Target: API = execute, method = POST. Set main_sql to INSERT INTO oms_order … and extend_sql_1 to INSERT INTO oms_order_bom …. Use the object-typed main_params and extend_params_1 to carry field values; parameter names must match SQL placeholders one-to-one.
Middleware mapping layer: Build the field mapping inside Qeasy and turn on idCheck to prevent duplicate writes. For code mappings—e.g., differences between Kingdee material numbers and OMS part_no—use "centralized code mapping management": build a reusable dictionary so multiple strategies can share it.
Schedule: crontab */3 * * * *, meaning one round every 3 minutes.
Implementation Steps
Phase 1 — Initialize the incremental cursor. Before the first run, pick a historical approval timestamp in Kingdee as the starting cursor (call it T0) and write it into the strategy's cursor variable. Each subsequent pull uses FApproveDate > T0, and T0 advances automatically.
Phase 2 — Trigger a full backfill. On go-live day, manually trigger a full historical backfill and reconcile quantities, amounts, and line-item counts on both sides. Do not switch to production scheduling until the diff is zero.
Phase 3 — Production scheduling + dual-track safety net. Run the production schedule every 3 minutes, but keep a full-volume script as an emergency channel. A common Qeasy pattern is "incremental and full dual-track": incremental handles daily traffic, full handles disaster recovery and data repair. Lock in the frequency first, observe for 1–2 weeks, then adjust based on load.
Lessons from the Field
1. Header and body out of sync. Writing only the header (or only the body) is the easiest way to fail here. The safe approach is to package header and body into a single scheduling unit tied together by the same order_uuid.
2. Code mappings scattered everywhere. A typical mistake is embedding material-code conversion logic into every individual strategy; three months later, changing a field name breaks everything. Extract all code mappings into Qeasy's centralized dictionary and reference them from new strategies.
3. Document-status semantics don't align. Kingdee's FDocumentStatus and OMS's order_status are not the same semantics; a 1:1 mapping loses information. Build a status translation table in the middleware layer, mapping "approving / approved / closed" to OMS-recognized business states.
4. Forgetting to set the incremental cursor. Without a cursor on the first run, the platform pulls every historical document, causing primary-key collisions on the target side. Set T0 explicitly before go-live and run a dry-run.
5. Too-aggressive scheduling overloading the source. A 3-minute cadence is fine for small volumes, but once orders reach tens of thousands, it pressures Kingdee. Add a "window merge" mechanism to combine requests covering the same approval-time range.
When to Use and When Not to
Use when: a multi-org group needs inter-org demand orders to flow between issuing and receiving orgs, the OMS side already has standardized order and BOM tables, and you want an observable, replayable mid-scale integration. Do not use when: you need second-level real-time sync, two-way conflict reconciliation, or the source document structure changes frequently—those cases are better served by event-driven or intermediate-database patterns.