feat: 新增数据库迁移,重命名 device_no 为 virtual_no,新增 iot_card.virtual_no 和 package.virtual_ratio 字段
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m3s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m3s
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -48,7 +48,7 @@ func (s *DeviceStore) GetByID(ctx context.Context, id uint) (*model.Device, erro
|
||||
|
||||
func (s *DeviceStore) GetByDeviceNo(ctx context.Context, deviceNo string) (*model.Device, error) {
|
||||
var device model.Device
|
||||
query := s.db.WithContext(ctx).Where("device_no = ?", deviceNo)
|
||||
query := s.db.WithContext(ctx).Where("virtual_no = ?", deviceNo)
|
||||
// 应用数据权限过滤(NULL shop_id 对代理用户不可见)
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
if err := query.First(&device).Error; err != nil {
|
||||
@@ -58,10 +58,10 @@ func (s *DeviceStore) GetByDeviceNo(ctx context.Context, deviceNo string) (*mode
|
||||
}
|
||||
|
||||
// GetByIdentifier 通过任意标识符查找设备
|
||||
// 支持 device_no(虚拟号)、imei、sn 三个字段的自动匹配
|
||||
// 支持 virtual_no(虚拟号)、imei、sn 三个字段的自动匹配
|
||||
func (s *DeviceStore) GetByIdentifier(ctx context.Context, identifier string) (*model.Device, error) {
|
||||
var device model.Device
|
||||
query := s.db.WithContext(ctx).Where("device_no = ? OR imei = ? OR sn = ?", identifier, identifier, identifier)
|
||||
query := s.db.WithContext(ctx).Where("virtual_no = ? OR imei = ? OR sn = ?", identifier, identifier, identifier)
|
||||
// 应用数据权限过滤(NULL shop_id 对代理用户不可见)
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
if err := query.First(&device).Error; err != nil {
|
||||
@@ -100,8 +100,8 @@ func (s *DeviceStore) List(ctx context.Context, opts *store.QueryOptions, filter
|
||||
// 应用数据权限过滤(NULL shop_id 对代理用户不可见)
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
|
||||
if deviceNo, ok := filters["device_no"].(string); ok && deviceNo != "" {
|
||||
query = query.Where("device_no LIKE ?", "%"+deviceNo+"%")
|
||||
if virtualNo, ok := filters["virtual_no"].(string); ok && virtualNo != "" {
|
||||
query = query.Where("virtual_no LIKE ?", "%"+virtualNo+"%")
|
||||
}
|
||||
if deviceName, ok := filters["device_name"].(string); ok && deviceName != "" {
|
||||
query = query.Where("device_name LIKE ?", "%"+deviceName+"%")
|
||||
@@ -184,17 +184,17 @@ func (s *DeviceStore) ExistsByDeviceNoBatch(ctx context.Context, deviceNos []str
|
||||
}
|
||||
|
||||
var existingDevices []struct {
|
||||
DeviceNo string
|
||||
VirtualNo string
|
||||
}
|
||||
if err := s.db.WithContext(ctx).Model(&model.Device{}).
|
||||
Select("device_no").
|
||||
Where("device_no IN ?", deviceNos).
|
||||
Select("virtual_no").
|
||||
Where("virtual_no IN ?", deviceNos).
|
||||
Find(&existingDevices).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, d := range existingDevices {
|
||||
result[d.DeviceNo] = true
|
||||
result[d.VirtualNo] = true
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -204,7 +204,7 @@ func (s *DeviceStore) GetByDeviceNos(ctx context.Context, deviceNos []string) ([
|
||||
if len(deviceNos) == 0 {
|
||||
return devices, nil
|
||||
}
|
||||
query := s.db.WithContext(ctx).Where("device_no IN ?", deviceNos)
|
||||
query := s.db.WithContext(ctx).Where("virtual_no IN ?", deviceNos)
|
||||
// 应用数据权限过滤(NULL shop_id 对代理用户不可见)
|
||||
query = middleware.ApplyShopFilter(ctx, query)
|
||||
if err := query.Find(&devices).Error; err != nil {
|
||||
|
||||
@@ -903,6 +903,26 @@ func (s *IotCardStore) BatchDelete(ctx context.Context, cardIDs []uint) error {
|
||||
Delete(&model.IotCard{}).Error
|
||||
}
|
||||
|
||||
// ExistsByVirtualNoBatch 批量检查 virtual_no 是否已存在
|
||||
func (s *IotCardStore) ExistsByVirtualNoBatch(ctx context.Context, virtualNos []string) (map[string]bool, error) {
|
||||
result := make(map[string]bool)
|
||||
if len(virtualNos) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var existingNos []string
|
||||
if err := s.db.WithContext(ctx).Model(&model.IotCard{}).
|
||||
Where("virtual_no IN ? AND virtual_no <> ''", virtualNos).
|
||||
Pluck("virtual_no", &existingNos).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, no := range existingNos {
|
||||
result[no] = true
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ==================== 列表计数缓存 ====================
|
||||
|
||||
func (s *IotCardStore) getCachedCount(ctx context.Context, table string, filters map[string]any) (int64, bool) {
|
||||
|
||||
@@ -104,7 +104,7 @@ func (s *PersonalCustomerDeviceStore) CreateOrUpdateLastUsed(ctx context.Context
|
||||
// 不存在,创建新记录
|
||||
newRecord := &model.PersonalCustomerDevice{
|
||||
CustomerID: customerID,
|
||||
DeviceNo: deviceNo,
|
||||
VirtualNo: deviceNo,
|
||||
Status: 1, // 启用
|
||||
}
|
||||
return s.Create(ctx, newRecord)
|
||||
|
||||
Reference in New Issue
Block a user