diff --git a/internal/contract/expense_contract.go b/internal/contract/expense_contract.go index ddc6f9e..c451e69 100644 --- a/internal/contract/expense_contract.go +++ b/internal/contract/expense_contract.go @@ -72,9 +72,12 @@ type ExpenseItemResponse struct { } type ListExpenseRequest struct { - Page int `json:"page" validate:"min=1"` - Limit int `json:"limit" validate:"min=1,max=100"` - Search string `json:"search,omitempty"` + Page int `json:"page" validate:"min=1"` + Limit int `json:"limit" validate:"min=1,max=100"` + Search string `json:"search,omitempty"` + OutletID string `json:"outlet_id,omitempty"` + StartDate string `json:"start_date,omitempty"` + EndDate string `json:"end_date,omitempty"` } type ListExpenseResponse struct { diff --git a/internal/handler/expense_handler.go b/internal/handler/expense_handler.go index c4980fd..1b3fc8e 100644 --- a/internal/handler/expense_handler.go +++ b/internal/handler/expense_handler.go @@ -164,6 +164,22 @@ func (h *ExpenseHandler) ListExpenses(c *gin.Context) { req.Search = search } + // Prioritize outlet_id from context (e.g. outlet-scoped user), + // fall back to query param if context has no outlet. + if contextInfo.OutletID != uuid.Nil { + req.OutletID = contextInfo.OutletID.String() + } else if outletID := c.Query("outlet_id"); outletID != "" { + req.OutletID = outletID + } + + if startDate := c.Query("start_date"); startDate != "" { + req.StartDate = startDate + } + + if endDate := c.Query("end_date"); endDate != "" { + req.EndDate = endDate + } + validationError, validationErrorCode := h.expenseValidator.ValidateListExpenseRequest(req) if validationError != nil { validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) diff --git a/internal/models/expense.go b/internal/models/expense.go index 37b3b13..68e8645 100644 --- a/internal/models/expense.go +++ b/internal/models/expense.go @@ -98,9 +98,12 @@ type UpdateExpenseItemRequest struct { } type ListExpenseRequest struct { - Page int `json:"page"` - Limit int `json:"limit"` - Search string `json:"search,omitempty"` + Page int `json:"page"` + Limit int `json:"limit"` + Search string `json:"search,omitempty"` + OutletID string `json:"outlet_id,omitempty"` + StartDate string `json:"start_date,omitempty"` + EndDate string `json:"end_date,omitempty"` } type ListExpenseResponse struct { diff --git a/internal/repository/expense_repository.go b/internal/repository/expense_repository.go index 1bfcad0..7711915 100644 --- a/internal/repository/expense_repository.go +++ b/internal/repository/expense_repository.go @@ -3,6 +3,7 @@ package repository import ( "context" "strings" + "time" "github.com/google/uuid" @@ -74,6 +75,14 @@ func (r *ExpenseRepositoryImpl) List(ctx context.Context, organizationID uuid.UU if outletID, ok := value.(uuid.UUID); ok { query = query.Where("outlet_id = ?", outletID) } + case "start_date": + if startDate, ok := value.(time.Time); ok { + query = query.Where("transaction_date >= ?", startDate) + } + case "end_date": + if endDate, ok := value.(time.Time); ok { + query = query.Where("transaction_date <= ?", endDate) + } default: query = query.Where(key+" = ?", value) } diff --git a/internal/service/expense_service.go b/internal/service/expense_service.go index a7f13df..24af26c 100644 --- a/internal/service/expense_service.go +++ b/internal/service/expense_service.go @@ -3,6 +3,7 @@ package service import ( "apskel-pos-be/internal/appcontext" "context" + "time" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" @@ -86,6 +87,23 @@ func (s *ExpenseServiceImpl) ListExpenses(ctx context.Context, apctx *appcontext if modelReq.Search != "" { filters["search"] = modelReq.Search } + if modelReq.OutletID != "" { + outletID, err := uuid.Parse(modelReq.OutletID) + if err == nil { + filters["outlet_id"] = outletID + } + } + if modelReq.StartDate != "" { + if startDate, err := time.Parse("2006-01-02", modelReq.StartDate); err == nil { + filters["start_date"] = startDate + } + } + if modelReq.EndDate != "" { + if endDate, err := time.Parse("2006-01-02", modelReq.EndDate); err == nil { + // include the full end date day + filters["end_date"] = endDate.Add(24*time.Hour - time.Nanosecond) + } + } expenses, totalPages, err := s.expenseProcessor.ListExpenses(ctx, apctx.OrganizationID, filters, modelReq.Page, modelReq.Limit) if err != nil { diff --git a/internal/transformer/expense_transformer.go b/internal/transformer/expense_transformer.go index 4b1d059..bbf0ce7 100644 --- a/internal/transformer/expense_transformer.go +++ b/internal/transformer/expense_transformer.go @@ -66,9 +66,12 @@ func UpdateExpenseItemRequestToModel(req *contract.UpdateExpenseItemRequest) mod func ListExpenseRequestToModel(req *contract.ListExpenseRequest) *models.ListExpenseRequest { return &models.ListExpenseRequest{ - Page: req.Page, - Limit: req.Limit, - Search: req.Search, + Page: req.Page, + Limit: req.Limit, + Search: req.Search, + OutletID: req.OutletID, + StartDate: req.StartDate, + EndDate: req.EndDate, } }