Stop silently dropping order line items
Every order created after orderheaderid 146119 had zero rows in orderdetails — the header saved fine but items never made it in, which also meant the stock pre-validation loop (it iterates over data.Items) never ran, so an order could go through without ever checking stock. Root cause: whichever client is sending these sends items as a sibling of "orders" rather than nested inside it, a shape neither existing parse strategy captures, so encoding/json silently dropped it. Add a third parse fallback for that sibling-items shape, and reject any order with zero items outright instead of letting it through as a phantom header-only row. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -303,6 +303,24 @@ func (ctl *OrderController) CreateOrderv3(c *fiber.Ctx) error {
|
||||
}
|
||||
}
|
||||
|
||||
// 🛠️ Strategy 3: some clients send the header under "orders" but the line
|
||||
// items as a SIBLING top-level "items" array rather than nested inside
|
||||
// it. Strategy 2's OrderWrapper only has an "orders" field, so
|
||||
// encoding/json silently drops that sibling key — the order header
|
||||
// parses fine but data.Items ends up empty, which used to let the order
|
||||
// go through with zero items and skip the stock check entirely (the
|
||||
// pre-validation loop below iterates over data.Items). Pick it up here
|
||||
// if strategies 1/2 left Items empty.
|
||||
if len(data.Items) == 0 {
|
||||
type ItemsWrapper struct {
|
||||
Items []models.OrderDetail `json:"items"`
|
||||
}
|
||||
var itemsWrapper ItemsWrapper
|
||||
if err := c.BodyParser(&itemsWrapper); err == nil && len(itemsWrapper.Items) > 0 {
|
||||
data.Items = itemsWrapper.Items
|
||||
}
|
||||
}
|
||||
|
||||
// Double check we have the required ID
|
||||
if data.Tenantid == 0 {
|
||||
return c.Status(http.StatusConflict).JSON(fiber.Map{
|
||||
@@ -312,6 +330,18 @@ func (ctl *OrderController) CreateOrderv3(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
// An order with no line items has nothing to check stock against — the
|
||||
// pre-validation loop in CreateOrder simply wouldn't run, silently
|
||||
// creating a phantom header-only order that never deducted stock.
|
||||
// Reject it outright instead.
|
||||
if len(data.Items) == 0 {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest,
|
||||
"message": "Order must contain at least one item",
|
||||
"status": false,
|
||||
})
|
||||
}
|
||||
|
||||
if strings.TrimSpace(data.Orderdate) == "" {
|
||||
data.Orderdate = time.Now().Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user