AI 写完订单后台,退货按钮点两次会怎样:Go + MySQL 幂等检查
AI 或代码生成器把订单、商品、库存页面做出来只能说明 CRUD 有了。退货按钮点两次库存会不会回滚两次退款回调晚到订单状态会不会倒退运营拿旧 token 直接打接口能不能绕过页面按钮。这些才是进销存后台上线前最该先验的地方。这篇不讲完整进销存系统怎么从零搭。我只拆一个很窄的动作退货。因为它同时碰到状态机、库存流水、幂等键、RBAC 权限和审计日志。页面看起来再完整如果这几个点没有验后面补起来很难受。退货不是一个 update很多后台初版会把退货写成这样UPDATE order_item SET refund_status refunded WHERE id 1001; UPDATE product_stock SET available_qty available_qty 2 WHERE sku_id 2001;这段 SQL 看着没问题实际少了几层判断订单是不是当前租户的订单是否已经发货、已退货或已取消同一个退货请求是不是重放过库存流水有没有唯一业务单号谁发起退货、走的是哪个权限码后面做导出、对账、补偿任务时能不能查回完整链路。AI 很容易根据表名生成“退货接口”但它不知道你的业务里退货能不能撤销、部分退货怎么算、支付退款和库存释放谁先谁后。这里不能靠页面验收要靠数据约束和接口重放验收。表结构先把幂等和租户写进去我会先把退货请求和库存流水分开。订单状态是一件事库存动作是另一件事。库存流水表里必须有业务动作、业务单号、租户和幂等键。CREATE TABLE inventory_flow ( id BIGINT PRIMARY KEY AUTO_INCREMENT, tenant_id BIGINT NOT NULL, sku_id BIGINT NOT NULL, order_id BIGINT NOT NULL, action VARCHAR(32) NOT NULL COMMENT sale/refund/reversal/adjust, qty INT NOT NULL, idempotency_key VARCHAR(96) NOT NULL, operator_id BIGINT NOT NULL, remark VARCHAR(255) DEFAULT , created_at DATETIME NOT NULL, UNIQUE KEY uk_tenant_idem (tenant_id, idempotency_key), KEY idx_tenant_sku_time (tenant_id, sku_id, created_at), KEY idx_order_action (tenant_id, order_id, action) );uk_tenant_idem是兜底不是装饰。接口层可以先查 Redis 或幂等表但数据库唯一键必须在最后拦住重复插入。否则网关重试、前端连点、定时补偿任务重复跑都可能把库存加两遍。订单明细也要带状态条件不要只按 id 更新UPDATE order_item SET refund_status refunded, updated_at NOW() WHERE tenant_id ? AND id ? AND refund_status none AND pay_status paid;这条 SQL 的返回行数很重要。影响 1 行才说明状态从none变到了refunded。影响 0 行不一定是数据库异常也可能是重复退货、跨租户、订单状态不允许退。接口要把这些分开记录不能统一回“操作失败”。Go 接口里先验权限再验状态退货接口的顺序不要写反。先验证登录和权限再拿租户上下文再进入业务事务。否则你会在日志里看到一堆状态错误却漏掉真正的问题没有退货权限的人已经打到了业务层。func RefundOrder(ctx context.Context, req RefundReq) error { user : auth.UserFromCtx(ctx) if user nil { return ErrUnauthorized } if !rbac.HasPermission(ctx, user.ID, inventory:refund) { return ErrForbidden } tenantID : user.TenantID idemKey : fmt.Sprintf(refund:%d:%d:%s, tenantID, req.OrderID, req.RequestNo) return dao.Transaction(ctx, func(ctx context.Context) error { item, err : dao.OrderItem. Ctx(ctx). Where(tenant_id, tenantID). Where(order_id, req.OrderID). Where(refund_status, none). ForUpdate(). One() if err ! nil { return err } if item.IsEmpty() { return ErrRefundState } _, err dao.InventoryFlow.Ctx(ctx).Insert(g.Map{ tenant_id: tenantID, sku_id: req.SkuID, order_id: req.OrderID, action: refund, qty: req.Qty, idempotency_key: idemKey, operator_id: user.ID, created_at: gtime.Now(), }) if isDuplicateKey(err) { return ErrDuplicateRefund } if err ! nil { return err } _, err dao.ProductStock.Ctx(ctx). Where(tenant_id, tenantID). Where(sku_id, req.SkuID). Increment(available_qty, req.Qty) if err ! nil { return err } _, err dao.OrderItem.Ctx(ctx). Where(tenant_id, tenantID). Where(order_id, req.OrderID). Where(refund_status, none). Data(g.Map{refund_status: refunded, updated_at: gtime.Now()}). Update() return err }) }这里的重点不是把代码照搬到项目里而是顺序权限、租户、状态锁、流水唯一键、库存释放、订单状态更新。少任何一个退货按钮都可能在正常测试里过关在重复请求或跨租户场景里翻车。用两次 curl 重放不要只看 200最小验收可以很土。拿同一个请求打两次看第二次是不是被幂等逻辑挡住。curl -i -X POST https://api.example.com/admin/inventory/refund \ -H Authorization: Bearer admin-token \ -H Content-Type: application/json \ -d { order_id: 10001, sku_id: 20001, qty: 2, request_no: refund-10001-001 } curl -i -X POST https://api.example.com/admin/inventory/refund \ -H Authorization: Bearer admin-token \ -H Content-Type: application/json \ -d { order_id: 10001, sku_id: 20001, qty: 2, request_no: refund-10001-001 }我希望看到的结果类似这样HTTP/1.1 200 OK {code:0,message:ok,flow_id:88123} HTTP/1.1 409 Conflict {code:40901,message:duplicate refund request}再查库存和流水SELECT available_qty FROM product_stock WHERE tenant_id 10 AND sku_id 20001; SELECT action, qty, idempotency_key, COUNT(*) AS cnt FROM inventory_flow WHERE tenant_id 10 AND order_id 10001 GROUP BY action, qty, idempotency_key;第二条查询里cnt应该是 1。库存只释放一次。这个检查比“页面提示退货成功”更可靠。跨租户和低权限账号要单独测进销存后台很容易把“能不能看到菜单”和“能不能打接口”混在一起。前端隐藏退货按钮只能减少误点不能当权限边界。接口层必须独立拦截。# 没登录 curl -i -X POST https://api.example.com/admin/inventory/refund # 期望401 # 登录了但没有退货权限 curl -i -X POST https://api.example.com/admin/inventory/refund \ -H Authorization: Bearer viewer-token # 期望403 # A 租户 token 操作 B 租户订单 curl -i -X POST https://api.example.com/admin/inventory/refund \ -H Authorization: Bearer tenant-a-token \ -H Content-Type: application/json \ -d {order_id:90001,sku_id:20001,qty:1,request_no:x-1} # 期望404 或 403但不能改到 B 租户库存后台权限最好拆到动作级。inventory:view、inventory:export、inventory:refund、inventory:reversal不能全塞进一个“库存管理”权限里。退货和冲销都在改库存但风险不同审批、日志和授权也应该不同。审计日志要能回答“谁把库存放回去了”退货出问题时运营不会只问“接口成功了吗”。他们会问哪个人、哪个租户、哪张订单、释放了哪个 SKU、是不是重复请求、当时的权限码是什么。日志至少要这样记录{ event: inventory.refund, tenant_id: 10, operator_id: 501, permission: inventory:refund, order_id: 10001, sku_id: 20001, qty: 2, idempotency_key: refund:10:10001:refund-10001-001, result: success, flow_id: 88123, request_id: req-20260730-0001 }失败也要记尤其是duplicate、forbidden、state_not_allowed。这些日志会决定后面能不能查账。如果只记“按钮点击成功”排查时基本等于没有日志。代码生成器适合生成骨架不适合替你决定业务状态我在看 XYGo Admin 的代码生成器时更愿意把它当后台骨架样本页面、权限和字段同步能先立起来但像退货幂等、库存释放和租户隔离这种业务动作生成后还要补验收。可以对照它的server/internal/logic/gencodes/generate.go、server/internal/logic/gencodes/sync_fields.go和server/internal/middleware/admin_permission.go看生成器、字段同步和接口权限分别落在哪一层。源码入口放这里方便对照路径GitHub 仓库。这里要说清楚边界它不是现成进销存 SaaS也不会替某个行业直接决定退货、冲销、支付退款和云打印规则。这个判断也能和仓库里的 Issue #9 对上用户问的是 SaaS、多租户、库销存、支付配置和云打印机需求真正难点就在业务动作和边界不是多生成几张表。适合参考的是后台底座怎么组织 RBAC、CRUD 生成器和字段同步业务动作还要按自己的订单状态和库存模型补。上线前我会保留这张检查表检查项期望结果常见坏味道重复退货请求第二次返回 duplicate库存不变两次都 200库存加两次低权限账号返回 403前端没按钮但接口能打跨租户订单查不到或 403只按 order_id 更新状态回退已退货不能再退只改 refund_status没有状态条件库存流水同一 idempotency_key 只有一条只有库存余额没有流水审计日志有 tenant、operator、permission、request_id只记“操作成功”导出对账可按订单和 SKU 查回流水导出只查余额表如果一个 AI 生成的后台连这张表都过不了我不会急着补页面细节。页面错了通常还能改库存和退货链路错了后面就是对账、退款和客服一起补锅。结尾留个问题你们验收进销存后台时会先看页面流程还是先用重复请求把库存接口打一遍

相关新闻

RGD-PEG-Mal 线肽 RGD - 聚乙二醇马来酰亚胺 靶向偶联试剂特性介绍

RGD-PEG-Mal 线肽 RGD - 聚乙二醇马来酰亚胺 靶向偶联试剂特性介绍

多链长规格可选 RGD-PEG-MAL 靶向巯基专用偶联试剂,分子结构整合线性 RGD 靶向三肽、柔性 PEG 亲水间隔链与末端 MAL 马来酰亚胺巯基特异性活性基团;该试剂适用于体外巯基修饰多肽、巯基荧光染料、巯基磷脂的定点靶向改性研究,依托巯基特异性…

2026/10/28 2:50:30 阅读更多 →
揭秘claude-powerline工作原理:核心组件与代码实现分析

揭秘claude-powerline工作原理:核心组件与代码实现分析

揭秘claude-powerline工作原理:核心组件与代码实现分析 【免费下载链接】claude-powerline Beautiful vim-style powerline for Claude Code 项目地址: https://gitcode.com/gh_mirrors/cl/claude-powerline claude-powerline是一款为Claude Code打造的vim风…

2026/10/24 18:12:17 阅读更多 →
react-native-biometrics性能优化:提升生物识别响应速度的5个技巧

react-native-biometrics性能优化:提升生物识别响应速度的5个技巧

react-native-biometrics性能优化:提升生物识别响应速度的5个技巧 【免费下载链接】react-native-biometrics React Native module for iOS and Android biometrics 项目地址: https://gitcode.com/gh_mirrors/re/react-native-biometrics react-native-biom…

2026/10/24 7:52:25 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/27 4:06:49 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/27 7:21:53 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/27 6:20:47 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/27 4:06:50 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 7:21:50 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 19:19:37 阅读更多 →