Sync Kingdee Production Orders to MySQL: A Hands-On Qeasy Configuration Guide
What This Strategy Solves
Syncing production orders from Kingdee Cloud (ERP) to MySQL looks trivial, but for a manufacturing client we worked with, this link is the data backbone feeding MES, scheduling, and shop-floor dashboards—one missing line and the workshop stalls. The common pain points: Kingdee production orders cycle through multiple statuses (created, approved, started, finished, closed), the header/line payload is huge, custom fields are sprinkled in, and any oversight results in "status changed in Kingdee but not in MySQL." This strategy uses the Qeasy Data Integration Platform to incrementally land production orders into MySQL reliably for downstream consumers.
Data Flow and Field Mapping
The flow is straightforward: Kingdee Cloud (source, side B) → Qeasy middle layer → MySQL (target, side A), direction B_TO_A, type QUERY_ONLY + SQL EXECUTE.
The source is Kingdee's executeBillQuery (POST), with FBillNo as the document number and FTreeEntity_FEntryId as the line-level primary key. Here is a curated field mapping (excerpt):
| Business Meaning | Source Field | Target MySQL Field | Notes |
|---|---|---|---|
| Doc primary key | FID | FID | Primary key, idempotency anchor |
| Document number | FBillNo | FBillNo | Business identifier |
| Workshop name | FWorkShopID0.FName | FWorkShopID0_FName | Linked to master data |
| Creator/Approver | FCREATORID.FName / FApproverId.FName | FCREATORID_FName / FApproverId_FName | Display name |
| Create/Approve date | FCreateDate / FApproveDate | FCreateDate / FApproveDate | Datetime |
| Material code/name | FMaterialId.FNumber / FName | FMaterialId_FNumber / FMaterialId_FName | Line level |
| Quantity | FQty | FQty | Line level |
| Planned start/finish | FPlanStartDate / FPlanFinishDate | FPlanStartDate / FPlanFinishDate | Line level |
| Sales order no. | FSaleOrderNo | FSaleOrderNo | Cross-doc link |
| Actual start/finish | FStartDate / FFinishDate | FStartDate / FFinishDate | Status inference |
| Status | FStatus | FStatus | Business status |
| Line primary key | FTreeEntity_FEntryId | FTreeEntity_FEntryId | Composite with FID |
| Lot / Unit | FLot / FUnitId | FLot / FUnitId | Line level |
The target side uses MySQL REPLACE INTO against table order_production. We use REPLACE (not plain INSERT) because production orders get "rewritten" whenever status changes—Kingdee will re-push, and we need primary-key-based overwrite. limit is set to 800, the conventional batch ceiling paired with source-side pagination.
How to Configure in Qeasy
In the Qeasy console, follow these configuration points:
- Source platform: pick
Kingdee.Cloud; configure tenant and authorization (we generalize the "Kingdee Cloud" instance description—no specific account book IDs). - Target platform: pick
MySQL; configure connection and target database. - Source action: API =
executeBillQuery, method = POST, effect = QUERY. - Target action: type = SQL, effect = EXECUTE; main statement uses
REPLACE INTO, limit = 800. - Field mapping: in Qeasy's mapping area, wire each source
requestfield to the target SQL parameter. Linked fields (e.g.,FWorkShopID0.FName) must be written invalueper Kingdee query syntax—not inlabel, which is display-only. - Code mapping: workshop, material, unit master data codes are centralized in Qeasy's mapping tables to avoid scattering across strategies.
- idCheck: enable on target with
idCheck=true, using FID + FTreeEntity_FEntryId as composite key. - Scheduling: source crontab =
*/15 7-22 * * *, target crontab =*/16 7-22 * * *. The 1-minute offset ensures "read-then-write" to avoid empty writes from racing ahead.
Implementation Steps
On the customer site, we typically walk through four steps:
Step 1: Align the incremental start point. Before any full run, ensure the order_production table is created in MySQL (with all fields and proper indexes) and reconcile the recent 30 days of orders with the source. Qeasy supports a "start time variable" so you can begin incremental pulls from a chosen point instead of years of history.
Step 2: Trigger the full sync. Manually trigger a full sync in Qeasy and observe return volume and latency. Focus here: does the Kingdee API paginate correctly? Are custom fields (F_QOQG_*) missing?
Step 3: Phased scheduling (header / line). Production orders are header + line. We recommend running header-related fields first (workshop, creator, status, memo), then line-level fields (material, qty, dates). In Qeasy's dependency graph, declare depends_on explicitly so the line data never lands before the header.
Step 4: Daily incremental + anomaly monitoring. Scheduling runs every */15 minutes; Qeasy logs pulled count, written count, and failure reasons per batch. Configure an alert for "2 consecutive zero-write batches" to catch silent upstream stalls.
Pitfall Post-Mortem
- Linked fields written into
label. The most common crash:FWorkShopID0.FNamemust go intovaluefor the Kingdee query API to recognize it;labelis just UI text. - Wrong choice between
REPLACE INTOandINSERT. Production order statuses cycle (start → pause → resume → finish); you must useREPLACEorINSERT ... ON DUPLICATE KEY UPDATE, or duplicates will accumulate. - Custom fields not fully configured. Kingdee's
F_QOQG_*are user-extended fields and easy to miss. Downstream MES often needs them for routing classification—missing one means a retrofit later. - Too-aggressive scheduling triggers Kingdee throttling.
executeBillQueryhas tenant-level call limits;*/15is the empirical sweet spot. Go faster and you'll get throttled. - Header/line ordering chaos. Without
depends_on, Qeasy runs in parallel and the line can arrive first. Downstream consumers judging by header status will then misbehave. The safe approach: declare explicit dependencies, or build a view in MySQL that joins header+line for eventual-consistency checks.
When This Applies (and When It Doesn't)
Applies: one-way sync of Kingdee Cloud → MySQL for production orders, where downstream MES/scheduling/BI consumes MySQL data and you need to preserve custom fields, lot numbers, and cross-doc links (sales order number).
Doesn't apply: scenarios requiring bidirectional write-back (MySQL changes pushed back to Kingdee); ultra-high-volume (>100k/day) Kingdee orders needing sub-minute latency—use Kingdee's open-platform message push instead of polling.