Files
go-cart-actor/cmd/inventory/reservations.go
T
mats 46be260fcc
Build and Publish / BuildAndDeployArm64 (push) Failing after 6s
Build and Publish / BuildAndDeployAmd64 (push) Failing after 4s
refactor
2026-06-29 12:34:58 +02:00

99 lines
2.9 KiB
Go

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})
}