mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
fix filter purchase query param and search
This commit is contained in:
@@ -30,6 +30,11 @@ func (ctrl *PurchaseController) GetAll(c *fiber.Ctx) error {
|
||||
query := &validation.Query{
|
||||
Page: c.QueryInt("page", 1),
|
||||
Limit: c.QueryInt("limit", 10),
|
||||
Search: strings.TrimSpace(c.Query("search")),
|
||||
ApprovalStatus: strings.TrimSpace(c.Query("approval_status")),
|
||||
PoDate: strings.TrimSpace(c.Query("po_date")),
|
||||
PoDateFrom: strings.TrimSpace(c.Query("po_date_from")),
|
||||
PoDateTo: strings.TrimSpace(c.Query("po_date_to")),
|
||||
CreatedFrom: strings.TrimSpace(c.Query("created_from")),
|
||||
CreatedTo: strings.TrimSpace(c.Query("created_to")),
|
||||
SupplierID: uint(c.QueryInt("supplier_id", 0)),
|
||||
|
||||
@@ -146,6 +146,27 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
||||
return nil, 0, utils.BadRequest(err.Error())
|
||||
}
|
||||
|
||||
var poDateStart *time.Time
|
||||
var poDateEnd *time.Time
|
||||
|
||||
if strings.TrimSpace(params.PoDate) != "" {
|
||||
poDate, parseErr := utils.ParseDateString(strings.TrimSpace(params.PoDate))
|
||||
if parseErr != nil {
|
||||
return nil, 0, utils.BadRequest("po_date must use format YYYY-MM-DD")
|
||||
}
|
||||
poDateStart = &poDate
|
||||
poDateEndValue := poDate.AddDate(0, 0, 1)
|
||||
poDateEnd = &poDateEndValue
|
||||
} else {
|
||||
poDateStart, poDateEnd, err = parsePoDateRangeForQuery(params.PoDateFrom, params.PoDateTo)
|
||||
if err != nil {
|
||||
return nil, 0, utils.BadRequest(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
search := strings.ToLower(strings.TrimSpace(params.Search))
|
||||
approvalStatus := normalizeApprovalStatusFilter(params.ApprovalStatus)
|
||||
|
||||
purchases, total, err := s.PurchaseRepo.GetAll(c.Context(), offset, params.Limit, func(db *gorm.DB) *gorm.DB {
|
||||
db = s.withRelations(db)
|
||||
db = db.Where("purchases.deleted_at IS NULL")
|
||||
@@ -162,6 +183,14 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
||||
db = db.Where("created_at < ?", *createdTo)
|
||||
}
|
||||
|
||||
if poDateStart != nil {
|
||||
db = db.Where("purchases.po_date >= ?", *poDateStart)
|
||||
}
|
||||
|
||||
if poDateEnd != nil {
|
||||
db = db.Where("purchases.po_date < ?", *poDateEnd)
|
||||
}
|
||||
|
||||
if scope.Restrict {
|
||||
if len(scope.IDs) == 0 {
|
||||
return db.Where("1 = 0")
|
||||
@@ -213,6 +242,70 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
||||
)
|
||||
}
|
||||
|
||||
if approvalStatus != "" {
|
||||
approvalLike := "%" + approvalStatus + "%"
|
||||
db = db.Where(
|
||||
`EXISTS (
|
||||
SELECT 1
|
||||
FROM approvals a
|
||||
WHERE a.approvable_type = ?
|
||||
AND a.approvable_id = purchases.id
|
||||
AND a.id = (
|
||||
SELECT a2.id
|
||||
FROM approvals a2
|
||||
WHERE a2.approvable_type = ?
|
||||
AND a2.approvable_id = purchases.id
|
||||
ORDER BY a2.action_at DESC, a2.id DESC
|
||||
LIMIT 1
|
||||
)
|
||||
AND (
|
||||
LOWER(COALESCE(a.step_name, '')) LIKE ?
|
||||
OR LOWER(COALESCE(CAST(a.action AS TEXT), '')) LIKE ?
|
||||
OR CAST(a.step_number AS TEXT) = ?
|
||||
)
|
||||
)`,
|
||||
utils.ApprovalWorkflowPurchase.String(),
|
||||
utils.ApprovalWorkflowPurchase.String(),
|
||||
approvalLike,
|
||||
approvalLike,
|
||||
approvalStatus,
|
||||
)
|
||||
}
|
||||
|
||||
if search != "" {
|
||||
like := "%" + search + "%"
|
||||
db = db.Where(
|
||||
`(
|
||||
LOWER(COALESCE(purchases.pr_number, '')) LIKE ?
|
||||
OR LOWER(COALESCE(purchases.po_number, '')) LIKE ?
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM suppliers s
|
||||
WHERE s.id = purchases.supplier_id
|
||||
AND LOWER(COALESCE(s.name, '')) LIKE ?
|
||||
)
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM users u
|
||||
WHERE u.id = purchases.created_by
|
||||
AND LOWER(COALESCE(u.name, '')) LIKE ?
|
||||
)
|
||||
OR EXISTS (
|
||||
SELECT 1
|
||||
FROM purchase_items pi
|
||||
JOIN products p ON p.id = pi.product_id
|
||||
WHERE pi.purchase_id = purchases.id
|
||||
AND LOWER(COALESCE(p.name, '')) LIKE ?
|
||||
)
|
||||
)`,
|
||||
like,
|
||||
like,
|
||||
like,
|
||||
like,
|
||||
like,
|
||||
)
|
||||
}
|
||||
|
||||
return db.Order("created_at DESC").Order("purchases.id DESC")
|
||||
})
|
||||
|
||||
@@ -221,10 +314,8 @@ func (s *purchaseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
||||
return nil, 0, utils.Internal("Failed to get purchases")
|
||||
}
|
||||
|
||||
for i := range purchases {
|
||||
if err := s.attachLatestApproval(c.Context(), &purchases[i]); err != nil {
|
||||
s.Log.Warnf("Unable to attach latest approval for purchase %d: %+v", purchases[i].Id, err)
|
||||
}
|
||||
if err := s.attachLatestApprovals(c.Context(), purchases); err != nil {
|
||||
s.Log.Warnf("Unable to attach latest approvals for purchases: %+v", err)
|
||||
}
|
||||
|
||||
return purchases, total, nil
|
||||
@@ -2028,6 +2119,78 @@ func (s *purchaseService) attachLatestApproval(ctx context.Context, item *entity
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *purchaseService) attachLatestApprovals(ctx context.Context, items []entity.Purchase) error {
|
||||
if len(items) == 0 || s.ApprovalSvc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ids := make([]uint, 0, len(items))
|
||||
for i := range items {
|
||||
if items[i].Id == 0 {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, items[i].Id)
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
latestMap, err := s.ApprovalSvc.LatestByTargets(ctx, utils.ApprovalWorkflowPurchase, ids, func(db *gorm.DB) *gorm.DB {
|
||||
return db.Preload("ActionUser")
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range items {
|
||||
items[i].LatestApproval = latestMap[items[i].Id]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parsePoDateRangeForQuery(fromStr, toStr string) (*time.Time, *time.Time, error) {
|
||||
var fromPtr *time.Time
|
||||
var toPtr *time.Time
|
||||
|
||||
if strings.TrimSpace(fromStr) != "" {
|
||||
parsed, err := utils.ParseDateString(strings.TrimSpace(fromStr))
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("po_date_from must use format YYYY-MM-DD")
|
||||
}
|
||||
fromValue := parsed
|
||||
fromPtr = &fromValue
|
||||
}
|
||||
|
||||
if strings.TrimSpace(toStr) != "" {
|
||||
parsed, err := utils.ParseDateString(strings.TrimSpace(toStr))
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("po_date_to must use format YYYY-MM-DD")
|
||||
}
|
||||
nextDay := parsed.AddDate(0, 0, 1)
|
||||
toPtr = &nextDay
|
||||
}
|
||||
|
||||
if fromPtr != nil && toPtr != nil && fromPtr.After(*toPtr) {
|
||||
return nil, nil, errors.New("po_date_from must be earlier than po_date_to")
|
||||
}
|
||||
|
||||
return fromPtr, toPtr, nil
|
||||
}
|
||||
|
||||
func normalizeApprovalStatusFilter(raw string) string {
|
||||
value := strings.ToLower(strings.TrimSpace(raw))
|
||||
switch value {
|
||||
case "disetujui":
|
||||
return "approved"
|
||||
case "ditolak":
|
||||
return "rejected"
|
||||
default:
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func parseApprovalActionInput(raw string) (entity.ApprovalAction, error) {
|
||||
value := strings.ToUpper(strings.TrimSpace(raw))
|
||||
switch value {
|
||||
|
||||
@@ -68,6 +68,10 @@ type Query struct {
|
||||
LocationID uint `query:"location_id" validate:"omitempty,gt=0"`
|
||||
ProductCategoryID uint `query:"product_category_id" validate:"omitempty,gt=0"`
|
||||
Search string `query:"search" validate:"omitempty,max=100"`
|
||||
ApprovalStatus string `query:"approval_status" validate:"omitempty,max=100"`
|
||||
PoDate string `query:"po_date" 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"`
|
||||
CreatedFrom string `query:"created_from" validate:"omitempty,datetime=2006-01-02"`
|
||||
CreatedTo string `query:"created_to" validate:"omitempty,datetime=2006-01-02"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user