Production Inbound Sync in Practice: MySQL to Kingdee Cloud for Material-Supplied Outsourcing
What This Strategy Solves
In a material-supplied outsourcing model, finished goods from the shop floor must be written back as inbound documents in the ERP. The source lives in a MySQL business database on the shop-floor side, and the target is Kingdee Cloud. Codes, organizations, and date conventions do not line up between the two, so once documents pile up, outsourcing reconciliation goes wrong. We use the Qeasy Data Integration Platform to wire this chain end to end: SQL extraction, document transformation, and target writeback become a single schedulable and observable strategy.
Data Flow and Field Mapping
The overall direction is MySQL (source) → Qeasy middle layer (transformation) → Kingdee Cloud (target). The source side is a SQL query that joins inbound confirmation details to planning tracking numbers and pricing tasks, and finally builds the production order number, inbound document number, date, and other key fields. The target side writes the production inbound document via batchSave.
The key field mapping table below shows source labels mapped to target fields; the middle layer mainly handles organization and document type mapping:
| MySQL Source Field | Meaning | Kingdee Cloud Target Field | Mapping Note |
|---|---|---|---|
| 入库单号 | Document number | FBillNo | Passed through; serves as unique identifier on the target |
| 日期 | Business date | FDate | Unified to yyyy-MM-dd |
| 供应组织 | Supply org code | FPrdOrgId / FStockOrgId | case mapping: T01.01→T01.06, T04→T04 |
| 成品编号 | Material number | FMaterialId | Translated via material mapping table |
| 入库数量 | Received quantity | FQty | Numeric pass-through |
| 生产订单号 | Source order | FPrdNo | Prefix distinguishes order type |
| 单据类型 | Fixed value | FBillType | Hard-coded to the production inbound document type |
The source-side document number is generated as RKB + primary key ID, and that same value flows into FBillNo on the target, giving natural idempotency.
Configuring in Qeasy
In the Qeasy Data Integration Platform, create a new strategy, select MySQL as the source platform and Kingdee Cloud as the target.
Source-side configuration essentials: choose select as the API type with SQL execution. Paste the main query into main_sql, expose paging with :limit and :offset, and surface both inside the main_params object. Use update_time as the incremental field; the starting point is managed by the Qeasy cursor — first run is full, later runs pick up deltas based on the schedule window.
Target-side configuration essentials: choose batchSave as the API, POST method, use the document number as the primary key, and turn on idCheck. FPrdOrgId and FStockOrgId use a _function case expression to resolve the supply organization dynamically; fields such as owner type and stock direction are written as fixed values or expressions driven by the material map and stock status.
One common approach for code mapping: do not scatter case logic across individual fields. Centralize organization, material, and customer mappings in Qeasy mapping tables, and let field expressions reference variables only. One of our customers got burned this way — organization mapping was scattered across more than two hundred strategies, and when the upstream org code was tweaked, it took a full week to fix.
Implementation Steps
Phase 1, confirm the incremental starting point. In the source MySQL database, locate the maximum already-synced update_time and use it as the starting point for the Qeasy cursor. Also confirm that the rows in sys_config referenced by the SQL are readable, otherwise the date-window logic in the query silently breaks.
Phase 2, trigger a full run. First run manually with a full load and watch the Qeasy runtime logs to confirm the inbound document number, date, and organization land correctly in Kingdee Cloud. Be sure to enable Qeasy's "exception document isolation" — failed rows should sit in a quarantine queue and be handled individually, not block the whole batch.
Phase 3, scheduling frequency. Source side every 3 minutes, target side every 4 minutes, with the windows offset so the target does not pull while the source is still extracting. Set the source crontab to the 3rd minute past the hour and the target to the 4th minute, naturally creating a 1-minute buffer.
Final step, route Qeasy alerts into enterprise WeChat or email so failures exceeding a threshold push a notification.
Lessons Learned from Rollouts
Organization mapping placed in the wrong spot. Writing case inline on every target field means one change has to be replicated many places. The safe approach is to push organization and material mapping into a centralized mapping table.
Date format drift. The source update_time is datetime, but the target expects yyyy-MM-dd; without conversion in the middle layer, you get odd results such as August 1st turning into 8.0. This is where things tend to go wrong; the reliable approach is an explicit DATE_FORMAT inside a _function.
Idempotency key not set. The source document number is RKB+ID; if idCheck is off on the target, reruns will create duplicates. Always turn idCheck on.
Hard-coded start time in SQL. A literal like a.update_time>'2023-08-01' in the source material is fine for a one-time backfill, but a production strategy must hand the cursor over to Qeasy.
No health check on configuration dependencies. The SQL depends heavily on sys_config. If rows are wiped, the entire strategy silently returns an empty set. Add a lightweight pre-check strategy in Qeasy that patrols the key configuration rows daily.
When to Use and When Not
This pattern fits production inbound documents flowing from a shop-floor MySQL database into Kingdee Cloud under a material-supplied outsourcing model, where document volume is moderate and near-real-time sync is required. It does not fit cross-legal-entity scenarios, month-end batch consolidation where combined vouchers are needed, or early-stage business systems whose table structures and field semantics are still unstable.