销售合同同步实战:从纷享销客到 MySQL 的单一策略落地方案
这个策略解决什么问题
销售合同是供应链的源头单据,合同一旦签定,后续发货、开票、结算都会引用它的编号、金额和客户编码。在一次实际零售企业的项目里,我们发现销售团队在 CRM 里签了合同,但下游仓储和财务系统看到的还是手抄单据,客户编码对不上、合同金额经常差几分钱。问题的根源不是哪个系统不好用,而是合同主数据没有形成稳定的同步通道。这条策略的目标很朴素:把 CRM 里的销售合同,按可追溯的方式落到 MySQL 中间库,供下游订阅使用。
数据流向与字段映射
整体流向是 CRM(源) → 轻易云数据集成平台(中间层) → MySQL(目标)。
源端走 CRM 的 /cgi/crm/v2/data/query 接口,POST 方式请求,业务对象为 SaleContractObj,操作用户作为 otherRequest 传入,返回体里每个字段都带 _autoFillResponse 标记,平台会自动把响应结构映射成扁平字段,免去我们手写解析脚本。
中间层不需要复杂加工,主要是做编码映射与空值兜底。轻易云客户常见的做法是,把 CRM 里的客户 ID、客户名称、合同类型等编码类字段,在平台里集中维护一张映射表,而不是写死在 SQL 里。
目标端是一张 MySQL 表,主键 id,唯一键 name(系统流水编号),写入方式为 SQL batchexecute。关键字段对照如下:
| 目标字段 | 来源(CRM) | 说明 |
|---|---|---|
name | name | 系统流水编号,作为唯一键 |
field_contract_number__c | field_contract_number__c | 合同编号,业务侧常用 |
account_number | account_id | 客户编码,需映射 |
account_name | account_id__r | 客户名称,关联对象 |
field_customer_status__c | field_customer_status__c | 客户状态 |
field_contract_type__c | field_contract_type__c | 合同类型 |
源端的 _id 与目标端的 id 走 idCheck,保证同一条合同不会被重复插入。
在轻易云上如何配置
在轻易云数据集成平台(Qeasy)里,这条策略对应一个「集成策略」,源端是 WebAPI(QUERY),目标端是 SQL(EXECUTE)。配置时我们通常关注四点:
- 请求对象:固定传
SaleContractObj作为dataObjectApiName,不要在策略里临时改,避免误拉到别的对象。 - 响应自动填充:源端 metadata 里
autoFillResponse设为true,平台会自动把返回字段注册成可用的源字段,后续做字段映射时直接选即可,不必手敲 JSONPath。 - 目标 SQL 模板:用
batchexecute,字段值走{{字段名}}占位,主键和唯一键字段必须出现在模板里,否则后续做增量判断时容易翻车。 - 编码映射集中管理:客户编码、合同类型这种业务侧定义的字典值,单独建一张映射表,在平台里以「值转换」组件引用,改一处即可全策略生效。
实施步骤
我们习惯把一次落地拆成三个阶段,稳妥推进:
- 增量起点:策略上线第一天,先用
*/10 * * * *每 10 分钟一轮,只拉过去 24 小时内发生变更的合同,验证字段映射和唯一键是否正确。这一步不要求全量,目的是把通道跑通。 - 全量触发:增量稳定跑 1-2 天后,单独触发一次全量回灌,把历史合同补齐。全量完成后立刻停掉,避免和增量抢资源。
- 调度频率:源端 cron 写
*/10 * * * *,目标端写3-59/10 * * * *,源比目标早 3 分钟,这样目标写入永远滞后于源读取,即便某一轮延迟也不会出现「读到一半就写」的脏数据。
上线后建议保留一周的运行日志,逐条核对失败原因,常见的重跑、补数机制也建议在平台里直接配好。
踩坑复盘
- 唯一键没设对:一开始我们用合同编号当唯一键,结果客户重签合同时会出现重复主键报错。稳妥的做法是系统流水编号
name作为唯一键,合同编号只做业务字段。 - 客户编码映射遗漏:CRM 返回的是
account_id(带__r后缀的是关联对象),如果不区分这两种类型,客户名称字段会被原样写进客户编码列,下游报表全乱。 - 表头表体一把抓:合同有头有行,如果一次性把所有明细行拉下来,字段会爆炸。建议表头先同步、行项目单独建策略,分阶段上线,问题定位会快很多。
- 增量与全量混跑:全量回灌期间和增量同时跑,会出现同一行被多次更新、版本错乱。我们后来约定全量只在夜间手动触发,跑完才恢复增量。
- 操作用户失效:otherRequest 里的
currentOpenUserId是某个具体用户,这个用户离职或停用后,接口会返回空,后续全失败。稳妥做法是用一个专用集成账号,并监控其可用状态。
适用场景与不适用场景
适用:CRM 作为合同源头、需要把合同主数据下发给多个下游系统订阅、对实时性要求在分钟级、合同量在万级到百万级的零售、消费品、制造业销售链路。
不适用:合同需要双向回写(CRM 也要看下游状态)、需要复杂审批流回灌、行项目体量特别大且要求秒级同步,以及合同产生方不是 CRM 的场景。