diff --git a/internal/model/dto/device_dto.go b/internal/model/dto/device_dto.go index 1113d35..1222a41 100644 --- a/internal/model/dto/device_dto.go +++ b/internal/model/dto/device_dto.go @@ -15,8 +15,9 @@ type ListDeviceRequest struct { BatchNo string `json:"batch_no" query:"batch_no" validate:"omitempty,max=100" maxLength:"100" description:"批次号"` DeviceType string `json:"device_type" query:"device_type" validate:"omitempty,max=50" maxLength:"50" description:"设备类型"` Manufacturer string `json:"manufacturer" query:"manufacturer" validate:"omitempty,max=255" maxLength:"255" description:"制造商(模糊查询)"` - CreatedAtStart *time.Time `json:"created_at_start" query:"created_at_start" description:"创建时间起始"` - CreatedAtEnd *time.Time `json:"created_at_end" query:"created_at_end" description:"创建时间结束"` + CreatedAtStart *time.Time `json:"created_at_start" query:"created_at_start" description:"创建时间起始"` + CreatedAtEnd *time.Time `json:"created_at_end" query:"created_at_end" description:"创建时间结束"` + HasActivePackage *bool `json:"has_active_package" query:"has_active_package" description:"是否有生效中的套餐(true:有生效中主套餐, false:无生效中主套餐)"` } type DeviceResponse struct { diff --git a/internal/service/device/service.go b/internal/service/device/service.go index 3f2843b..bb28c28 100644 --- a/internal/service/device/service.go +++ b/internal/service/device/service.go @@ -124,6 +124,9 @@ func (s *Service) List(ctx context.Context, req *dto.ListDeviceRequest) (*dto.Li if req.SeriesID != nil { filters["series_id"] = *req.SeriesID } + if req.HasActivePackage != nil { + filters["has_active_package"] = *req.HasActivePackage + } devices, total, err := s.deviceStore.List(ctx, opts, filters) if err != nil { diff --git a/internal/store/postgres/device_store.go b/internal/store/postgres/device_store.go index cfb45af..6be57bb 100644 --- a/internal/store/postgres/device_store.go +++ b/internal/store/postgres/device_store.go @@ -177,9 +177,27 @@ func (s *DeviceStore) applyDeviceFilters(query *gorm.DB, filters map[string]any) if seriesID, ok := filters["series_id"].(uint); ok && seriesID > 0 { query = query.Where("series_id = ?", seriesID) } + if hasActive, ok := filters["has_active_package"].(bool); ok { + query = s.applyHasActivePackageFilter(query, hasActive) + } return query } +// applyHasActivePackageFilter 按"是否有生效中主套餐"过滤设备。 +// true: 设备在 tb_package_usage 中存在生效中(status=PackageUsageStatusActive)的主套餐记录; +// false: 不存在上述记录。 +func (s *DeviceStore) applyHasActivePackageFilter(query *gorm.DB, hasActive bool) *gorm.DB { + subQuery := `SELECT 1 FROM tb_package_usage AS pu + WHERE pu.device_id = tb_device.id + AND pu.status = ? + AND pu.master_usage_id IS NULL + AND pu.deleted_at IS NULL` + if hasActive { + return query.Where("EXISTS ("+subQuery+")", constants.PackageUsageStatusActive) + } + return query.Where("NOT EXISTS ("+subQuery+")", constants.PackageUsageStatusActive) +} + func (s *DeviceStore) applyActivationStatusFilter(query *gorm.DB, activationStatus int) *gorm.DB { activeCondition := `EXISTS ( SELECT 1