Production Order Rejection Sync in Practice: Designing the Revoke Link from Weaver OA to Kingdee Cloud
What This Strategy Solves
In the supply chain of a certain manufacturing enterprise, production orders are initiated for approval in Weaver OA. Once the approval is rejected, the OA-side process closes, but the production order in Kingdee Cloud that has already reserved capacity and occupied materials is not automatically revoked — the workshop still draws materials against it, and the subcontractor still prepares stock based on it.
Strategy SD003 closes this gap: when OA rejects a production order, it automatically sends the revoke signal to Kingdee to void or close that production order. We use the Qeasy Data Integration Platform to do this — turning the rejection event into a traceable revoke request, rather than having business staff manually search for the order in the Kingdee backend.
Data Flow and Field Mapping
The entire link is one-way triggered: Weaver OA (process rejection event) → Qeasy middle layer (assemble revoke request) → Kingdee Cloud (production order revoke/void).
Key field mapping:
| Business meaning | Weaver OA source field | Kingdee target field | Processing notes |
|---|---|---|---|
| Production order number | Application number / process ID | FBillNo / production order document number | One-to-one correspondence, serves as revoke lookup primary key |
| Rejection node | Current approval node | Write into revoke remark or custom field | Used for traceability of rejection reason on Kingdee side |
| Rejection reason | Approval comment | Remark / cancel reason | Truncate length to avoid exceeding API limits |
| Rejection time | OA process end time | Revoke operation time | Based on OA-side time |
| Operator | Current handler account | Revoke operator | Goes through unified identity mapping |
The middle layer writes no business logic — it is only responsible for field translation and event routing. The encoding mapping is centrally maintained in Qeasy's mapping table — one of the common practices among Qeasy customers — to avoid hardcoding scattered across scripts that no one can change three months later.
How to Configure on Qeasy
Source event trigger: Listen to the Weaver OA process-end event, filter out the "rejected" final state, and only collect production-order-related processes. Qeasy's process event listener can be used, with a whitelist to filter only production order processes.
Target revoke action: Kingdee Cloud's production order revoke uses the "void" or "close" interface, depending on the customer's state machine convention. In the Qeasy adapter, these two actions are made configurable items, selected at implementation according to the customer's actual state machine.
Field mapping: All field mappings are uniformly placed in Qeasy's mapping configuration center, where OA fields, Kingdee fields, conversion rules, and default values are all visualized and editable. When adding new fields, only this one place needs to be changed — no code modification.
Idempotency and deduplication: Rejection events may be pushed repeatedly by OA. Qeasy adds a deduplication key in the middle layer — usually a combination of source document number + rejection timestamp + operator — and checks the idempotency table before writing. Already-processed ones are skipped directly.
Exception handling: When the Kingdee-side revoke fails (for example, the order has already been drawn by downstream), Qeasy returns the exception to the corresponding process in OA, sending an in-site message to the applicant for manual handling in Kingdee. This exception link is safer than automatic retry — automatically retrying to revoke an order that has already been put into production is dangerous.
Implementation Steps
We split this synchronization into three rollout phases:
Phase 1 — Incremental starting point: First get the forward link of production order creation (OA → Kingdee new) working. After two weeks of stable operation, layer the revoke on top. Revoke cannot go live together with creation, otherwise you won't know which link has the problem.
Phase 2 — Full trigger: After the incremental link stabilizes, enable the rejection event listener. At first, use sandbox accounts or test documents to run real rejections, verifying that the middle layer can correctly assemble the revoke request and that Kingdee can correctly receive it.
Phase 3 — Scheduling frequency: Rejection is event-driven, not scheduled polling, so the core is the event trigger. But in Qeasy we additionally configure a daily reconciliation task that pulls production orders in the "void/closed" state from the past 24 hours on the Kingdee side and back-checks whether the corresponding rejection records on the OA side match. This reconciliation task runs once a day and can scan through in 5 minutes.
This is a very common "incremental + full reconciliation dual-track" pattern among Qeasy customers: the real-time link carries the main load, and the reconciliation task catches any drift.
Lessons Learned
Pitfall 1: Treating "rejection" as "deletion". Kingdee's production order is a financial/supply chain document with a state machine — physical deletion is almost impossible. The correct semantics are "void" or "close". On the first implementation, we misunderstood it as OA's "delete process" and wrote a DELETE call that failed directly. The safe approach is to clearly list Kingdee's state machine enumerations in the Qeasy adapter, then decide which action to call.
Pitfall 2: Stuffing overly long text into the rejection reason. OA's approval comments are rich text. When truncating, it is easy to miss line breaks or HTML tags. Kingdee's API field length limits are strict. We later unified cleaning in Qeasy's converter: strip HTML, compress line breaks, truncate to 200 characters, and discard the overflow into the next line of the remark.
Pitfall 3: Choosing the wrong idempotency key caused duplicate revokes. Initially we used the single field "source document number" as the idempotency key, but if the same production order was rejected twice (revoked and resubmitted, then rejected again), the first revoke would be swallowed. After changing to a combination of "document number + rejection timestamp", this problem disappeared.
Pitfall 4: Not considering the situation where Kingdee has already been occupied downstream. For production orders already in production or already drawn for materials, the revoke interface returns a failure but it is not a fatal error. The Qeasy side needs to distinguish business exceptions from system exceptions — the former should flow back to OA for manual handling, while the latter should be retried.
Pitfall 5: Weaver OA's process-end event cannot distinguish "normal end", "rejection", or "withdrawal". The three final-state events look identical, so filtering must be done by the final-state field — otherwise normally archived processes will also trigger a revoke. This is a hard requirement for adding filter conditions in the Qeasy event listener.
Applicable and Non-applicable Scenarios
Applicable: Enterprises with private deployment where OA serves as the process entry point and ERP handles execution; production order lifecycle is fully controlled in OA, while ERP only takes over execution and revoke. Not applicable: Scenarios where OA is only auxiliary approval and ERP is the master data source — in that case, rejection should first return to ERP to change state, then flow back to OA, and the link is reversed. It is also not applicable to business models where the production order has already been fully put into production in ERP and cannot be revoked.