2026-06-23 11:53:00 +08:00

110 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package wallet
import (
"context"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
"hyapp/services/wallet-service/internal/domain/ledger"
"strings"
)
// ListVipPackages 返回可购买 VIP 包和当前会员状态。
func (s *Service) ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) {
if userID <= 0 {
return ledger.UserVip{}, nil, xerr.New(xerr.InvalidArgument, "user_id is required")
}
if s.repository == nil {
return ledger.UserVip{}, nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
return s.repository.ListVipPackages(ctx, userID)
}
// GetMyVip 返回当前用户会员状态;过期会员会按 active=false 投影。
func (s *Service) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip, error) {
if userID <= 0 {
return ledger.UserVip{}, xerr.New(xerr.InvalidArgument, "user_id is required")
}
if s.repository == nil {
return ledger.UserVip{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
return s.repository.GetMyVip(ctx, userID)
}
// PurchaseVip 执行 VIP 购买、升级或续期;降级由 repository 在锁内按当前会员状态拒绝。
func (s *Service) PurchaseVip(ctx context.Context, command ledger.PurchaseVipCommand) (ledger.PurchaseVipReceipt, error) {
if command.CommandID == "" || command.UserID <= 0 || command.Level <= 0 {
return ledger.PurchaseVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip purchase command is incomplete")
}
if s.repository == nil {
return ledger.PurchaseVipReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
command.AppCode = appcode.Normalize(command.AppCode)
ctx = appcode.WithContext(ctx, command.AppCode)
return s.repository.PurchaseVip(ctx, command)
}
// GrantVip 是活动和后台赠送 VIP 的统一入口;购买仍走 PurchaseVip 完成扣费。
func (s *Service) GrantVip(ctx context.Context, command ledger.GrantVipCommand) (ledger.GrantVipReceipt, error) {
if command.CommandID == "" || command.TargetUserID <= 0 || command.Level <= 0 {
return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip grant command is incomplete")
}
if len(command.CommandID) > 128 {
return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "command_id is too long")
}
command.GrantSource = ledger.NormalizeVipGrantSource(command.GrantSource)
switch command.GrantSource {
case ledger.VipGrantSourceAdmin, ledger.VipGrantSourceManagerCenter:
if command.OperatorUserID <= 0 {
return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "operator_user_id is required")
}
case ledger.VipGrantSourceActivity:
if command.OperatorUserID < 0 {
return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "operator_user_id is invalid")
}
default:
return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "vip grant_source is invalid")
}
command.Reason = strings.TrimSpace(command.Reason)
if command.Reason == "" {
command.Reason = command.GrantSource
}
if len(command.Reason) > 512 {
return ledger.GrantVipReceipt{}, xerr.New(xerr.InvalidArgument, "reason is too long")
}
if s.repository == nil {
return ledger.GrantVipReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
command.AppCode = appcode.Normalize(command.AppCode)
ctx = appcode.WithContext(ctx, command.AppCode)
return s.repository.GrantVip(ctx, command)
}
// ListAdminVipLevels 返回后台 VIP 配置页的 10 级配置快照。
func (s *Service) ListAdminVipLevels(ctx context.Context) ([]ledger.VipLevel, error) {
if s.repository == nil {
return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
return s.repository.ListAdminVipLevels(ctx)
}
// UpdateAdminVipLevels 保存后台 VIP 等级配置;完整校验下沉到 repository保证和购买事务一致。
func (s *Service) UpdateAdminVipLevels(ctx context.Context, levels []ledger.AdminVipLevelCommand, operatorUserID int64) ([]ledger.VipLevel, error) {
if operatorUserID <= 0 {
return nil, xerr.New(xerr.InvalidArgument, "operator_user_id is required")
}
if s.repository == nil {
return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
normalized := make([]ledger.AdminVipLevelCommand, 0, len(levels))
for _, level := range levels {
level.Name = strings.TrimSpace(level.Name)
level.Status = strings.ToLower(strings.TrimSpace(level.Status))
normalized = append(normalized, level)
}
ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
return s.repository.UpdateAdminVipLevels(ctx, normalized, operatorUserID)
}