Files
mp-java/docs/水票配送订单-后端提示词.md
赵忠林 922e7def9d feat(ticket): 添加水票订单配送流程功能
- 在GltTicketOrder实体类中新增配送相关的字段,包括配送状态、配送时间、收货人信息等
- 实现配送员端订单查询接口,支持按配送状态筛选和权限隔离
- 添加配送流程核心接口:接单、开始配送、确认送达、用户确认收货等功能
- 实现配送状态流转的状态机校验和并发安全的原子更新操作
- 优化数据库查询SQL,增加配送状态和租户ID的索引提升查询性能
- 添加配送员身份验证和权限检查机制,确保操作安全性
2026-02-06 22:00:59 +08:00

7.0 KiB
Raw Permalink Blame History

水票配送订单:后端提示词(可直接发给后端)

目标:把“水票下单后 -> 配送员接单/配送 -> 用户确认 -> 自动确认”的闭环放到后端,用明确的字段 + 状态机校验保证不越权、不乱跳状态、并发不重复接单。

接口前缀:当前后端控制器为 @RequestMapping("/api/glt/glt-ticket-order"),下文默认都带 /api 前缀(如需兼容旧路径,可做网关转发或保留旧路由)。

0) 角色与权限边界(务必在后端兜底)

  • 用户端(小程序用户):只能看/操作自己的订单(userId = token userId
  • 配送员端:只能看/操作分配给自己的订单(riderId = token userId / rider userId
  • 管理端:按后台权限控制(可查询/派单/改状态,但仍需 tenantId 隔离)。

建议:对“配送员端接口”忽略前端传入的 riderId/userId/tenantId,统一从登录态注入,避免越权。

1) 订单查询(配送员端)

建议提供配送员专用分页接口:GET /api/glt/glt-ticket-order/rider/page(避免与后台管理分页混用)。 请支持以下筛选,并保证权限隔离:

  • deliveryStatus10待配送、20配送中、30待客户确认、40已完成配送员端必要不传默认=10
  • keywords:支持按地址/备注等模糊搜索(可选)
  • 排序:建议默认 sendTime asc, createTime desc(或沿用后端默认排序,但请告知前端)

权限隔离要求(配送员端):

  • 只返回当前登录配送员的订单:后端强制 param.riderId = loginUserId(前端传不传都一样)。
  • tenantId/deleted 等同样后端兜底(只查当前租户、只查未删除)。

返回字段建议(配送员端用得上):

  • 门店/仓库/用户/配送员的展示字段:storeName/storeAddress/storePhonewarehouseName/warehouseAddressnickname/phone/avatarriderName/riderPhone(现有 pageRel/listRel 已在做关联返回)。
  • 导航相关(详见第 5 节):收货地址 lat/lng、门店/仓库 lngAndLat(可关联返回或做快照字段)。

2) 配送流程字段(建议后端落库并回传)

订单表建议确保有以下字段(当前前端已按这些字段做流程判断/展示):

  • riderId/riderName/riderPhone:配送员信息
  • deliveryStatus10/20/30/40
  • sendStartTime:配送员点击“开始配送”的时间(建议 datetime
  • sendEndTime:配送员点击“确认送达”的时间(建议 datetime
  • sendEndImg:送达拍照留档图片 URL可选/必填由后端策略决定;建议 varchar(512)
  • receiveConfirmTime:客户确认收货时间(建议 datetime
  • receiveConfirmType10客户手动确认、20配送照片自动确认、30超时自动确认

数据库变更示例SQL见docs/sql/2026-02-06_glt_ticket_order_delivery_fields.sql)。

强烈建议把“配送状态”与“业务状态(status=0/1、deleted=0/1)”分开,避免混用:

  • status/deleted:系统通用字段(现有逻辑)
  • deliveryStatus:配送流程状态(本需求新增)

3) 状态流转与校验(强烈建议在后端做)

请在更新订单时做状态机校验,避免前端绕过流程:

  • 10 -> 20:仅允许订单属于当前配送员,且未开始/未送达
  • 20 -> 30:配送员确认送达(可带 sendEndImg
  • 20/30 -> 40:完成;来源可能是
    • 客户手动确认(写 receiveConfirmTime + receiveConfirmType=10
    • 配送照片直接完成(写 receiveConfirmTime + receiveConfirmType=20,并要求 sendEndImg
    • 超时自动确认(写 receiveConfirmTime + receiveConfirmType=30,建议由定时任务执行)

并发/幂等建议(避免重复点击/重复请求带来的脏数据):

  • 所有“状态变更接口”用条件更新实现原子校验:UPDATE ... SET ... WHERE id=? AND rider_id=? AND delivery_status=? AND deleted=0
  • 对重复调用做幂等:
    • start:如果已是 20 则直接返回成功;如果已到 30/40 返回“状态不允许”
    • delivered:如果已是 30/40 则返回成功(或提示已送达);避免重复写 sendEndTime
    • confirm-receive:如果已是 40 则返回成功(或提示已完成)

4) 建议新增/明确的接口能力

为了避免并发抢单/越权更新,建议新增更语义化的接口(或在 update 内做等价校验):

  • 接单(抢单/派单):POST /api/glt/glt-ticket-order/{id}/accept
    • 配送员端:后端原子校验:仅当 rider_id IS NULL(或为 0时才能写入当前 rider 信息
    • 管理端派单:允许传 riderId,但需校验骑手归属门店/租户(如有该约束)
  • 开始配送:POST /api/glt/glt-ticket-order/{id}/start
    • 写:sendStartTime=nowdeliveryStatus=20
    • 校验:必须 riderId=当前登录配送员 且当前 deliveryStatus=10
  • 确认送达:POST /api/glt/glt-ticket-order/{id}/delivered
    • 入参:sendEndImg(可选/必填,按策略)
    • 写:sendEndTime=nowdeliveryStatus=30sendEndImg
    • 可选策略 A推荐可配置sendEndImg 必填且存在,则可直接 deliveryStatus=40 并写 receiveConfirmTime/Type=20
  • 客户确认收货:POST /api/glt/glt-ticket-order/{id}/confirm-receive
    • 校验:只能本人 userId 操作,且必须 deliveryStatus=30
    • 写:deliveryStatus=40receiveConfirmTime=nowreceiveConfirmType=10

接口返回建议:

  • 成功统一返回 ApiResult.success(...)
  • 失败请返回明确 msg例如无权限订单不存在订单状态不允许订单已被其他配送员接单

5) 为了“导航到收货地址/取货点”的字段补充(建议)

当前仅有 address 字符串,无法在小程序内 openLocation 精准导航;建议补充:

  • 收货地址(推荐至少返回):receiverNamereceiverPhoneprovince/city/region/address/fullAddresslat/lng
  • 取货点(门店/仓库,推荐至少返回):store.lngAndLatwarehouse.lngAndLat

实现方式二选一:

  • 方式 A更快查询时关联 shop_user_addressshop_storeshop_warehouse,把经纬度字段透出给前端。
  • 方式 B更稳下单时把收货地址的 name/phone/lat/lng/fullAddress 以及门店/仓库 lngAndLat 做快照写入订单,避免后续数据变更影响历史订单导航。

6)(可选但很有用)超时自动确认规则

  • 建议后端提供可配置项:autoConfirmHours(例如 24h/48h
  • 定时任务扫描:deliveryStatus=30sendEndTime < now - autoConfirmHours 的订单
  • 原子更新:只更新仍处于 30 的订单,写入 deliveryStatus=40receiveConfirmTime=nowreceiveConfirmType=30

7)(可选)字段/枚举建议(便于前后端对齐)

  • deliveryStatus10待配送、20配送中、30待客户确认、40已完成
  • receiveConfirmType10客户手动确认、20配送照片自动确认、30超时自动确认
  • 时间字段统一返回格式:yyyy-MM-dd HH:mm:ss(与项目现有 @JsonFormat 风格一致)