Sync Strategy Tutorial: Pingshuitan Sales Orders → DingTalk Gift & Internal Purchase Application with Returned Order Number
What this strategy solves
A retail client runs an internal "gift & internal purchase" application form on DingTalk for employee benefits and sample requests. Once approved, the order lands in Pingshuitan as a sales order. The pain point: the approval ticket and the sales ticket live on different sides with different numbering schemes. Employees manually copy the order number back to DingTalk, and after three months the two ledgers diverge, forcing finance to chase business owners every month.
This strategy is tightly scoped: push Pingshuitan sales orders back into the DingTalk application form and write the Pingshuitan-generated order number onto the DingTalk side. In one project we used the Qeasy data integration platform to host this chain — a single strategy is enough to close the loop, no custom middle table required.
Data flow and field mapping
The flow is "Pingshuitan → middle layer → DingTalk application form", followed by a write-back into DingTalk.
Key field mapping (source: Pingshuitan sales order / target: DingTalk application form):
| Business meaning | Pingshuitan sales order (source) | DingTalk form (target) | Handling |
|---|---|---|---|
| Application number | External order no. / io_id | Form primary key | Direct map, used as join key |
| Sales order number | so_id (generated) | Custom field "Sales Order No" | Write-back |
| Applicant | Customer / order creator | Applicant | Map |
| Line items | Body: sku, qty, price | Body: line rows | Body row-by-row map |
| Total amount | Order total | Application amount | Map |
| Approval status | Order status | Approval result | Status value mapping |
A point we keep reinforcing on customer sites: centralize code mapping. Pingshuitan SKUs correspond to "item name" on DingTalk. We keep the mapping in Qeasy's encoding-mapping component so adding a new SKU on the source side never produces an orphan row.
How to configure it on Qeasy
- Connect source and target: source is the Pingshuitan sales order API; target is the DingTalk custom approval flow bound to that application form.
- Source filter: filter Pingshuitan on
order_status = approvedso drafts are not pushed. - Field mapping: bind header fields one by one; route the body through a "line items" mapping node aligned on
sku + qty. - Write-back: add a "write-back node" at the end of the flow to write the Pingshuitan-generated
so_idinto the DingTalk form's "Sales Order No" custom field. - Exception branches: missing mapping, field overflow, and DingTalk-side form recall each go through separate alerting channels.
Implementation steps (phased scheduling)
We usually roll this out in three stages:
- Stage 1: incremental starting point. Run a one-off backfill for the last 7 days of approved sales orders that have a matching DingTalk application, reconcile both sides, then turn scheduling on.
- Stage 2: full backfill. In Qeasy run a one-time "full write-back" that fills in any application that still has no sales order number. Run this in off-peak hours as a safety net.
- Stage 3: scheduling frequency. Normal polling every 5 minutes, using "last modified time" as the incremental condition. With large order volumes you can compress it to 1–2 minutes, but keep concurrency under DingTalk's rate-limit threshold.
The write-back is split into a sub-flow with the trigger "only fire when source produced a result" so it does not pollute the data with empty writes.
Lessons learned from the trenches
- The write-back field had no uniqueness check. On the first go-live the same DingTalk form was written twice. The safe pattern: before writing back, check whether
so_idis already populated; if yes, skip. - Header arrives before body. Pingshuitan's API sometimes delivers the body one frame later than the header, so DingTalk briefly showed "amount present, lines empty". We later added a "whole document ready" merge condition in Qeasy's assembly node.
- DingTalk-side form recall. After an employee recalled the form, Pingshuitan kept processing the order and the two ledgers diverged. Fix: change the source filter to
order_status ∈ {approved, not approved and not recalled}and route anomalies to a manual queue. - SKU mapping was scattered in scripts. Early on we hardcoded it in JS for speed; once SKUs multiplied it became unmanageable. The common pattern among Qeasy customers is to centralize encoding mapping — load it fully into memory and refresh the delta on a scheduled task.
- Rate limits ignored. DingTalk's custom form write API has a QPS cap. A 5-minute cycle is fine, but a large batch backfill needs pagination plus back-off.
When to use and when not to
Use when the business is approval-driven (internal benefits, sample requests, employee internal purchases) where the order is created from an application and you need the business number written back for reconciliation. Do not use for pure external sales order sync (no DingTalk approval involved), cross-org consignment (approval flow lives elsewhere), or extremely large volumes that need streaming — those should go through a dedicated bulk channel.