104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
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,
|
|
},
|
|
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)
|
|
}
|