Co-authored-by: matst80 <mats.tornberg@gmail.com> Reviewed-on: #8 Co-authored-by: Mats Törnberg <mats@tornberg.me> Co-committed-by: Mats Törnberg <mats@tornberg.me>
81 lines
2.2 KiB
Go
81 lines
2.2 KiB
Go
package cart
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
messages "git.k6n.net/go-cart-actor/proto/cart"
|
|
)
|
|
|
|
// mutation_change_quantity.go
|
|
//
|
|
// Registers the ChangeQuantity mutation.
|
|
//
|
|
// Behavior:
|
|
// - Locates an item by its cart-local line item Id (not source item_id).
|
|
// - If requested quantity <= 0 the line is removed.
|
|
// - Otherwise the line's Quantity field is updated.
|
|
// - Totals are recalculated (WithTotals).
|
|
//
|
|
// Error handling:
|
|
// - Returns an error if the item Id is not found.
|
|
// - Returns an error if payload is nil (defensive).
|
|
//
|
|
// Concurrency:
|
|
// - Uses the grain's RW-safe mutation pattern: we mutate in place under
|
|
// the grain's implicit expectation that higher layers control access.
|
|
// (If strict locking is required around every mutation, wrap logic in
|
|
// an explicit g.mu.Lock()/Unlock(), but current model mirrors prior code.)
|
|
|
|
func (c *CartMutationContext) ChangeQuantity(g *CartGrain, m *messages.ChangeQuantity) error {
|
|
if m == nil {
|
|
return fmt.Errorf("ChangeQuantity: nil payload")
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
foundIndex := -1
|
|
for i, it := range g.Items {
|
|
if it.Id == uint32(m.Id) {
|
|
foundIndex = i
|
|
break
|
|
}
|
|
}
|
|
if foundIndex == -1 {
|
|
return fmt.Errorf("ChangeQuantity: item id %d not found", m.Id)
|
|
}
|
|
|
|
if m.Quantity <= 0 {
|
|
// Remove the item
|
|
itemToRemove := g.Items[foundIndex]
|
|
err := c.ReleaseItem(ctx, g.Id, itemToRemove.Sku, itemToRemove.StoreId)
|
|
if err != nil {
|
|
log.Printf("unable to release reservation for %s in location: %v", itemToRemove.Sku, itemToRemove.StoreId)
|
|
}
|
|
g.Items = append(g.Items[:foundIndex], g.Items[foundIndex+1:]...)
|
|
g.UpdateTotals()
|
|
return nil
|
|
}
|
|
item := g.Items[foundIndex]
|
|
if item == nil {
|
|
return fmt.Errorf("ChangeQuantity: item id %d not found", m.Id)
|
|
}
|
|
if item.ReservationEndTime != nil {
|
|
err := c.ReleaseItem(ctx, g.Id, item.Sku, item.StoreId)
|
|
if err != nil {
|
|
log.Printf("unable to release reservation for %s in location: %v", item.Sku, item.StoreId)
|
|
}
|
|
|
|
}
|
|
endTime, err := c.ReserveItem(ctx, g.Id, item.Sku, item.StoreId, uint16(m.Quantity))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
item.ReservationEndTime = endTime
|
|
item.Quantity = uint16(m.Quantity)
|
|
g.UpdateTotals()
|
|
|
|
return nil
|
|
}
|