From 5e7e68cce7e1c3f3ccc76806188428f3969e4741 Mon Sep 17 00:00:00 2001 From: huang Date: Tue, 19 May 2026 12:04:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20has=5Factive=5Fpackage=20=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DTO ListDeviceRequest 增加 HasActivePackage *bool 字段(query/json: has_active_package) - Service List 方法将 HasActivePackage 透传至 filters["has_active_package"] - Store applyDeviceFilters 新增 applyHasActivePackageFilter: true → EXISTS 子查询(生效中主套餐) false → NOT EXISTS 子查询 均限制 master_usage_id IS NULL、deleted_at IS NULL,状态使用 constants.PackageUsageStatusActive Co-Authored-By: Claude Sonnet 4.6 --- internal/model/dto/device_dto.go | 5 +++-- internal/service/device/service.go | 3 +++ internal/store/postgres/device_store.go | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) 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