Sync Sales Outbound Tracking Number Back to Kingdee Cosmos: An Incremental Single-Strategy Walkthrough
What This Strategy Solves
After a sales outbound, the MES side writes the tracking number into its own attribute table; the sales outbound document in Kingdee Cosmos must reflect that number, otherwise downstream invoicing, reconciliation and logistics matching will stall. This strategy does one thing: push records in MySQL that already have a tracking number and have not yet been written to Kingdee, into the Kingdee sales outbound document and trigger a save. It is a typical "field-level write-back", not a full document rebuild.
Data Flow and Field Mapping
Data flows from MySQL, through the middleware layer of the Qeasy integration platform (轻易云数据集成平台), into Kingdee Cosmos.
The source side (MySQL, WebAPI query) joins three tables: mt_so_delivery_not_label_approve for the document number, mt_instruction_doc for the internal ID, and mt_instruction_doc_attr for the tracking number and last update time. The key filter conditions are attr_name = 'TRACKING_NUMBER', the tracking number is non-empty, the document number does not start with XSCK, and the "sync flag" is either null or last_update_date >= last sync time, ensuring only incremental records are picked up.
The target side (Kingdee Cosmos, BatchSave) only writes three fields: FID uses the source-side internal ID, F_FSYNCMOM is set to true as the sync flag, and FCarriageNO receives the tracking number. FormId is fixed as SAL_OUTSTOCK, Operation is BatchSave.
| Source Field (MySQL) | Middleware Variable | Target Field (Kingdee Cosmos) | Notes |
|---|---|---|---|
instruction_doc_id | sourceid | FID | Document ID on Kingdee side |
sd_code | 单据编号 | — | Used for filtering only, not written |
attr_value (TRACKING_NUMBER) | 运输单号 | FCarriageNO | Core write-back field |
last_update_date | 更新时间 | — | Used for incremental judgment |
| — | — | F_FSYNCMOM | Fixed as true, flag of write-back completion |
How to Configure in Qeasy
The source side uses a WebAPI query node with api=select; the request carries main_params placeholder, and the SQL uses :limit :offset dynamic pagination. Note that :limit is not string concatenation but parameter binding; Qeasy injects in placeholder order, otherwise pagination will overflow in later pages.
The target side uses a batchSave execution node with api=batchSave, FormId=SAL_OUTSTOCK, Operation=BatchSave. The request body carries only three fields — keep it lean.
Qeasy's "centralized encoding mapping management" shines in this scenario: the tracking number itself does not need encoding conversion, but the semantics of the "sync flag" is best maintained centrally as a constant dictionary in the platform rather than scattered across strategies — when similar write-back strategies are added later, only one place needs to change.
Implementation Steps
Step 1, confirm the incremental start point. On first go-live, do not use a full sync; use last_update_date >= last sync time to filter out historically written records and only write back truly new tracking numbers. If the full volume is poured in initially, the existing F_FSYNCMOM=true records on the Kingdee side will be written again, bloating logs needlessly.
Step 2, set source scheduling to */7 * * * * and target to */3 * * * *. Slower source pulling is fine; the target save frequency is higher, ensuring tracking numbers land within minutes.
Step 3, first manually run the save API on 2-3 historical documents in Kingdee to confirm BatchSave permissions and required fields for SAL_OUTSTOCK. A typical error is that Kingdee has an "enable" switch for custom fields; if not enabled, writes are silently discarded.
Step 4, small-volume canary. Restrict the site_id range in the source SQL to one factory first, run for half a day and observe whether FCarriageNO is written back successfully on the Kingdee side and whether F_FSYNCMOM is set.
Step 5, broaden the scope and start formal scheduling.
Pitfall Review
Pitfall 1, the sync flag is not a universal idempotency guard. The source SQL reads "t4.attr_value is null or t4.attr_value <> 1", meaning unset or not set to 1 are both treated as incremental. But if the same tracking number is changed on the MES side, last_update_date updates, and it will be pushed again as incremental to Kingdee — this is by design, but be aware of it.
Pitfall 2, the sd_code not like 'XSCK%' filter is critical. Some document number prefixes in MES conflict with Kingdee's sales outbound prefix; if not excluded, internal MES documents will be pushed to Kingdee and fail outright. The safe practice is to hardcode the "source identifier" filter in every write-back strategy.
Pitfall 3, Kingdee BatchSave is unfriendly to empty values. If FCarriageNO is an empty string, some versions refuse to save. The source SQL already filters attr_value <> '', but if the Qeasy middleware accidentally passes empty values through, errors will only appear at the save stage, making the troubleshooting chain long.
Pitfall 4, :limit :offset overflows on large MySQL result sets. When historical tracking numbers accumulate, offset gets slower the deeper it goes. The safe practice is to use a last_update_date + id dual-key cursor for pagination rather than pure offset.
Pitfall 5, inconsistent scheduling frequencies cause order chaos. Source every 7 minutes, target every 3 minutes; if the same batch is fetched twice by the source, the target writes twice, triggering concurrent save validation on the Kingdee side. The recommendation is to keep the target at the same cadence as the source, or add a lightweight "same sourceid serialization" lock in Qeasy.
Applicable and Non-Applicable Scenarios
Applicable: field-level write-back after sales outbound, single-field write-back for tracking number/batch number/logistics number, incremental sync in private deployment environments. Not applicable: full document rebuild, scenarios requiring row-level strong transactional consistency, or cross-organization bulk write-back.