From 4bb8613570f6c3dd9a91beed95e6aa11bdec9894 Mon Sep 17 00:00:00 2001 From: hy001 Date: Wed, 24 Jun 2026 15:39:42 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=8F=E7=90=86=E4=B8=AD=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/service/managercenter/service.go | 38 +++++++------ .../service/managercenter/service_test.go | 56 +++++++++++++------ internal/service/managercenter/types.go | 18 +++--- .../055_team_manager_country_switch.sql | 16 ++++++ 4 files changed, 86 insertions(+), 42 deletions(-) create mode 100644 migrations/055_team_manager_country_switch.sql diff --git a/internal/service/managercenter/service.go b/internal/service/managercenter/service.go index 47af0d1..b1da867 100644 --- a/internal/service/managercenter/service.go +++ b/internal/service/managercenter/service.go @@ -15,17 +15,18 @@ import ( ) type teamManagerInfoRow struct { - ID int64 `gorm:"column:id;primaryKey"` - UserID int64 `gorm:"column:user_id"` - Origin string `gorm:"column:sys_origin"` - Contact string `gorm:"column:contact"` - RegionID string `gorm:"column:region_id"` - CanAddBDLeader *bool `gorm:"column:can_add_bd_leader"` - CanGiftProps *bool `gorm:"column:can_gift_props"` - CanBanUser *bool `gorm:"column:can_ban_user"` - CanUnbanUser *bool `gorm:"column:can_unban_user"` - CreateUser int64 `gorm:"column:create_user"` - UpdateUser int64 `gorm:"column:update_user"` + ID int64 `gorm:"column:id;primaryKey"` + UserID int64 `gorm:"column:user_id"` + Origin string `gorm:"column:sys_origin"` + Contact string `gorm:"column:contact"` + RegionID string `gorm:"column:region_id"` + CanAddBDLeader *bool `gorm:"column:can_add_bd_leader"` + CanGiftProps *bool `gorm:"column:can_gift_props"` + CanBanUser *bool `gorm:"column:can_ban_user"` + CanUnbanUser *bool `gorm:"column:can_unban_user"` + CanChangeCountry *bool `gorm:"column:can_change_country"` + CreateUser int64 `gorm:"column:create_user"` + UpdateUser int64 `gorm:"column:update_user"` } func (teamManagerInfoRow) TableName() string { @@ -378,9 +379,9 @@ func (s *Service) UnbanUser(ctx context.Context, user AuthUser, req UnbanUserReq }, nil } -// ChangeUserCountry 只允许经理移动普通用户国家;用户已有业务身份时拒绝,避免跨国家后团队、币商和主播归属数据不一致。 +// ChangeUserCountry 只允许 admin 开启改国家权限的经理移动普通用户国家;目标用户已有业务身份时拒绝,避免跨国家后团队、币商和主播归属数据不一致。 func (s *Service) ChangeUserCountry(ctx context.Context, user AuthUser, req ChangeUserCountryRequest) (*ChangeUserCountryResponse, error) { - if err := s.ensureManager(ctx, user); err != nil { + if _, err := s.requireManagerFeature(ctx, user, managerFeatureChangeCountry); err != nil { return nil, err } if req.UserID.Int64() <= 0 { @@ -459,10 +460,11 @@ func (s *Service) requireManagerFeature(ctx context.Context, user AuthUser, feat func managerFeaturesFromRow(row teamManagerInfoRow) ManagerFeatures { return ManagerFeatures{ - AddBDLeader: defaultEnabled(row.CanAddBDLeader), - GiftProps: defaultEnabled(row.CanGiftProps), - BanUser: defaultEnabled(row.CanBanUser), - UnbanUser: defaultEnabled(row.CanUnbanUser), + AddBDLeader: defaultEnabled(row.CanAddBDLeader), + GiftProps: defaultEnabled(row.CanGiftProps), + BanUser: defaultEnabled(row.CanBanUser), + UnbanUser: defaultEnabled(row.CanUnbanUser), + ChangeCountry: defaultEnabled(row.CanChangeCountry), } } @@ -480,6 +482,8 @@ func (features ManagerFeatures) enabled(feature managerFeature) bool { return features.BanUser case managerFeatureUnbanUser: return features.UnbanUser + case managerFeatureChangeCountry: + return features.ChangeCountry default: return false } diff --git a/internal/service/managercenter/service_test.go b/internal/service/managercenter/service_test.go index 68d4d35..0f818d4 100644 --- a/internal/service/managercenter/service_test.go +++ b/internal/service/managercenter/service_test.go @@ -180,10 +180,11 @@ func TestGetProfileReturnsManagerFeatures(t *testing.T) { service, _ := newManagerCenterTestService(t) db := service.db.(*gorm.DB) seedManagerWithFeatures(t, db, 1, ManagerFeatures{ - AddBDLeader: true, - GiftProps: false, - BanUser: true, - UnbanUser: false, + AddBDLeader: true, + GiftProps: false, + BanUser: true, + UnbanUser: false, + ChangeCountry: true, }) seedUsers(t, db, userBaseInfoRow{ID: 1, Account: "1"}) @@ -191,7 +192,7 @@ func TestGetProfileReturnsManagerFeatures(t *testing.T) { if err != nil { t.Fatalf("GetProfile() error = %v", err) } - if !resp.Features.AddBDLeader || resp.Features.GiftProps || !resp.Features.BanUser || resp.Features.UnbanUser { + if !resp.Features.AddBDLeader || resp.Features.GiftProps || !resp.Features.BanUser || resp.Features.UnbanUser || !resp.Features.ChangeCountry { t.Fatalf("features = %+v, want row switches returned", resp.Features) } } @@ -793,6 +794,25 @@ func TestChangeUserCountryUpdatesCountryAndClearsCache(t *testing.T) { } } +func TestChangeUserCountryRejectsDisabledFeature(t *testing.T) { + service, _ := newManagerCenterTestService(t) + db := service.db.(*gorm.DB) + seedManagerWithFeatures(t, db, 1, ManagerFeatures{AddBDLeader: true, GiftProps: true, BanUser: true, UnbanUser: true}) + seedUsers(t, db, userBaseInfoRow{ID: 2, Account: "2", CountryID: 10, CountryCode: "SA", CountryName: "Saudi Arabia"}) + seedCountries(t, db, sysCountryCodeRow{ID: 11, AlphaTwo: "AE", CountryName: "United Arab Emirates", Open: true}) + + _, err := service.ChangeUserCountry(context.Background(), AuthUser{UserID: 1}, ChangeUserCountryRequest{UserID: ID(2), CountryID: ID(11)}) + assertAppErrorCode(t, err, "manager_feature_disabled") + + var row userBaseInfoRow + if err := db.Where("id = ?", int64(2)).First(&row).Error; err != nil { + t.Fatalf("load user: %v", err) + } + if row.CountryID != 10 || row.CountryCode != "SA" { + t.Fatalf("user row = %+v, want unchanged country when feature disabled", row) + } +} + func TestChangeUserCountryRejectsHistoryIdentity(t *testing.T) { service, _ := newManagerCenterTestService(t) db := service.db.(*gorm.DB) @@ -867,24 +887,26 @@ func newManagerCenterTestService(t *testing.T) (*Service, *fakeManagerGateway) { func seedManager(t *testing.T, db *gorm.DB, userID int64) { t.Helper() seedManagerWithFeatures(t, db, userID, ManagerFeatures{ - AddBDLeader: true, - GiftProps: true, - BanUser: true, - UnbanUser: true, + AddBDLeader: true, + GiftProps: true, + BanUser: true, + UnbanUser: true, + ChangeCountry: true, }) } func seedManagerWithFeatures(t *testing.T, db *gorm.DB, userID int64, features ManagerFeatures) { t.Helper() if err := db.Create(&teamManagerInfoRow{ - ID: userID, - UserID: userID, - Origin: "LIKEI", - RegionID: "SA", - CanAddBDLeader: boolPtr(features.AddBDLeader), - CanGiftProps: boolPtr(features.GiftProps), - CanBanUser: boolPtr(features.BanUser), - CanUnbanUser: boolPtr(features.UnbanUser), + ID: userID, + UserID: userID, + Origin: "LIKEI", + RegionID: "SA", + CanAddBDLeader: boolPtr(features.AddBDLeader), + CanGiftProps: boolPtr(features.GiftProps), + CanBanUser: boolPtr(features.BanUser), + CanUnbanUser: boolPtr(features.UnbanUser), + CanChangeCountry: boolPtr(features.ChangeCountry), }).Error; err != nil { t.Fatalf("seed manager: %v", err) } diff --git a/internal/service/managercenter/types.go b/internal/service/managercenter/types.go index 1f8bd6f..00b4df2 100644 --- a/internal/service/managercenter/types.go +++ b/internal/service/managercenter/types.go @@ -41,10 +41,11 @@ const ( type managerFeature string const ( - managerFeatureAddBDLeader managerFeature = "add_bd_leader" - managerFeatureGiftProps managerFeature = "gift_props" - managerFeatureBanUser managerFeature = "ban_user" - managerFeatureUnbanUser managerFeature = "unban_user" + managerFeatureAddBDLeader managerFeature = "add_bd_leader" + managerFeatureGiftProps managerFeature = "gift_props" + managerFeatureBanUser managerFeature = "ban_user" + managerFeatureUnbanUser managerFeature = "unban_user" + managerFeatureChangeCountry managerFeature = "change_country" ) type AppError = common.AppError @@ -121,10 +122,11 @@ type ProfileResponse struct { } type ManagerFeatures struct { - AddBDLeader bool `json:"addBdLeader"` - GiftProps bool `json:"giftProps"` - BanUser bool `json:"banUser"` - UnbanUser bool `json:"unbanUser"` + AddBDLeader bool `json:"addBdLeader"` + GiftProps bool `json:"giftProps"` + BanUser bool `json:"banUser"` + UnbanUser bool `json:"unbanUser"` + ChangeCountry bool `json:"changeCountry"` } type UserSearchResponse struct { diff --git a/migrations/055_team_manager_country_switch.sql b/migrations/055_team_manager_country_switch.sql new file mode 100644 index 0000000..5b553fe --- /dev/null +++ b/migrations/055_team_manager_country_switch.sql @@ -0,0 +1,16 @@ +SET @table_schema = DATABASE(); + +SET @ddl = IF( + EXISTS( + SELECT 1 + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = @table_schema + AND TABLE_NAME = 'team_manager_base_info' + AND COLUMN_NAME = 'can_change_country' + ), + 'SELECT 1', + "ALTER TABLE `team_manager_base_info` ADD COLUMN `can_change_country` tinyint(1) NOT NULL DEFAULT 1 COMMENT '经理中心是否允许修改用户国家' AFTER `can_unban_user`" +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt;