package main import ( "encoding/json" "errors" "net/http" "time" "git.k6n.net/mats/go-redis-inventory/pkg/inventory" ) type reservationLineReq struct { SKU string `json:"sku"` LocationID string `json:"locationId"` Quantity uint32 `json:"quantity"` } type reservationBatchReq struct { HolderID string `json:"holderId"` TTLSeconds int64 `json:"ttlSeconds,omitempty"` Lines []reservationLineReq `json:"lines"` } func (srv *Server) reserveInventoryHandler(w http.ResponseWriter, r *http.Request) { var req reservationBatchReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "invalid request body", http.StatusBadRequest) return } if req.HolderID == "" { http.Error(w, "missing holderId", http.StatusBadRequest) return } if len(req.Lines) == 0 { http.Error(w, "missing lines", http.StatusBadRequest) return } ttl := 15 * time.Minute if req.TTLSeconds > 0 { ttl = time.Duration(req.TTLSeconds) * time.Second } for _, line := range req.Lines { if line.SKU == "" || line.LocationID == "" || line.Quantity == 0 { http.Error(w, "each line must include sku, locationId, and quantity", http.StatusBadRequest) return } if err := srv.reservationService.ReserveForCart(r.Context(), inventory.CartReserveRequest{ InventoryReference: &inventory.InventoryReference{ SKU: inventory.SKU(line.SKU), LocationID: inventory.LocationID(line.LocationID), }, CartID: inventory.CartID(req.HolderID), Quantity: line.Quantity, TTL: ttl, }); err != nil { status := http.StatusInternalServerError if errors.Is(err, inventory.ErrInsufficientInventory) { status = http.StatusConflict } http.Error(w, err.Error(), status) return } } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]any{"status": "reserved", "holderId": req.HolderID}) } func (srv *Server) releaseReservationHandler(w http.ResponseWriter, r *http.Request) { var req reservationBatchReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "invalid request body", http.StatusBadRequest) return } if req.HolderID == "" { http.Error(w, "missing holderId", http.StatusBadRequest) return } if len(req.Lines) == 0 { http.Error(w, "missing lines", http.StatusBadRequest) return } for _, line := range req.Lines { if line.SKU == "" || line.LocationID == "" { http.Error(w, "each line must include sku and locationId", http.StatusBadRequest) return } if err := srv.reservationService.ReleaseForCart(r.Context(), inventory.SKU(line.SKU), inventory.LocationID(line.LocationID), inventory.CartID(req.HolderID), ); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]any{"status": "released", "holderId": req.HolderID}) }