8f62496250
fix(fin): 补全提现审批人字段 FIN-01
...
- Approve updates map 补充 approved_by 和 approved_at 字段,确保审批人信息正确填充
2026-03-28 10:36:33 +08:00
9a4d87a0d4
feat(01-03): 充值回调触发自动购包任务入队(CRITICAL-04)
...
- recharge.Service struct 新增 queueClient *queue.Client 字段
- recharge.New() 新增 queueClient 参数
- HandlePaymentCallback 事务成功后,LinkedPackageIDs 非空时入队 TaskTypeAutoPurchaseAfterRecharge
- bootstrap/services.go 的 recharge.New() 传入 deps.QueueClient
2026-03-27 23:29:05 +08:00
f74b7da25f
fix(01-04): 修正场景5代理代购下级的sellerCostPrice赋值
...
- 三处代理代购下级分支(wallet场景子场景2.2)均将 sellerCostPrice = buyerCostPrice 改为 sellerCostPrice = operatorCostPrice
- buyerCostPrice 是下级成本价,operatorCostPrice 是操作方(代理自己)的成本价
- 使用 buyerCostPrice 会导致佣金差额为 0,所有上级代理无法获得应有佣金
- 修复涉及三个函数(普通下单/后台下单/H5下单),行号分别约在 264/551/813
2026-03-27 23:24:16 +08:00
da50a35a62
fix(01-01): 修复 C 端实名校验使用常量(CRITICAL-02)
...
- client_order/service.go: 实名校验 assetInfo.RealNameStatus != 1 改为常量比较
- client_realname.go: 实名状态检查 == 1 改为 constants.RealNameStatusVerified
- go build ./... 编译通过,无遗留硬编码 != 1 / == 1 的实名判断
2026-03-27 22:54:50 +08:00
1fd0072f69
fix(01-01): 统一实名状态常量(CRITICAL-01 核心)
...
- polling_handler.go: parseRealnameStatus 不再返回硬编码 2,改为 constants.RealNameStatusVerified(=1)
- polling_handler.go: isFirstRealname 判断改用常量比较,不再使用 == 2
- polling_handler.go: HandleProtectConsistencyCheck 注释更正为 real_name_status=1
- iot_card.go: RealNameStatus gorm comment 统一为 0-未实名 1-已实名(去除行业卡说明)
- asset_dto.go: RealNameStatus description 更正为 0未实名 1已实名(去除错误的 1实名中 2已实名)
- scheduler.go: getCardCondition 改用常量替代硬编码 0/1/2 判断
- iot_card/service.go: parseGatewayRealnameStatus 注释更正,返回值改为常量
2026-03-27 22:53:30 +08:00
db166807c7
fix(01-05): 提现冻结并发校验缺失(CRITICAL-08)
...
- 冻结余额改为 result := tx...Updates(),分离结果对象
- 检查 result.Error 处理数据库错误
- 检查 result.RowsAffected == 0 防止并发余额不足时仍创建提现单
- RowsAffected == 0 时返回 errors.New(CodeInsufficientBalance, ...)
2026-03-27 22:50:18 +08:00
7dfcf41b41
fix: 修复卡类型资产绑定键错误导致归属校验永远失败
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m48s
resolveAssetBindingKey 对卡类型错误地返回 card.ICCID 作为绑定键,
但归属校验 isCustomerOwnAsset 使用 card.VirtualNo 比对,二者不一致
导致所有卡资产的 C 端接口返回 403 无权限。
修复:卡类型绑定键改为 card.VirtualNo,与设计文档一致。
附带数据迁移修正已有的错误绑定记录。
2026-03-21 11:33:57 +08:00
ed334b946b
refactor: 清理重构遗留的死代码
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- personal_customer.Service: 删除已迁移到 client_auth 的死方法
(GetProfile/SendVerificationCode/VerifyCode),移除多余的
verificationService/jwtManager 依赖
- 删除 internal/service/customer/ 整个目录(零引用的早期残留)
2026-03-21 11:33:06 +08:00
d2494798aa
fix: 修正停复机接口错误码,网关失败不再返回模糊的内部服务器错误
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m13s
- 单卡停复机:网关错误从 CodeInternalError(2001) 改为 CodeGatewayError(1110),前端可看到具体失败原因
- 单卡停复机:DB 更新裸返 GORM error 改为 CodeDatabaseError(2002) 包装
- 设备复机:全部卡失败时错误码从 CodeInternalError 改为 CodeGatewayError
2026-03-19 18:37:03 +08:00
b9733c4913
fix: 修正零售价架构错误 + 清理旧微信配置 + 归档提案 + 前端接口文档
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m12s
1. 修正 retail_price 架构:
- 删除 batch-pricing 接口的 pricing_target 字段和 retail_price 分支
(上级只能改下级成本价,不能改零售价)
- 新增 PATCH /api/admin/packages/:id/retail-price 接口
(代理自己改自己的零售价,校验 retail_price >= cost_price)
2. 清理旧微信 YAML 配置(已全部迁移到数据库 tb_wechat_config):
- 删除 config.yaml 中 wechat.official_account 配置节
- 删除 NewOfficialAccountApp() 旧工厂函数
- 清理 personal_customer service 中的死代码(旧登录/绑定微信方法)
- 清理 docker-compose.prod.yml 中旧微信环境变量和证书挂载注释
3. 归档四个已完成提案到 openspec/changes/archive/
4. 新增前端接口变更说明文档(docs/前端接口变更说明.md)
5. 修正归档提案和 specs 中关于 pricing_target 的错误描述
2026-03-19 17:39:43 +08:00
9bd55a1695
feat: 实现客户端核心业务接口(client-core-business-api)
...
新增客户端资产、钱包、订单、实名、设备管理等核心业务 Handler 与 DTO:
- 客户端资产信息查询、套餐列表、套餐历史、资产刷新
- 客户端钱包详情、流水、充值校验、充值订单、充值记录
- 客户端订单创建、列表、详情
- 客户端实名认证链接获取
- 客户端设备卡列表、重启、恢复出厂、WiFi配置、切卡
- 客户端订单服务(含微信/支付宝支付流程)
- 强充自动代购异步任务处理
- 数据库迁移 000084:充值记录增加自动代购状态字段
2026-03-19 13:28:04 +08:00
e78f5794b9
feat: 实现客户端换货系统(client-exchange-system)
...
新增完整换货生命周期管理:后台发起 → 客户端填收货信息 → 后台发货 → 确认完成(含可选全量迁移) → 旧资产转新再销售
后台接口(7个):
- POST /api/admin/exchanges(发起换货)
- GET /api/admin/exchanges(换货列表)
- GET /api/admin/exchanges/:id(换货详情)
- POST /api/admin/exchanges/:id/ship(发货)
- POST /api/admin/exchanges/:id/complete(确认完成+可选迁移)
- POST /api/admin/exchanges/:id/cancel(取消)
- POST /api/admin/exchanges/:id/renew(旧资产转新)
客户端接口(2个):
- GET /api/c/v1/exchange/pending(查询换货通知)
- POST /api/c/v1/exchange/:id/shipping-info(填写收货信息)
核心能力:
- ExchangeOrder 模型与状态机(1待填写→2待发货→3已发货→4已完成,1/2可取消→5)
- 全量迁移事务(11张表:钱包、套餐、标签、客户绑定等)
- 旧资产转新(generation+1、状态重置、新钱包、历史隔离)
- 旧 CardReplacementRecord 表改名为 legacy,is_replaced 过滤改为查新表
- 数据库迁移:000085 新建 tb_exchange_order,000086 旧表改名
2026-03-19 13:26:54 +08:00
df76e33105
feat: 实现 C 端完整认证系统(client-auth-system)
...
实现面向个人客户的 7 个认证接口(A1-A7),覆盖资产验证、
微信公众号/小程序登录、手机号绑定/换绑、退出登录完整流程。
主要变更:
- 新增 PersonalCustomerOpenID 模型,支持多 AppID 多 OpenID 管理
- 实现有状态 JWT(JWT + Redis 双重校验),支持服务端主动失效
- 扩展微信 SDK:小程序 Code2Session + 3 个 DB 动态工厂函数
- 实现 A1 资产验证 IP 限流(30/min)和 A4 三层验证码限流
- 新增 7 个错误码(1180-1186)和 6 个 Redis Key 函数
- 注册 /api/c/v1/auth/* 下 7 个端点并更新 OpenAPI 文档
- 数据库迁移 000083:新建 tb_personal_customer_openid 表
2026-03-19 11:33:41 +08:00
ec86dbf463
feat: 客户端接口数据模型基础准备
...
- 新增资产状态、订单来源、操作人类型、实名链接类型常量
- 8个模型新增字段(asset_status/generation/source/retail_price等)
- 数据库迁移000082:7张表15+字段,含存量retail_price回填
- BUG-1修复:代理零售价渠道隔离,cost_price分配锁定
- BUG-2修复:一次性佣金仅客户端订单触发
- BUG-4修复:充值回调Store操作纳入事务
- 新增资产手动停用接口(PATCH /iot-cards/:id/deactivate、/devices/:id/deactivate)
- Carrier管理新增实名链接配置
- 后台订单generation写时快照
- BatchUpdatePricing支持retail_price调价目标
- 清理全部H5旧接口和个人客户旧登录方法
2026-03-19 10:56:50 +08:00
b44363b335
fix: 修复新建店铺未初始化代理钱包导致充值订单报错
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m6s
新建店铺时在 shop.Service.Create() 中自动初始化主钱包(main)和分佣钱包(commission),修复充值订单创建时「目标店铺主钱包不存在」错误
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-17 14:08:26 +08:00
269769bfe4
refactor: 改造订单和资产充值 Service,支持动态支付配置
...
- order/service.go: 注入 wechatConfigService,CreateH5Order/CreateAdminOrder 下单时查询 active 配置并记录 payment_config_id;无配置时拒绝第三方支付;WechatPayJSAPI/WechatPayH5/FuiouPayJSAPI/FuiouPayMiniApp 添加 TODO 留桩
- recharge/service.go: Create 方法记录 payment_config_id,HandlePaymentCallback 留桩
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 23:30:05 +08:00
89f9875a97
feat: 新增代理预充值模块(DTO、Service、Handler、路由)
...
- agent_recharge_dto.go: 创建/列表/详情请求响应 DTO
- service.go: 权限验证(代理只能充自己店铺)、金额范围校验、查询 active 配置、创建订单、线下充值确认(乐观锁+审计日志)、回调幂等处理
- agent_recharge.go Handler: Create/List/Get/OfflinePay 共 4 个方法
- agent_recharge.go 路由: 注册到 /api/admin/agent-recharges/*,路由层拦截企业账号
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 23:29:42 +08:00
c86afbfa8f
feat: 新增微信参数配置模块(Model、DTO、Store、Service)
...
- wechat_config.go: WechatConfig GORM 模型,含 ProviderTypeWechat/Fuiou 常量
- wechat_config_dto.go: Create/Update/List 请求 DTO,响应 DTO 含脱敏逻辑
- wechat_config_store.go: CRUD、GetActive、ActivateInTx(事务内唯一激活)、软删除保护查询
- service.go: 业务逻辑,按渠道校验必填字段、Redis 缓存管理(wechat:config:active)、删除保护、审计日志
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 23:29:11 +08:00
876c92095c
fix: 平台账号后台创建钱包订单时,绕过代理套餐分配检查
...
后台钱包支付下单时,原逻辑根据卡/设备所属代理店铺触发
套餐分配上架校验,导致平台账号无法为属于代理的卡购买
未被该代理分配的套餐(如 0 元赠送套餐)。
修复:在 CreateAdminOrder wallet 分支中,按买家类型区分:
- 代理账号:保留原有校验,确保卡所属代理已分配该套餐
- 平台/超管账号:跳过代理分配检查,仅验证套餐全局状态
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-16 15:51:01 +08:00
2248558bd3
refactor: 适配 asset_wallet 更名,更新订单、充值和购买验证服务
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 15:43:37 +08:00
2aae31ac5f
feat: 新增 AssetWallet Service,实现资产钱包业务逻辑
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 15:43:29 +08:00
0ef136f008
fix: 修复资产套餐列表时间字段返回异常时区偏移问题
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m54s
待生效套餐的 activated_at/expires_at 在 DB 中存储为零值(0001-01-01),
Go 序列化时因 Asia/Shanghai 历史 LMT(+08:05:36)导致输出异常时区偏移。
- AssetPackageResponse.ActivatedAt/ExpiresAt 改为 *time.Time + omitempty
- 新增 nonZeroTimePtr 辅助函数,零值时间转 nil,避免序列化问题
- 同步修复 GetPackages 和 GetCurrentPackage 两处赋值
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-16 11:42:39 +08:00
b1d6355a7d
fix: resolve 接口 series_name 永远为空,asset service 注入套餐系列 store
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m58s
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 10:59:29 +08:00
907e500ffb
修复列表没有正确返回新增字段问题
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m58s
2026-03-16 10:51:15 +08:00
275debdd38
fix: IoT 卡列表补充 virtual_no 字段和查询过滤,修正设备/卡导入 API 文档描述
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-16 10:44:38 +08:00
b9c3875c08
feat: 新增数据库迁移,重命名 device_no 为 virtual_no,新增 iot_card.virtual_no 和 package.virtual_ratio 字段
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m3s
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-14 18:27:28 +08:00
b5147d1acb
设备的部分改造
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m34s
2026-03-10 10:34:08 +08:00
b52cb9a078
fix: 修复梯度佣金档位字段缺失,补全授权接口响应字段及强充有效状态
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m27s
- OneTimeCommissionTierDTO 补充 operator 字段映射
- GrantCommissionTierItem 补充 dimension/stat_scope 字段(从全局配置合并)
- 系列授权列表/详情补充强充锁定状态和强充金额的有效值计算
- 同步 OpenSpec 主规范并归档变更文档
2026-03-05 11:23:28 +08:00
c7b8ecfebf
refactor: 佣金计算适配梯度阶梯 Operator 比较,套餐服务集成代理强充逻辑
...
commission_calculation: matchOneTimeCommissionTier() 接收 agentTiers 参数,根据 tier.Operator(>、>=、<、<=,默认 >=)执行对应比较逻辑,支持代理专属梯度阶梯计算。package/service: 套餐购买预检调用更新后的强充层级判断接口。
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-04 11:37:02 +08:00
2ca33b7172
fix: 强充预检按平台/代理层级判断,代理自设强充在平台未设时生效
...
checkForceRechargeRequirement() 新增层级逻辑:平台(PackageSeries)的强充配置具有最高优先级;平台未设强充时,读取 order.SellerShopID 对应的 ShopSeriesAllocation 强充配置;两者均未设时返回 need_force_recharge=false(降级处理)。GetPurchaseCheck 复用同一函数,无需额外修改。
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-04 11:36:49 +08:00
ad3a7a770a
feat: 新增系列授权 Service,支持固定/梯度佣金模式和代理自设强充
...
实现 /shop-series-grants 全套业务逻辑:
- 创建授权(固定/梯度模式):原子性创建 ShopSeriesAllocation + ShopPackageAllocation;校验分配者天花板和阶梯阈值匹配;平台创建无天花板限制
- 强充层级:首次充值类型由平台锁定;累计充值类型平台已设时代理配置被忽略,平台未设时代理可自设
- 查询(列表/详情):聚合套餐列表,梯度模式从 PackageSeries 读取 operator 合并响应
- 更新佣金和强充配置;套餐增删改(事务保证)
- 删除:有下级依赖时禁止删除
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-04 11:36:09 +08:00
beed9d25e0
refactor: 删除旧套餐系列分配和套餐分配 Service
...
业务逻辑已全部迁移至 shop_series_grant/service.go,旧 Service 层完整删除。底层 Store(shop_series_allocation_store、shop_package_allocation_store)保留,仍被佣金计算、订单服务和 Grant Service 使用。
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-03-04 11:35:56 +08:00
61155952a7
feat: 新增代理分配套餐上架状态(shelf_status)功能
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m56s
- 新增数据库迁移:为 shop_package_allocation 表添加 shelf_status 字段
- 更新模型/DTO:ShopPackageAllocation 增加 ShelfStatus 字段及相关枚举
- 更新套餐分配 Service:支持上架/下架状态管理逻辑
- 更新套餐 Store/Service:根据 shelf_status 过滤可售套餐
- 更新购买验证 Service:引入上架状态校验逻辑
- 归档 OpenSpec 变更:2026-03-02-agent-allocation-shelf-status
- 同步更新主规范文档:allocation-shelf-status、package-management、purchase-validation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-02 15:38:54 +08:00
8efe79526a
fix: 修复平台自营资源(未分配代理)无法线下下单的问题
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m56s
offline 支付分支新增平台自营子场景判断:
- 资源 shopID 为空时(未分配给任何代理商),使用零售价直接创建订单
- 资源 shopID 不为空时(属于代理商),走原有平台代购逻辑
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-02 11:44:18 +08:00
c5429e7287
fix: 修复平台/超管用户订单列表查询为空的问题
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m5s
Service 层无条件将空 buyer_type 和 0 buyer_id 写入查询过滤条件,
导致平台/超管用户查询时附加 WHERE buyer_type = '' AND buyer_id = 0,
与任何订单均不匹配,返回空列表。
修复方式:仅当 buyerType 非空且 buyerID 非零时才添加过滤条件,
平台/超管用户不限定买家范围,可查看全部订单。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-02 10:48:11 +08:00
e661b59bb9
feat: 实现订单超时自动取消功能,支持钱包余额解冻和 Asynq Scheduler 统一调度
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m58s
- 新增 expires_at 字段和复合索引,待支付订单 30 分钟超时自动取消
- 实现 cancelOrder/unfreezeWalletForCancel 钱包余额解冻逻辑
- 创建 Asynq 定时任务(order_expire/alert_check/data_cleanup)
- 将原有 time.Ticker 轮询迁移至 Asynq Scheduler 统一调度
- 同步 delta specs 到 main specs 并归档变更
2026-02-28 17:16:15 +08:00
5bb0ff0ddf
fix: 修复代理钱包订单创建逻辑,拆分后台/H5端下单方法并归档变更
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m54s
- 拆分订单创建为 CreateAdminOrder(后台一步支付)和 CreateH5Order(H5 两步支付)
- 新增 CreateAdminOrderRequest DTO,后台仅允许 wallet/offline 支付方式
- 同步 delta specs 到主规格(order-payment 更新 + admin-order-creation 新增)
- 归档 fix-agent-wallet-order-creation 变更
- 新增 implement-order-expiration 变更提案
2026-02-28 16:31:31 +08:00
8ed3d9da93
feat: 实现代理钱包订单创建和订单角色追踪功能
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m0s
新增功能:
- 代理在后台使用 wallet 支付时,订单直接完成(扣款 + 激活套餐)
- 支持代理自购和代理代购场景
- 新增订单角色追踪字段(operator_id、operator_type、actual_paid_amount、purchase_role)
- 订单查询支持 OR 逻辑(buyer_id 或 operator_id)
- 钱包流水记录交易子类型和关联店铺
- 佣金逻辑调整:代理代购不产生佣金
数据库变更:
- 订单表新增 4 个字段和 2 个索引
- 钱包流水表新增 2 个字段
- 包含迁移脚本和回滚脚本
文档:
- 功能总结文档
- 部署指南
- OpenAPI 文档更新
- Specs 同步(新增 agent-order-role-tracking capability)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-28 14:11:42 +08:00
c5bf85c8de
refactor: 移除 IoT 卡未使用的价格字段
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m2s
- 移除 IotCard 模型的 cost_price 和 distribute_price 字段
- 移除 StandaloneIotCardResponse DTO 中对应的字段
- 添加数据库迁移文件 000066_remove_iot_card_price_fields
- 更新 opencode.json 配置
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-27 15:38:33 +08:00
f5000f2bfc
修复超管无法回收资产的问题
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m0s
2026-02-27 11:03:44 +08:00
4189dbe98f
debug: 添加资产回收店铺查询的调试日志
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m3s
在 RecallCards 方法中添加日志,用于诊断平台账号回收资产失败的问题:
- 记录操作者店铺ID
- 记录请求查询的店铺IDs
- 记录实际查询到的店铺数量和IDs
- 记录直属下级店铺集合
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-27 09:36:48 +08:00
03a0960c4d
refactor: 数据权限过滤从 GORM Callback 改为 Store 层显式调用
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m2s
- 移除 RegisterDataPermissionCallback 和 SkipDataPermission 机制
- 在 Auth 中间件预计算 SubordinateShopIDs 并注入 Context
- 新增 ApplyShopFilter/ApplyEnterpriseFilter/ApplyOwnerShopFilter 等 Helper 函数
- 所有 Store 层查询方法显式调用数据权限过滤函数
- 权限检查函数 CanManageShop/CanManageEnterprise 改为从 Context 获取数据
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-26 16:38:52 +08:00
4ba1f5b99d
fix: 添加角色名重复检查
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m46s
- 创建角色时检查角色名是否已存在
- 更新角色时检查角色名是否与其他角色重复
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-26 14:55:46 +08:00
1382cbbf47
fix: 修复代理用户能看到未分配套餐系列的问题
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
问题:代理用户登录后能看到所有套餐系列,即使没有分配给该店铺
原因:PackageSeries 模型没有 shop_id 字段,GORM Callback 无法自动过滤
修复:
- 在 package_series Service 的 List 方法中添加权限过滤
- 代理用户只能看到通过 shop_series_allocation 分配给自己店铺的系列
- 平台用户/超级管理员可以看到所有套餐系列
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-26 14:54:52 +08:00
c1eec5d4f1
fix: 新增店铺时为初始账号分配默认角色
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m0s
问题:创建店铺时只创建了 shop_roles 记录(店铺可用角色),
但没有创建 account_roles 记录,导致初始账号没有任何权限。
修复:在创建初始账号后,立即为其分配默认角色到 account_roles 表。
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-25 16:47:36 +08:00
efe8a362aa
fix: 平台账号可回收所有店铺的卡和设备
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m4s
之前平台用户回收时只能回收一级代理的资产,现在允许回收所有店铺的资产。
修改:
- iot_card/service.go: isDirectSubordinate 对平台用户返回 true
- device/service.go: RecallDevices 平台用户跳过直属下级验证
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-25 16:37:23 +08:00
6dc6afece0
fix: 修复已删除店铺名称无法显示的问题
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m6s
店铺被软删除后,GORM 默认过滤 deleted_at IS NOT NULL 的记录,
导致查询店铺名称时找不到对应店铺,shop_name 字段被 omitempty 省略。
修复方案:在加载店铺名称的查询中添加 Unscoped(),包含已删除的店铺。
影响接口:
- GET /api/admin/devices(设备列表)
- GET /api/admin/iot-cards/standalone(独立卡列表)
- GET /api/admin/asset-allocation-records(分配记录列表)
- GET /api/admin/enterprises(企业列表)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-25 16:27:58 +08:00
037595c22e
feat: 单卡回收接口优化 & 店铺禁用登录拦截
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m0s
单卡回收优化:
- 移除 from_shop_id 参数,系统自动识别卡所属店铺
- 保持直属下级限制,混合来源分别处理
- 新增 GetDistributedStandaloneByICCIDRange/GetDistributedStandaloneByFilters 方法
店铺禁用拦截:
- 登录时检查关联店铺状态,禁用店铺无法登录
- 新增 CodeShopDisabled 错误码
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-25 15:54:53 +08:00
25e9749564
feat: 新增店铺时自动设置默认角色
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m1s
- CreateShopRequest 新增必填字段 default_role_id
- 创建店铺时验证默认角色(必须存在、是客户角色、已启用)
- 创建店铺后自动设置 ShopRole,初始账号立即拥有权限
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2026-02-25 14:33:13 +08:00
18daeae65a
feat: 钱包系统分离 - 代理钱包与卡钱包完全隔离
...
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m17s
## 变更概述
将统一钱包系统拆分为代理钱包和卡钱包两个独立系统,实现数据表和代码层面的完全隔离。
## 数据库变更
- 新增 6 张表:tb_agent_wallet、tb_agent_wallet_transaction、tb_agent_recharge_record、tb_card_wallet、tb_card_wallet_transaction、tb_card_recharge_record
- 删除 3 张旧表:tb_wallet、tb_wallet_transaction、tb_recharge_record
- 代理钱包:按 (shop_id, wallet_type) 唯一标识,支持主钱包和分佣钱包
- 卡钱包:按 (resource_type, resource_id) 唯一标识,支持物联网卡和设备
## 代码变更
- Model 层:新增 AgentWallet、AgentWalletTransaction、AgentRechargeRecord、CardWallet、CardWalletTransaction、CardRechargeRecord 模型
- Store 层:新增 6 个独立 Store,支持事务、乐观锁、Redis 缓存
- Service 层:重构 commission_calculation、commission_withdrawal、order、recharge 等 8 个服务
- Bootstrap 层:更新 Store 和 Service 依赖注入
- 常量层:按钱包类型重新组织常量和 Redis Key 生成函数
## 技术特性
- 乐观锁:使用 version 字段防止并发冲突
- 多租户:支持 shop_id_tag 和 enterprise_id_tag 过滤
- 事务管理:所有余额变动使用事务保证 ACID
- 缓存策略:Cache-Aside 模式,余额变动后删除缓存
## 业务影响
- 代理钱包和卡钱包业务完全隔离,互不影响
- 为独立监控、优化、扩展打下基础
- 提升代理钱包的稳定性和独立性
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-25 09:51:00 +08:00