feat: 实现运营商模块重构,添加冗余字段优化查询性能
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m16s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m16s
主要变更: - 新增 Carrier CRUD API(创建、列表、详情、更新、删除、状态更新) - IotCard/IotCardImportTask 添加 carrier_type/carrier_name 冗余字段 - 移除 Carrier 表的 channel_name/channel_code 字段 - 查询时直接使用冗余字段,避免 JOIN Carrier 表 - 添加数据库迁移脚本(000021-000023) - 添加单元测试和集成测试 - 同步更新 OpenAPI 文档和 specs
This commit is contained in:
@@ -274,6 +274,7 @@ func TestIotCard_ImportTaskList(t *testing.T) {
|
||||
Status: model.ImportTaskStatusCompleted,
|
||||
CarrierID: 1,
|
||||
CarrierType: "CMCC",
|
||||
CarrierName: "中国移动",
|
||||
TotalCount: 100,
|
||||
}
|
||||
require.NoError(t, env.db.Create(task).Error)
|
||||
@@ -294,7 +295,7 @@ func TestIotCard_ImportTaskList(t *testing.T) {
|
||||
assert.Equal(t, 0, result.Code)
|
||||
})
|
||||
|
||||
t.Run("获取导入任务详情", func(t *testing.T) {
|
||||
t.Run("获取导入任务详情-应包含冗余字段", func(t *testing.T) {
|
||||
url := fmt.Sprintf("/api/admin/iot-cards/import-tasks/%d", task.ID)
|
||||
req := httptest.NewRequest("GET", url, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+env.adminToken)
|
||||
@@ -309,6 +310,10 @@ func TestIotCard_ImportTaskList(t *testing.T) {
|
||||
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, result.Code)
|
||||
|
||||
dataMap := result.Data.(map[string]interface{})
|
||||
assert.Equal(t, "CMCC", dataMap["carrier_type"], "任务详情应返回冗余的运营商类型")
|
||||
assert.Equal(t, "中国移动", dataMap["carrier_name"], "任务详情应返回冗余的运营商名称")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -575,23 +580,97 @@ func startTestWorker(t *testing.T, db *gorm.DB, rdb *redis.Client, logger *zap.L
|
||||
return workerServer
|
||||
}
|
||||
|
||||
func TestIotCard_CarrierRedundantFields(t *testing.T) {
|
||||
env := setupIotCardTestEnv(t)
|
||||
defer env.teardown()
|
||||
|
||||
carrierCode := fmt.Sprintf("REDUND_%d", time.Now().UnixNano())
|
||||
carrier := &model.Carrier{
|
||||
CarrierCode: carrierCode,
|
||||
CarrierName: "冗余字段测试运营商",
|
||||
CarrierType: "CUCC",
|
||||
Status: 1,
|
||||
}
|
||||
require.NoError(t, env.db.Create(carrier).Error)
|
||||
|
||||
testICCID := fmt.Sprintf("8986%016d", time.Now().UnixNano()%10000000000000000)
|
||||
card := &model.IotCard{
|
||||
ICCID: testICCID,
|
||||
CarrierID: carrier.ID,
|
||||
CarrierType: carrier.CarrierType,
|
||||
CarrierName: carrier.CarrierName,
|
||||
CardType: "data_card",
|
||||
Status: 1,
|
||||
}
|
||||
require.NoError(t, env.db.Create(card).Error)
|
||||
|
||||
t.Run("单卡列表应返回冗余字段", func(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/api/admin/iot-cards/standalone?iccid="+testICCID, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+env.adminToken)
|
||||
|
||||
resp, err := env.app.Test(req, -1)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
var result response.Response
|
||||
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, result.Code, "API应返回成功,实际: %v", result.Message)
|
||||
|
||||
dataMap, ok := result.Data.(map[string]interface{})
|
||||
require.True(t, ok, "Data应为map类型,实际: %T", result.Data)
|
||||
items, ok := dataMap["items"].([]interface{})
|
||||
require.True(t, ok, "items字段应存在且为数组,dataMap: %+v", dataMap)
|
||||
require.GreaterOrEqual(t, len(items), 1, "列表应至少有1条记录,ICCID: %s", testICCID)
|
||||
|
||||
cardData := items[0].(map[string]interface{})
|
||||
assert.Equal(t, "CUCC", cardData["carrier_type"], "列表应返回冗余的运营商类型")
|
||||
assert.Equal(t, "冗余字段测试运营商", cardData["carrier_name"], "列表应返回冗余的运营商名称")
|
||||
})
|
||||
|
||||
t.Run("单卡详情应返回冗余字段", func(t *testing.T) {
|
||||
url := fmt.Sprintf("/api/admin/iot-cards/by-iccid/%s", card.ICCID)
|
||||
req := httptest.NewRequest("GET", url, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+env.adminToken)
|
||||
|
||||
resp, err := env.app.Test(req, -1)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
var result response.Response
|
||||
err = json.NewDecoder(resp.Body).Decode(&result)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, result.Code)
|
||||
|
||||
dataMap := result.Data.(map[string]interface{})
|
||||
assert.Equal(t, "CUCC", dataMap["carrier_type"], "详情应返回冗余的运营商类型")
|
||||
assert.Equal(t, "冗余字段测试运营商", dataMap["carrier_name"], "详情应返回冗余的运营商名称")
|
||||
})
|
||||
}
|
||||
|
||||
func TestIotCard_GetByICCID(t *testing.T) {
|
||||
env := setupIotCardTestEnv(t)
|
||||
defer env.teardown()
|
||||
|
||||
// 创建测试运营商
|
||||
carrierCode := fmt.Sprintf("ICCID_%d", time.Now().UnixNano())
|
||||
carrier := &model.Carrier{
|
||||
CarrierCode: "TEST001",
|
||||
CarrierCode: carrierCode,
|
||||
CarrierName: "测试运营商",
|
||||
CarrierType: "CMCC",
|
||||
Status: 1,
|
||||
}
|
||||
require.NoError(t, env.db.Create(carrier).Error)
|
||||
|
||||
// 创建测试 IoT 卡
|
||||
testICCID := fmt.Sprintf("8986%016d", time.Now().UnixNano()%10000000000000000)
|
||||
card := &model.IotCard{
|
||||
ICCID: "TEST_ICCID_001",
|
||||
ICCID: testICCID,
|
||||
CarrierID: carrier.ID,
|
||||
CarrierType: carrier.CarrierType,
|
||||
CarrierName: carrier.CarrierName,
|
||||
MSISDN: "13800000001",
|
||||
CardType: "physical",
|
||||
CardCategory: "normal",
|
||||
@@ -617,11 +696,12 @@ func TestIotCard_GetByICCID(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, result.Code)
|
||||
|
||||
// 验证返回数据
|
||||
dataMap, ok := result.Data.(map[string]interface{})
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, "TEST_ICCID_001", dataMap["iccid"])
|
||||
assert.Equal(t, testICCID, dataMap["iccid"])
|
||||
assert.Equal(t, "13800000001", dataMap["msisdn"])
|
||||
assert.Equal(t, "CMCC", dataMap["carrier_type"], "应返回冗余的运营商类型")
|
||||
assert.Equal(t, "测试运营商", dataMap["carrier_name"], "应返回冗余的运营商名称")
|
||||
})
|
||||
|
||||
t.Run("通过不存在的ICCID查询-应返回错误", func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user