package main import ( "fmt" messages "git.tornberg.me/go-cart-actor/pkg/messages" ) // mutation_add_request.go // // Registers the AddRequest mutation. This mutation is a higher-level intent // (add by SKU + quantity) which may translate into either: // - Increasing quantity of an existing line (same SKU), OR // - Creating a new item by performing a product lookup (via getItemData inside CartGrain.AddItem) // // Behavior: // - Validates non-empty SKU and quantity > 0 // - If an item with the SKU already exists: increments its quantity // - Else delegates to CartGrain.AddItem (which itself produces an AddItem mutation) // - Totals recalculated automatically (WithTotals) // // NOTE: // - This handler purposely avoids duplicating the detailed AddItem logic; // it reuses CartGrain.AddItem which then flows through the AddItem mutation // registry handler. // - Double total recalculation can occur (AddItem has WithTotals too), but // is acceptable for clarity. Optimize later if needed. // // Potential future improvements: // - Stock validation before increasing quantity // - Reservation logic or concurrency guards around stock updates // - Coupon / pricing rules applied conditionally during add-by-sku func init() { RegisterMutation[messages.AddRequest]( "AddRequest", func(g *CartGrain, m *messages.AddRequest) error { if m == nil { return fmt.Errorf("AddRequest: nil payload") } if m.Sku == "" { return fmt.Errorf("AddRequest: sku is empty") } if m.Quantity < 1 { return fmt.Errorf("AddRequest: invalid quantity %d", m.Quantity) } // Existing line: accumulate quantity only. if existing, found := g.FindItemWithSku(m.Sku); found { existing.Quantity += int(m.Quantity) return nil } // New line: delegate to higher-level AddItem flow (product lookup). // We intentionally ignore the returned *CartGrain; registry will // do totals again after this handler returns (harmless). _, err := g.AddItem(m.Sku, int(m.Quantity), m.Country, m.StoreId) return err }, WithTotals(), ) }