From 2823ff13bff9627d662861af4f95b5dcfbfdd597 Mon Sep 17 00:00:00 2001 From: break Date: Mon, 20 Jul 2026 11:56:25 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=E6=8E=92=E9=98=9F?= =?UTF-8?q?=E9=A1=BA=E5=BB=B6=E5=A5=97=E9=A4=90=E6=BF=80=E6=B4=BB=E6=97=B6?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=8C=89=E4=B8=8B=E5=8D=95=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E7=94=9F=E6=95=88=E6=97=A5=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit activatePendingUsage 被"前一个主套餐到期后顺延激活下一个待生效套餐"和 "等待实名认证后激活"两种场景共用,但其中 ExpiryBase=from_purchase 计时 基准分支(REALNAME-04)本来只为后者设计,却被无差别套用到前者。 导致主套餐配置为 from_purchase 且需要排队等待前一个套餐到期才能生效的 套餐,激活时错误地把生效时间算成下单时间,而不是真正开始生效的那一刻, 使到期时间提前了排队等待的天数,客户少享受了相应天数的服务。 现改为只有当 usage.PendingRealnameActivation 为 true(确实是在等实名) 时才按 ExpiryBase 选择计时基准,纯排队顺延场景一律使用当前时刻,即顺延 语义。 --- internal/service/package/activation_service.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/service/package/activation_service.go b/internal/service/package/activation_service.go index 65fdd3c..e6a1a90 100644 --- a/internal/service/package/activation_service.go +++ b/internal/service/package/activation_service.go @@ -552,8 +552,12 @@ func (s *ActivationService) isCarrierRealnamed(ctx context.Context, tx *gorm.DB, } func (s *ActivationService) activatePendingUsage(ctx context.Context, tx *gorm.DB, usage *model.PackageUsage, pkg *model.Package, carrierType string, carrierID uint, now time.Time, logMessage string) error { + // ExpiryBase=from_purchase 只用于"等待实名激活"场景(REALNAME-04):套餐已购买但资产未实名, + // 计时基准按购买时间算,实名只是解锁使用权。此函数同时被"前一个主套餐到期后排队顺延"场景复用, + // 这种情况下 usage.PendingRealnameActivation 为 false,不应该套用购买时间,否则排队等待的天数会 + // 从到期时间里被扣掉。只有当这条记录确实是因为等实名才被搁置时,才按 ExpiryBase 选基准。 var activatedAt time.Time - if pkg.ExpiryBase == "from_purchase" { + if usage.PendingRealnameActivation && pkg.ExpiryBase == "from_purchase" { activatedAt = usage.CreatedAt } else { activatedAt = now