bulk request and approve
This commit is contained in:
@@ -18,22 +18,59 @@ func NewStockRequestController(stockRequestService services.StockRequestService)
|
||||
return &StockRequestController{stockRequestService: stockRequestService}
|
||||
}
|
||||
|
||||
// CreateStockRequest accepts one request or a list of them.
|
||||
//
|
||||
// A shop restocking after a delivery is asking for twenty things at once, and
|
||||
// sending twenty HTTP requests to say so is slow, gives no single answer, and
|
||||
// leaves a half-sent batch behind when the connection drops. The single-object
|
||||
// form is unchanged, so every existing caller keeps working.
|
||||
//
|
||||
// Each row is reported individually rather than the batch failing whole: a
|
||||
// request for a product that no longer exists should not discard the other
|
||||
// nineteen, and the requester needs to know WHICH one it was.
|
||||
func (ctl *StockRequestController) CreateStockRequest(c *fiber.Ctx) error {
|
||||
var input models.StockRequest
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
inputs, err := parseStockRequests(c)
|
||||
if err != nil {
|
||||
return c.JSON(fiber.Map{"code": http.StatusBadRequest, "message": "Invalid input", "status": false})
|
||||
}
|
||||
|
||||
if input.Status == "" {
|
||||
input.Status = "Pending"
|
||||
if len(inputs) == 0 {
|
||||
return c.JSON(fiber.Map{"code": http.StatusBadRequest, "message": "send at least one request", "status": false})
|
||||
}
|
||||
|
||||
err := ctl.stockRequestService.CreateStockRequest(&input)
|
||||
if err != nil {
|
||||
return c.JSON(fiber.Map{"code": http.StatusInternalServerError, "message": err.Error(), "status": false})
|
||||
created := make([]models.StockRequest, 0, len(inputs))
|
||||
failed := make([]fiber.Map, 0)
|
||||
|
||||
for i := range inputs {
|
||||
if inputs[i].Status == "" {
|
||||
inputs[i].Status = "Pending"
|
||||
}
|
||||
if err := ctl.stockRequestService.CreateStockRequest(&inputs[i]); err != nil {
|
||||
failed = append(failed, fiber.Map{
|
||||
"productid": inputs[i].Productid,
|
||||
"reason": err.Error(),
|
||||
})
|
||||
continue
|
||||
}
|
||||
created = append(created, inputs[i])
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"code": 200, "message": "Stock request created", "status": true, "details": input})
|
||||
// A single-object caller gets the object back, exactly as before.
|
||||
if len(inputs) == 1 && len(failed) == 0 {
|
||||
return c.JSON(fiber.Map{"code": 200, "message": "Stock request created", "status": true, "details": created[0]})
|
||||
}
|
||||
|
||||
if len(created) == 0 {
|
||||
return c.JSON(fiber.Map{
|
||||
"code": http.StatusInternalServerError, "status": false,
|
||||
"message": "no requests could be created", "details": fiber.Map{"failed": failed},
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"code": 200, "status": true,
|
||||
"message": stockBatchMessage(len(created), len(failed), "created"),
|
||||
"details": fiber.Map{"created": created, "failed": failed},
|
||||
})
|
||||
}
|
||||
|
||||
func (ctl *StockRequestController) GetStockRequests(c *fiber.Ctx) error {
|
||||
@@ -52,19 +89,70 @@ func (ctl *StockRequestController) GetStockRequests(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{"code": 200, "message": "Success", "status": true, "details": data})
|
||||
}
|
||||
|
||||
// UpdateStockRequest decides one request or a batch of them.
|
||||
//
|
||||
// `requestid` for one, `requestids` for many, one status for the batch. That
|
||||
// shape rather than a list of {id,status} pairs because the action a merchant
|
||||
// takes is "approve these" or "reject these" — a mixed batch is two actions,
|
||||
// and letting one call do both makes an accidental mass-approve possible.
|
||||
//
|
||||
// Approving is not a status write: the service adds the requested quantity to
|
||||
// the branch’s stock. So each id is applied on its own and reported on its own.
|
||||
// If the fourth of ten fails, the first three have really been received and the
|
||||
// merchant has to know that, rather than being told the batch failed and
|
||||
// approving it a second time.
|
||||
func (ctl *StockRequestController) UpdateStockRequest(c *fiber.Ctx) error {
|
||||
var input struct {
|
||||
RequestID int `json:"requestid"`
|
||||
Status string `json:"status"`
|
||||
RequestID int `json:"requestid"`
|
||||
RequestIDs []int `json:"requestids"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.JSON(fiber.Map{"code": http.StatusBadRequest, "message": "Invalid input", "status": false})
|
||||
}
|
||||
|
||||
err := ctl.stockRequestService.UpdateStockRequest(input.RequestID, input.Status)
|
||||
if err != nil {
|
||||
return c.JSON(fiber.Map{"code": http.StatusInternalServerError, "message": err.Error(), "status": false})
|
||||
if input.Status == "" {
|
||||
return c.JSON(fiber.Map{"code": http.StatusBadRequest, "status": false,
|
||||
"message": "status is required"})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"code": 200, "message": "Stock request updated", "status": true})
|
||||
ids := input.RequestIDs
|
||||
if input.RequestID != 0 {
|
||||
ids = append([]int{input.RequestID}, ids...)
|
||||
}
|
||||
ids = dedupeIDs(ids)
|
||||
if len(ids) == 0 {
|
||||
return c.JSON(fiber.Map{"code": http.StatusBadRequest, "status": false,
|
||||
"message": "send requestid, or requestids for several"})
|
||||
}
|
||||
|
||||
updated := make([]int, 0, len(ids))
|
||||
failed := make([]fiber.Map, 0)
|
||||
for _, id := range ids {
|
||||
if err := ctl.stockRequestService.UpdateStockRequest(id, input.Status); err != nil {
|
||||
failed = append(failed, fiber.Map{"requestid": id, "reason": err.Error()})
|
||||
continue
|
||||
}
|
||||
updated = append(updated, id)
|
||||
}
|
||||
|
||||
// The single-id caller keeps the answer it has always had.
|
||||
if len(ids) == 1 {
|
||||
if len(failed) > 0 {
|
||||
return c.JSON(fiber.Map{"code": http.StatusInternalServerError, "status": false,
|
||||
"message": failed[0]["reason"]})
|
||||
}
|
||||
return c.JSON(fiber.Map{"code": 200, "message": "Stock request updated", "status": true})
|
||||
}
|
||||
|
||||
if len(updated) == 0 {
|
||||
return c.JSON(fiber.Map{"code": http.StatusInternalServerError, "status": false,
|
||||
"message": "no requests could be updated", "details": fiber.Map{"failed": failed}})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"code": 200, "status": true,
|
||||
"message": stockBatchMessage(len(updated), len(failed), "updated"),
|
||||
"details": fiber.Map{"updated": updated, "failed": failed},
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user