Qeasy Cloud
Get Started

Writing Back DingTalk Production Approval Status to a CRM Production Order: A Single-Strategy Tutorial

· 系统管理员· Integration Solutions· 23 views· 4 min read
小满OKKICRMDingTalk单策略教程钉钉集成生产订单审批回写公有云

What This Strategy Solves

At a manufacturing customer, production-approval workflows run in DingTalk. Once an approval completes, the business expects the production-order status in the CRM to automatically flip from "pending" to "completed." It sounds like changing a single field, but in practice DingTalk's approval-instance callbacks are often delayed and the form-control field names are messy, so manual syncing drops entries. This single strategy exists for one job: DingTalk production-approval outcome → CRM production-order status.

Data Flow and Field Mapping

The flow is DingTalk → Qeasy → CRM. The source calls topapi/processinstance/get to pull approval instances; the target calls /v1/invoices/order/push to push the status. The middleware does two things: normalize the cryptic TextNote_* control fields from DingTalk, and reverse-lookup order_id in the CRM by order number.

RoleKey FieldNotes
Source – DingTalk流水号 (serial number)Approval-instance unique key, used for deduplication
Source – DingTalkTextNote_IQXZ8ZWDA0G0 / TextNote_16OTUV6D29UK0Business fields on the form, must be normalized in the middleware
Source – DingTalk发起部门 / 下单品牌所属部门Used for permission and ownership checks
Middleware订单编号 (normalized)Bridge to the CRM side
Target – CRMorder_idReverse-looked-up from order number; required on update
Target – CRMstatusA fixed constant for the "completed" state

One important point: order_id is not carried directly from the source. It is produced by a _findCollection reverse-lookup keyed on the order number — and this is the single most failure-prone part of the strategy.

How to Configure It on Qeasy

We built this on the Qeasy Data Integration Platform during on-site work. The configuration has three blocks:

  1. Source collector: WebAPI type, endpoint topapi/processinstance/get, method POST, effect=QUERY. Response fields are expanded via _autoFillResponse so every TextNote_*, 发起部门, and 下单品牌所属部门 is surfaced — otherwise downstream mapping will silently miss fields.
  2. Target executor: EXECUTE type, endpoint /v1/invoices/order/push. order_id is bound through _findCollection to an order-mapping collection using where order_no={{订单编号}}; status is a fixed constant — the numeric value that represents "completed." This reflects a common pattern among Qeasy customers: centralized code mapping, so magic numbers like status codes don't drift across scripts.
  3. Scheduling: the source runs every 10 minutes (0-59/10 7-22 * * *); the target is offset by one minute (1-59/10 7-22 * * *) so both ends never contend for the same row.

Implementation Steps

  1. Incremental starting point: do not scan historical approval instances on the first run. Configure the incremental cursor to only fetch approvals that are newly created after the start time and already in the "completed" state. Historical data is backfilled by a separate one-shot job — otherwise the database takes a hit on day one.
  2. Full-trigger rollout: once the strategy has run stably for two or three cycles, manually trigger a one-off full re-scan to backfill any "completed" approvals that were missed. Run it once and stop — do not put it into the regular schedule.
  3. Schedule frequency: every 10 minutes during business hours; lower to 30 minutes or pause at night. Approval callbacks themselves have minute-level latency; polling more aggressively just wastes quota.
  4. Post-launch: for one week, sample 10 records per day and compare DingTalk's approval state with the CRM's order state to confirm consistency. Also watch the target endpoint's failure rate — most failures come from order_id lookups that return empty, which we cover in the lessons section.

Lessons from the Field

  • Typical mistake: pushing the raw TextNote_* field straight into the CRM as the order number. Control-field names can be renamed by form admins at any time. Business fields must be normalized in the middleware first; the safe approach is to reference a dedicated "approval field → business field" mapping table.
  • order_id lookup returns empty: the order number on the approval form and the CRM's order_no differ in format — case, surrounding whitespace, prefixes — so _findCollection finds nothing. The safe approach is to add a trim + case-normalize step in the middleware, and to fall back to fuzzy matching when needed.
  • Duplicate writes: the same approval instance is fetched by multiple scheduling cycles, the target endpoint has no idempotency check, and the CRM gets hit repeatedly. The mitigation is incremental and full-scan on separate tracks: incrementals rely on the dedup key (serial number + completed state) inside the scheduling window, while full-scans rely on the target endpoint's idempotent field.
  • Hard-coded status values: the numeric code for "completed" can differ across tenants and business lines. Don't scatter it across multiple strategies. Keep it in a centralized code-mapping table so that switching business lines later only requires one change.
  • Approval-callback latency: DingTalk's approval-completed callbacks are commonly delayed by 5–10 minutes. If the strategy only listens to the live callback, data will be lost. This is precisely why the source uses polling rather than relying solely on callbacks — polling catches up delayed records.

When to Use It and When Not To

Use it for write-backs in a single business line, with stable approval-form fields and a small enum of status values — for example, production-approval completed, contract-approval completed. Don't use it when the approval form changes frequently, when multiple business lines share the same approval template, or when the target-side state machine is more complex than a single "completed" value (e.g., "partially completed," "rejected" each require their own write-back). In those cases, split into multiple strategies instead of stuffing everything into one.

Original content. Please credit the source when reposting: https://www.qeasy.cloud/insights/solutions/strat-okkicrm-dingtalk-5780-ne3141496-7a57e3b7

Comments