diff --git a/internal/model/dto/account_dto.go b/internal/model/dto/account_dto.go index f759bc9..f02b661 100644 --- a/internal/model/dto/account_dto.go +++ b/internal/model/dto/account_dto.go @@ -20,27 +20,31 @@ type UpdateAccountRequest struct { // AccountListRequest 账号列表查询请求 type AccountListRequest struct { - Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"` - PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` - Username string `json:"username" query:"username" validate:"omitempty,max=50" maxLength:"50" description:"用户名模糊查询"` - Phone string `json:"phone" query:"phone" validate:"omitempty,max=20" maxLength:"20" description:"手机号模糊查询"` - UserType *int `json:"user_type" query:"user_type" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` - Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` + Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"` + PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"` + Username string `json:"username" query:"username" validate:"omitempty,max=50" maxLength:"50" description:"用户名模糊查询"` + Phone string `json:"phone" query:"phone" validate:"omitempty,max=20" maxLength:"20" description:"手机号模糊查询"` + UserType *int `json:"user_type" query:"user_type" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + Status *int `json:"status" query:"status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"状态 (0:禁用, 1:启用)"` + ShopID *uint `json:"shop_id" query:"shop_id" validate:"omitempty,min=1" minimum:"1" description:"店铺ID筛选"` + EnterpriseID *uint `json:"enterprise_id" query:"enterprise_id" validate:"omitempty,min=1" minimum:"1" description:"企业ID筛选"` } // AccountResponse 账号响应 type AccountResponse struct { - ID uint `json:"id" description:"账号ID"` - Username string `json:"username" description:"用户名"` - Phone string `json:"phone" description:"手机号"` - UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` - ShopID *uint `json:"shop_id,omitempty" description:"关联店铺ID"` - EnterpriseID *uint `json:"enterprise_id,omitempty" description:"关联企业ID"` - Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` - Creator uint `json:"creator" description:"创建人ID"` - Updater uint `json:"updater" description:"更新人ID"` - CreatedAt string `json:"created_at" description:"创建时间"` - UpdatedAt string `json:"updated_at" description:"更新时间"` + ID uint `json:"id" description:"账号ID"` + Username string `json:"username" description:"用户名"` + Phone string `json:"phone" description:"手机号"` + UserType int `json:"user_type" description:"用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)"` + ShopID *uint `json:"shop_id,omitempty" description:"关联店铺ID"` + ShopName string `json:"shop_name,omitempty" description:"店铺名称"` + EnterpriseID *uint `json:"enterprise_id,omitempty" description:"关联企业ID"` + EnterpriseName string `json:"enterprise_name,omitempty" description:"企业名称"` + Status int `json:"status" description:"状态 (0:禁用, 1:启用)"` + Creator uint `json:"creator" description:"创建人ID"` + Updater uint `json:"updater" description:"更新人ID"` + CreatedAt string `json:"created_at" description:"创建时间"` + UpdatedAt string `json:"updated_at" description:"更新时间"` } // AssignRolesRequest 分配角色请求 diff --git a/internal/model/dto/iot_card_dto.go b/internal/model/dto/iot_card_dto.go index 01fb40f..d0580b1 100644 --- a/internal/model/dto/iot_card_dto.go +++ b/internal/model/dto/iot_card_dto.go @@ -22,7 +22,6 @@ type ListStandaloneIotCardRequest struct { type StandaloneIotCardResponse struct { ID uint `json:"id" description:"卡ID"` ICCID string `json:"iccid" description:"ICCID"` - CardType string `json:"card_type" description:"卡类型"` CardCategory string `json:"card_category" description:"卡业务类型 (normal:普通卡, industry:行业卡)"` CarrierID uint `json:"carrier_id" description:"运营商ID"` CarrierType string `json:"carrier_type,omitempty" description:"运营商类型 (CMCC:中国移动, CUCC:中国联通, CTCC:中国电信, CBN:中国广电)"` diff --git a/internal/model/iot_card.go b/internal/model/iot_card.go index b37367d..4c6512d 100644 --- a/internal/model/iot_card.go +++ b/internal/model/iot_card.go @@ -13,7 +13,6 @@ type IotCard struct { gorm.Model BaseModel `gorm:"embedded"` ICCID string `gorm:"column:iccid;type:varchar(20);uniqueIndex:idx_iot_card_iccid,where:deleted_at IS NULL;not null;comment:ICCID(唯一标识,电信19位/其他20位)" json:"iccid"` - CardType string `gorm:"column:card_type;type:varchar(50);not null;comment:卡类型" json:"card_type"` CardCategory string `gorm:"column:card_category;type:varchar(20);default:'normal';not null;comment:卡业务类型 normal-普通卡 industry-行业卡" json:"card_category"` CarrierID uint `gorm:"column:carrier_id;index;not null;comment:运营商ID" json:"carrier_id"` CarrierType string `gorm:"column:carrier_type;type:varchar(20);comment:运营商类型(CMCC/CUCC/CTCC/CBN),导入时快照" json:"carrier_type"` diff --git a/internal/model/number_card.go b/internal/model/number_card.go index 632b3f6..05b7945 100644 --- a/internal/model/number_card.go +++ b/internal/model/number_card.go @@ -12,7 +12,6 @@ type NumberCard struct { BaseModel `gorm:"embedded"` VirtualProductCode string `gorm:"column:virtual_product_code;type:varchar(100);uniqueIndex:idx_number_card_code,where:deleted_at IS NULL;not null;comment:虚拟商品编码(用于对应运营商订单)" json:"virtual_product_code"` CardName string `gorm:"column:card_name;type:varchar(255);not null;comment:号卡名称" json:"card_name"` - CardType string `gorm:"column:card_type;type:varchar(50);comment:号卡类型" json:"card_type"` Carrier string `gorm:"column:carrier;type:varchar(50);comment:运营商" json:"carrier"` DataAmountMB int64 `gorm:"column:data_amount_mb;type:bigint;comment:流量额度(MB)" json:"data_amount_mb"` Price int64 `gorm:"column:price;type:bigint;comment:价格(分为单位)" json:"price"` diff --git a/internal/service/account/service.go b/internal/service/account/service.go index 6934416..c1b4d99 100644 --- a/internal/service/account/service.go +++ b/internal/service/account/service.go @@ -336,7 +336,7 @@ func (s *Service) Delete(ctx context.Context, id uint) error { } // List 查询账号列表 -func (s *Service) List(ctx context.Context, req *dto.AccountListRequest) ([]*model.Account, int64, error) { +func (s *Service) List(ctx context.Context, req *dto.AccountListRequest) ([]*dto.AccountResponse, int64, error) { opts := &store.QueryOptions{ Page: req.Page, PageSize: req.PageSize, @@ -362,8 +362,28 @@ func (s *Service) List(ctx context.Context, req *dto.AccountListRequest) ([]*mod if req.Status != nil { filters["status"] = *req.Status } + if req.ShopID != nil { + filters["shop_id"] = *req.ShopID + } + if req.EnterpriseID != nil { + filters["enterprise_id"] = *req.EnterpriseID + } - return s.accountStore.List(ctx, opts, filters) + accounts, total, err := s.accountStore.List(ctx, opts, filters) + if err != nil { + return nil, 0, err + } + + shopMap := s.loadShopNames(ctx, accounts) + enterpriseMap := s.loadEnterpriseNames(ctx, accounts) + + responses := make([]*dto.AccountResponse, 0, len(accounts)) + for _, acc := range accounts { + resp := s.toAccountResponse(acc, shopMap, enterpriseMap) + responses = append(responses, resp) + } + + return responses, total, nil } // AssignRoles 为账号分配角色(支持空数组清空所有角色,超级管理员禁止分配) @@ -696,3 +716,78 @@ func (s *Service) CreateSystemAccount(ctx context.Context, account *model.Accoun return nil } + +// loadShopNames 批量加载店铺名称 +func (s *Service) loadShopNames(ctx context.Context, accounts []*model.Account) map[uint]string { + shopIDs := make([]uint, 0) + shopIDSet := make(map[uint]bool) + + for _, acc := range accounts { + if acc.ShopID != nil && *acc.ShopID > 0 && !shopIDSet[*acc.ShopID] { + shopIDs = append(shopIDs, *acc.ShopID) + shopIDSet[*acc.ShopID] = true + } + } + + shopMap := make(map[uint]string) + if len(shopIDs) > 0 { + shops, err := s.shopStore.GetByIDs(ctx, shopIDs) + if err == nil { + for _, shop := range shops { + shopMap[shop.ID] = shop.ShopName + } + } + } + return shopMap +} + +// loadEnterpriseNames 批量加载企业名称 +func (s *Service) loadEnterpriseNames(ctx context.Context, accounts []*model.Account) map[uint]string { + enterpriseIDs := make([]uint, 0) + enterpriseIDSet := make(map[uint]bool) + + for _, acc := range accounts { + if acc.EnterpriseID != nil && *acc.EnterpriseID > 0 && !enterpriseIDSet[*acc.EnterpriseID] { + enterpriseIDs = append(enterpriseIDs, *acc.EnterpriseID) + enterpriseIDSet[*acc.EnterpriseID] = true + } + } + + enterpriseMap := make(map[uint]string) + if len(enterpriseIDs) > 0 { + enterprises, err := s.enterpriseStore.GetByIDs(ctx, enterpriseIDs) + if err == nil { + for _, ent := range enterprises { + enterpriseMap[ent.ID] = ent.EnterpriseName + } + } + } + return enterpriseMap +} + +// toAccountResponse 组装账号响应,填充关联名称 +func (s *Service) toAccountResponse(acc *model.Account, shopMap map[uint]string, enterpriseMap map[uint]string) *dto.AccountResponse { + resp := &dto.AccountResponse{ + ID: acc.ID, + Username: acc.Username, + Phone: acc.Phone, + UserType: acc.UserType, + ShopID: acc.ShopID, + EnterpriseID: acc.EnterpriseID, + Status: acc.Status, + Creator: acc.Creator, + Updater: acc.Updater, + CreatedAt: acc.CreatedAt.Format("2006-01-02 15:04:05"), + UpdatedAt: acc.UpdatedAt.Format("2006-01-02 15:04:05"), + } + + if acc.ShopID != nil && *acc.ShopID > 0 { + resp.ShopName = shopMap[*acc.ShopID] + } + + if acc.EnterpriseID != nil && *acc.EnterpriseID > 0 { + resp.EnterpriseName = enterpriseMap[*acc.EnterpriseID] + } + + return resp +} diff --git a/internal/service/account/service_test.go b/internal/service/account/service_test.go index 94faa08..63f6791 100644 --- a/internal/service/account/service_test.go +++ b/internal/service/account/service_test.go @@ -37,6 +37,14 @@ func (m *MockShopStore) GetByID(ctx context.Context, id uint) (*model.Shop, erro return args.Get(0).(*model.Shop), args.Error(1) } +func (m *MockShopStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Shop, error) { + args := m.Called(ctx, ids) + if args.Get(0) == nil { + return nil, args.Error(1) + } + return args.Get(0).([]*model.Shop), args.Error(1) +} + func (m *MockShopStore) GetSubordinateShopIDs(ctx context.Context, shopID uint) ([]uint, error) { args := m.Called(ctx, shopID) if args.Get(0) == nil { @@ -57,6 +65,14 @@ func (m *MockEnterpriseStore) GetByID(ctx context.Context, id uint) (*model.Ente return args.Get(0).(*model.Enterprise), args.Error(1) } +func (m *MockEnterpriseStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Enterprise, error) { + args := m.Called(ctx, ids) + if args.Get(0) == nil { + return nil, args.Error(1) + } + return args.Get(0).([]*model.Enterprise), args.Error(1) +} + func TestAccountService_Create_SuperAdminSuccess(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) diff --git a/internal/service/enterprise_card/authorization_service_test.go b/internal/service/enterprise_card/authorization_service_test.go index a0b79de..136d73b 100644 --- a/internal/service/enterprise_card/authorization_service_test.go +++ b/internal/service/enterprise_card/authorization_service_test.go @@ -52,7 +52,6 @@ func TestAuthorizationService_BatchAuthorize_BoundCardRejected(t *testing.T) { unboundCard := &model.IotCard{ ICCID: "UNBOUND_CARD_001", - CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, @@ -61,7 +60,6 @@ func TestAuthorizationService_BatchAuthorize_BoundCardRejected(t *testing.T) { boundCard := &model.IotCard{ ICCID: "BOUND_CARD_001", - CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, @@ -132,7 +130,6 @@ func TestAuthorizationService_BatchAuthorize_BoundCardRejected(t *testing.T) { t.Run("混合卡列表中有绑定卡时整体拒绝", func(t *testing.T) { unboundCard2 := &model.IotCard{ ICCID: "UNBOUND_CARD_002", - CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, diff --git a/internal/service/enterprise_device/service_test.go b/internal/service/enterprise_device/service_test.go index bb4a56e..e2e0aaf 100644 --- a/internal/service/enterprise_device/service_test.go +++ b/internal/service/enterprise_device/service_test.go @@ -93,7 +93,6 @@ func setupTestEnv(t *testing.T, prefix string) *testEnv { for i := 0; i < 4; i++ { cards[i] = &model.IotCard{ ICCID: fmt.Sprintf("%s%04d", prefix, i+1), - CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, @@ -775,7 +774,6 @@ func TestService_GetDeviceDetail_WithNetworkStatusOn(t *testing.T) { card := &model.IotCard{ ICCID: prefix + "0001", - CardType: "normal", CarrierID: carrier.ID, Status: 2, NetworkStatus: 1, @@ -876,7 +874,6 @@ func TestService_ValidateCardOperation_RevokedDeviceAuth(t *testing.T) { card := &model.IotCard{ ICCID: prefix + "0001", - CardType: "normal", CarrierID: carrier.ID, Status: 2, } diff --git a/internal/service/iot_card/service.go b/internal/service/iot_card/service.go index 14715ee..14d4eff 100644 --- a/internal/service/iot_card/service.go +++ b/internal/service/iot_card/service.go @@ -172,7 +172,6 @@ func (s *Service) toStandaloneResponse(card *model.IotCard, shopMap map[uint]str resp := &dto.StandaloneIotCardResponse{ ID: card.ID, ICCID: card.ICCID, - CardType: card.CardType, CardCategory: card.CardCategory, CarrierID: card.CarrierID, CarrierType: card.CarrierType, diff --git a/internal/service/iot_card/service_test.go b/internal/service/iot_card/service_test.go index 6e22c7c..d98c9b3 100644 --- a/internal/service/iot_card/service_test.go +++ b/internal/service/iot_card/service_test.go @@ -56,9 +56,9 @@ func TestIotCardService_BatchSetSeriesBinding(t *testing.T) { prefix := uniqueTestICCIDPrefix() cards := []*model.IotCard{ - {ICCID: prefix + "001", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shop.ID}, - {ICCID: prefix + "002", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shop.ID}, - {ICCID: prefix + "003", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil}, + {ICCID: prefix + "001", CarrierID: 1, Status: 1, ShopID: &shop.ID}, + {ICCID: prefix + "002", CarrierID: 1, Status: 1, ShopID: &shop.ID}, + {ICCID: prefix + "003", CarrierID: 1, Status: 1, ShopID: nil}, } require.NoError(t, iotCardStore.CreateBatch(ctx, cards)) diff --git a/internal/service/recharge/service_test.go b/internal/service/recharge/service_test.go index 967b0ef..1714dae 100644 --- a/internal/service/recharge/service_test.go +++ b/internal/service/recharge/service_test.go @@ -61,7 +61,6 @@ func createTestIotCard(t *testing.T, tx *gorm.DB, shopID *uint, seriesAllocation Updater: 1, }, ICCID: fmt.Sprintf("89860%014d", timestamp%100000000000000), - CardType: "流量卡", CardCategory: "normal", CarrierID: 1, CarrierType: "CMCC", diff --git a/internal/store/postgres/account_store.go b/internal/store/postgres/account_store.go index 6f4ea40..33180a3 100644 --- a/internal/store/postgres/account_store.go +++ b/internal/store/postgres/account_store.go @@ -113,6 +113,12 @@ func (s *AccountStore) List(ctx context.Context, opts *store.QueryOptions, filte if status, ok := filters["status"].(int); ok { query = query.Where("status = ?", status) } + if shopID, ok := filters["shop_id"].(uint); ok && shopID > 0 { + query = query.Where("shop_id = ?", shopID) + } + if enterpriseID, ok := filters["enterprise_id"].(uint); ok && enterpriseID > 0 { + query = query.Where("enterprise_id = ?", enterpriseID) + } // 计算总数 if err := query.Count(&total).Error; err != nil { diff --git a/internal/store/postgres/device_sim_binding_store_test.go b/internal/store/postgres/device_sim_binding_store_test.go index 340bcc0..2e2d6fe 100644 --- a/internal/store/postgres/device_sim_binding_store_test.go +++ b/internal/store/postgres/device_sim_binding_store_test.go @@ -28,7 +28,7 @@ func TestDeviceSimBindingStore_Create_DuplicateCard(t *testing.T) { require.NoError(t, deviceStore.Create(ctx, device1)) require.NoError(t, deviceStore.Create(ctx, device2)) - card := &model.IotCard{ICCID: "89860012345678910001", CardType: "data_card", CarrierID: 1, Status: 1} + card := &model.IotCard{ICCID: "89860012345678910001", CarrierID: 1, Status: 1} require.NoError(t, cardStore.Create(ctx, card)) now := time.Now() @@ -70,8 +70,8 @@ func TestDeviceSimBindingStore_Create_DuplicateSlot(t *testing.T) { device := &model.Device{DeviceNo: "TEST-DEV-UC-003", Status: 1, MaxSimSlots: 4} require.NoError(t, deviceStore.Create(ctx, device)) - card1 := &model.IotCard{ICCID: "89860012345678910011", CardType: "data_card", CarrierID: 1, Status: 1} - card2 := &model.IotCard{ICCID: "89860012345678910012", CardType: "data_card", CarrierID: 1, Status: 1} + card1 := &model.IotCard{ICCID: "89860012345678910011", CarrierID: 1, Status: 1} + card2 := &model.IotCard{ICCID: "89860012345678910012", CarrierID: 1, Status: 1} require.NoError(t, cardStore.Create(ctx, card1)) require.NoError(t, cardStore.Create(ctx, card2)) @@ -114,8 +114,8 @@ func TestDeviceSimBindingStore_Create_DifferentSlots(t *testing.T) { device := &model.Device{DeviceNo: "TEST-DEV-UC-004", Status: 1, MaxSimSlots: 4} require.NoError(t, deviceStore.Create(ctx, device)) - card1 := &model.IotCard{ICCID: "89860012345678910021", CardType: "data_card", CarrierID: 1, Status: 1} - card2 := &model.IotCard{ICCID: "89860012345678910022", CardType: "data_card", CarrierID: 1, Status: 1} + card1 := &model.IotCard{ICCID: "89860012345678910021", CarrierID: 1, Status: 1} + card2 := &model.IotCard{ICCID: "89860012345678910022", CarrierID: 1, Status: 1} require.NoError(t, cardStore.Create(ctx, card1)) require.NoError(t, cardStore.Create(ctx, card2)) @@ -156,7 +156,7 @@ func TestDeviceSimBindingStore_ConcurrentBinding(t *testing.T) { require.NoError(t, deviceStore.Create(ctx, device1)) require.NoError(t, deviceStore.Create(ctx, device2)) - card := &model.IotCard{ICCID: "89860012345678920001", CardType: "data_card", CarrierID: 1, Status: 1} + card := &model.IotCard{ICCID: "89860012345678920001", CarrierID: 1, Status: 1} require.NoError(t, cardStore.Create(ctx, card)) t.Cleanup(func() { diff --git a/internal/store/postgres/enterprise_card_authorization_store_test.go b/internal/store/postgres/enterprise_card_authorization_store_test.go index d0bee6b..12d90ac 100644 --- a/internal/store/postgres/enterprise_card_authorization_store_test.go +++ b/internal/store/postgres/enterprise_card_authorization_store_test.go @@ -41,9 +41,9 @@ func TestEnterpriseCardAuthorizationStore_RevokeByDeviceAuthID(t *testing.T) { require.NoError(t, tx.Create(carrier).Error) cards := []*model.IotCard{ - {ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2}, - {ICCID: prefix + "0002", CardType: "normal", CarrierID: carrier.ID, Status: 2}, - {ICCID: prefix + "0003", CardType: "normal", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0002", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0003", CarrierID: carrier.ID, Status: 2}, } for _, c := range cards { require.NoError(t, tx.Create(c).Error) @@ -115,7 +115,6 @@ func TestEnterpriseCardAuthorizationStore_Create(t *testing.T) { card := &model.IotCard{ ICCID: prefix + "0001", - CardType: "normal", CarrierID: carrier.ID, Status: 2, } @@ -162,8 +161,8 @@ func TestEnterpriseCardAuthorizationStore_BatchCreate(t *testing.T) { require.NoError(t, tx.Create(carrier).Error) cards := []*model.IotCard{ - {ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2}, - {ICCID: prefix + "0002", CardType: "normal", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0002", CarrierID: carrier.ID, Status: 2}, } for _, c := range cards { require.NoError(t, tx.Create(c).Error) @@ -215,8 +214,8 @@ func TestEnterpriseCardAuthorizationStore_ListByEnterprise(t *testing.T) { require.NoError(t, tx.Create(carrier).Error) cards := []*model.IotCard{ - {ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2}, - {ICCID: prefix + "0002", CardType: "normal", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0002", CarrierID: carrier.ID, Status: 2}, } for _, c := range cards { require.NoError(t, tx.Create(c).Error) @@ -274,9 +273,9 @@ func TestEnterpriseCardAuthorizationStore_GetActiveAuthsByCardIDs(t *testing.T) require.NoError(t, tx.Create(carrier).Error) cards := []*model.IotCard{ - {ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2}, - {ICCID: prefix + "0002", CardType: "normal", CarrierID: carrier.ID, Status: 2}, - {ICCID: prefix + "0003", CardType: "normal", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0002", CarrierID: carrier.ID, Status: 2}, + {ICCID: prefix + "0003", CarrierID: carrier.ID, Status: 2}, } for _, c := range cards { require.NoError(t, tx.Create(c).Error) diff --git a/internal/store/postgres/enterprise_store.go b/internal/store/postgres/enterprise_store.go index d1096e2..5fba63b 100644 --- a/internal/store/postgres/enterprise_store.go +++ b/internal/store/postgres/enterprise_store.go @@ -125,3 +125,15 @@ func (s *EnterpriseStore) GetPlatformEnterprises(ctx context.Context) ([]*model. } return enterprises, nil } + +// GetByIDs 批量查询企业 +func (s *EnterpriseStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Enterprise, error) { + if len(ids) == 0 { + return []*model.Enterprise{}, nil + } + var enterprises []*model.Enterprise + if err := s.db.WithContext(ctx).Where("id IN ?", ids).Find(&enterprises).Error; err != nil { + return nil, err + } + return enterprises, nil +} diff --git a/internal/store/postgres/iot_card_store_test.go b/internal/store/postgres/iot_card_store_test.go index fbfd787..2e895fc 100644 --- a/internal/store/postgres/iot_card_store_test.go +++ b/internal/store/postgres/iot_card_store_test.go @@ -27,7 +27,6 @@ func TestIotCardStore_Create(t *testing.T) { card := &model.IotCard{ ICCID: "89860012345678901234", - CardType: "data_card", CarrierID: 1, Status: 1, } @@ -47,7 +46,6 @@ func TestIotCardStore_ExistsByICCID(t *testing.T) { card := &model.IotCard{ ICCID: "89860012345678901111", - CardType: "data_card", CarrierID: 1, Status: 1, } @@ -71,9 +69,9 @@ func TestIotCardStore_ExistsByICCIDBatch(t *testing.T) { ctx := context.Background() cards := []*model.IotCard{ - {ICCID: "89860012345678902001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678902002", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678902003", CardType: "data_card", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678902001", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678902002", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678902003", CarrierID: 1, Status: 1}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -102,15 +100,14 @@ func TestIotCardStore_ListStandalone(t *testing.T) { prefix := uniqueICCIDPrefix() standaloneCards := []*model.IotCard{ - {ICCID: prefix + "0001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: prefix + "0002", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: prefix + "0003", CardType: "data_card", CarrierID: 2, Status: 2}, + {ICCID: prefix + "0001", CarrierID: 1, Status: 1}, + {ICCID: prefix + "0002", CarrierID: 1, Status: 1}, + {ICCID: prefix + "0003", CarrierID: 2, Status: 2}, } require.NoError(t, s.CreateBatch(ctx, standaloneCards)) boundCard := &model.IotCard{ ICCID: prefix + "0004", - CardType: "data_card", CarrierID: 1, Status: 1, } @@ -197,9 +194,9 @@ func TestIotCardStore_ListStandalone_Filters(t *testing.T) { shopID := uint(time.Now().UnixNano() % 1000000) cards := []*model.IotCard{ - {ICCID: prefix + "A001", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shopID, BatchNo: batchPrefix + "01", MSISDN: msisdnPrefix + "01"}, - {ICCID: prefix + "A002", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil, BatchNo: batchPrefix + "01", MSISDN: msisdnPrefix + "02"}, - {ICCID: prefix + "A003", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil, BatchNo: batchPrefix + "02", MSISDN: msisdnPrefix + "03"}, + {ICCID: prefix + "A001", CarrierID: 1, Status: 1, ShopID: &shopID, BatchNo: batchPrefix + "01", MSISDN: msisdnPrefix + "01"}, + {ICCID: prefix + "A002", CarrierID: 1, Status: 1, ShopID: nil, BatchNo: batchPrefix + "01", MSISDN: msisdnPrefix + "02"}, + {ICCID: prefix + "A003", CarrierID: 1, Status: 1, ShopID: nil, BatchNo: batchPrefix + "02", MSISDN: msisdnPrefix + "03"}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -264,9 +261,9 @@ func TestIotCardStore_GetByICCIDs(t *testing.T) { ctx := context.Background() cards := []*model.IotCard{ - {ICCID: "89860012345678905001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678905002", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678905003", CardType: "data_card", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678905001", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678905002", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678905003", CarrierID: 1, Status: 1}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -299,10 +296,10 @@ func TestIotCardStore_GetStandaloneByICCIDRange(t *testing.T) { shopID := uint(100) cards := []*model.IotCard{ - {ICCID: "89860012345678906001", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil}, - {ICCID: "89860012345678906002", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil}, - {ICCID: "89860012345678906003", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shopID}, - {ICCID: "89860012345678906004", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shopID}, + {ICCID: "89860012345678906001", CarrierID: 1, Status: 1, ShopID: nil}, + {ICCID: "89860012345678906002", CarrierID: 1, Status: 1, ShopID: nil}, + {ICCID: "89860012345678906003", CarrierID: 1, Status: 1, ShopID: &shopID}, + {ICCID: "89860012345678906004", CarrierID: 1, Status: 1, ShopID: &shopID}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -335,9 +332,9 @@ func TestIotCardStore_GetStandaloneByFilters(t *testing.T) { shopID := uint(100) cards := []*model.IotCard{ - {ICCID: "89860012345678907001", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil, BatchNo: "BATCH001"}, - {ICCID: "89860012345678907002", CardType: "data_card", CarrierID: 2, Status: 1, ShopID: nil, BatchNo: "BATCH002"}, - {ICCID: "89860012345678907003", CardType: "data_card", CarrierID: 1, Status: 2, ShopID: &shopID, BatchNo: "BATCH001"}, + {ICCID: "89860012345678907001", CarrierID: 1, Status: 1, ShopID: nil, BatchNo: "BATCH001"}, + {ICCID: "89860012345678907002", CarrierID: 2, Status: 1, ShopID: nil, BatchNo: "BATCH002"}, + {ICCID: "89860012345678907003", CarrierID: 1, Status: 2, ShopID: &shopID, BatchNo: "BATCH001"}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -367,8 +364,8 @@ func TestIotCardStore_BatchUpdateShopIDAndStatus(t *testing.T) { ctx := context.Background() cards := []*model.IotCard{ - {ICCID: "89860012345678908001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678908002", CardType: "data_card", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678908001", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678908002", CarrierID: 1, Status: 1}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -400,9 +397,9 @@ func TestIotCardStore_GetBoundCardIDs(t *testing.T) { ctx := context.Background() cards := []*model.IotCard{ - {ICCID: "89860012345678909001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678909002", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678909003", CardType: "data_card", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678909001", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678909002", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678909003", CarrierID: 1, Status: 1}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -435,8 +432,8 @@ func TestIotCardStore_BatchUpdateSeriesID(t *testing.T) { ctx := context.Background() cards := []*model.IotCard{ - {ICCID: "89860012345678910001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "89860012345678910002", CardType: "data_card", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678910001", CarrierID: 1, Status: 1}, + {ICCID: "89860012345678910002", CarrierID: 1, Status: 1}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -482,9 +479,9 @@ func TestIotCardStore_ListBySeriesID(t *testing.T) { seriesID := uint(200) cards := []*model.IotCard{ - {ICCID: "89860012345678911001", CardType: "data_card", CarrierID: 1, Status: 1, SeriesID: &seriesID}, - {ICCID: "89860012345678911002", CardType: "data_card", CarrierID: 1, Status: 1, SeriesID: &seriesID}, - {ICCID: "89860012345678911003", CardType: "data_card", CarrierID: 1, Status: 1, SeriesID: nil}, + {ICCID: "89860012345678911001", CarrierID: 1, Status: 1, SeriesID: &seriesID}, + {ICCID: "89860012345678911002", CarrierID: 1, Status: 1, SeriesID: &seriesID}, + {ICCID: "89860012345678911003", CarrierID: 1, Status: 1, SeriesID: nil}, } require.NoError(t, s.CreateBatch(ctx, cards)) @@ -507,9 +504,9 @@ func TestIotCardStore_ListStandalone_SeriesIDFilter(t *testing.T) { prefix := uniqueICCIDPrefix() seriesID := uint(300) cards := []*model.IotCard{ - {ICCID: prefix + "S001", CardType: "data_card", CarrierID: 1, Status: 1, SeriesID: &seriesID}, - {ICCID: prefix + "S002", CardType: "data_card", CarrierID: 1, Status: 1, SeriesID: &seriesID}, - {ICCID: prefix + "S003", CardType: "data_card", CarrierID: 1, Status: 1, SeriesID: nil}, + {ICCID: prefix + "S001", CarrierID: 1, Status: 1, SeriesID: &seriesID}, + {ICCID: prefix + "S002", CarrierID: 1, Status: 1, SeriesID: &seriesID}, + {ICCID: prefix + "S003", CarrierID: 1, Status: 1, SeriesID: nil}, } require.NoError(t, s.CreateBatch(ctx, cards)) diff --git a/internal/store/postgres/shop_store.go b/internal/store/postgres/shop_store.go index 9536e45..c855379 100644 --- a/internal/store/postgres/shop_store.go +++ b/internal/store/postgres/shop_store.go @@ -203,3 +203,15 @@ func (s *ShopStore) GetByParentID(ctx context.Context, parentID uint) ([]*model. } return shops, nil } + +// GetByIDs 批量查询店铺 +func (s *ShopStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Shop, error) { + if len(ids) == 0 { + return []*model.Shop{}, nil + } + var shops []*model.Shop + if err := s.db.WithContext(ctx).Where("id IN ?", ids).Find(&shops).Error; err != nil { + return nil, err + } + return shops, nil +} diff --git a/internal/task/device_import_test.go b/internal/task/device_import_test.go index ecd7939..919a8db 100644 --- a/internal/task/device_import_test.go +++ b/internal/task/device_import_test.go @@ -27,9 +27,9 @@ func TestDeviceImportHandler_ProcessBatch_AllOrNothingValidation(t *testing.T) { ctx := context.Background() shopID := uint(100) - platformCard := &model.IotCard{ICCID: "89860012345670001001", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil} - platformCard2 := &model.IotCard{ICCID: "89860012345670001003", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil} - shopCard := &model.IotCard{ICCID: "89860012345670001002", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shopID} + platformCard := &model.IotCard{ICCID: "89860012345670001001", CarrierID: 1, Status: 1, ShopID: nil} + platformCard2 := &model.IotCard{ICCID: "89860012345670001003", CarrierID: 1, Status: 1, ShopID: nil} + shopCard := &model.IotCard{ICCID: "89860012345670001002", CarrierID: 1, Status: 1, ShopID: &shopID} require.NoError(t, cardStore.Create(ctx, platformCard)) require.NoError(t, cardStore.Create(ctx, platformCard2)) require.NoError(t, cardStore.Create(ctx, shopCard)) @@ -119,8 +119,8 @@ func TestDeviceImportHandler_ProcessBatch_AllOrNothingValidation(t *testing.T) { }) t.Run("多张卡全部可用-成功", func(t *testing.T) { - newCard1 := &model.IotCard{ICCID: "89860012345670001010", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil} - newCard2 := &model.IotCard{ICCID: "89860012345670001011", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil} + newCard1 := &model.IotCard{ICCID: "89860012345670001010", CarrierID: 1, Status: 1, ShopID: nil} + newCard2 := &model.IotCard{ICCID: "89860012345670001011", CarrierID: 1, Status: 1, ShopID: nil} require.NoError(t, cardStore.Create(ctx, newCard1)) require.NoError(t, cardStore.Create(ctx, newCard2)) @@ -159,9 +159,9 @@ func TestDeviceImportHandler_ProcessImport_AllOrNothing(t *testing.T) { ctx := context.Background() shopID := uint(200) - platformCard1 := &model.IotCard{ICCID: "89860012345680001001", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil} - platformCard2 := &model.IotCard{ICCID: "89860012345680001002", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: nil} - shopCard := &model.IotCard{ICCID: "89860012345680001003", CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shopID} + platformCard1 := &model.IotCard{ICCID: "89860012345680001001", CarrierID: 1, Status: 1, ShopID: nil} + platformCard2 := &model.IotCard{ICCID: "89860012345680001002", CarrierID: 1, Status: 1, ShopID: nil} + shopCard := &model.IotCard{ICCID: "89860012345680001003", CarrierID: 1, Status: 1, ShopID: &shopID} require.NoError(t, cardStore.Create(ctx, platformCard1)) require.NoError(t, cardStore.Create(ctx, platformCard2)) require.NoError(t, cardStore.Create(ctx, shopCard)) diff --git a/internal/task/iot_card_import_test.go b/internal/task/iot_card_import_test.go index 26259cf..770dccb 100644 --- a/internal/task/iot_card_import_test.go +++ b/internal/task/iot_card_import_test.go @@ -54,7 +54,6 @@ func TestIotCardImportHandler_ProcessImport(t *testing.T) { t.Run("跳过已存在的ICCID", func(t *testing.T) { existingCard := &model.IotCard{ ICCID: "89860012345678906001", - CardType: "data_card", CarrierID: 1, Status: 1, } @@ -108,7 +107,6 @@ func TestIotCardImportHandler_ProcessImport(t *testing.T) { t.Run("混合场景-成功跳过和失败", func(t *testing.T) { existingCard := &model.IotCard{ ICCID: "89860012345678908001", - CardType: "data_card", CarrierID: 1, Status: 1, } @@ -166,7 +164,6 @@ func TestIotCardImportHandler_ProcessBatch(t *testing.T) { t.Run("验证行号和MSISDN正确记录", func(t *testing.T) { existingCard := &model.IotCard{ ICCID: "89860012345678909002", - CardType: "data_card", CarrierID: 1, Status: 1, } diff --git a/migrations/000041_remove_card_type_field.down.sql b/migrations/000041_remove_card_type_field.down.sql new file mode 100644 index 0000000..13a5c1d --- /dev/null +++ b/migrations/000041_remove_card_type_field.down.sql @@ -0,0 +1,10 @@ +-- 回滚:恢复 card_type 字段 +-- 注意:回滚后字段值为空,需要手动填充数据 + +-- 恢复 IoT 卡表的 card_type 列 +ALTER TABLE tb_iot_card ADD COLUMN card_type VARCHAR(50); +COMMENT ON COLUMN tb_iot_card.card_type IS '卡类型(已废弃,仅用于回滚)'; + +-- 恢复号卡表的 card_type 列 +ALTER TABLE tb_number_card ADD COLUMN card_type VARCHAR(50); +COMMENT ON COLUMN tb_number_card.card_type IS '号卡类型(已废弃,仅用于回滚)'; diff --git a/migrations/000041_remove_card_type_field.up.sql b/migrations/000041_remove_card_type_field.up.sql new file mode 100644 index 0000000..c8d3d02 --- /dev/null +++ b/migrations/000041_remove_card_type_field.up.sql @@ -0,0 +1,9 @@ +-- 删除 IoT 卡和号卡表中无用的 card_type 字段 +-- 原因:该字段设计为存储技术规格("4G"、"5G"、"NB-IoT"),但实际业务中完全未使用 +-- 影响:无业务逻辑依赖该字段,删除不影响现有功能 + +-- 删除 IoT 卡表的 card_type 列 +ALTER TABLE tb_iot_card DROP COLUMN IF EXISTS card_type; + +-- 删除号卡表的 card_type 列 +ALTER TABLE tb_number_card DROP COLUMN IF EXISTS card_type; diff --git a/pkg/middleware/permission_helper.go b/pkg/middleware/permission_helper.go index ffa4f65..1337ea3 100644 --- a/pkg/middleware/permission_helper.go +++ b/pkg/middleware/permission_helper.go @@ -12,6 +12,7 @@ import ( // 用于权限检查时查询店铺信息和下级店铺ID type ShopStoreInterface interface { GetByID(ctx context.Context, id uint) (*model.Shop, error) + GetByIDs(ctx context.Context, ids []uint) ([]*model.Shop, error) GetSubordinateShopIDs(ctx context.Context, shopID uint) ([]uint, error) } @@ -19,6 +20,7 @@ type ShopStoreInterface interface { // 用于权限检查时查询企业信息 type EnterpriseStoreInterface interface { GetByID(ctx context.Context, id uint) (*model.Enterprise, error) + GetByIDs(ctx context.Context, ids []uint) ([]*model.Enterprise, error) } // CanManageShop 检查当前用户是否有权管理目标店铺的账号 diff --git a/pkg/middleware/permission_helper_test.go b/pkg/middleware/permission_helper_test.go index 53b853e..fc2bf4e 100644 --- a/pkg/middleware/permission_helper_test.go +++ b/pkg/middleware/permission_helper_test.go @@ -23,6 +23,14 @@ func (m *MockShopStore) GetByID(ctx context.Context, id uint) (*model.Shop, erro return args.Get(0).(*model.Shop), args.Error(1) } +func (m *MockShopStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Shop, error) { + args := m.Called(ctx, ids) + if args.Get(0) == nil { + return nil, args.Error(1) + } + return args.Get(0).([]*model.Shop), args.Error(1) +} + func (m *MockShopStore) GetSubordinateShopIDs(ctx context.Context, shopID uint) ([]uint, error) { args := m.Called(ctx, shopID) if args.Get(0) == nil { @@ -43,6 +51,14 @@ func (m *MockEnterpriseStore) GetByID(ctx context.Context, id uint) (*model.Ente return args.Get(0).(*model.Enterprise), args.Error(1) } +func (m *MockEnterpriseStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Enterprise, error) { + args := m.Called(ctx, ids) + if args.Get(0) == nil { + return nil, args.Error(1) + } + return args.Get(0).([]*model.Enterprise), args.Error(1) +} + func TestCanManageShop_SuperAdmin(t *testing.T) { ctx := context.Background() ctx = context.WithValue(ctx, constants.ContextKeyUserType, constants.UserTypeSuperAdmin) diff --git a/tests/integration/account_test.go b/tests/integration/account_test.go index d80fca7..044e1a2 100644 --- a/tests/integration/account_test.go +++ b/tests/integration/account_test.go @@ -834,3 +834,103 @@ func TestAccount_InvalidID(t *testing.T) { require.NoError(t, err) assert.Equal(t, errors.CodeInvalidParam, result.Code) } + +// ============================================================================= +// 关联查询测试 +// ============================================================================= + +func TestAccountList_FilterByShopID_WithShopName(t *testing.T) { + env := integ.NewIntegrationTestEnv(t) + + shop1 := env.CreateTestShop("测试店铺A", 1, nil) + shop2 := env.CreateTestShop("测试店铺B", 1, nil) + + account1 := env.CreateTestAccount("shop_account_1", "password123", constants.UserTypeAgent, &shop1.ID, nil) + account2 := env.CreateTestAccount("shop_account_2", "password123", constants.UserTypeAgent, &shop1.ID, nil) + account3 := env.CreateTestAccount("shop_account_3", "password123", constants.UserTypeAgent, &shop2.ID, nil) + + url := fmt.Sprintf("/api/admin/accounts?shop_id=%d&page=1&page_size=10", shop1.ID) + resp, err := env.AsSuperAdmin().Request("GET", url, nil) + require.NoError(t, err) + defer resp.Body.Close() + assert.Equal(t, fiber.StatusOK, resp.StatusCode) + + var result response.Response + err = json.NewDecoder(resp.Body).Decode(&result) + require.NoError(t, err) + assert.Equal(t, 0, result.Code) + + data := result.Data.(map[string]interface{}) + items := data["items"].([]interface{}) + assert.GreaterOrEqual(t, len(items), 2) + + foundAccount1 := false + foundAccount2 := false + for _, item := range items { + accountData := item.(map[string]interface{}) + accountID := uint(accountData["id"].(float64)) + + if accountID == account1.ID || accountID == account2.ID { + assert.Equal(t, float64(shop1.ID), accountData["shop_id"]) + assert.Equal(t, shop1.ShopName, accountData["shop_name"]) + + if accountID == account1.ID { + foundAccount1 = true + } + if accountID == account2.ID { + foundAccount2 = true + } + } + + if accountID == account3.ID { + t.Errorf("不应该返回 shop2 的账号,但返回了账号 %d", account3.ID) + } + } + + assert.True(t, foundAccount1, "应该返回 account1") + assert.True(t, foundAccount2, "应该返回 account2") +} + +func TestAccountList_FilterByEnterpriseID_WithEnterpriseName(t *testing.T) { + env := integ.NewIntegrationTestEnv(t) + + shop := env.CreateTestShop("归属店铺", 1, nil) + enterprise1 := env.CreateTestEnterprise("测试企业A", &shop.ID) + enterprise2 := env.CreateTestEnterprise("测试企业B", &shop.ID) + + account1 := env.CreateTestAccount("enterprise_account_1", "password123", constants.UserTypeEnterprise, nil, &enterprise1.ID) + account2 := env.CreateTestAccount("enterprise_account_2", "password123", constants.UserTypeEnterprise, nil, &enterprise2.ID) + + url := fmt.Sprintf("/api/admin/accounts?enterprise_id=%d&page=1&page_size=10", enterprise1.ID) + resp, err := env.AsSuperAdmin().Request("GET", url, nil) + require.NoError(t, err) + defer resp.Body.Close() + assert.Equal(t, fiber.StatusOK, resp.StatusCode) + + var result response.Response + err = json.NewDecoder(resp.Body).Decode(&result) + require.NoError(t, err) + assert.Equal(t, 0, result.Code) + + data := result.Data.(map[string]interface{}) + items := data["items"].([]interface{}) + assert.GreaterOrEqual(t, len(items), 1) + + foundAccount1 := false + for _, item := range items { + accountData := item.(map[string]interface{}) + accountID := uint(accountData["id"].(float64)) + + if accountID == account1.ID { + foundAccount1 = true + assert.Equal(t, float64(enterprise1.ID), accountData["enterprise_id"]) + assert.Equal(t, enterprise1.EnterpriseName, accountData["enterprise_name"]) + } + + if accountID == account2.ID { + t.Errorf("不应该返回 enterprise2 的账号,但返回了账号 %d", account2.ID) + } + } + + assert.True(t, foundAccount1, "应该返回 account1") +} diff --git a/tests/integration/authorization_test.go b/tests/integration/authorization_test.go index af23f28..ea07db6 100644 --- a/tests/integration/authorization_test.go +++ b/tests/integration/authorization_test.go @@ -25,14 +25,14 @@ func TestAuthorization_List(t *testing.T) { card1 := &model.IotCard{ ICCID: fmt.Sprintf("AC1%d", ts), MSISDN: "13800001001", - CardType: "data_card", + Status: 1, ShopID: &shop.ID, } card2 := &model.IotCard{ ICCID: fmt.Sprintf("AC2%d", ts), MSISDN: "13800001002", - CardType: "data_card", + Status: 1, ShopID: &shop.ID, } @@ -131,7 +131,7 @@ func TestAuthorization_GetDetail(t *testing.T) { card1 := &model.IotCard{ ICCID: fmt.Sprintf("AC1%d", ts), MSISDN: "13800001001", - CardType: "data_card", + Status: 1, ShopID: &shop.ID, } @@ -195,7 +195,7 @@ func TestAuthorization_UpdateRemark(t *testing.T) { card1 := &model.IotCard{ ICCID: fmt.Sprintf("AC1%d", ts), MSISDN: "13800001001", - CardType: "data_card", + Status: 1, ShopID: &shop.ID, } @@ -255,7 +255,7 @@ func TestAuthorization_DataPermission(t *testing.T) { card1 := &model.IotCard{ ICCID: fmt.Sprintf("AC1%d", ts), MSISDN: "13800001001", - CardType: "data_card", + Status: 1, ShopID: &shop.ID, } @@ -282,7 +282,7 @@ func TestAuthorization_DataPermission(t *testing.T) { otherCard := &model.IotCard{ ICCID: fmt.Sprintf("OC%d", ts2), MSISDN: "13800002001", - CardType: "data_card", + Status: 1, ShopID: &otherShop.ID, } @@ -379,7 +379,7 @@ func TestAuthorization_UpdateRemarkPermission(t *testing.T) { card := &model.IotCard{ ICCID: fmt.Sprintf("PERM%d", ts), MSISDN: "13800003001", - CardType: "data_card", + Status: 1, ShopID: &shop.ID, } diff --git a/tests/integration/enterprise_device_h5_test.go b/tests/integration/enterprise_device_h5_test.go index 9c2bc7c..581accb 100644 --- a/tests/integration/enterprise_device_h5_test.go +++ b/tests/integration/enterprise_device_h5_test.go @@ -81,7 +81,7 @@ func TestEnterpriseDeviceH5_GetDeviceDetail(t *testing.T) { } require.NoError(t, env.TX.Create(device).Error) - card := &model.IotCard{ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, NetworkStatus: 1} + card := &model.IotCard{ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, NetworkStatus: 1} require.NoError(t, env.TX.Create(card).Error) now := time.Now() @@ -168,7 +168,7 @@ func TestEnterpriseDeviceH5_SuspendCard(t *testing.T) { } require.NoError(t, env.TX.Create(device).Error) - card := &model.IotCard{ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, NetworkStatus: 1} + card := &model.IotCard{ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, NetworkStatus: 1} require.NoError(t, env.TX.Create(card).Error) now := time.Now() @@ -215,7 +215,7 @@ func TestEnterpriseDeviceH5_SuspendCard(t *testing.T) { }) t.Run("卡不属于设备返回错误", func(t *testing.T) { - card2 := &model.IotCard{ICCID: prefix + "0002", CardType: "normal", CarrierID: carrier.ID, Status: 2} + card2 := &model.IotCard{ICCID: prefix + "0002", CarrierID: carrier.ID, Status: 2} require.NoError(t, env.TX.Create(card2).Error) reqBody := dto.DeviceCardOperationReq{Reason: "测试停机"} @@ -252,7 +252,7 @@ func TestEnterpriseDeviceH5_ResumeCard(t *testing.T) { } require.NoError(t, env.TX.Create(device).Error) - card := &model.IotCard{ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, NetworkStatus: 0} + card := &model.IotCard{ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID, NetworkStatus: 0} require.NoError(t, env.TX.Create(card).Error) now := time.Now() diff --git a/tests/integration/enterprise_device_test.go b/tests/integration/enterprise_device_test.go index 87722e4..d2eaac1 100644 --- a/tests/integration/enterprise_device_test.go +++ b/tests/integration/enterprise_device_test.go @@ -44,7 +44,7 @@ func TestEnterpriseDevice_AllocateDevices(t *testing.T) { carrier := &model.Carrier{CarrierName: "测试运营商", CarrierType: "CMCC", Status: 1} require.NoError(t, env.TX.Create(carrier).Error) - card := &model.IotCard{ICCID: prefix + "0001", CardType: "normal", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID} + card := &model.IotCard{ICCID: prefix + "0001", CarrierID: carrier.ID, Status: 2, ShopID: &shop.ID} require.NoError(t, env.TX.Create(card).Error) now := time.Now() diff --git a/tests/integration/iot_card_gateway_test.go b/tests/integration/iot_card_gateway_test.go index add30b8..930cd03 100644 --- a/tests/integration/iot_card_gateway_test.go +++ b/tests/integration/iot_card_gateway_test.go @@ -19,7 +19,7 @@ func TestGatewayCard_GetStatus(t *testing.T) { card := &model.IotCard{ ICCID: "89860001234567890001", - CardType: "data_card", + CarrierID: 1, Status: 1, } @@ -48,7 +48,7 @@ func TestGatewayCard_GetStatus(t *testing.T) { card2 := &model.IotCard{ ICCID: "89860001234567890002", - CardType: "data_card", + CarrierID: 1, Status: 1, ShopID: &shop2.ID, @@ -78,7 +78,7 @@ func TestGatewayCard_GetFlow(t *testing.T) { card := &model.IotCard{ ICCID: "89860001234567890003", - CardType: "data_card", + CarrierID: 1, Status: 1, } @@ -107,7 +107,7 @@ func TestGatewayCard_GetFlow(t *testing.T) { card2 := &model.IotCard{ ICCID: "89860001234567890004", - CardType: "data_card", + CarrierID: 1, Status: 1, ShopID: &shop2.ID, @@ -137,7 +137,7 @@ func TestGatewayCard_GetRealname(t *testing.T) { card := &model.IotCard{ ICCID: "89860001234567890005", - CardType: "data_card", + CarrierID: 1, Status: 1, } @@ -166,7 +166,7 @@ func TestGatewayCard_GetRealname(t *testing.T) { card2 := &model.IotCard{ ICCID: "89860001234567890006", - CardType: "data_card", + CarrierID: 1, Status: 1, ShopID: &shop2.ID, @@ -196,7 +196,7 @@ func TestGatewayCard_GetRealnameLink(t *testing.T) { card := &model.IotCard{ ICCID: "89860001234567890007", - CardType: "data_card", + CarrierID: 1, Status: 1, } @@ -225,7 +225,7 @@ func TestGatewayCard_GetRealnameLink(t *testing.T) { card2 := &model.IotCard{ ICCID: "89860001234567890008", - CardType: "data_card", + CarrierID: 1, Status: 1, ShopID: &shop2.ID, @@ -255,7 +255,7 @@ func TestGatewayCard_StopCard(t *testing.T) { card := &model.IotCard{ ICCID: "89860001234567890009", - CardType: "data_card", + CarrierID: 1, Status: 1, } @@ -284,7 +284,7 @@ func TestGatewayCard_StopCard(t *testing.T) { card2 := &model.IotCard{ ICCID: "89860001234567890010", - CardType: "data_card", + CarrierID: 1, Status: 1, ShopID: &shop2.ID, @@ -314,7 +314,7 @@ func TestGatewayCard_StartCard(t *testing.T) { card := &model.IotCard{ ICCID: "89860001234567890011", - CardType: "data_card", + CarrierID: 1, Status: 1, } @@ -343,7 +343,7 @@ func TestGatewayCard_StartCard(t *testing.T) { card2 := &model.IotCard{ ICCID: "89860001234567890012", - CardType: "data_card", + CarrierID: 1, Status: 1, ShopID: &shop2.ID, diff --git a/tests/integration/iot_card_test.go b/tests/integration/iot_card_test.go index 2e8fe2f..6d50e5e 100644 --- a/tests/integration/iot_card_test.go +++ b/tests/integration/iot_card_test.go @@ -23,9 +23,9 @@ func TestIotCard_ListStandalone(t *testing.T) { env := integ.NewIntegrationTestEnv(t) cards := []*model.IotCard{ - {ICCID: "TEST0012345678901001", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "TEST0012345678901002", CardType: "data_card", CarrierID: 1, Status: 1}, - {ICCID: "TEST0012345678901003", CardType: "data_card", CarrierID: 2, Status: 2}, + {ICCID: "TEST0012345678901001", CarrierID: 1, Status: 1}, + {ICCID: "TEST0012345678901002", CarrierID: 1, Status: 1}, + {ICCID: "TEST0012345678901003", CarrierID: 2, Status: 2}, } for _, card := range cards { require.NoError(t, env.TX.Create(card).Error) @@ -424,8 +424,8 @@ func TestIotCard_CarrierRedundantFields(t *testing.T) { CarrierID: carrier.ID, CarrierType: carrier.CarrierType, CarrierName: carrier.CarrierName, - CardType: "data_card", - Status: 1, + + Status: 1, } require.NoError(t, env.TX.Create(card).Error) @@ -485,12 +485,12 @@ func TestIotCard_GetByICCID(t *testing.T) { testICCID := fmt.Sprintf("8986%016d", time.Now().UnixNano()%10000000000000000) card := &model.IotCard{ - ICCID: testICCID, - CarrierID: carrier.ID, - CarrierType: carrier.CarrierType, - CarrierName: carrier.CarrierName, - MSISDN: "13800000001", - CardType: "physical", + ICCID: testICCID, + CarrierID: carrier.ID, + CarrierType: carrier.CarrierType, + CarrierName: carrier.CarrierName, + MSISDN: "13800000001", + CardCategory: "normal", CostPrice: 1000, DistributePrice: 1500, @@ -557,9 +557,9 @@ func TestIotCard_BatchSetSeriesBinding(t *testing.T) { // 创建测试卡(归属于该店铺) timestamp := time.Now().Unix() % 1000000 cards := []*model.IotCard{ - {ICCID: fmt.Sprintf("TEST%06d001", timestamp), CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shop.ID}, - {ICCID: fmt.Sprintf("TEST%06d002", timestamp), CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shop.ID}, - {ICCID: fmt.Sprintf("TEST%06d003", timestamp), CardType: "data_card", CarrierID: 1, Status: 1, ShopID: &shop.ID}, + {ICCID: fmt.Sprintf("TEST%06d001", timestamp), CarrierID: 1, Status: 1, ShopID: &shop.ID}, + {ICCID: fmt.Sprintf("TEST%06d002", timestamp), CarrierID: 1, Status: 1, ShopID: &shop.ID}, + {ICCID: fmt.Sprintf("TEST%06d003", timestamp), CarrierID: 1, Status: 1, ShopID: &shop.ID}, } for _, card := range cards { require.NoError(t, env.TX.Create(card).Error) @@ -694,8 +694,8 @@ func TestIotCard_BatchSetSeriesBinding(t *testing.T) { // 创建另一个店铺和卡 otherShop := env.CreateTestShop("其他店铺", 1, nil) otherCard := &model.IotCard{ - ICCID: fmt.Sprintf("OTH%010d", time.Now().Unix()%10000000000), - CardType: "data_card", + ICCID: fmt.Sprintf("OTH%010d", time.Now().Unix()%10000000000), + CarrierID: 1, Status: 1, ShopID: &otherShop.ID, @@ -726,8 +726,8 @@ func TestIotCard_BatchSetSeriesBinding(t *testing.T) { // 创建另一个店铺和卡 anotherShop := env.CreateTestShop("另一个店铺", 1, nil) anotherCard := &model.IotCard{ - ICCID: fmt.Sprintf("ADM%010d", time.Now().Unix()%10000000000), - CardType: "data_card", + ICCID: fmt.Sprintf("ADM%010d", time.Now().Unix()%10000000000), + CarrierID: 1, Status: 1, ShopID: &anotherShop.ID, diff --git a/tests/integration/standalone_card_allocation_test.go b/tests/integration/standalone_card_allocation_test.go index 966051e..570d618 100644 --- a/tests/integration/standalone_card_allocation_test.go +++ b/tests/integration/standalone_card_allocation_test.go @@ -25,9 +25,9 @@ func TestStandaloneCardAllocation_AllocateByList(t *testing.T) { agentAccount := env.CreateTestAccount("agent_alloc", "password123", constants.UserTypeAgent, &shop.ID, nil) cards := []*model.IotCard{ - {ICCID: "ALLOC_TEST001", CardType: "data_card", CarrierID: 1, Status: constants.IotCardStatusInStock}, - {ICCID: "ALLOC_TEST002", CardType: "data_card", CarrierID: 1, Status: constants.IotCardStatusInStock}, - {ICCID: "ALLOC_TEST003", CardType: "data_card", CarrierID: 1, Status: constants.IotCardStatusInStock}, + {ICCID: "ALLOC_TEST001", CarrierID: 1, Status: constants.IotCardStatusInStock}, + {ICCID: "ALLOC_TEST002", CarrierID: 1, Status: constants.IotCardStatusInStock}, + {ICCID: "ALLOC_TEST003", CarrierID: 1, Status: constants.IotCardStatusInStock}, } for _, card := range cards { require.NoError(t, env.TX.Create(card).Error) @@ -132,8 +132,8 @@ func TestStandaloneCardAllocation_Recall(t *testing.T) { shopID := shop.ID cards := []*model.IotCard{ - {ICCID: "ALLOC_TEST101", CardType: "data_card", CarrierID: 1, Status: constants.IotCardStatusDistributed, ShopID: &shopID}, - {ICCID: "ALLOC_TEST102", CardType: "data_card", CarrierID: 1, Status: constants.IotCardStatusDistributed, ShopID: &shopID}, + {ICCID: "ALLOC_TEST101", CarrierID: 1, Status: constants.IotCardStatusDistributed, ShopID: &shopID}, + {ICCID: "ALLOC_TEST102", CarrierID: 1, Status: constants.IotCardStatusDistributed, ShopID: &shopID}, } for _, card := range cards { require.NoError(t, env.TX.Create(card).Error) diff --git a/tests/unit/commission_calculation_service_test.go b/tests/unit/commission_calculation_service_test.go index 8b15bcf..07ea4c9 100644 --- a/tests/unit/commission_calculation_service_test.go +++ b/tests/unit/commission_calculation_service_test.go @@ -62,7 +62,7 @@ func TestCommissionCalculation_AccumulatedRecharge(t *testing.T) { card := &model.IotCard{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, ICCID: fmt.Sprintf("898600%013d", time.Now().Unix()%10000000000000), - CardType: "4G", + CardCategory: "normal", CarrierID: 1, CarrierType: "CMCC", @@ -327,7 +327,7 @@ func TestCommissionCalculation_OneTimeCommissionLogic(t *testing.T) { card := &model.IotCard{ BaseModel: model.BaseModel{Creator: 1, Updater: 1}, ICCID: fmt.Sprintf("898600%013d", time.Now().Unix()%10000000000000+1), - CardType: "4G", + CardCategory: "normal", CarrierID: 1, CarrierType: "CMCC",