mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
fix filter purchase ?approval_status=approved,rejected and ?product_category_id=1,2,3
This commit is contained in:
@@ -40,7 +40,7 @@ func (ctrl *PurchaseController) GetAll(c *fiber.Ctx) error {
|
|||||||
SupplierID: uint(c.QueryInt("supplier_id", 0)),
|
SupplierID: uint(c.QueryInt("supplier_id", 0)),
|
||||||
AreaID: uint(c.QueryInt("area_id", 0)),
|
AreaID: uint(c.QueryInt("area_id", 0)),
|
||||||
LocationID: uint(c.QueryInt("location_id", 0)),
|
LocationID: uint(c.QueryInt("location_id", 0)),
|
||||||
ProductCategoryID: uint(c.QueryInt("product_category_id", 0)),
|
ProductCategoryID: strings.TrimSpace(c.Query("product_category_id")),
|
||||||
}
|
}
|
||||||
|
|
||||||
if query.Page < 1 || query.Limit < 1 {
|
if query.Page < 1 || query.Limit < 1 {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -146,6 +147,11 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
|||||||
return nil, 0, utils.BadRequest(err.Error())
|
return nil, 0, utils.BadRequest(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
productCategoryIDs, err := parseUintCSVFilter(params.ProductCategoryID, "product_category_id")
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, utils.BadRequest(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
var poDateStart *time.Time
|
var poDateStart *time.Time
|
||||||
var poDateEnd *time.Time
|
var poDateEnd *time.Time
|
||||||
|
|
||||||
@@ -165,7 +171,10 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
|||||||
}
|
}
|
||||||
|
|
||||||
search := strings.ToLower(strings.TrimSpace(params.Search))
|
search := strings.ToLower(strings.TrimSpace(params.Search))
|
||||||
approvalStatus := normalizeApprovalStatusFilter(params.ApprovalStatus)
|
approvalStatuses := parseStringCSVFilter(params.ApprovalStatus)
|
||||||
|
for i := range approvalStatuses {
|
||||||
|
approvalStatuses[i] = normalizeApprovalStatusFilter(approvalStatuses[i])
|
||||||
|
}
|
||||||
|
|
||||||
purchases, total, err := s.PurchaseRepo.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
|
purchases, total, err := s.PurchaseRepo.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
|
||||||
db = s.withRelations(db)
|
db = s.withRelations(db)
|
||||||
@@ -230,46 +239,53 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.ProductCategoryID > 0 {
|
if len(productCategoryIDs) > 0 {
|
||||||
db = db.Where(
|
db = db.Where(
|
||||||
`EXISTS (
|
`EXISTS (
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM purchase_items pi
|
FROM purchase_items pi
|
||||||
JOIN products p ON p.id = pi.product_id
|
JOIN products p ON p.id = pi.product_id
|
||||||
WHERE pi.purchase_id = purchases.id AND p.product_category_id = ?
|
WHERE pi.purchase_id = purchases.id AND p.product_category_id IN ?
|
||||||
)`,
|
)`,
|
||||||
params.ProductCategoryID,
|
productCategoryIDs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if approvalStatus != "" {
|
if len(approvalStatuses) > 0 {
|
||||||
approvalLike := "%" + approvalStatus + "%"
|
approvalConditions := make([]string, 0, len(approvalStatuses))
|
||||||
db = db.Where(
|
approvalArgs := make([]any, 0, 2+(len(approvalStatuses)*3))
|
||||||
`EXISTS (
|
approvalArgs = append(approvalArgs, utils.ApprovalWorkflowPurchase.String(), utils.ApprovalWorkflowPurchase.String())
|
||||||
SELECT 1
|
for _, status := range approvalStatuses {
|
||||||
FROM approvals a
|
if status == "" {
|
||||||
WHERE a.approvable_type = ?
|
continue
|
||||||
AND a.approvable_id = purchases.id
|
}
|
||||||
AND a.id = (
|
like := "%" + status + "%"
|
||||||
SELECT a2.id
|
approvalConditions = append(approvalConditions, `(LOWER(COALESCE(a.step_name, '')) LIKE ? OR LOWER(COALESCE(CAST(a.action AS TEXT), '')) LIKE ? OR CAST(a.step_number AS TEXT) = ?)`)
|
||||||
FROM approvals a2
|
approvalArgs = append(approvalArgs, like, like, status)
|
||||||
WHERE a2.approvable_type = ?
|
}
|
||||||
AND a2.approvable_id = purchases.id
|
|
||||||
ORDER BY a2.action_at DESC, a2.id DESC
|
if len(approvalConditions) > 0 {
|
||||||
LIMIT 1
|
approvalClause := strings.Join(approvalConditions, " OR ")
|
||||||
)
|
approvalQuery := fmt.Sprintf(
|
||||||
AND (
|
`EXISTS (
|
||||||
LOWER(COALESCE(a.step_name, '')) LIKE ?
|
SELECT 1
|
||||||
OR LOWER(COALESCE(CAST(a.action AS TEXT), '')) LIKE ?
|
FROM approvals a
|
||||||
OR CAST(a.step_number AS TEXT) = ?
|
WHERE a.approvable_type = ?
|
||||||
)
|
AND a.approvable_id = purchases.id
|
||||||
)`,
|
AND a.id = (
|
||||||
utils.ApprovalWorkflowPurchase.String(),
|
SELECT a2.id
|
||||||
utils.ApprovalWorkflowPurchase.String(),
|
FROM approvals a2
|
||||||
approvalLike,
|
WHERE a2.approvable_type = ?
|
||||||
approvalLike,
|
AND a2.approvable_id = purchases.id
|
||||||
approvalStatus,
|
ORDER BY a2.action_at DESC, a2.id DESC
|
||||||
)
|
LIMIT 1
|
||||||
|
)
|
||||||
|
AND (%s)
|
||||||
|
)`,
|
||||||
|
approvalClause,
|
||||||
|
)
|
||||||
|
db = db.Where(approvalQuery, approvalArgs...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if search != "" {
|
if search != "" {
|
||||||
@@ -2191,6 +2207,51 @@ func normalizeApprovalStatusFilter(raw string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseUintCSVFilter(raw, fieldName string) ([]uint, error) {
|
||||||
|
parts := strings.Split(raw, ",")
|
||||||
|
result := make([]uint, 0, len(parts))
|
||||||
|
seen := make(map[uint]struct{}, len(parts))
|
||||||
|
|
||||||
|
for _, part := range parts {
|
||||||
|
value := strings.TrimSpace(part)
|
||||||
|
if value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
num, err := strconv.ParseUint(value, 10, 64)
|
||||||
|
if err != nil || num == 0 {
|
||||||
|
return nil, fmt.Errorf("%s contains invalid value: %s", fieldName, value)
|
||||||
|
}
|
||||||
|
u := uint(num)
|
||||||
|
if _, exists := seen[u]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[u] = struct{}{}
|
||||||
|
result = append(result, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseStringCSVFilter(raw string) []string {
|
||||||
|
parts := strings.Split(raw, ",")
|
||||||
|
result := make([]string, 0, len(parts))
|
||||||
|
seen := make(map[string]struct{}, len(parts))
|
||||||
|
|
||||||
|
for _, part := range parts {
|
||||||
|
value := strings.ToLower(strings.TrimSpace(part))
|
||||||
|
if value == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, exists := seen[value]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[value] = struct{}{}
|
||||||
|
result = append(result, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func parseApprovalActionInput(raw string) (entity.ApprovalAction, error) {
|
func parseApprovalActionInput(raw string) (entity.ApprovalAction, error) {
|
||||||
value := strings.ToUpper(strings.TrimSpace(raw))
|
value := strings.ToUpper(strings.TrimSpace(raw))
|
||||||
switch value {
|
switch value {
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ type Query struct {
|
|||||||
SupplierID uint `query:"supplier_id" validate:"omitempty,gt=0"`
|
SupplierID uint `query:"supplier_id" validate:"omitempty,gt=0"`
|
||||||
AreaID uint `query:"area_id" validate:"omitempty,gt=0"`
|
AreaID uint `query:"area_id" validate:"omitempty,gt=0"`
|
||||||
LocationID uint `query:"location_id" validate:"omitempty,gt=0"`
|
LocationID uint `query:"location_id" validate:"omitempty,gt=0"`
|
||||||
ProductCategoryID uint `query:"product_category_id" validate:"omitempty,gt=0"`
|
ProductCategoryID string `query:"product_category_id" validate:"omitempty,max=500"`
|
||||||
Search string `query:"search" validate:"omitempty,max=100"`
|
Search string `query:"search" validate:"omitempty,max=100"`
|
||||||
ApprovalStatus string `query:"approval_status" validate:"omitempty,max=100"`
|
ApprovalStatus string `query:"approval_status" validate:"omitempty,max=500"`
|
||||||
PoDate string `query:"po_date" validate:"omitempty,datetime=2006-01-02"`
|
PoDate string `query:"po_date" validate:"omitempty,datetime=2006-01-02"`
|
||||||
PoDateFrom string `query:"po_date_from" validate:"omitempty,datetime=2006-01-02"`
|
PoDateFrom string `query:"po_date_from" validate:"omitempty,datetime=2006-01-02"`
|
||||||
PoDateTo string `query:"po_date_to" validate:"omitempty,datetime=2006-01-02"`
|
PoDateTo string `query:"po_date_to" validate:"omitempty,datetime=2006-01-02"`
|
||||||
|
|||||||
Reference in New Issue
Block a user