Files
junhong_cmp_fiber/internal/service/device/service_test.go
huang 37f43d2e2d 重构: 将卡/设备的套餐系列绑定从分配ID改为系列ID
- 数据库: 重命名 series_allocation_id → series_id
- Model: IotCard 和 Device 字段重命名
- DTO: 所有请求/响应字段统一为 series_id
- Store: 方法重命名,新增 GetByShopAndSeries 查询
- Service: 业务逻辑优化,系列验证和权限验证分离
- 测试: 更新所有测试用例,新增 shop_series_allocation_store_test.go
- 文档: 更新 API 文档说明参数变更

BREAKING CHANGE: API 参数从 series_allocation_id 改为 series_id
2026-02-02 12:09:53 +08:00

151 lines
4.7 KiB
Go

package device
import (
"context"
"fmt"
"testing"
"time"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"github.com/break/junhong_cmp_fiber/tests/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func uniqueTestDeviceNoPrefix() string {
return fmt.Sprintf("D%d", time.Now().UnixNano()%1000000000)
}
func TestDeviceService_BatchSetSeriesBinding(t *testing.T) {
tx := testutils.NewTestTransaction(t)
rdb := testutils.GetTestRedis(t)
testutils.CleanTestRedisKeys(t, rdb)
deviceStore := postgres.NewDeviceStore(tx, rdb)
deviceSimBindingStore := postgres.NewDeviceSimBindingStore(tx, rdb)
iotCardStore := postgres.NewIotCardStore(tx, rdb)
shopStore := postgres.NewShopStore(tx, rdb)
assetAllocationRecordStore := postgres.NewAssetAllocationRecordStore(tx, rdb)
seriesAllocationStore := postgres.NewShopSeriesAllocationStore(tx)
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
svc := New(tx, deviceStore, deviceSimBindingStore, iotCardStore, shopStore, assetAllocationRecordStore, seriesAllocationStore, packageSeriesStore)
ctx := context.Background()
shop := &model.Shop{
ShopName: "测试店铺",
ShopCode: fmt.Sprintf("SHOP%d", time.Now().UnixNano()%1000000),
Level: 1,
Status: 1,
}
require.NoError(t, tx.Create(shop).Error)
series := &model.PackageSeries{
SeriesCode: fmt.Sprintf("SERIES%d", time.Now().UnixNano()%1000000),
SeriesName: "测试系列",
Status: 1,
}
require.NoError(t, tx.Create(series).Error)
allocation := &model.ShopSeriesAllocation{
ShopID: shop.ID,
SeriesID: series.ID,
Status: 1,
}
require.NoError(t, tx.Create(allocation).Error)
prefix := uniqueTestDeviceNoPrefix()
devices := []*model.Device{
{DeviceNo: prefix + "001", DeviceName: "测试设备1", Status: 1, ShopID: &shop.ID},
{DeviceNo: prefix + "002", DeviceName: "测试设备2", Status: 1, ShopID: &shop.ID},
{DeviceNo: prefix + "003", DeviceName: "测试设备3", Status: 1, ShopID: nil},
}
require.NoError(t, deviceStore.CreateBatch(ctx, devices))
t.Run("成功设置系列绑定", func(t *testing.T) {
req := &dto.BatchSetDeviceSeriesBindngRequest{
DeviceIDs: []uint{devices[0].ID, devices[1].ID},
SeriesID: allocation.SeriesID,
}
resp, err := svc.BatchSetSeriesBinding(ctx, req, nil)
require.NoError(t, err)
assert.Equal(t, 2, resp.SuccessCount)
assert.Equal(t, 0, resp.FailCount)
var updatedDevices []*model.Device
require.NoError(t, tx.Where("id IN ?", req.DeviceIDs).Find(&updatedDevices).Error)
for _, device := range updatedDevices {
require.NotNil(t, device.SeriesID)
assert.Equal(t, allocation.SeriesID, *device.SeriesID)
}
})
t.Run("设备不属于套餐系列分配的店铺", func(t *testing.T) {
req := &dto.BatchSetDeviceSeriesBindngRequest{
DeviceIDs: []uint{devices[2].ID},
SeriesID: allocation.SeriesID,
}
resp, err := svc.BatchSetSeriesBinding(ctx, req, nil)
require.NoError(t, err)
assert.Equal(t, 0, resp.SuccessCount)
assert.Equal(t, 1, resp.FailCount)
assert.Equal(t, "设备不属于套餐系列分配的店铺", resp.FailedItems[0].Reason)
})
t.Run("设备不存在", func(t *testing.T) {
req := &dto.BatchSetDeviceSeriesBindngRequest{
DeviceIDs: []uint{99999},
SeriesID: allocation.SeriesID,
}
resp, err := svc.BatchSetSeriesBinding(ctx, req, nil)
require.NoError(t, err)
assert.Equal(t, 0, resp.SuccessCount)
assert.Equal(t, 1, resp.FailCount)
assert.Equal(t, "设备不存在", resp.FailedItems[0].Reason)
})
t.Run("清除系列绑定", func(t *testing.T) {
req := &dto.BatchSetDeviceSeriesBindngRequest{
DeviceIDs: []uint{devices[0].ID},
SeriesID: 0,
}
resp, err := svc.BatchSetSeriesBinding(ctx, req, nil)
require.NoError(t, err)
assert.Equal(t, 1, resp.SuccessCount)
var updatedDevice model.Device
require.NoError(t, tx.First(&updatedDevice, devices[0].ID).Error)
assert.Nil(t, updatedDevice.SeriesID)
})
t.Run("代理用户只能操作自己店铺的设备", func(t *testing.T) {
otherShopID := uint(99999)
req := &dto.BatchSetDeviceSeriesBindngRequest{
DeviceIDs: []uint{devices[1].ID},
SeriesID: 0,
}
resp, err := svc.BatchSetSeriesBinding(ctx, req, &otherShopID)
require.NoError(t, err)
assert.Equal(t, 0, resp.SuccessCount)
assert.Equal(t, 1, resp.FailCount)
assert.Equal(t, "无权操作此设备", resp.FailedItems[0].Reason)
})
t.Run("套餐系列分配不存在", func(t *testing.T) {
req := &dto.BatchSetDeviceSeriesBindngRequest{
DeviceIDs: []uint{devices[1].ID},
SeriesID: 99999,
}
_, err := svc.BatchSetSeriesBinding(ctx, req, nil)
require.Error(t, err)
})
}