even more refactoring
Some checks failed
Build and Publish / BuildAndDeploy (push) Successful in 3m7s
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled

This commit is contained in:
matst80
2025-10-10 11:46:19 +00:00
parent 12d87036f6
commit 716f1121aa
32 changed files with 3857 additions and 953 deletions

View File

@@ -1,11 +1,8 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"slices"
"sync"
messages "git.tornberg.me/go-cart-actor/proto"
@@ -265,235 +262,14 @@ func GetTaxAmount(total int64, tax int) int64 {
func (c *CartGrain) Apply(content interface{}, isReplay bool) (*CartGrain, error) {
grainMutations.Inc()
switch msg := content.(type) {
case *messages.SetCartRequest:
c.mu.Lock()
c.Items = make([]*CartItem, 0, len(msg.Items))
c.mu.Unlock()
for _, it := range msg.Items {
c.AddItem(it.Sku, int(it.Quantity), it.Country, it.StoreId)
updated, err := ApplyRegistered(c, content)
if err != nil {
if err == ErrMutationNotRegistered {
return nil, fmt.Errorf("unsupported mutation type %T (not registered)", content)
}
case *messages.AddRequest:
if existing, found := c.FindItemWithSku(msg.Sku); found {
existing.Quantity += int(msg.Quantity)
c.UpdateTotals()
} else {
return c.AddItem(msg.Sku, int(msg.Quantity), msg.Country, msg.StoreId)
}
case *messages.AddItem:
if msg.Quantity < 1 {
return nil, fmt.Errorf("invalid quantity")
}
if existing, found := c.FindItemWithSku(msg.Sku); found {
existing.Quantity += int(msg.Quantity)
c.UpdateTotals()
} else {
c.mu.Lock()
c.lastItemId++
tax := 2500
if msg.Tax > 0 {
tax = int(msg.Tax)
}
taxAmount := GetTaxAmount(msg.Price, tax)
c.Items = append(c.Items, &CartItem{
Id: c.lastItemId,
ItemId: int(msg.ItemId),
Quantity: int(msg.Quantity),
Sku: msg.Sku,
Name: msg.Name,
Price: msg.Price,
TotalPrice: msg.Price * int64(msg.Quantity),
TotalTax: int64(taxAmount * int64(msg.Quantity)),
Image: msg.Image,
Stock: StockStatus(msg.Stock),
Disclaimer: msg.Disclaimer,
Brand: msg.Brand,
Category: msg.Category,
Category2: msg.Category2,
Category3: msg.Category3,
Category4: msg.Category4,
Category5: msg.Category5,
OrgPrice: msg.OrgPrice,
ArticleType: msg.ArticleType,
Outlet: msg.Outlet,
SellerId: msg.SellerId,
SellerName: msg.SellerName,
Tax: int(taxAmount),
TaxRate: tax,
StoreId: msg.StoreId,
})
c.UpdateTotals()
c.mu.Unlock()
}
case *messages.ChangeQuantity:
for i, item := range c.Items {
if item.Id == int(msg.Id) {
if msg.Quantity <= 0 {
c.Items = append(c.Items[:i], c.Items[i+1:]...)
} else {
item.Quantity = int(msg.Quantity)
}
break
}
}
c.UpdateTotals()
case *messages.RemoveItem:
newItems := make([]*CartItem, 0, len(c.Items))
for _, it := range c.Items {
if it.Id != int(msg.Id) {
newItems = append(newItems, it)
}
}
c.Items = newItems
c.UpdateTotals()
case *messages.SetDelivery:
c.lastDeliveryId++
items := make([]int, 0)
withDelivery := c.ItemsWithDelivery()
if len(msg.Items) == 0 {
items = append(items, c.ItemsWithoutDelivery()...)
} else {
for _, id := range msg.Items {
for _, it := range c.Items {
if it.Id == int(id) {
if slices.Contains(withDelivery, it.Id) {
return nil, fmt.Errorf("item already has delivery")
}
items = append(items, int(it.Id))
break
}
}
}
}
if len(items) > 0 {
c.Deliveries = append(c.Deliveries, &CartDelivery{
Id: c.lastDeliveryId,
Provider: msg.Provider,
PickupPoint: msg.PickupPoint,
Price: 4900,
Items: items,
})
c.UpdateTotals()
}
case *messages.RemoveDelivery:
dels := make([]*CartDelivery, 0, len(c.Deliveries))
for _, d := range c.Deliveries {
if d.Id == int(msg.Id) {
c.TotalPrice -= d.Price
} else {
dels = append(dels, d)
}
}
c.Deliveries = dels
c.UpdateTotals()
case *messages.SetPickupPoint:
for _, d := range c.Deliveries {
if d.Id == int(msg.DeliveryId) {
d.PickupPoint = &messages.PickupPoint{
Id: msg.Id,
Address: msg.Address,
City: msg.City,
Zip: msg.Zip,
Country: msg.Country,
Name: msg.Name,
}
break
}
}
case *messages.CreateCheckoutOrder:
orderLines := make([]*Line, 0, len(c.Items))
c.PaymentInProgress = true
c.Processing = true
for _, item := range c.Items {
orderLines = append(orderLines, &Line{
Type: "physical",
Reference: item.Sku,
Name: item.Name,
Quantity: item.Quantity,
UnitPrice: int(item.Price),
TaxRate: 2500,
QuantityUnit: "st",
TotalAmount: int(item.TotalPrice),
TotalTaxAmount: int(item.TotalTax),
ImageURL: fmt.Sprintf("https://www.elgiganten.se%s", item.Image),
})
}
for _, line := range c.Deliveries {
if line.Price > 0 {
orderLines = append(orderLines, &Line{
Type: "shipping_fee",
Reference: line.Provider,
Name: "Delivery",
Quantity: 1,
UnitPrice: int(line.Price),
TaxRate: 2500,
QuantityUnit: "st",
TotalAmount: int(line.Price),
TotalTaxAmount: int(GetTaxAmount(line.Price, 2500)),
})
}
}
order := CheckoutOrder{
PurchaseCountry: "SE",
PurchaseCurrency: "SEK",
Locale: "sv-se",
OrderAmount: int(c.TotalPrice),
OrderTaxAmount: int(c.TotalTax),
OrderLines: orderLines,
MerchantReference1: c.Id.String(),
MerchantURLS: &CheckoutMerchantURLS{
Terms: msg.Terms,
Checkout: msg.Checkout,
Confirmation: msg.Confirmation,
Validation: msg.Validation,
Push: msg.Push,
},
}
orderPayload, err := json.Marshal(order)
if err != nil {
return nil, err
}
var klarnaOrder *CheckoutOrder
var klarnaError error
if c.OrderReference != "" {
log.Printf("Updating order id %s", c.OrderReference)
klarnaOrder, klarnaError = KlarnaInstance.UpdateOrder(c.OrderReference, bytes.NewReader(orderPayload))
} else {
klarnaOrder, klarnaError = KlarnaInstance.CreateOrder(bytes.NewReader(orderPayload))
}
if klarnaError != nil {
log.Printf("error from klarna: %v", klarnaError)
return nil, klarnaError
}
if c.OrderReference == "" {
c.OrderReference = klarnaOrder.ID
c.PaymentStatus = klarnaOrder.Status
}
// This originally returned a FrameWithPayload; now returns the grain state.
// The caller (gRPC handler) is responsible for wrapping this.
return c, nil
case *messages.OrderCreated:
c.OrderReference = msg.OrderId
c.PaymentStatus = msg.Status
c.PaymentInProgress = false
default:
return nil, fmt.Errorf("unsupported mutation type %T", content)
return nil, err
}
// (Optional) Append to new storage mechanism here if still required.
return c, nil
return updated, nil
}
func (c *CartGrain) UpdateTotals() {