diff --git a/VEZA_COMPLETE_MVP_TODOLIST.json b/VEZA_COMPLETE_MVP_TODOLIST.json index 1e511f8ae..badd0edc2 100644 --- a/VEZA_COMPLETE_MVP_TODOLIST.json +++ b/VEZA_COMPLETE_MVP_TODOLIST.json @@ -2850,7 +2850,7 @@ "description": "GET /api/v1/marketplace/orders/:id to get order details", "owner": "backend", "estimated_hours": 2, - "status": "todo", + "status": "completed", "files_involved": [], "implementation_steps": [ { @@ -2871,7 +2871,9 @@ "Unit tests", "Integration tests" ], - "notes": "" + "notes": "", + "completed_at": "2025-12-24T15:00:31.104125", + "implementation_notes": "Implemented GET /api/v1/marketplace/orders/:id endpoint. Added GetOrder method to marketplace service that retrieves a specific order by ID, validates ownership (buyer_id must match), and preloads order items. Added GetOrder handler. Route registered in protected group." }, { "id": "BE-API-040", diff --git a/veza-backend-api/internal/api/router.go b/veza-backend-api/internal/api/router.go index 579d70962..2a9092330 100644 --- a/veza-backend-api/internal/api/router.go +++ b/veza-backend-api/internal/api/router.go @@ -249,9 +249,11 @@ func (r *APIRouter) setupMarketplaceRoutes(router *gin.RouterGroup) { return product.SellerID, nil } protected.PUT("/products/:id", r.config.AuthMiddleware.RequireOwnershipOrAdmin("product", productOwnerResolver), marketHandler.UpdateProduct) - + // BE-API-038: List orders endpoint protected.GET("/orders", marketHandler.ListOrders) + // BE-API-039: Get order details endpoint + protected.GET("/orders/:id", marketHandler.GetOrder) protected.POST("/orders", marketHandler.CreateOrder) protected.GET("/download/:product_id", marketHandler.GetDownloadURL) } diff --git a/veza-backend-api/internal/core/marketplace/service.go b/veza-backend-api/internal/core/marketplace/service.go index 6cfc391f1..4aa331989 100644 --- a/veza-backend-api/internal/core/marketplace/service.go +++ b/veza-backend-api/internal/core/marketplace/service.go @@ -14,6 +14,7 @@ import ( var ( ErrProductNotFound = errors.New("product not found") + ErrOrderNotFound = errors.New("order not found") ErrInsufficientFunds = errors.New("insufficient funds") ErrOrderFailed = errors.New("order failed processing") ErrInvalidSeller = errors.New("seller does not own the track") @@ -42,6 +43,7 @@ type MarketplaceService interface { // Purchasing CreateOrder(ctx context.Context, buyerID uuid.UUID, items []NewOrderItem) (*Order, error) + GetOrder(ctx context.Context, orderID uuid.UUID, buyerID uuid.UUID) (*Order, error) ListOrders(ctx context.Context, buyerID uuid.UUID) ([]Order, error) ProcessPaymentWebhook(ctx context.Context, payload []byte) error @@ -260,6 +262,24 @@ func (s *Service) CreateOrder(ctx context.Context, buyerID uuid.UUID, items []Ne return order, nil } +// GetOrder retrieves a specific order by ID +// BE-API-039: Implement marketplace order details endpoint +// Validates that the user owns the order +func (s *Service) GetOrder(ctx context.Context, orderID uuid.UUID, buyerID uuid.UUID) (*Order, error) { + var order Order + if err := s.db.WithContext(ctx). + Where("id = ? AND buyer_id = ?", orderID, buyerID). + Preload("Items"). + First(&order).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, ErrOrderNotFound + } + s.logger.Error("Failed to get order", zap.Error(err)) + return nil, err + } + return &order, nil +} + // ListOrders retrieves all orders for a buyer // BE-API-038: Implement marketplace order list endpoint func (s *Service) ListOrders(ctx context.Context, buyerID uuid.UUID) ([]Order, error) { diff --git a/veza-backend-api/internal/handlers/marketplace.go b/veza-backend-api/internal/handlers/marketplace.go index f0fe50111..99858eb63 100644 --- a/veza-backend-api/internal/handlers/marketplace.go +++ b/veza-backend-api/internal/handlers/marketplace.go @@ -336,3 +336,44 @@ func (h *MarketplaceHandler) ListOrders(c *gin.Context) { response.Success(c, orders) } + +// GetOrder gère la récupération des détails d'une commande +// BE-API-039: GET /api/v1/marketplace/orders/:id to get order details +// @Summary Get order details +// @Description Get details of a specific order (only order owner can access) +// @Tags Marketplace +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path string true "Order ID" +// @Success 200 {object} marketplace.Order +// @Failure 400 {object} response.APIResponse "Validation Error" +// @Failure 401 {object} response.APIResponse "Unauthorized" +// @Failure 403 {object} response.APIResponse "Forbidden - Not order owner" +// @Failure 404 {object} response.APIResponse "Order not found" +// @Router /api/v1/marketplace/orders/{id} [get] +func (h *MarketplaceHandler) GetOrder(c *gin.Context) { + userID, ok := GetUserIDUUID(c) + if !ok { + return // Erreur déjà envoyée par GetUserIDUUID + } + + orderIDStr := c.Param("id") + orderID, err := uuid.Parse(orderIDStr) + if err != nil { + response.BadRequest(c, "Invalid order id") + return + } + + order, err := h.service.GetOrder(c.Request.Context(), orderID, userID) + if err != nil { + if err == marketplace.ErrOrderNotFound { + response.NotFound(c, "Order not found") + return + } + response.InternalServerError(c, "Failed to get order") + return + } + + response.Success(c, order) +}