Commit Graph

528 Commits

Author SHA1 Message Date
shanshanzhong147 c92495c5b9 修复(#3): 抽奖 EligibilitySnapshot.UnmetReasons 空字符串违反 MySQL JSON 校验
Closes HIF-3 (Stage 1 P0 from QA smoke)

F4 (P0): EligibilitySnapshot.UnmetReasons=\"\" → MySQL error 3140 (Invalid JSON text: The document is empty)
- 修法:方式 A 对称守卫 UnmetReasons=\"[]\" (与 PrizeSnapshot.Config 的 \"{}\" 守卫模式一致)
- Stage 1 只有 passed=true 分支进 insertSnapshots,语义正确

F5 (P2 顺手): EvaluatedAt 显式 time.Now() 避免 GORM zero time 触 sql_mode STRICT

回归护栏:TestInsertSnapshots_UnmetReasonsIsValidJSON 用 sqlmock per-arg matcher (unmetReasonsNotEmpty + evaluatedAtNotZero),退化时 t.Fatalf 立即抛出
CI 全绿;2 files, +108/-0;无 DB 变更

架构师侧透明:这是 PR C review 时漏检查——PrizeSnapshot.Config 的空串守卫看到了,但没同步检查 EligibilitySnapshot.UnmetReasons。single-code-path 的错觉是审查盲点,Stage 2 起会 sweep 所有 JSON/字符串写库字段。
2026-07-09 08:56:19 -07:00
shanshanzhong147 92cf2921dd 修复(#3): 抽奖 Stage 1 后台审计 IP/UA 丢失 + 冒烟脚本 Bearer 前缀
Closes HIF-3 (Stage 1 P1 defects from QA smoke report)

F2: admin_action_log.ip / user_agent 恒为空
- 根因:requestMeta 从 ctx 读裸字符串 key,全库无 writer 塞
- 修复:新增 AdminMetaMiddleware 用 typed constant.CtxKeyIP / CtxKeyUserAgent
- 挂载:lottery admin 组末尾(不 gate access)
- 回归护栏:UsesTypedKey + IgnoresBareStringKeys 双向断言 typed key,防止未来退化回裸字符串

F3: qa/lottery/stage1_curl.sh Bearer 前缀
- 删除两处 Bearer 前缀 + 加注释说明 ppanel AuthMiddleware 不 strip

单测 5 用例全绿;scope 严格限于 lottery admin 组,其它路径零改动;无 DB 变更。

Merged: architect review 后,将触发 staging 二次部署 — 期望这次能一并解决 shanshanzhong147 手工 SSH 后 Lottery.Enable=true 未生效的问题(若真是 mount/restart 未正确 pick up)。
2026-07-09 07:45:58 -07:00
shanshanzhong147 ce3babcc33 新功能(#3): 抽奖 Stage 1 收官 — 用户 API + 后台 CRUD + 集成
Closes HIF-3

Stage 1 完整闭环 PR C:用户 API + 后台 CRUD + 抽奖事务服务 + 审计 + QA curl。合并后 Stage 1 可交测试。

架构师 review R1(rulecaps depth≤8/nodes≤64/bytes≤8KB)+ R2(InviteHook source_ref 加 order: 前缀)已全部落地。

- 迁移 02158_admin_action_log:后台写操作审计
- xerr 100xxx 段:抽奖错误码(NotEligible/NoChances/ActivityEnded/RateLimited/NotClaimable/InternalError/RuleTooDeep/RuleTooMany/RuleTooLarge)
- feature flag config.Lottery.Enable 默认 false,合并后线上零副作用
- draw service:feature flag → rate limit → pre-tx reads → nonce dedupe → Consume → Pick → 乐观扣库存 → 双快照 → Dispatch → finalize
- 用户 API 4 个:GET /config、POST /draw、GET /records、POST /claim(Stage 1 返回 100010)
- 后台 CRUD:活动 / 奖品 / rules PUT(rulecaps gate)/ chances/grant
- audit.WriteAdminAction:与调用方 tx 同生共死,SHA1 body 摘要
- QA 脚本:qa/lottery/stage1_curl.sh 全链路 curl

测试覆盖:model 76.5% / draw 69% / handler 68.3% / hook 91.9% / rulecaps 87.8% / audit 100%
100 并发抢库存 + 10000 次概率分布 e2e 推 QA 环境(sqlmock 无法忠实模拟 InnoDB 行锁)
CI 全绿:构建/Vet/测试 + golangci-lint
2026-07-08 22:33:18 -07:00
shanshanzhong147 a46fb83054 新功能(#3): 抽奖 Stage 1 handler 真实业务对接 + 邀请钩子
Closes HIF-3 (阶段 PR B)

PR B:handler 真实业务对接 + 邀请钩子(迭代含 R1 修复)

- 迁移 02157_lottery_grant_ledger:external_ref UNIQUE 作为发奖幂等键
- log.CommissionTypeLottery=339(架构师批准的新常量)
- DispatchRequest.IdempotencyKey(架构师 review 建议第 2 条)
- GrantLedger + LedgerService.Reserve:INSERT ON CONFLICT DO NOTHING 幂等 upsert
- VPNDurationHandler:ResolveEffectiveUser 归位家庭 owner + UpdateSubscribe,ExpireTime 三分支对齐 grantGiftDays
- CommissionHandler:UpdateCommission + WriteCommissionLog(339),发给中奖者本人,不做家庭组归位
- Handler 从 model 层迁到 logic 层(避免 model → logic 反向依赖);noop 保留在 model 层
- InviteHook:fire-and-forget 独立 goroutine + 10s timeout,扫 running 活动的 invite_success 源
- ServiceContext 新增 LotteryChance / LotteryLedger / LotteryInviteHook
- activateOrderLogic.handleCommission 两条分支通过 invokeInviteHookIfEligible 助手触发,助手内统一 gate IsNew(架构师 R1 打回后的修复)

架构师 R1 打回:branch B 未按"首次付款激活"gate,续费也会给 referer 发抽奖机会 → 已通过助手函数集中收拢,避免 branch A/B 判断漂移。

测试覆盖率:model 76.5% / handler 73.2% / hook 91.7%;补 4 个回归测试覆盖 IsNew 门槛(含关键的 DoesNotFireOnRenewal)。

线上仍零可见变更:无对外路由,钩子仅在活动 status=running 时生效,Stage 1 全流程无活动记录时 loadRunningActivities 返回空。
2026-07-08 21:19:28 -07:00
shanshanzhong147 9933d34bdd 新功能(#3): 抽奖活动 Stage 1 骨架(DB + 规则引擎 + Handler 抽象)
Closes HIF-3

Stage 1 骨架:7 张表迁移 + 门槛规则引擎 + 加权选奖 + 次数入账/消耗(幂等)+ 发奖 handler 抽象与注册表。

- 单测覆盖 75.5%(未覆盖行 = stub handler ErrNotImplemented,合理)
- CI 全绿(构建/Vet/测试 + golangci-lint)
- 骨架不接入真实业务,vpn_duration/commission handler 在 Dispatch 中返回 ErrNotImplemented;合并后线上零变更

架构师 review 通过,4 项决策已在 issue 上给出:
1. 邀请转化语义 = 首次付款激活
2. 佣金日志类型 = 新增 CommissionTypeLottery=339
3. 家庭组归属 = 穿透到 owner
4. 管理端 IP 白名单 = 不做(推到 nginx/ingress 层)

后续 PR B/C 补真实业务对接 + 用户 API + 后台 CRUD + 集成/并发/概率测试。
2026-07-08 20:05:05 -07:00
shanshanzhong147 d2710d356f fix: align revenue statistics with order type 2026-06-23 09:29:17 -07:00
shanshanzhong147 f0a5288e20 修复(#51): 修正封禁用户订阅返回码
封禁用户拉订阅时返回纯文本 500 退化为业务码 20004,统一走 result.HttpResult。覆盖 /api/subscribe 和泛域名两条入口,补回归测试。
2026-06-16 07:53:37 -07:00
shanshanzhong147 77fa0cadd2 新功能(#48): 用户封禁链路接入 (#32)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-16 06:28:47 -07:00
shanshanzhong147 3d1a31a19f 修复: 用户维度限速在过期节点组分支生效 + 统一 speed_limit 单位为 Mbps
- getServerUserListLogic.getExpiredUsers 之前完全忽略 user_subscribe.speed_limit,
  现在带出用户级覆盖并与过期节点组 speed_limit 取更严(mergeSpeedLimit:0 视为无限制)
- node_group.SpeedLimit 注释从 "KB/s" 修正为 "Mbps"(旧注释是笔误,实际下发节点的
  ServerUser.SpeedLimit 字段语义就是 Mbps,节点端 ppanel-node 按 *1e6/8 换算为 Byte/s)
- apis/node/node.api 给 ServerUser.SpeedLimit 加 Mbps 单位注释
- 新增 TestMergeSpeedLimit 表驱动测试覆盖 8 种边界

主链路(活跃用户、套餐 traffic_limit 阶梯)行为不变,已在生产 (server_id=52)
验证 147 个限速用户下发正确,与 DB 完全对应。
2026-06-12 22:39:15 -07:00
shanshanzhong147 08434cfa32 新功能: 佣金回退日志 content 改成中文友好描述
之前接口返回原始 JSON 字符串(前端不好展示):
  "{\"type\":333,\"amount\":-649,\"order_no\":\"xxx\",\"timestamp\":\"...\"}"

改为可读文字:
  333 订单退款回佣 → "订单退款回佣(订单号 xxx)"
  337 提现驳回   → "提现申请被驳回,佣金已退回"
  338 提现取消   → "已取消提现,佣金已退回"

同时影响以下两个接口的 content 字段:
- /v1/public/user/withdrawal_log?biz_type=commission_refund (deprecated)
- /v1/public/user/commission_return_log
2026-06-12 20:35:27 -07:00
shanshanzhong147 be09a115ec 新功能: withdrawal_log 接口加 summary 字段 + admin 禁直接扣减 commission
接口侧:
- /v1/public/user/withdrawal_log 响应新增 summary 字段, 包含:
  - commission_balance (当前余额)
  - locked_by_pending (待审批占用)
  - available_to_withdraw (可提现)
  - total_historical_amount (已通过提现总额)
  - total_refunded_amount (退款回扣总额)
  - total_income_amount (收入总额)
- 前端可据此自洽展示账目对账, 用户能在一个接口里看清整笔账

代码守护:
- updateUserBasicInfoLogic 拒绝任何 change<0 的 commission 修改
- 扣减必须走 approveWithdrawal 写 type=334 日志
- 防止未来 admin 误操作再次造成 user.commission 与 system_logs 失衡

时间戳修复:
- queryWithdrawalLogLogic 和 queryCommissionReturnLogLogic 的时间戳
  从 UnixMilli 改回 Unix (秒级), 符合项目"后端统一秒级"约定

测试:
- 补 buildSummary 的 4 个 mock 查询期望
- 加 summary 字段值正确性断言
2026-06-12 19:49:03 -07:00
shanshanzhong147 cfb253d96f 修复(#38): commission_refund 收窄到只查 type=333(移除 337/338 提现退佣混入)
Closes HIF-38

owner 业务定义:commission_refund 这个分类只应返回「下级退单导致用户拿到的佣金被扣回」记录。

改动:
- queryWithdrawalLogLogic.go: ?biz_type=commission_refund 分支 SQL 过滤从 IN(333,337,338) 改为 = 333
- 同步更新 logic/handler 单测

不在范围:
- /commission_return_log(新推荐接口)继续返回 333/337/338 — 前端暂未切,owner 决定不动
- 337/338 不另外开 UI 入口 — 提现记录 status 字段(rejected/cancelled)已表达
2026-06-12 01:51:48 -07:00
shanshanzhong147 f11097ab83 新功能(#26): 拆分退款日志查询接口
拆分用户中心退款日志查询:

- 新增 GET /v1/public/user/commission_return_log(333/337/338)
- 旧 GET /v1/public/user/withdrawal_log?biz_type=commission_refund 复用新逻辑做兼容
- 默认 withdrawal_log 行为不变(仍查 withdrawals 表)
- 单测覆盖 333/337/338 happy path、坏 JSON 跳过、object_id 隔离、handler 级 HTTP 响应

父 issue: HIF-25
子 issue: HIF-26
2026-06-11 22:02:22 -07:00
shanshanzhong147 c39bfd39dd 修复(#21): 禁止通用订单状态写入claimed (#20)
* 修复(#21): 禁止通用订单状态写入claimed

Co-authored-by: multica-agent <github@multica.ai>

* 文档(#21): 补充PR说明

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
2026-06-11 02:47:48 -07:00
shanshanzhong147 de388ac1ef fix: expose user subscription speed override
测试环境部署 / 构建镜像并部署到测试环境 (push) Has been cancelled
持续集成 / 构建/Vet/测试 (pull_request) Has been cancelled
持续集成 / golangci-lint (pull_request) Has been cancelled
2026-06-11 02:39:16 -07:00
shanshanzhong147 6157b2c571 修复(#23): 修复用户订阅列表未回显用户级限速
* 修复(#23): 修复用户订阅列表未回显用户级限速

Co-authored-by: multica-agent <github@multica.ai>

* 修复(#23): 移除 PR 草稿文件

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
2026-06-11 01:50:47 -07:00
shanshanzhong147 268ae1ebf8 修复(#19): 续费订单支持限时活动价 (#19)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-10 00:31:24 -07:00
shanshanzhong147 f5ad26b943 新功能(#18): 用户提现记录支持区分提现和退佣 (#18)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-10 00:19:12 -07:00
shanshanzhong147 9b5ff89ee8 修复(#17): 修复订阅流量限制更新未生效
Closes HIF-17
2026-06-09 22:56:40 -07:00
shanshanzhong147 e74958e17f 修复(#16): 修复订单退款状态与后台恢复冲突 (#16)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-09 11:31:31 -07:00
shanshanzhong147 21811f4d63 修复(#13): 邀请列表返回设备标识和设备号 (#15)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-08 22:24:51 -07:00
shanshanzhong147 24caf58987 修复(#12): 优化用户列表限速计算性能 (#14)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-07 23:29:15 -07:00
shanshanzhong147 b98d718f3c 修复(#11): 修复家庭组订单退款订阅归属 (#13)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-07 08:23:19 -07:00
shanshanzhong147 bcb8cd222c 修复(#10): 禁止通用订单状态接口标记退款 (#12)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-05 23:35:42 -07:00
shanshanzhong147 34cd1c524e 修复(#8): 分组管理核心缺陷与测试覆盖 (#11)
Co-authored-by: multica-agent <github@multica.ai>
2026-06-04 03:13:38 -07:00
shanshanzhong147 19d28a8f89 修复(#1): 服务器用户列表缓存按 protocol 隔离 + 兜底不写缓存
服务器用户列表缓存跨协议污染修复(HIF-1 / 详见 PR #5 四件套):

1. 缓存 key 加 protocol 维度(`server:user:{server_id}:{protocol}`),对齐 ServerConfig 已有约定
2. 显式枚举协议清除用户列表缓存(AllProtocols + ServerUserListCacheKeysForServer),不用 SCAN
3. 三个兜底分支不写缓存 + Errorw 日志(带 server_id + protocol 字段)
4. hysteria2 → hysteria 兼容归一化 + 6 个新单测

Closes HIF-1
2026-06-03 05:37:03 -07:00
shanshanzhong147 c540091ef9 修复(#143): 邀请权益查询排序,消除 map 迭代序 flake
Closes HIF-143. 让 `inviteeAndInviterIds` 在 append 后 `slices.Sort` 升序,让 sqlmock IN 参数匹配稳定,同时让生产 SQL EXPLAIN 计划稳定。修复 GitHub Actions Deploy Staging 自 2026-06-03 03:51 起连续 8 次 `go test ./...` 失败问题。

测试: go test -count=10 修复前 4/10 fail, 修复后 30/30 pass.
改动: 2 files, +4/-2 (internal/logic/admin/invite/{benefits.go,benefits_test.go})
2026-06-02 22:04:16 -07:00
shanshanzhong147 87ebfa1fac 修复(#137): DeferCloseOrder 关单前反查支付网关 (启用 confirmationPayment)
Build docker and publish / build (20.15.1) (push) Failing after 18m47s
Build docker and publish / build (20.15.1) (pull_request) Failing after 19m31s
Squash merge of fix/137-defer-close-反查网关 (1367c4f).

DeferCloseOrder 直接将 status=1 订单关单,会把已经在网关侧完成支付但
notify 静默失败的订单错误关闭。本次在关单前调用 EPay 的网关查询接口
(confirmationPayment) 拿到三态结果:

- Paid: 原子化把 status 1->2,写回 trade_no,再投递 asynq 走激活流程
- Unpaid: 继续原来的 close 事务,把 status 改为 cancelled
- Unknown / 网关失败: 保持 status=1,下一轮 DeferClose 再试

新增 closeOrderLogic_test.go (232 行),覆盖三态分支 + recoverPaidOrder
的并发幂等。单测全量 PASS, go build + go vet 均干净。E2E 验收因测试环境
访问受限暂未跑,QA 已在 issue 上注明阻塞原因 (qa_partial_blocked_on_e2e_access)。

Co-authored-by: multica-agent <github@multica.ai>
2026-06-02 20:24:32 -07:00
shanshanzhong147 ac25eb4d91 修复(#140): 去掉 cancelWithdrawalLogic 在新流程下的重复退款
Build docker and publish / build (20.15.1) (push) Has been cancelled
Build docker and publish / build (20.15.1) (pull_request) Has been cancelled
Squash merge of fix/140-去掉撤销提现的重复退款 (86896cd).

HIF-22 引入 rejectWithdrawal 反查支付网关后,cancelWithdrawalLogic 仍在
事务体内调用 UpdateCommission(+amount),对已在 rejectWithdrawal 中退还
的金额做了二次退款。本次只保留 withdrawal.status -> Cancelled,与
rejectWithdrawal 行为对齐。

新增 cancelWithdrawalLogic_test.go 用 sqlmock 严格断言:撤销 happy path
只触发 BEGIN / SELECT FOR UPDATE / UPDATE withdrawals / COMMIT 四条 SQL,
对 user / system_logs 零读零写。

Co-authored-by: multica-agent <github@multica.ai>
2026-06-02 20:23:45 -07:00
架构师 750b7be424 修复(#136): EPay notify 静默失败硬化 + 回写 trade_no
Build docker and publish / build (20.15.1) (push) Failing after 8m55s
Build docker and publish / build (20.15.1) (pull_request) Failing after 22m22s
P01 签名校验失败由 return nil 改为返回 xerr.SignatureInvalid,handler 回 400,EPay 网关重试;Debug 旁路保留
P02 订单不存在维持 error 返回,仅 status=5 Finished 保留 nil 作幂等短路
P03 支付完成路径写入 order.trade_no = req.TradeNo,再 UpdateOrderStatus 刷缓存
附加:TradeStatus != TRADE_SUCCESS 降为 INFO 日志 + metric epay_notify_trade_not_success
抽离纯决策函数 evaluateEPayNotify,新增单测覆盖 4 个核心分支 + 签名优先级回归 + SQL 写路径 + URL 解析(9/9 PASS,-race 干净)

仅 internal/logic/notify/ePayNotifyLogic.go 与对应单测,无其他文件变更。

Co-authored-by: multica-agent <github@multica.ai>
2026-06-01 03:08:31 -07:00
架构师 aa11588c8f 修复(#129): 新注册无历史用户不再误命中沉默促销
Build docker and publish / build (20.15.1) (push) Failing after 22m17s
Build docker and publish / build (20.15.1) (pull_request) Failing after 22m28s
evaluateInactiveUserPromo 在 ErrRecordNotFound 时之前 return true,导致
新注册无任何订阅历史的用户被错误判定为"沉默用户"命中 inactive_user 规则。
改为 return false 保持判定语义一致:没有历史订阅 ≠ 沉默用户。

Squash from origin/fix/129-新注册误命中沉默促销 (77377ed)

Co-authored-by: multica-agent <github@multica.ai>
2026-06-01 00:28:26 -07:00
shanshanzhong147 5b9f384f81 修复(#132): 退款幂等校验 + 已退款订单防重新激活
Build docker and publish / build (20.15.1) (push) Failing after 21m4s
Build docker and publish / build (20.15.1) (pull_request) Failing after 21m47s
P01:refundOrderLogic.RefundOrder 在事务内 FOR UPDATE 后、lockCommissionSource 前新增
333 退款日志扫描,命中即返回 OrderAlreadyRefunded(61006),不再写日志/扣 commission/
改 order.status。

P02:堵住已退款订单状态被回退入口
- queue/logic/order/stuckOrderRecoveryLogic.go:批扫 status=6 时新增 333 日志守卫,
  已退款订单不再被重置为 5 + 重新入队 activate(HIF-131 trace 中订单 53647 被刷回 5
  的真凶)
- queue/logic/order/activateOrderLogic.go:releaseClaim 同步加守卫做防御性兜底

新增 internal/model/log/refund.go 共享 helper HasRefundCommissionLog:
type=33 + content LIKE 走索引粗筛,再 JSON 反序列化确认 content.type==333 AND
content.order_no==orderNo,防 LIKE 子串误判。

测试:单元测试覆盖正常退款 / 已有 333 日志拒绝 / 子串误判防御 / 脏 JSON 容错;
sqlmock 严格断言命中后事务序列只含 BEGIN/SELECT order FOR UPDATE/SELECT
system_logs/ROLLBACK,无任何 commission 写入。

不做:calculateCommission、status 枚举拆分、表结构变更、支付通道 notify、用户余额回补。

Co-authored-by: multica-agent <github@multica.ai>
2026-05-31 20:19:35 -07:00
shanshanzhong147 7236ca4cf2 修复(#128): 按规则类型决定促销资格,让 InactiveUser/Campaign 对老用户生效
Build docker and publish / build (20.15.1) (push) Has been cancelled
Build docker and publish / build (20.15.1) (pull_request) Has been cancelled
此前 calculatePurchasePrice 把 allowPromo 绑死在 orderType == 1,导致只要用户
有任何过往付费订阅(含已过期),就会被 paidSubscriptionQuery 路由为续费
(orderType=2),跳过所有促销评估。后果:

  - InactiveUser 召回促销永远无法触发(其目标人群恰好就是有过期订阅的用户)
  - Campaign 全员活动对老用户 / 升级加购场景完全失效
  - 套餐列表(loadSubscribePromoMap)直接调 EvaluatePromo 不感知 orderType,
    可能显示促销价但下单时却拿到原价

修复方式:把 isFirstPurchase 下放给 EvaluatePromo,由规则类型决定 gating:

  - NewUser    要求 isFirstPurchase=true(保留首购语义)
  - InactiveUser 由规则自身的"上次订阅过期 N 月以上"条件判定
  - Campaign   时间窗内对任意用户生效

新增 common.HasPaidSubscription 助手,套餐列表与下单走同一份 isFirstPurchase
判定,确保展示价与实际下单价口径一致。

测试:补充 EvaluatePromo / calculatePurchasePrice 的 NewUser 屏蔽 + Campaign
放开用例;更新 loadSubscribePromoMap 测试覆盖新增 HasPaidSubscription 查询。

注:renewalLogic.go 仍未接入促销(属于方向 B 的彻底统一,本次未涵盖)。
2026-05-31 19:00:30 -07:00
shanshanzhong147 ae126296e3 修复(#128): 统一续费场景促销判断
Build docker and publish / build (20.15.1) (push) Failing after 23m3s
Build docker and publish / build (20.15.1) (pull_request) Failing after 19m4s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-30 23:12:39 -07:00
shanshanzhong147 1e99cfb83c 修复(#128): 兼容促销规则毫秒时间戳
Build docker and publish / build (20.15.1) (push) Failing after 19m21s
Build docker and publish / build (20.15.1) (pull_request) Failing after 19m48s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-30 04:16:21 -07:00
shanshanzhong147 0659a930f8 修复(#128): 修复家庭成员邀请流水可见性
Build docker and publish / build (20.15.1) (push) Failing after 18m41s
Build docker and publish / build (20.15.1) (pull_request) Failing after 19m16s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-30 03:27:04 -07:00
shanshanzhong147 c2d1b5a0d8 修复(#130): 统一家庭成员促销资格口径
Build docker and publish / build (20.15.1) (push) Failing after 22m15s
Build docker and publish / build (20.15.1) (pull_request) Failing after 18m6s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-30 01:58:15 -07:00
shanshanzhong147 3644e9ce3f 修复(#128): 统一促销价格资格口径
Build docker and publish / build (20.15.1) (push) Failing after 18m40s
Build docker and publish / build (20.15.1) (pull_request) Failing after 19m24s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-29 22:42:04 -07:00
shanshanzhong147 e5d6539d79 修复(#126): 修复家庭组邀请记录漏查验收分支
Build docker and publish / build (20.15.1) (push) Failing after 20m3s
Build docker and publish / build (20.15.1) (pull_request) Failing after 21m10s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-29 20:35:37 -07:00
shanshanzhong147 e17dc4a273 修复: GET /v1/admin/promo/price/list 字段不匹配导致 400
Build docker and publish / build (20.15.1) (push) Failing after 21m12s
Build docker and publish / build (20.15.1) (pull_request) Failing after 22m17s
前端发 rule_id/subscribe_id (均可选), 后端 API 定义为 promo_rule_id
(required), 直接返回 "PromoRuleId is a required field"。

对齐前端约定 (与 usage/list 命名一致):
- API: promo_rule_id(required) → rule_id + subscribe_id, 均可选
- model.QueryPriceList: 改为接 PriceFilter, 按条件过滤
- 同步 fake mock 与校验测试签名
2026-05-29 01:04:37 -07:00
shanshanzhong147 b162022d39 修复: 邀请列表 UNIX_TIMESTAMP 在 DATETIME(N) 上返回小数导致 Scan int64 失败
Build docker and publish / build (20.15.1) (pull_request) Successful in 7m37s
Build docker and publish / build (20.15.1) (push) Failing after 20m37s
MySQL DATETIME 带小数秒精度时, UNIX_TIMESTAMP() 返回 "1779966403.631"
形式的 DECIMAL, Go 端 int64 字段无法 Scan, 触发 100 条 Scan error,
前端拿到的 invited_at/created_at 全为 0。

改用 CAST(UNIX_TIMESTAMP(...) AS SIGNED) 在 SQL 层截断转 BIGINT,
与 getInviteRecordsLogic / getInviteSalesLogic 的现有约定一致。
2026-05-28 23:15:13 -07:00
shanshanzhong147 075c1215ca 还原: 撤销 fefbd4f5 的 go-zero stub 方案,回到 goctl 1.7.2 + gin 原生 routes
Build docker and publish / build (20.15.1) (pull_request) Failing after 21m54s
Build docker and publish / build (20.15.1) (push) Failing after 20m31s
fefbd4f5 (#104) 用本地 third_party/gozero stub 假冒 go-zero 依赖,
让 goctl 1.9.2 生成的 rest.Server/rest.Route 风格 routes.go 能编译,
但带来非标 vendor、Dockerfile 漏拷、新人误解等维护成本。

本次回到 fefbd4f5 之前的方案:
- routes.go 用 gin 原生 publicUserGroupRouter.GET(...) 风格(goctl 1.7.2)
- server.go 直接 handler.RegisterHandlers(r, svc),无需 rest.NewGinServer
- svc/serviceContext.go 不再持有 AuthMiddleware/DeviceMiddleware/ServerMiddleware 字段
- go.mod 删除 zeromicro/go-zero require + replace 指令
- 删除 third_party/gozero/ stub 模块
- 删除 fefbd4f5 引入的 28 个 goctl 生成的空 stub 文件和 nodeserver/apple 转发器
- Dockerfile 不再需要 COPY third_party/

invite_sales 还原路由保留(gin 老风格写法)。
2026-05-28 21:46:33 -07:00
shanshanzhong147 3e265bd837 新功能: 还原 v1/public/user/invite_sales 接口 + promo schema 修复迁移
Build docker and publish / build (20.15.1) (push) Failing after 13m47s
Build docker and publish / build (20.15.1) (pull_request) Failing after 15m7s
- 还原 /v1/public/user/invite_sales 接口及 /invite/sales 别名(与 invite_records 并存)
  逻辑/handler/types 与 197fed7d 删除前版本完全一致,按 fefbd4f5 新 routes 结构注册
- 新增迁移 02155_promo_schema_fix: 幂等修复 subscribe_promo / order 列类型与索引偏差
- 同步 etc/ppanel.yaml 数据库连接配置
- 补齐相关需求与设计文档
2026-05-28 20:46:37 -07:00
shanshanzhong147 fefbd4f56a 修复(#104): 修复 goctl 重新生成代码漂移
Build docker and publish / build (20.15.1) (push) Failing after 58s
Build docker and publish / build (20.15.1) (pull_request) Failing after 52s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 23:54:26 -07:00
shanshanzhong147 197fed7d12 新功能(#102): 新增邀请记录接口并删除旧邀请销售接口
Build docker and publish / build (20.15.1) (push) Failing after 10m56s
Build docker and publish / build (20.15.1) (pull_request) Successful in 8m50s
Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 22:50:16 -07:00
shanshanzhong147 f452f80100 配置(#98): 扩展文件上传 Content-Type 白名单支持图片
Build docker and publish / build (20.15.1) (push) Failing after 9m55s
Build docker and publish / build (20.15.1) (pull_request) Successful in 8m7s
- 在 etc/ppanel.yaml 与 internal/config/config.go 的 S3.AllowedContentTypes 新增 image/jpeg,image/jpg,image/png,image/webp,image/gif,image/heic,image/heif,image/bmp
- 保留原 zip/gzip/text/json/octet-stream
- validateInitRequest 在拒绝时携带 content_type is not allowed 业务消息
- 新增 internal/logic/public/file/common_test.go,覆盖允许/拒绝及无 Content-Type 嗅探
- doc/tapi-file-upload-zh.md 同步允许类型列表与错误码说明

Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 19:50:51 -07:00
shanshanzhong147 1022160ff8 新功能(#89): 增强邀请列表接口 + 新增全局邀请管理接口
Build docker and publish / build (20.15.1) (push) Failing after 9m30s
Build docker and publish / build (20.15.1) (pull_request) Successful in 7m48s
P01: GET /v1/admin/user/invite/list 增加 search/enable/user_id_search
筛选参数,响应新增 order_count/has_purchased/inviter_commission/
inviter_gift_days/invitee_gift_days 权益字段。

P02: 新增 GET /v1/admin/invite/list 全局邀请管理接口,支持按
邀请人/被邀请人筛选和搜索,返回邀请关系及权益聚合数据。

共用 QueryBenefits 批量查询防 N+1,分页上限 100。

Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 10:32:28 -07:00
shanshanzhong147 82eff47f38 新功能(#69): 用户级限速覆盖 — 数据层 + 核心逻辑 + 管理接口
Build docker and publish / build (20.15.1) (push) Failing after 8m52s
Build docker and publish / build (20.15.1) (pull_request) Successful in 7m51s
- 新增 migration 02153: user_subscribe 表添加 speed_limit、traffic_limit 列(幂等)
- model 层 Subscribe/SubscribeDetails 新增用户级限速字段(*string 类型支持 nil 回退)
- server 用户列表和管理员详情接口支持用户级限速覆盖优先级计算
- 更新管理员订阅更新接口支持写入/清除用户级限速

Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 08:07:16 -07:00
shanshanzhong147 d351b50066 修复(#71): 管理员订阅限速接口拒绝负数限速和非法 traffic_limit
Build docker and publish / build (20.15.1) (push) Failing after 8m50s
Build docker and publish / build (20.15.1) (pull_request) Successful in 7m56s
- SpeedLimit 加 validate:"gte=0" 校验
- TrafficLimit 加 JSON 格式校验
- 新增单测覆盖负数限速和非法 JSON 场景

Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 07:13:05 -07:00
shanshanzhong147 4366a9be8b 修复(#79): 促销管理后台API + 审查问题修复
Build docker and publish / build (20.15.1) (push) Failing after 9m10s
Build docker and publish / build (20.15.1) (pull_request) Successful in 8m18s
- 实现促销管理接口:规则CRUD、优惠价配置、使用记录查询
- 修复 UpsertPrices 新增记录时提前 return 的问题
- DeleteRule/DeletePrice 不存在记录返回 code=404
- SetPromoPriceRequest.items 空数组校验
- 分页参数限制 page>0、1<=size<=200
- 下单侧促销价格按数量档总价口径计算(含 #87 修复)

Co-authored-by: multica-agent <github@multica.ai>
2026-05-27 06:32:42 -07:00