feature/expense #13

Merged
aefril merged 10 commits from feature/expense into main 2026-06-01 17:20:29 +00:00
6 changed files with 61 additions and 9 deletions
Showing only changes of commit 66a8126da0 - Show all commits

View File

@ -72,9 +72,12 @@ type ExpenseItemResponse struct {
} }
type ListExpenseRequest struct { type ListExpenseRequest struct {
Page int `json:"page" validate:"min=1"` Page int `json:"page" validate:"min=1"`
Limit int `json:"limit" validate:"min=1,max=100"` Limit int `json:"limit" validate:"min=1,max=100"`
Search string `json:"search,omitempty"` 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 { type ListExpenseResponse struct {

View File

@ -164,6 +164,22 @@ func (h *ExpenseHandler) ListExpenses(c *gin.Context) {
req.Search = search 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) validationError, validationErrorCode := h.expenseValidator.ValidateListExpenseRequest(req)
if validationError != nil { if validationError != nil {
validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error())

View File

@ -98,9 +98,12 @@ type UpdateExpenseItemRequest struct {
} }
type ListExpenseRequest struct { type ListExpenseRequest struct {
Page int `json:"page"` Page int `json:"page"`
Limit int `json:"limit"` Limit int `json:"limit"`
Search string `json:"search,omitempty"` 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 { type ListExpenseResponse struct {

View File

@ -3,6 +3,7 @@ package repository
import ( import (
"context" "context"
"strings" "strings"
"time"
"github.com/google/uuid" "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 { if outletID, ok := value.(uuid.UUID); ok {
query = query.Where("outlet_id = ?", outletID) 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: default:
query = query.Where(key+" = ?", value) query = query.Where(key+" = ?", value)
} }

View File

@ -3,6 +3,7 @@ package service
import ( import (
"apskel-pos-be/internal/appcontext" "apskel-pos-be/internal/appcontext"
"context" "context"
"time"
"apskel-pos-be/internal/constants" "apskel-pos-be/internal/constants"
"apskel-pos-be/internal/contract" "apskel-pos-be/internal/contract"
@ -86,6 +87,23 @@ func (s *ExpenseServiceImpl) ListExpenses(ctx context.Context, apctx *appcontext
if modelReq.Search != "" { if modelReq.Search != "" {
filters["search"] = 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) expenses, totalPages, err := s.expenseProcessor.ListExpenses(ctx, apctx.OrganizationID, filters, modelReq.Page, modelReq.Limit)
if err != nil { if err != nil {

View File

@ -66,9 +66,12 @@ func UpdateExpenseItemRequestToModel(req *contract.UpdateExpenseItemRequest) mod
func ListExpenseRequestToModel(req *contract.ListExpenseRequest) *models.ListExpenseRequest { func ListExpenseRequestToModel(req *contract.ListExpenseRequest) *models.ListExpenseRequest {
return &models.ListExpenseRequest{ return &models.ListExpenseRequest{
Page: req.Page, Page: req.Page,
Limit: req.Limit, Limit: req.Limit,
Search: req.Search, Search: req.Search,
OutletID: req.OutletID,
StartDate: req.StartDate,
EndDate: req.EndDate,
} }
} }