refactor: 删除 identity 用户存储中与 memberlevel 重复的会员等级写入方法

This commit is contained in:
dujiao-next committed 2026-10-11 12:49:26 +08:00
1 parent 812a0581ba
commit 807bda7602
6 files changed
+4 -69

No files matched your search

@@ -4,8 +4,6 @@ import (
"time"
userdomain "github.com/dujiao-next/internal/modules/identity/user/domain"
"github.com/shopspring/decimal"
)
// ListFilter describes the administration user-directory query.
@@ -30,12 +28,8 @@ type Store interface {
ListByIDs([]uint) ([]userdomain.User, error)
Create(*userdomain.User) error
Update(*userdomain.User) error
IncrementTotalRecharged(uint, decimal.Decimal) error
IncrementTotalSpent(uint, decimal.Decimal) error
UpdateMemberLevelIfCurrent(uint, uint, uint) (int64, error)
List(ListFilter) ([]userdomain.User, int64, error)
BatchUpdateStatus([]uint, string) error
AssignDefaultMemberLevel(uint) (int64, error)
UpdateTOTPPending(uint, string, time.Time) error
UpdateTOTPEnabled(uint, string, time.Time, string) error
UpdateRecoveryCodes(uint, string) error
@@ -9,9 +9,7 @@ import (
"github.com/dujiao-next/internal/constants"
usercontract "github.com/dujiao-next/internal/modules/identity/user/contract"
userdomain "github.com/dujiao-next/internal/modules/identity/user/domain"
"github.com/dujiao-next/internal/shared/money"
"github.com/shopspring/decimal"
"gorm.io/gorm"
)
@@ -78,46 +76,6 @@ func (r *Store) Update(user *userdomain.User) error {
Updates(user).Error
}
// IncrementTotalRecharged 原子累加用户累计充值金额。
func (r *Store) IncrementTotalRecharged(userID uint, amount decimal.Decimal) error {
return r.incrementMoneyColumn(userID, "total_recharged", amount)
}
// IncrementTotalSpent 原子累加用户累计消费金额。
func (r *Store) IncrementTotalSpent(userID uint, amount decimal.Decimal) error {
return r.incrementMoneyColumn(userID, "total_spent", amount)
}
func (r *Store) incrementMoneyColumn(userID uint, column string, amount decimal.Decimal) error {
if userID == 0 {
return nil
}
amount = amount.Round(2)
if amount.LessThanOrEqual(decimal.Zero) {
return nil
}
return r.db.Model(&userdomain.User{}).
Where("id = ? AND deleted_at IS NULL", userID).
Updates(map[string]interface{}{
column: gorm.Expr(column+" + ?", money.FromDecimal(amount)),
"updated_at": time.Now(),
}).Error
}
// UpdateMemberLevelIfCurrent 仅在用户当前等级未被其他流程改变时更新会员等级。
func (r *Store) UpdateMemberLevelIfCurrent(userID, currentLevelID, nextLevelID uint) (int64, error) {
if userID == 0 || currentLevelID == nextLevelID {
return 0, nil
}
result := r.db.Model(&userdomain.User{}).
Where("id = ? AND member_level_id = ? AND deleted_at IS NULL", userID, currentLevelID).
Updates(map[string]interface{}{
"member_level_id": nextLevelID,
"updated_at": time.Now(),
})
return result.RowsAffected, result.Error
}
// List 用户列表
func (r *Store) List(filter usercontract.ListFilter) ([]userdomain.User, int64, error) {
query := r.db.Model(&userdomain.User{}).Where("users.deleted_at IS NULL")
@@ -213,20 +171,6 @@ func (r *Store) BatchUpdateStatus(userIDs []uint, status string) error {
return r.db.Model(&userdomain.User{}).Where("id IN ? AND deleted_at IS NULL", userIDs).Updates(updates).Error
}
// AssignDefaultMemberLevel 为所有未分配等级(member_level_id=0)的用户批量分配默认等级
func (r *Store) AssignDefaultMemberLevel(defaultLevelID uint) (int64, error) {
if defaultLevelID == 0 {
return 0, nil
}
result := r.db.Model(&userdomain.User{}).
Where("(member_level_id = 0 OR member_level_id IS NULL) AND deleted_at IS NULL").
Updates(map[string]interface{}{
"member_level_id": defaultLevelID,
"updated_at": time.Now(),
})
return result.RowsAffected, result.Error
}
// UpdateTOTPPending 写入待绑定 secret 与过期时间
func (r *Store) UpdateTOTPPending(userID uint, encSecret string, expiresAt time.Time) error {
if userID == 0 {
@@ -177,9 +177,6 @@ func TestStoreSoftDeleteExcludesUserFromReadsListsAndMutations(t *testing.T) {
if err := store.BatchUpdateStatus([]uint{user.ID}, "disabled"); err != nil {
t.Fatalf("batch update deleted user: %v", err)
}
if err := store.IncrementTotalRecharged(user.ID, decimal.NewFromInt(5)); err != nil {
t.Fatalf("increment deleted user: %v", err)
}
if err := store.ClearTOTP(user.ID); err != nil {
t.Fatalf("clear deleted user TOTP: %v", err)
}
@@ -376,7 +376,7 @@ func TestLoginWithTelegramAssignsDefaultMemberLevel(t *testing.T) {
svc.SetMemberLevelService(memberlevelapp.NewService(
memberlevelgormstore.NewLevelStore(db),
nil,
userstore.New(db),
memberlevelgormstore.NewUserStore(db),
))
res, err := svc.LoginVerifiedTelegram(&telegramauthapp.IdentityVerified{
@@ -308,7 +308,7 @@ func TestPreviewOrderAppliesMemberDiscountForManualProductBeforeFormCompleted(t
ProductStore: productgormstore.NewProductStore(db),
ProductSKUStore: productgormstore.NewSKUStore(db),
PromotionRepo: promotiongormstore.New(db),
MemberLevelService: memberlevelapp.NewService(levelRepo, priceRepo, userRepo),
MemberLevelService: memberlevelapp.NewService(levelRepo, priceRepo, memberlevelgormstore.NewUserStore(db)),
ExpireMinutes: 15,
})
@@ -439,7 +439,7 @@ func TestBuildOrderResultStacksPromotionAndMemberDiscount(t *testing.T) {
ProductStore: productgormstore.NewProductStore(db),
ProductSKUStore: productgormstore.NewSKUStore(db),
PromotionRepo: promotiongormstore.New(db),
MemberLevelService: memberlevelapp.NewService(levelRepo, priceRepo, userRepo),
MemberLevelService: memberlevelapp.NewService(levelRepo, priceRepo, memberlevelgormstore.NewUserStore(db)),
ExpireMinutes: 15,
})
@@ -161,7 +161,7 @@ func setupWholesaleOrderFixture(t *testing.T, name string, wholesalePrices produ
PromotionRepo: promotiongormstore.New(db),
CouponStore: coupongormstore.New(db),
CouponUsageStore: coupongormstore.NewUsageStore(db),
MemberLevelService: memberlevelapp.NewService(levelRepo, priceRepo, userRepo),
MemberLevelService: memberlevelapp.NewService(levelRepo, priceRepo, memberlevelgormstore.NewUserStore(db)),
ExpireMinutes: 15,
})