refactor(account): 移除卡类型字段、优化账号列表查询和权限检查
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m18s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m18s
- 移除 IoT 卡和号卡的 card_type 字段(数据库迁移) - 优化账号列表查询,支持按店铺和企业筛选 - 账号响应增加店铺名称和企业名称字段 - 实现批量加载店铺和企业名称,避免 N+1 查询 - 更新权限检查中间件,完善权限验证逻辑 - 更新相关测试用例,确保功能正确性
This commit is contained in:
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user