Qeasy Cloud
Get Started

Purchase Requisition Approval Event Write-Back: A Practical Integration Solution from DingTalk to Kingdee Cloud Cosmos

· 系统管理员· Integration Solutions· 8 views· 4 min read
Kingdee CloudDingTalk采购申请单同步钉钉金蝶集成审批事件回写轻易云供应链集成私有化部署

What This Strategy Solves (Scenario and Value)

In one of our real projects, a retail company ran its purchase requisition flow as follows: the business team initiates requests in DingTalk → the approval flow runs inside DingTalk → a purchase requisition is then created in Kingdee Cloud Cosmos. The problem was: once the approval was completed, fields such as the document status, approval number, and handler on the Kingdee side remained empty, and the business team often had to go back into Kingdee and fill them in manually.

This strategy is meant to solve exactly that — taking the "approval completed" event from DingTalk, along with the approval number and handler, and writing them back in a stable manner to the corresponding purchase requisition in Kingdee Cloud Cosmos, so the approval trail and the business document stay aligned. It is not responsible for the initial creation of the document; it only handles the "approval write-back" segment — a typical lightweight, directional, low-frequency sync.

Data Flow and Field Mapping (Source → Middle Layer → Target)

The data flow is unidirectional: DingTalk (source) → Qeasy middle layer → Kingdee Cloud Cosmos (target). The schedule runs every 3 minutes (*/3 * * * *), executing as a "polling pull + incremental filter" pattern.

On the source side, key fields of this approval instance are read from DingTalk's approval instance endpoint (topapi/processinstance/get, POST), including the document number, handler, request reason, request date, purchasing organization, etc., serving as the business context for the write-back.

On the target side, Kingdee Cloud Cosmos's batchSave endpoint is called (POST, Operation=Save), with the business object FormId fixed to PUR_Requisition. The key field mapping is as follows:

Business MeaningDingTalk FieldQeasy Middle VariableKingdee FieldNotes
Document idDocument number{{单据编号}}FIDRetrieved via _findCollection by FBillNo
DingTalk approval numberbusiness_id{{extend.business_id}}F_ora_PSWZ_TextUnique identifier, used for idempotency
Approval-completed flagF_ora_CheckBoxFixed value "0", used for business filtering
FormIdPUR_RequisitionRequired, identifies the business object

There is one important engineering point here: FID is not passed in from DingTalk — it is looked up inside Qeasy via _findCollection against the Kingdee purchase requisition collection by document number. This is one of the common patterns we see among Qeasy customers — "centralized encoding mapping management," where the cross-system business-number ↔ system-primary-key mapping is converged into the integration platform rather than stored separately in both business systems, which makes reconciliation much easier later on.

How to Configure It on Qeasy

In the Qeasy data integration platform, this strategy follows a three-part structure: source mapping + target mapping + scheduling.

Source-side configuration highlights: select the endpoint topapi/processinstance/get, set Effect to QUERY, turn on autoFillResponse. Only keep the response fields that are actually used downstream — document number, handler, request reason, request date, purchasing organization — no need to pull everything. Turn on idCheck and use the DingTalk-side instance id for deduplication, so the same approval is never written back twice.

Target-side configuration highlights: select the endpoint batchSave, set Effect to EXECUTE, set the business object FormId to PUR_Requisition, and Operation to Save. For the FID field, use _findCollection to look up FID in Kingdee's purchase requisition collection by FBillNo = {{单据编号}}. This converges the "DingTalk document number → Kingdee internal primary key" mapping into the Qeasy layer. Set F_ora_PSWZ_Text to {{extend.business_id}} as the idempotency key; set F_ora_CheckBox to the fixed value "0".

For scheduling, the crontab is */3 * * * * with idCheck enabled, ensuring the same approval event will not be persisted multiple times.

Implementation Steps (Phased Scheduling)

Phase 1 — define the incremental starting point: first stabilize the upstream strategy "purchase requisition Kingdee → DingTalk," so that corresponding documents exist in Kingdee and corresponding approval instances exist in DingTalk, and the two ends can match via FBillNo ↔ business_id. This is the prerequisite for the write-back strategy — depends_on cannot be empty.

Phase 2 — trigger full-volume verification: do not enable the formal schedule yet. First, use approval events from the past 1–2 days to perform a one-time backfill, and observe whether _findCollection consistently finds FID and whether the approval number is correctly written into F_ora_PSWZ_Text. If the lookup hit rate is low here, it means the encoding mapping rules on the two ends are inconsistent, and you should fix the upstream strategy rather than hard-patching inside the write-back.

Phase 3 — connect the formal schedule: set the crontab to */3 * * * *, run in observation mode first, and check whether the count of write-backs over 1–2 business days roughly matches the count of DingTalk approval-completed events before switching to production. Running incremental and full-volume in parallel is the conservative approach we commonly see among Qeasy customers — daily incrementals are handled by the scheduled job, while a one-time full-volume catch-up is used when data anomalies occur.

Pitfalls and Lessons Learned

  1. Low lookup hit rate, errors thrown directly. A classic mistake here is "Kingdee's FBillNo is prefixed but DingTalk's isn't," causing _findCollection to fail to find FID. The safe approach is to maintain the FBillNo generation rule centrally in Qeasy and have both strategies share the same definition.
  2. Duplicate write-backs, multiple approval records appearing on the Kingdee side. The cause is idCheck not being enabled, or being enabled on the wrong field. The idempotency key for approval events must be the DingTalk-side approval instance id, not the document number.
  3. Write-back succeeds but the business side cannot see the approval number. This is usually because the custom field F_ora_PSWZ_Text has not been attached to the PUR_Requisition header, or the field has not been published. The custom field must be created and published on the Kingdee side first, then mapped in Qeasy — the order cannot be reversed.
  4. With */3 frequency, queues pile up during peak approval hours. Such short-interval polling is suitable for lightweight write-backs; if the batch pulled in one round grows larger, you need to add pagination or rate limiting instead of blindly tightening the crontab.
  5. In private-deployment environments, DingTalk callbacks fail and polling is used repeatedly. You need to determine whether this is a DingTalk-side app configuration issue or a network issue. Do not repeatedly change the api inside the Qeasy strategy — troubleshoot the source side first.

Applicable and Non-Applicable Scenarios

Applicable: DingTalk is used for approvals, Kingdee is used as the business backbone, documents are created in Kingdee, and approval events need to be written back to align the trail — typical cases are purchase requisitions, expense reimbursement forms, and other processes where approvals and business documents must correspond one-to-one.

Not applicable: scenarios where the document needs to be created for the first time in Kingdee (that should go through the "purchase requisition Kingdee → DingTalk" strategy); nor is it suitable for large-volume, cross-organization, complex approval orchestration — that kind of scenario requires a dedicated approval middle platform, not a write-back strategy that runs every 3 minutes.

Original content. Please credit the source when reposting: https://www.qeasy.cloud/insights/solutions/strat-kingdee-cloud-dingtalk-2030-n90c3d572-d03bd451

Comments