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/7/31 19:06:38 阅读更多 →
揭秘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/7/31 19:05:38 阅读更多 →
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/7/31 19:05:38 阅读更多 →

最新新闻

10分钟快速掌握RyzenAdj:释放AMD Ryzen处理器性能潜力的终极指南

10分钟快速掌握RyzenAdj:释放AMD Ryzen处理器性能潜力的终极指南

10分钟快速掌握RyzenAdj:释放AMD Ryzen处理器性能潜力的终极指南 【免费下载链接】RyzenAdj Adjust power management settings for Ryzen APUs 项目地址: https://gitcode.com/gh_mirrors/ry/RyzenAdj 你是否曾经感觉自己的AMD Ryzen处理器性能没有被完全释…

2026/7/31 19:53:14 阅读更多 →
关于我的博客文章被设置为“VIP可见”的说明

关于我的博客文章被设置为“VIP可见”的说明

各位读者好:最近偶然翻了一下自己的博客后台,发现一件让我挺意外的事情——我有大量原本设置为“全站可见”的技术文章,在不知情的情况下,被系统自动改成了“VIP可见”。熟悉我的朋友可能知道,我写博客的习惯一直都是全…

2026/7/31 19:53:14 阅读更多 →
Norm与StreamData强强联合:自动生成测试数据的完整指南

Norm与StreamData强强联合:自动生成测试数据的完整指南

Norm与StreamData强强联合:自动生成测试数据的完整指南 【免费下载链接】norm Data specification and generation 项目地址: https://gitcode.com/gh_mirrors/no/norm Norm是一个强大的数据规范系统,它不仅能用于数据验证,还能与Stre…

2026/7/31 19:53:14 阅读更多 →
通用大模型为什么水土不服:企业AI花了大价钱,却养了个“废话生成器”

通用大模型为什么水土不服:企业AI花了大价钱,却养了个“废话生成器”

320万的教训去年某制造企业干了件挺猛的事——重金采购了当时最强的通用大模型,320万年费,全公司推广。老板的逻辑很简单:最强模型全员使用效率飞升。结果呢?系统上线三个月,日活率11.7%。员工反馈出奇一致&#xff1a…

2026/7/31 19:53:14 阅读更多 →
3步掌握数据主权:用开源工具永久保存你的微信聊天记录

3步掌握数据主权:用开源工具永久保存你的微信聊天记录

3步掌握数据主权:用开源工具永久保存你的微信聊天记录 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeCha…

2026/7/31 19:53:14 阅读更多 →
Twitter API v2集成实战:Twitter, together!开发指南

Twitter API v2集成实战:Twitter, together!开发指南

Twitter API v2集成实战:Twitter, together!开发指南 【免费下载链接】action :bird: A GitHub action to tweet from a repository 项目地址: https://gitcode.com/gh_mirrors/act/action Twitter, together! 是一款基于 GitHub Action 的强大工具&#xff…

2026/7/31 19:52:14 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/31 4:19:39 阅读更多 →

月新闻