127 lines
2.5 KiB
Go
127 lines
2.5 KiB
Go
package request
|
|
|
|
import (
|
|
"enaklo-pos-be/internal/entity"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/pkg/errors"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type QueryParser struct {
|
|
defaultLimit int
|
|
maxLimit int
|
|
}
|
|
|
|
func NewQueryParser() *QueryParser {
|
|
return &QueryParser{
|
|
defaultLimit: 20,
|
|
maxLimit: 100,
|
|
}
|
|
}
|
|
|
|
func (p *QueryParser) ParseSearchRequest(c *gin.Context) (*entity.SearchRequest, error) {
|
|
req := &entity.SearchRequest{}
|
|
|
|
if status := c.Query("status"); status != "" {
|
|
req.Status = status
|
|
}
|
|
|
|
limit, err := p.parseLimit(c.Query("limit"))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "invalid limit parameter")
|
|
}
|
|
req.Limit = limit
|
|
|
|
offset, err := p.parseOffset(c.Query("offset"))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "invalid offset parameter")
|
|
}
|
|
req.Offset = offset
|
|
|
|
if err := p.parseDateRange(c, req); err != nil {
|
|
return nil, errors.Wrap(err, "invalid date parameters")
|
|
}
|
|
|
|
return req, nil
|
|
}
|
|
|
|
func (p *QueryParser) parseLimit(limitStr string) (int, error) {
|
|
if limitStr == "" {
|
|
return p.defaultLimit, nil
|
|
}
|
|
|
|
limit, err := strconv.Atoi(limitStr)
|
|
if err != nil {
|
|
return 0, errors.New("limit must be a valid integer")
|
|
}
|
|
|
|
if limit <= 0 {
|
|
return p.defaultLimit, nil
|
|
}
|
|
|
|
if limit > p.maxLimit {
|
|
limit = p.maxLimit
|
|
}
|
|
|
|
return limit, nil
|
|
}
|
|
|
|
func (p *QueryParser) parseOffset(offsetStr string) (int, error) {
|
|
if offsetStr == "" {
|
|
return 0, nil
|
|
}
|
|
|
|
offset, err := strconv.Atoi(offsetStr)
|
|
if err != nil {
|
|
return 0, errors.New("offset must be a valid integer")
|
|
}
|
|
|
|
if offset < 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
return offset, nil
|
|
}
|
|
|
|
func (p *QueryParser) parseDateRange(c *gin.Context, req *entity.SearchRequest) error {
|
|
if startDateStr := c.Query("start_date"); startDateStr != "" {
|
|
startDate, err := p.parseDate(startDateStr)
|
|
if err != nil {
|
|
return errors.Wrap(err, "invalid start_date format")
|
|
}
|
|
req.Start = startDate
|
|
}
|
|
|
|
if endDateStr := c.Query("end_date"); endDateStr != "" {
|
|
endDate, err := p.parseDate(endDateStr)
|
|
if err != nil {
|
|
return errors.Wrap(err, "invalid end_date format")
|
|
}
|
|
req.End = endDate
|
|
}
|
|
|
|
if !req.Start.IsZero() && !req.End.IsZero() && req.Start.After(req.End) {
|
|
return errors.New("start_date cannot be after end_date")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *QueryParser) parseDate(dateStr string) (time.Time, error) {
|
|
formats := []string{
|
|
time.RFC3339,
|
|
"2006-01-02T15:04:05",
|
|
"2006-01-02",
|
|
"2006-01-02 15:04:05",
|
|
}
|
|
|
|
for _, format := range formats {
|
|
if date, err := time.Parse(format, dateStr); err == nil {
|
|
return date, nil
|
|
}
|
|
}
|
|
|
|
return time.Time{}, errors.New("unsupported date format")
|
|
}
|