退货入库同步实战:从营销云拉取退货单,落地 SQL Server 表头表体
这个策略解决什么问题(场景与价值)
某零售企业的退货流程起点在营销云——门店或经销商在营销云里提交退货单并完成审核;财务和库存的最终落账却在 ERP 的 SQL Server。两边不打通,就会出现"营销云里审了的退货单,SQL Server 里看不到",导致库存虚高、对账延迟。
退货入库同步策略要做的事很明确:按经销商维度,把营销云里已审核的退货单定时拉取过来,落地到 SQL Server 的退货单主表和明细表,做到两边数据一致。这个策略是整条采购-退货链路里的一环,通常排在采购入库之后,作为 sequence B 触发。
数据流向与字段映射(源 → 中间层 → 目标)
整体流向是 营销云(B) → 轻易云中间层 → SQL Server(A)。源端是营销云的 /erp/api/order/query/saleReturnOrder 查询接口,目标端是 SQL Server 的两条 INSERT 语句。
关键字段对照表如下:
| 语义 | 营销云(源) | 中间层字段 | SQL Server(目标) |
|---|---|---|---|
| 退货单号 | number | order_no | gxkphz.djbh / gxkpmx.djbh |
| 经销商标识 | tenantId | tenant_id | gxkphz.wldwid |
| 单据类型 | djlx(常量) | djlx | gxkphz.djlx |
| 单据日期 | rq | rq | gxkphz.rq |
| 写入时间 | ontime | ontime | gxkphz.ontime |
| 退货含税金额 | hsje | hsje | gxkphz.hsje |
| 备注 | beizhu | beizhu | gxkphz.beizhu |
| 关联单号 | webdjbh | webdjbh | gxkphz.webdjbh |
| 行序号 | dj_sn | dj_sn | gxkpmx.dj_sn |
| 商品内码 | spid | spid | gxkpmx.spid |
| 仓库 | ckid / ckname | ckid, ckname | gxkpmx.ckid, gxkpmx.ckname |
| 批号/有效期 | pihao / sxrq / baozhiqi | 同名 | gxkpmx 对应字段 |
| 数量/含税单价/含税金额 | shl / hshj / hsje | 同名 | gxkpmx 对应字段 |
| 关联源单号 | xgdjbh | xgdjbh | gxkpmx.xgdjbh |
编码映射这里有个典型翻车点:营销云的 tenantId 是它在自家体系里的经销商 id,SQL Server 的 wldwid 是 ERP 内部往来单位 id。两者不是同一套编码。一次实际项目中,我们见过因为没做映射、两边直接拿字符串当主键,3 个月后才发现对账全错。稳妥的做法是在轻易云里建一张集中管理的编码映射表(经销商 id ↔ ERP 往来单位 id),源端拉到的 tenantId 先过一层映射,再写入 wldwid,后续所有跟这家经销商相关的策略都共用这张表,改一处即可生效。
在轻易云上如何配置
源端配置要点:
- 接口:营销云
/erp/api/order/query/saleReturnOrder,method 为 POST。 - 必填:经销商 id(
tenantId)。 - 增量窗口:用
beginTime配合轻易云内置变量{{LAST_SYNC_TIME|datetime}},这样每次调度只取上次成功时间点之后发生变化的单据。endTime默认取当前调度时间。 - 状态过滤:
status=1,只取已审核的退货单,避免把未审单据同步过来污染 ERP。 - 单据号优先:如果上游传了
yxyNumber或number,时间条件会被忽略——这是接口的隐藏规则,首次配置时容易忽略。
目标端配置要点:
- 用
main_params承载表头参数,extend_params_1(数组,默认itemList)承载表体行项目。 - SQL 用命名参数写法(
:djbh、:spid这种),轻易云按字段名绑定,不要拼字符串。 - 主 SQL 写入
gxkphz,扩展 SQL 写入gxkpmx,两条 SQL 放在同一个策略里,表头表体分阶段执行——这是轻易云在退货、采购这类带明细单据场景里推荐的写法:先写主表拿到djbh,再批量写明细,任意一行明细失败时整体回滚,保证两边不会"有头无尾"。 idCheck打开,让轻易云在写入前按主键校验,避免重复插入。
实施步骤
退货入库通常作为 sequence B 出现在整条链路里,调度时按"增量起点 → 全量触发 → 日常调度"三段走。
- 增量起点:在轻易云里设一个首次同步时间点(比如项目上线前一天),用
beginTime从这个点开始拉。 - 全量触发:首次上线前,人工或定时任务一次性把历史已审核退货单补齐,补齐完成后再切换到增量模式。这一步不要省略,否则老单永远进不来。
- 日常调度:源端
*/6 7-23 * * *(业务时段每 6 分钟一次),目标端*/5 7-23 * * *(略密于源端,保证下游能跟得上)。两条链路错开几分钟,避免上下游同时跑把数据库打满。
踩坑复盘
- 编码映射没集中管理:经销商 id 与 ERP 往来单位 id 的映射关系散落在多个策略里,某次新增一家经销商忘了同步,导致那张退货单进了 ERP 但往来单位挂空,月底对账才发现。
- 表头表体没分阶段:早期有人把退货明细直接拼到一条 SQL 里循环插入,中间一行失败后表头已经写入,出现"有头无尾"。分阶段执行后,失败即整体回滚,数据干净很多。
- 增量窗口用了创建时间:营销云接口的
timeType默认是创建时间,但退货单审核后还会改单,只用创建时间会漏更新。把timeType切到更新时间后,改单也能被追上。 - 调度频率过高:某次把两条链路的 crontab 调到同一分钟,源端拉一批还没写完目标端就触发,数据库连接数被打满。错开 1-2 分钟立刻缓解。
- idCheck 没开:重复执行时把同一张退货单插了两遍,ERP 里出现负库存告警。打开
idCheck即可。
适用场景与不适用场景
适用:退货单据需要在营销云(经销商侧系统)与 ERP(SQL Server)之间做数据汇聚,单据具备明确的"已审核"状态、且需要表头表体一致落库。
不适用:实时性要求秒级、退货流程需要在 ERP 内反向回写营销云、或者经销商侧不是营销云而是其他渠道——这些场景需要另外设计双向同步或准实时通道。