package cart import ( "fmt" messages "git.tornberg.me/go-cart-actor/pkg/messages" ) // mutation_add_item.go // // Registers the AddItem cart mutation in the generic mutation registry. // This replaces the legacy switch-based logic previously found in CartGrain.Apply. // // Behavior: // * Validates quantity > 0 // * If an item with same SKU exists -> increases quantity // * Else creates a new CartItem with computed tax amounts // * Totals recalculated automatically via WithTotals() // // NOTE: Any future field additions in messages.AddItem that affect pricing / tax // must keep this handler in sync. func AddItem(g *CartGrain, m *messages.AddItem) error { if m == nil { return fmt.Errorf("AddItem: nil payload") } if m.Quantity < 1 { return fmt.Errorf("AddItem: invalid quantity %d", m.Quantity) } // Merge with any existing item having same SKU and matching StoreId (including both nil). for _, existing := range g.Items { if existing.Sku != m.Sku { continue } sameStore := (existing.StoreId == nil && m.StoreId == nil) || (existing.StoreId != nil && m.StoreId != nil && *existing.StoreId == *m.StoreId) if !sameStore { continue } existing.Quantity += int(m.Quantity) existing.Stock = StockStatus(m.Stock) // If existing had nil store but new has one, adopt it. if existing.StoreId == nil && m.StoreId != nil { existing.StoreId = m.StoreId } return nil } g.mu.Lock() defer g.mu.Unlock() g.lastItemId++ taxRate := float32(25.0) if m.Tax > 0 { taxRate = float32(int(m.Tax) / 100) } pricePerItem := NewPriceFromIncVat(m.Price, taxRate) g.Items = append(g.Items, &CartItem{ Id: g.lastItemId, ItemId: uint32(m.ItemId), Quantity: int(m.Quantity), Sku: m.Sku, Tax: int(taxRate * 100), Meta: &ItemMeta{ Name: m.Name, Image: m.Image, Brand: m.Brand, Category: m.Category, Category2: m.Category2, Category3: m.Category3, Category4: m.Category4, Category5: m.Category5, Outlet: m.Outlet, SellerId: m.SellerId, SellerName: m.SellerName, Cgm: m.Cgm, }, SaleStatus: m.SaleStatus, ParentId: m.ParentId, Price: *pricePerItem, TotalPrice: *MultiplyPrice(*pricePerItem, int64(m.Quantity)), Stock: StockStatus(m.Stock), Disclaimer: m.Disclaimer, OrgPrice: getOrgPrice(m.OrgPrice, taxRate), ArticleType: m.ArticleType, StoreId: m.StoreId, }) g.UpdateTotals() return nil } func getOrgPrice(orgPrice int64, taxRate float32) *Price { if orgPrice <= 0 { return nil } return NewPriceFromIncVat(orgPrice, taxRate) }