Merge branch 'fix/multiple-filter-finance' into 'development'

fix(BE): multiple filter, all search

See merge request mbugroup/lti-api!308
This commit is contained in:
Hafizh A. Y.
2026-02-05 03:28:26 +00:00
3 changed files with 110 additions and 50 deletions
@@ -24,46 +24,81 @@ func NewTransactionController(transactionService service.TransactionService) *Tr
} }
func (u *TransactionController) GetAll(c *fiber.Ctx) error { func (u *TransactionController) GetAll(c *fiber.Ctx) error {
parseOptionalUint := func(key string) (*uint, error) { parseUintListParam := func(key string) ([]uint, error) {
raw := strings.TrimSpace(c.Query(key, "")) raw := strings.TrimSpace(c.Query(key, ""))
if raw == "" { if raw == "" {
return nil, nil return nil, nil
} }
parsed, err := strconv.ParseUint(raw, 10, 64) parts := strings.Split(raw, ",")
if err != nil { ids := make([]uint, 0, len(parts))
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid "+key) for _, part := range parts {
trimmed := strings.TrimSpace(part)
if trimmed == "" {
return nil, strconv.ErrSyntax
}
parsed, err := strconv.ParseUint(trimmed, 10, 64)
if err != nil {
return nil, err
}
if parsed == 0 {
continue
}
ids = append(ids, uint(parsed))
} }
if parsed == 0 { if len(ids) == 0 {
return nil, nil return nil, nil
} }
value := uint(parsed) return ids, nil
return &value, nil
} }
bankId, err := parseOptionalUint("bank_id") parseStringListParam := func(key string) ([]string, error) {
if err != nil { raw := strings.TrimSpace(c.Query(key, ""))
return err if raw == "" {
return nil, nil
}
parts := strings.Split(raw, ",")
values := make([]string, 0, len(parts))
for _, part := range parts {
trimmed := strings.TrimSpace(part)
if trimmed == "" {
return nil, strconv.ErrSyntax
}
values = append(values, trimmed)
}
if len(values) == 0 {
return nil, nil
}
return values, nil
} }
customerId, err := parseOptionalUint("customer_id")
bankIDs, err := parseUintListParam("bank_ids")
if err != nil { if err != nil {
return err return fiber.NewError(fiber.StatusBadRequest, "Invalid bank_ids")
} }
supplierId, err := parseOptionalUint("supplier_id") customerIDs, err := parseUintListParam("customer_ids")
if err != nil { if err != nil {
return err return fiber.NewError(fiber.StatusBadRequest, "Invalid customer_ids")
}
supplierIDs, err := parseUintListParam("supplier_ids")
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid supplier_ids")
}
transactionTypes, err := parseStringListParam("transaction_types")
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid transaction_types")
} }
query := &validation.Query{ query := &validation.Query{
Page: c.QueryInt("page", 1), Page: c.QueryInt("page", 1),
Limit: c.QueryInt("limit", 10), Limit: c.QueryInt("limit", 10),
Search: c.Query("search", ""), Search: c.Query("search", ""),
TransactionType: c.Query("transaction_type", ""), TransactionTypes: transactionTypes,
BankId: bankId, BankIDs: bankIDs,
CustomerId: customerId, CustomerIDs: customerIDs,
SupplierId: supplierId, SupplierIDs: supplierIDs,
SortDate: c.Query("sort_date", ""), SortDate: c.Query("sort_date", ""),
StartDate: c.Query("start_date", ""), StartDate: c.Query("start_date", ""),
EndDate: c.Query("end_date", ""), EndDate: c.Query("end_date", ""),
} }
if query.Page < 1 || query.Limit < 1 { if query.Page < 1 || query.Limit < 1 {
@@ -74,33 +74,58 @@ func (s transactionService) GetAll(c *fiber.Ctx, params *validation.Query) ([]en
if params.Search != "" { if params.Search != "" {
like := "%" + strings.ToLower(strings.TrimSpace(params.Search)) + "%" like := "%" + strings.ToLower(strings.TrimSpace(params.Search)) + "%"
db = db.Joins(
"LEFT JOIN customers ON customers.id = payments.party_id AND payments.party_type = ? AND customers.deleted_at IS NULL",
string(utils.PaymentPartyCustomer),
).Joins(
"LEFT JOIN suppliers ON suppliers.id = payments.party_id AND payments.party_type = ? AND suppliers.deleted_at IS NULL",
string(utils.PaymentPartySupplier),
).Joins(
"LEFT JOIN banks ON banks.id = payments.bank_id AND banks.deleted_at IS NULL",
)
db = db.Where( db = db.Where(
`LOWER(payment_code) LIKE ? OR `LOWER(payment_code) LIKE ? OR
LOWER(COALESCE(reference_number, '')) LIKE ? OR LOWER(COALESCE(reference_number, '')) LIKE ? OR
LOWER(COALESCE(transaction_type, '')) LIKE ? OR LOWER(COALESCE(transaction_type, '')) LIKE ? OR
LOWER(COALESCE(notes, '')) LIKE ?`, LOWER(COALESCE(notes, '')) LIKE ? OR
like, like, like, like, LOWER(COALESCE(customers.name, '')) LIKE ? OR
LOWER(COALESCE(suppliers.name, '')) LIKE ? OR
LOWER(COALESCE(banks.name, '')) LIKE ?`,
like, like, like, like, like, like, like,
) )
} }
if strings.TrimSpace(params.TransactionType) != "" { if len(params.TransactionTypes) > 0 {
db = db.Where("transaction_type = ?", strings.ToUpper(strings.TrimSpace(params.TransactionType))) types := make([]string, 0, len(params.TransactionTypes))
for _, transactionType := range params.TransactionTypes {
normalized := strings.ToUpper(strings.TrimSpace(transactionType))
if normalized == "" {
continue
}
types = append(types, normalized)
}
if len(types) > 0 {
db = db.Where("transaction_type IN ?", types)
}
} }
if params.BankId != nil { if len(params.BankIDs) > 0 {
db = db.Where("bank_id = ?", *params.BankId) db = db.Where("bank_id IN ?", params.BankIDs)
} }
if params.CustomerId != nil && params.SupplierId != nil { customerIDs := params.CustomerIDs
supplierIDs := params.SupplierIDs
if len(customerIDs) > 0 && len(supplierIDs) > 0 {
db = db.Where( db = db.Where(
"(party_type = ? AND party_id = ?) OR (party_type = ? AND party_id = ?)", "(party_type = ? AND party_id IN ?) OR (party_type = ? AND party_id IN ?)",
string(utils.PaymentPartyCustomer), *params.CustomerId, string(utils.PaymentPartyCustomer), customerIDs,
string(utils.PaymentPartySupplier), *params.SupplierId, string(utils.PaymentPartySupplier), supplierIDs,
) )
} else if params.CustomerId != nil { } else if len(customerIDs) > 0 {
db = db.Where("party_type = ? AND party_id = ?", string(utils.PaymentPartyCustomer), *params.CustomerId) db = db.Where("party_type = ? AND party_id IN ?", string(utils.PaymentPartyCustomer), customerIDs)
} else if params.SupplierId != nil { } else if len(supplierIDs) > 0 {
db = db.Where("party_type = ? AND party_id = ?", string(utils.PaymentPartySupplier), *params.SupplierId) db = db.Where("party_type = ? AND party_id IN ?", string(utils.PaymentPartySupplier), supplierIDs)
} }
if startDate != nil { if startDate != nil {
@@ -1,22 +1,22 @@
package validation package validation
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3"` Name string `json:"name" validate:"required_strict,min=3"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty"` Name *string `json:"name,omitempty" validate:"omitempty"`
} }
type Query struct { type Query struct {
Page int `query:"page" validate:"omitempty,number,min=1,gt=0"` Page int `query:"page" validate:"omitempty,number,min=1,gt=0"`
Limit int `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"` Limit int `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"`
Search string `query:"search" validate:"omitempty,max=50"` Search string `query:"search" validate:"omitempty,max=50"`
TransactionType string `query:"transaction_type" validate:"omitempty,max=50"` TransactionTypes []string `query:"transaction_types" validate:"omitempty,dive,max=50"`
BankId *uint `query:"bank_id" validate:"omitempty,number,gt=0"` BankIDs []uint `query:"bank_ids" validate:"omitempty,dive,gt=0"`
CustomerId *uint `query:"customer_id" validate:"omitempty,number,gt=0"` CustomerIDs []uint `query:"customer_ids" validate:"omitempty,dive,gt=0"`
SupplierId *uint `query:"supplier_id" validate:"omitempty,number,gt=0"` SupplierIDs []uint `query:"supplier_ids" validate:"omitempty,dive,gt=0"`
SortDate string `query:"sort_date" validate:"omitempty,oneof=created_at payment_date"` SortDate string `query:"sort_date" validate:"omitempty,oneof=created_at payment_date"`
StartDate string `query:"start_date" validate:"omitempty,datetime=2006-01-02"` StartDate string `query:"start_date" validate:"omitempty,datetime=2006-01-02"`
EndDate string `query:"end_date" validate:"omitempty,datetime=2006-01-02"` EndDate string `query:"end_date" validate:"omitempty,datetime=2006-01-02"`
} }