From d9b51a7616588578f8051008ec56b40d42bef447 Mon Sep 17 00:00:00 2001 From: Efril Date: Thu, 14 May 2026 16:17:28 +0700 Subject: [PATCH] update ordedr list --- internal/handler/order_handler.go | 5 +-- internal/repository/order_repository.go | 60 ++++++++++++++++--------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/internal/handler/order_handler.go b/internal/handler/order_handler.go index 751f3d5..fa3971b 100644 --- a/internal/handler/order_handler.go +++ b/internal/handler/order_handler.go @@ -140,10 +140,7 @@ func (h *OrderHandler) ListOrders(c *gin.Context) { if modelReq.OutletID == nil && contextInfo.OutletID != uuid.Nil { modelReq.OutletID = &contextInfo.OutletID } - if modelReq.OutletID == nil { - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("validation_failed", "OrderHandler::ListOrders", "outlet_id is required")}), "OrderHandler::ListOrders") - return - } + response, err := h.orderService.ListOrders(c.Request.Context(), modelReq) if err != nil { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError("internal_error", "OrderHandler::ListOrders", err.Error())}), "OrderHandler::ListOrders") diff --git a/internal/repository/order_repository.go b/internal/repository/order_repository.go index 1ba460b..97ca112 100644 --- a/internal/repository/order_repository.go +++ b/internal/repository/order_repository.go @@ -98,7 +98,42 @@ func (r *OrderRepositoryImpl) List(ctx context.Context, filters map[string]inter var orders []*entities.Order var total int64 - query := r.db.WithContext(ctx).Model(&entities.Order{}). + // organization_id is mandatory to prevent cross-org data leaks + organizationID, ok := filters["organization_id"] + if !ok { + return nil, 0, fmt.Errorf("organization_id is required for listing orders") + } + + baseQuery := r.db.WithContext(ctx).Model(&entities.Order{}). + Where("organization_id = ?", organizationID) + + // outlet_id is optional — if present, scope to that outlet; otherwise return all outlets in the org + if outletID, exists := filters["outlet_id"]; exists { + baseQuery = baseQuery.Where("outlet_id = ?", outletID) + } + + for key, value := range filters { + switch key { + case "organization_id", "outlet_id": + // already handled above + case "search": + searchValue := "%" + value.(string) + "%" + baseQuery = baseQuery.Where("order_number ILIKE ?", searchValue) + case "date_from": + baseQuery = baseQuery.Where("created_at >= ?", value) + case "date_to": + baseQuery = baseQuery.Where("created_at <= ?", value) + default: + baseQuery = baseQuery.Where(key+" = ?", value) + } + } + + // Use separate queries for count and find to avoid GORM state mutation issues + if err := baseQuery.Count(&total).Error; err != nil { + return nil, 0, err + } + + err := baseQuery. Preload("Organization"). Preload("Outlet"). Preload("User"). @@ -107,27 +142,8 @@ func (r *OrderRepositoryImpl) List(ctx context.Context, filters map[string]inter Preload("OrderItems.ProductVariant"). Preload("Payments"). Preload("Payments.PaymentMethod"). - Preload("Payments.PaymentOrderItems") - - for key, value := range filters { - switch key { - case "search": - searchValue := "%" + value.(string) + "%" - query = query.Where("order_number ILIKE ?", searchValue) - case "date_from": - query = query.Where("created_at >= ?", value) - case "date_to": - query = query.Where("created_at <= ?", value) - default: - query = query.Where(key+" = ?", value) - } - } - - if err := query.Count(&total).Error; err != nil { - return nil, 0, err - } - - err := query.Limit(limit).Offset(offset).Order("created_at DESC").Find(&orders).Error + Preload("Payments.PaymentOrderItems"). + Limit(limit).Offset(offset).Order("created_at DESC").Find(&orders).Error return orders, total, err }