diff --git a/backend/internal/api/handlers/order.go b/backend/internal/api/handlers/order.go index ace74ff..d157c69 100644 --- a/backend/internal/api/handlers/order.go +++ b/backend/internal/api/handlers/order.go @@ -278,11 +278,13 @@ func (h *OrderHandler) Create(c *gin.Context) { } var inventory models.Inventory - if err := utils.DB.Where("product_id = ?", cart.ProductID).First(&inventory).Error; err == nil { - if inventory.Quantity < cart.Quantity { - c.JSON(http.StatusBadRequest, gin.H{"error": "Insufficient stock for " + cart.Product.Name}) - return - } + if err := utils.DB.Where("product_id = ?", cart.ProductID).First(&inventory).Error; err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "No inventory record for " + cart.Product.Name}) + return + } + if inventory.Quantity < cart.Quantity { + c.JSON(http.StatusBadRequest, gin.H{"error": "Insufficient stock for " + cart.Product.Name + ". Available: " + strconv.Itoa(inventory.Quantity)}) + return } subtotal += cart.Product.Price * float64(cart.Quantity) @@ -723,3 +725,52 @@ func (h *OrderHandler) ConfirmReceipt(c *gin.Context) { utils.DB.Model(&order).Update("status", models.OrderStatusCompleted) c.JSON(http.StatusOK, gin.H{"message": "Order confirmed successfully"}) } + +func (h *OrderHandler) AdminUpdateStatus(c *gin.Context) { + id, _ := strconv.Atoi(c.Param("id")) + + var order models.Order + if err := utils.DB.First(&order, id).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"}) + return + } + + var req struct { + Status string `json:"status" binding:"required"` + TrackingNumber string `json:"tracking_number"` + } + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + validStatuses := []string{ + models.OrderStatusPendingPayment, + models.OrderStatusPendingConfirm, + models.OrderStatusPendingShip, + models.OrderStatusShipped, + models.OrderStatusCompleted, + models.OrderStatusRefunding, + models.OrderStatusRefunded, + models.OrderStatusCancelled, + } + valid := false + for _, s := range validStatuses { + if s == req.Status { + valid = true + break + } + } + if !valid { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid status"}) + return + } + + updates := map[string]interface{}{"status": req.Status} + if req.TrackingNumber != "" { + updates["tracking_number"] = req.TrackingNumber + } + + utils.DB.Model(&order).Updates(updates) + c.JSON(http.StatusOK, gin.H{"message": "Order status updated successfully"}) +} diff --git a/backend/internal/api/routes/routes.go b/backend/internal/api/routes/routes.go index aa09a0a..9c25660 100644 --- a/backend/internal/api/routes/routes.go +++ b/backend/internal/api/routes/routes.go @@ -188,9 +188,10 @@ func SetupRoutes(r *gin.Engine) { adminOrders := admin.Group("/orders") { adminOrders.GET("", orderHandler.AdminList) - adminOrders.GET("/:id", orderHandler.AdminGetByID) + adminOrders.GET("/:id", orderHandler.AdminGetByID) adminOrders.GET("/export", orderHandler.Export) adminOrders.PUT("/:id/refund", orderHandler.ProcessRefund) + adminOrders.PUT("/:id/status", orderHandler.AdminUpdateStatus) } adminLotteries := admin.Group("/lotteries") diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index baaebdf..73d8131 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -152,6 +152,7 @@ export const adminApi = { getOrderById: (id: number) => api.get(`/admin/orders/${id}`), exportOrders: () => api.get('/admin/orders/export'), processRefund: (id: number, data: any) => api.put(`/admin/orders/${id}/refund`, data), + updateOrderStatus: (id: number, data: any) => api.put(`/admin/orders/${id}/status`, data), getSuppliers: () => api.get('/admin/suppliers'), createSupplier: (data: any) => api.post('/admin/suppliers', data), diff --git a/frontend/src/views/admin/Orders.vue b/frontend/src/views/admin/Orders.vue index 6794a09..a7267ad 100644 --- a/frontend/src/views/admin/Orders.vue +++ b/frontend/src/views/admin/Orders.vue @@ -48,13 +48,33 @@