BOM Master Sync in Practice: Incremental Pattern from Kingdee Cloud to MES
What This Strategy Solves
Pushing the Bill of Materials (BOM) from Kingdee Cloud to MES is almost always on the integration roadmap for any manufacturer. The hard part is not "can we push it," but rather: BOM is a parent-child structure with many lines that change frequently with process revisions; documents have draft/approved/closed states; and the field naming for quantity, scrap, and BOM version never matches between two systems. In one real project, the shop floor reported quantity mismatches three months after BOM went live; root cause was that document-status filtering was missing and the quantity numerator/denominator was not actually being passed through. So this strategy must solve: getting approved or closed BOMs into MES incrementally, safely, and at a controllable cadence.
Data Flow and Field Mapping
End-to-end flow: Kingdee Cloud (source) → Qeasy Data Integration Platform (middleware) → YSD MES (target). The source uses executeBillQuery to pull ENG_BOM; the target uses /api/bom/createBom (create) or /api/bom/editBom (update).
Key field mapping:
| Target Field (MES) | Source/Rule (Kingdee) | Mapping Type | Notes |
|---|---|---|---|
| companyCode | fdd8dc88 | CONSTANT | Fixed company code |
| erpId | FID | DIRECT | ERP primary key |
| erpParentId | 0 | CONSTANT | Root node fixed |
| materialUuid | FMATERIALID | DIRECT | Parent material ID |
| outerPartNo | FMATERIALID_FNumber | DIRECT | Parent material code |
| lossRate | FSCRAPRATE | DIRECT | Variable scrap rate |
| source | FITEMPPROPERTY | DIRECT | 1 Purchase / 2 Make / 3 Subcontract |
| property | 1 | CONSTANT | Physical |
| bomVersion | FNumber | DIRECT | BOM version |
| createName | FCreatorId | DIRECT | Creator |
| createTime | REPLACE(FCreateDate,'T',' ') | TRANSFORM | ISO time normalization |
| items | sub-collection | COLLECTION | Children mapped separately |
doseSon/doseMom are currently hard-coded to 1/1 — a classic "ship the wiring first, refine later" placeholder.
How to Configure on Qeasy
We used the Qeasy Data Integration Platform (轻易云) to host this strategy. Four configuration layers:
- Source connector: Register Kingdee Cloud, configure
executeBillQuerywith form IDENG_BOM, enable incremental time-window mode. - Target connector: Register the MES API connector with both
/api/bom/createBomand/api/bom/editBomfor create vs. update. - Field mapping: In the visual mapping panel, apply DIRECT / CONSTANT / TRANSFORM / COLLECTION per the table above;
createTimeuses_function REPLACE('{{FCreateDate}}','T',' ')to normalize the date format. - Centralized code mapping: Kingdee
FITEMPPROPERTYand MESsourceare aligned today, so direct mapping works; if they diverge, promote the rule into a centralized code-mapping table rather than scattering it across strategies — one of the most common patterns we see on Qeasy projects.
Implementation Steps
- Phase 1 — Materials before BOM. BOM depends on parent materials existing in MES. Run the material strategy first and stabilize it, then start BOM. We follow an A→B→C sequence ordering.
- Phase 2 — Full trigger. First go-live uses full sync: remove the time filter and flush every approved/closed BOM as a baseline.
- Phase 3 — Switch to incremental. After baseline, change the filter to
FDocumentStatus in ('C','D') AND (FModifyDate >= LAST_SYNC_TIME OR FApproveDate >= LAST_SYNC_TIME). - Phase 4 — Scheduling. Run at the top of every hour (
crontab: * 7-22 * * *), covering 7:00–22:00 working hours. If BOM changes are very frequent, tighten to every 15 minutes, but watch source API QPS. - Phase 5 — Header and body staged go-live. Bring up header mapping first, then enable the
itemscollection. This is another common Qeasy pattern — staging makes issues easier to localize.
Lessons from the Trenches
- Status filter missing. Writing only the time window without status filtering pushed drafts and rejected BOMs as well, polluting MES. Safer rule: status condition first, time condition second.
- Quantity hard-coded to 1. Using
1/1as a placeholder works to get the wiring live, but forgetting to replace it later caused quantity mismatches. Mark the mapping with a "TODO: connect FNUMERATOR/FDENOMINATOR" note and review. - The
Tin ISO dates not replaced. Kingdee returns ISO timestamps withT; MES rejected them. One_function REPLACE('{{FCreateDate}}','T',' ')fixed it — a typical use of Qeasy expression functions. - Sub-item collection not configured. Header ran, but
itemswas left unmapped — shop floor could not pick materials. Header and body must be staged and verified. - Wrong dependency order. Running BOM before materials made
materialUuidunresolvable and writes failed. Qeasy'sdepends_onfield exists precisely for this kind of prerequisite ordering.
When This Fits and When It Does Not
Fits: manufacturers running ERP and MES as decoupled systems, with BOM master data owned in ERP and consumed by MES; clear document state machines; moderate document volumes. Does not fit: scenarios where BOM is owned by MES, change frequency is extreme (per-second, requires a message queue), or ERP and MES share the same database.