// Package employeecollection 提供员工代收款账单与线下收款方式字典的只读投影。 // Query 只做权限范围、筛选、分页与 DTO 投影,不修改任何状态。 package employeecollection import ( "context" "strings" "gorm.io/gorm" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" ) // PaymentMethodQuery 查询线下收款方式字典。 type PaymentMethodQuery struct { db *gorm.DB } // NewPaymentMethodQuery 创建线下收款方式字典查询。 func NewPaymentMethodQuery(db *gorm.DB) *PaymentMethodQuery { return &PaymentMethodQuery{db: db} } // List 分页查询线下收款方式。 // 超级管理员可查询全部字典项;其他后台账号仅返回启用项,保证停用方式不可用于新申请。 func (q *PaymentMethodQuery) List( ctx context.Context, request dto.EmployeeCollectionPaymentMethodListRequest, ) (*dto.EmployeeCollectionPaymentMethodListResponse, error) { if q == nil || q.db == nil { return nil, errors.New(errors.CodeServiceUnavailable, "线下收款方式查询尚未配置") } isSuperAdmin := middleware.GetUserTypeFromContext(ctx) == constants.UserTypeSuperAdmin if !isSuperAdmin && middleware.GetUserIDFromContext(ctx) == 0 { return nil, errors.New(errors.CodeUnauthorized) } page, pageSize := normalizePage(request.Page, request.PageSize) query := q.db.WithContext(ctx).Model(&model.EmployeeCollectionPaymentMethod{}) if !isSuperAdmin { query = query.Where("status = ?", constants.EmployeeCollectionPaymentMethodStatusEnabled) } else if request.Enabled != nil { status := constants.EmployeeCollectionPaymentMethodStatusDisabled if *request.Enabled { status = constants.EmployeeCollectionPaymentMethodStatusEnabled } query = query.Where("status = ?", status) } if keyword := strings.TrimSpace(request.Keyword); keyword != "" { pattern := "%" + keyword + "%" query = query.Where("code LIKE ? OR name LIKE ?", pattern, pattern) } var total int64 if err := query.Count(&total).Error; err != nil { return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询线下收款方式总数失败") } var items []model.EmployeeCollectionPaymentMethod if err := query.Order("sort_order ASC, id ASC"). Offset((page - 1) * pageSize).Limit(pageSize). Find(&items).Error; err != nil { return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询线下收款方式列表失败") } list := make([]*dto.EmployeeCollectionPaymentMethodResponse, 0, len(items)) for index := range items { list = append(list, toPaymentMethodResponse(&items[index])) } return &dto.EmployeeCollectionPaymentMethodListResponse{ List: list, Total: total, Page: page, PageSize: pageSize, }, nil } // toPaymentMethodResponse 将字典项投影为对外响应,只暴露既有对象键与稳定字段。 func toPaymentMethodResponse(paymentMethod *model.EmployeeCollectionPaymentMethod) *dto.EmployeeCollectionPaymentMethodResponse { return &dto.EmployeeCollectionPaymentMethodResponse{ ID: paymentMethod.ID, Code: paymentMethod.Code, Name: paymentMethod.Name, Enabled: paymentMethod.Status == constants.EmployeeCollectionPaymentMethodStatusEnabled, Sort: paymentMethod.SortOrder, Remark: paymentMethod.Remark, CreatedAt: paymentMethod.CreatedAt, UpdatedAt: paymentMethod.UpdatedAt, } } // normalizePage 归一化分页参数,执行 DefaultPageSize 与 MaxPageSize 上限。 func normalizePage(page, pageSize int) (int, int) { if page <= 0 { page = constants.DefaultPage } if pageSize <= 0 { pageSize = constants.DefaultPageSize } if pageSize > constants.MaxPageSize { pageSize = constants.MaxPageSize } return page, pageSize }