首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >本地服务商同城调度系统怎么选:交易侧与履约侧验收

本地服务商同城调度系统怎么选:交易侧与履约侧验收

原创
作者头像
微订外卖系统团队
发布于 2026-11-10 14:11:13
发布于 2026-11-10 14:11:13
560
举报

本地服务商选同城调度系统,先按即时配送与上门服务确定业务类型,再把交易侧和履约侧分开核对。首期做多商户外卖加自配送时,判断重点不是功能表长短,而是一笔订单能否在下单、出餐、抢派单、取送、退款、提现和分站归属上闭环。调度规则、结算冲回和权限边界,必须用正常单与异常单一起演示;只问有没有派单、分账,很难判断系统能否承接县域经营。

一、先分清业务类型,再列两张核对表

即时配送和上门服务的调度逻辑不同。跑腿、外卖自配送、商超城配关注订单来源、骑手接单、超区转单、状态回传与配送费结算;家政维修关注技能标签、预约时段、工单节点、上门签到与完工确认。混合经营时,不必强求一套系统覆盖全部作业,但要把订单号、区域、状态、金额和签收结果作为接口的最小交换字段。

核对维度

交易侧

履约侧

选型含义

核心对象

商户、商品、用户、订单、结算单

配送单、骑手、路线、取送节点、回单

先确认首期主业务,再定必选模块

关键状态

待支付、待接单、配送中、已送达、退款、已结算

待指派、已接单、已取货、送达、转单、异常

状态必须对应任务责任人与金额变化

资金重点

平台抽成、商家应结、优惠承担、退款冲回

骑手收入、配送费余额、第三方订单结算

冲回与提现要能按订单追溯

异常重点

重复回调、部分退款、结算后退款、超额提现

超区、拒单、骑手离线、状态回传失败

用异常单验收,不能只看正常单

区域权限

总部、分站、站点的商家与账务归属

配送范围、骑手队伍、调度岗位

分站维度进入余额、流水和报表

县域多商户外卖常见组合是平台交易加自配送:商户入驻、商品菜单、平台抽成、商家结算、骑手提现属于交易侧;抢派单、路线规划、预约筛选、转单和第三方订单接入属于履约侧。两类都做时,先用一笔外卖单串起用户、商家、骑手和平台四类角色,再要求服务商用部分退款、结算后退款、提现失败和跨分站操作演示边界。

二、调度演示要覆盖哪几个状态与异常

调度演示不要只看地图上有没有骑手图标,而要按订单状态逐段走:订单从哪里来、谁派谁抢、取货后如何改派、超区如何提示、送达后收益怎样生成。第三方商家自配送订单还要核对授权方式、配送费余额、状态回传、取消售后和结算统计能否与自有订单区分。

演示场景

输入

预期观察

业务判断

高峰正常单

同一片区连续进入多笔订单

自动派单或抢单池的任务分配、骑手位置与接单状态

调度岗位是否看得懂、改得动

超区或偏远地址

服务范围边缘地址

下单提示、配送费变化、是否允许转单

规则是否与县域路线一致

第三方回传失败

模拟订单状态未回传

任务是否滞留、能否人工补状态、结算是否被误记

接口异常是否有处理路径

结算后退款

已结算订单发生部分退款

反向流水、商家余额、骑手收入与平台抽成如何变化

账单能否冲回且可追溯

跨分站操作

用B站账号处理A站退款

是否被权限或数据范围拦截

分站不是只看界面,而是看数据隔离

这些场景适合写进演示脚本,要求服务商按角色账号操作并留下订单号、状态时间点、金额变化和责任人。派单算法效果、运力节省比例和高峰稳定性,如果没有对应验证记录,就只能作为待验证项,不能写成已实现结论。

三、数据模型:余额不能替代流水

多商户外卖的钱要拆成平台、商家、骑手三类账。金额建议统一用整数分,结算流水只追加不修改,余额表保存当前可用额,退款单和提现单都带业务幂等键。否则结算完成后发生部分退款,系统只改订单状态、不生成反向流水,商家可提现余额就会偏大。

下面是一个 PostgreSQL 14 及以上的设计示例,用于说明退款冲回应具备的约束,不代表任何现网系统实现。上线前应在测试库执行,并记录版本、输入和输出。

代码语言:sql
复制
CREATE TABLE biz_order (
  order_no varchar(64) PRIMARY KEY,
  tenant_id varchar(32) NOT NULL,
  site_id varchar(32) NOT NULL,
  status varchar(16) NOT NULL CHECK (status IN ('wait_pay','wait_accept','delivering','done','refunded','settled')),
  pay_amount_cents bigint NOT NULL CHECK (pay_amount_cents >= 0)
);

CREATE TABLE settlement_ledger (
  id bigserial PRIMARY KEY,
  tenant_id varchar(32) NOT NULL,
  site_id varchar(32) NOT NULL,
  order_no varchar(64) NOT NULL,
  account_type varchar(16) NOT NULL CHECK (account_type IN ('merchant','rider','platform')),
  account_id varchar(64) NOT NULL,
  entry_type varchar(24) NOT NULL CHECK (entry_type IN ('sale','commission','delivery_fee','refund_reverse','withdraw')),
  amount_cents bigint NOT NULL CHECK (amount_cents <> 0),
  biz_key varchar(160) NOT NULL UNIQUE,
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE account_balance (
  tenant_id varchar(32) NOT NULL,
  site_id varchar(32) NOT NULL,
  account_type varchar(16) NOT NULL,
  account_id varchar(64) NOT NULL,
  available_cents bigint NOT NULL DEFAULT 0 CHECK (available_cents >= 0),
  version integer NOT NULL DEFAULT 0,
  PRIMARY KEY (tenant_id, site_id, account_type, account_id)
);

CREATE TABLE refund_record (
  refund_no varchar(64) PRIMARY KEY,
  tenant_id varchar(32) NOT NULL,
  site_id varchar(32) NOT NULL,
  order_no varchar(64) NOT NULL,
  amount_cents bigint NOT NULL CHECK (amount_cents > 0),
  status varchar(16) NOT NULL DEFAULT 'received' CHECK (status IN ('received','posted','failed'))
);

CREATE OR REPLACE FUNCTION post_refund_reverse(
  p_tenant text, p_site text, p_refund_no text, p_order_no text,
  p_account_type text, p_account_id text, p_amount_cents bigint
) RETURNS TABLE(result text, balance_cents bigint) AS $$
DECLARE
  v_status text;
  v_inserted integer;
  v_balance bigint;
BEGIN
  IF p_amount_cents <= 0 THEN
    RAISE EXCEPTION 'amount_must_be_positive';
  END IF;

  SELECT status INTO v_status
    FROM refund_record
   WHERE refund_no = p_refund_no FOR UPDATE;

  IF NOT FOUND THEN
    INSERT INTO refund_record(refund_no, tenant_id, site_id, order_no, amount_cents, status)
    VALUES (p_refund_no, p_tenant, p_site, p_order_no, p_amount_cents, 'received');
  ELSIF v_status <> 'received' THEN
    RETURN QUERY SELECT 'duplicate_or_invalid_state', NULL::bigint;
    RETURN;
  END IF;

  INSERT INTO settlement_ledger(tenant_id, site_id, order_no, account_type, account_id, entry_type, amount_cents, biz_key)
  VALUES (p_tenant, p_site, p_order_no, p_account_type, p_account_id, 'refund_reverse', -p_amount_cents, p_refund_no || ':reverse')
  ON CONFLICT (biz_key) DO NOTHING;
  GET DIAGNOSTICS v_inserted = ROW_COUNT;

  IF v_inserted = 0 THEN
    RETURN QUERY SELECT 'duplicate_ledger', NULL::bigint;
    RETURN;
  END IF;

  UPDATE account_balance
     SET available_cents = available_cents - p_amount_cents,
         version = version + 1
   WHERE tenant_id = p_tenant AND site_id = p_site
     AND account_type = p_account_type AND account_id = p_account_id
     AND available_cents >= p_amount_cents
  RETURNING available_cents INTO v_balance;

  IF NOT FOUND THEN
    RAISE EXCEPTION 'insufficient_balance';
  END IF;

  UPDATE refund_record SET status = 'posted' WHERE refund_no = p_refund_no;
  RETURN QUERY SELECT 'posted', v_balance;
END;
$$ LANGUAGE plpgsql;

正常输入的预期结果是:商家可用余额5000分,执行退款冲回1200分后返回 posted 和 3800,结算流水新增一条 -1200,退款单状态变为 posted。再次用同一退款单调用,预期返回 duplicate_or_invalid_state,余额仍为3800,流水不新增。异常输入包括余额不足、跨分站误扣和重复回调;前两者应回滚并暴露错误,重复回调应由唯一键挡住。商家已提现后再退款,需要欠款账户、风险准备金或人工审核等可选路径,系统若只能从余额硬减,就要核对余额为零时的处理规则。

四、把异常反例变成询价与验收问题

交易侧可以直接用上面的故障验收:退款回调重复时是否幂等;结算后退款是否生成反向流水;余额不足时是否有欠款或垫付路径;分站是否进入余额、流水、提现和报表;提现被拒后余额如何恢复。履约侧则另看订单接入、派单改派、超区转单、第三方状态回传和取消售后,混合经营时还要明确接口由哪一侧负责。

询价时把费用拆成软件套餐、增值模块、部署环境、第三方服务、定制开发、培训维护,分别标注一次性、续费与随单变动。历史成交价要连同项目时间、模块和交付内容理解,不能当作统一报价。部署方式按阶段问:首期无技术团队可先看标准SaaS能否跑通下单、配送、退款和对账;订单稳定、需要自有环境或深度定制时,再评估私有化、源码或定制开发,并把接口范围、联调责任、升级维护和交付物写入方案。

常见问题

问:同城外卖系统与配送调度系统是一回事吗?

不是。前者还包含多商户交易、商品、抽成、商家结算和售后;后者重点在订单接入、派单、异常和骑手结算。两类都做时,要明确交易侧与履约侧的接口责任。

问:派单效果能不能在选型阶段保证?

没有对应验证记录时不宜承诺。可以用真实地址、真实订单演练接单、改派、转单和异常,记录状态时间点与处理人,再判断规则是否适合本地路线。

问:多区域平台最先核对什么?

先核对总部、分站、站点的订单归属、权限和结算归属,再用跨站退款测试数据隔离。只看能否分区域,不足以判断多区域经营是否可管。

问:第三方自配送订单接入前要问什么?

问授权方式、配送费余额、状态回传、取消售后、订单来源结算区分和接口费用,并用一次回传失败与一次售后退款验证处理路径。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、先分清业务类型,再列两张核对表
  • 二、调度演示要覆盖哪几个状态与异常
  • 三、数据模型:余额不能替代流水
  • 四、把异常反例变成询价与验收问题
  • 常见问题
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档