diff --git a/cart-grain.go b/cart-grain.go index a482871..ca97cc4 100644 --- a/cart-grain.go +++ b/cart-grain.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "slices" "time" messages "git.tornberg.me/go-cart-actor/proto" @@ -118,6 +119,43 @@ func (c *CartGrain) GetStorageMessage(since int64) []StorableMessage { return ret } +func (c *CartGrain) GetState() ([]byte, error) { + return json.Marshal(c) +} + +func (c *CartGrain) ItemsWithDelivery() []int { + ret := make([]int, 0, len(c.Items)) + for _, item := range c.Items { + for _, delivery := range c.Deliveries { + for _, id := range delivery.Items { + if item.Id == id { + ret = append(ret, id) + } + } + } + } + return ret +} + +func (c *CartGrain) ItemsWithoutDelivery() []int { + ret := make([]int, 0, len(c.Items)) + hasDelivery := c.ItemsWithDelivery() + for _, item := range c.Items { + found := false + for _, id := range hasDelivery { + if item.Id == id { + found = true + break + } + } + + if !found { + ret = append(ret, item.Id) + } + } + return ret +} + func (c *CartGrain) HandleMessage(message *Message, isReplay bool) ([]byte, error) { if message.TimeStamp == nil { now := time.Now().Unix() @@ -195,18 +233,26 @@ func (c *CartGrain) HandleMessage(message *Message, isReplay bool) ([]byte, erro } } } - case AddDeliveryType: + case SetDeliveryType: msg, ok := message.Content.(*messages.SetDelivery) if !ok { err = fmt.Errorf("expected SetDelivery") } else { c.lastDeliveryId++ items := make([]int, 0) - for _, id := range msg.Items { - for _, item := range c.Items { - if item.Id == int(id) { - items = append(items, int(item.Id)) - break + withDelivery := c.ItemsWithDelivery() + if len(msg.Items) == 0 { + items = append(items, c.ItemsWithoutDelivery()...) + } else { + for _, id := range msg.Items { + for _, item := range c.Items { + if item.Id == int(id) { + if slices.Contains(withDelivery, item.Id) { + return nil, fmt.Errorf("item already has delivery") + } + items = append(items, int(item.Id)) + break + } } } } diff --git a/cart-grain_test.go b/cart-grain_test.go index 4b3263b..ccb5961 100644 --- a/cart-grain_test.go +++ b/cart-grain_test.go @@ -7,6 +7,15 @@ import ( messages "git.tornberg.me/go-cart-actor/proto" ) +func GetMessage(t uint16, data interface{}) *Message { + ts := time.Now().Unix() + return &Message{ + TimeStamp: &ts, + Type: t, + Content: data, + } +} + func TestAddToCart(t *testing.T) { grain, err := spawn(ToCartId("kalle")) if err != nil { @@ -15,19 +24,14 @@ func TestAddToCart(t *testing.T) { if len(grain.Items) != 0 { t.Errorf("Expected 0 items, got %d\n", len(grain.Items)) } - addItem := messages.AddItem{ + msg := GetMessage(AddItemType, &messages.AddItem{ Quantity: 2, Price: 100, Sku: "123", Name: "Test item", Image: "test.jpg", - } - ts := time.Now().Unix() - msg := &Message{ - TimeStamp: &ts, - Type: AddItemType, - Content: &addItem, - } + }) + result, err := grain.HandleMessage(msg, false) if err != nil { @@ -59,3 +63,109 @@ func TestAddToCart(t *testing.T) { t.Errorf("Expected total price 400, got %d\n", grain.TotalPrice) } } + +func TestSetDelivery(t *testing.T) { + grain, err := spawn(ToCartId("kalle")) + if err != nil { + t.Errorf("Error spawning: %v\n", err) + } + if len(grain.Items) != 0 { + t.Errorf("Expected 0 items, got %d\n", len(grain.Items)) + } + msg := GetMessage(AddItemType, &messages.AddItem{ + Quantity: 2, + Price: 100, + Sku: "123", + Name: "Test item", + Image: "test.jpg", + }) + + grain.HandleMessage(msg, false) + + msg = GetMessage(AddItemType, &messages.AddItem{ + Quantity: 2, + Price: 100, + Sku: "123", + Name: "Test item", + Image: "test.jpg", + }) + + result, err := grain.HandleMessage(msg, false) + + if err != nil { + t.Errorf("Error handling message: %v\n", err) + } + if len(result) == 0 { + t.Errorf("Expected result, got nil\n") + } + + setDelivery := GetMessage(SetDeliveryType, &messages.SetDelivery{ + Provider: "test", + Items: []int64{1}, + }) + + _, err = grain.HandleMessage(setDelivery, false) + if err != nil { + t.Errorf("Error handling message: %v\n", err) + } + if len(grain.Deliveries) != 1 { + t.Errorf("Expected 1 delivery, got %d\n", len(grain.Deliveries)) + } + if len(grain.Deliveries[0].Items) != 1 { + t.Errorf("Expected 1 items in delivery, got %d\n", len(grain.Deliveries[0].Items)) + } +} + +func TestSetDeliveryOnAll(t *testing.T) { + grain, err := spawn(ToCartId("kalle")) + if err != nil { + t.Errorf("Error spawning: %v\n", err) + } + if len(grain.Items) != 0 { + t.Errorf("Expected 0 items, got %d\n", len(grain.Items)) + } + msg := GetMessage(AddItemType, &messages.AddItem{ + Quantity: 2, + Price: 100, + Sku: "123", + Name: "Test item", + Image: "test.jpg", + }) + + grain.HandleMessage(msg, false) + + msg = GetMessage(AddItemType, &messages.AddItem{ + Quantity: 2, + Price: 100, + Sku: "1233", + Name: "Test item2", + Image: "test.jpg", + }) + + result, err := grain.HandleMessage(msg, false) + + if err != nil { + t.Errorf("Error handling message: %v\n", err) + } + if len(result) == 0 { + t.Errorf("Expected result, got nil\n") + } + + setDelivery := GetMessage(SetDeliveryType, &messages.SetDelivery{ + Provider: "test", + Items: []int64{}, + }) + + _, err = grain.HandleMessage(setDelivery, false) + if err != nil { + t.Errorf("Error handling message: %v\n", err) + } + if len(grain.Deliveries) != 1 { + t.Errorf("Expected 1 delivery, got %d\n", len(grain.Deliveries)) + } + + if len(grain.Deliveries[0].Items) != 2 { + t.Errorf("Expected 2 items in delivery, got %d\n", len(grain.Deliveries[0].Items)) + } + +} diff --git a/message-handler_test.go b/message-handler_test.go index 601806a..9195457 100644 --- a/message-handler_test.go +++ b/message-handler_test.go @@ -88,3 +88,42 @@ func TestItemRequest(t *testing.T) { t.Errorf("Expected sku '123', got %s\n", r.Sku) } } + +func TestSetDeliveryMssage(t *testing.T) { + h, err := GetMessageHandler(SetDeliveryType) + if err != nil { + t.Errorf("Error getting message handler: %v\n", err) + } + if h == nil { + t.Errorf("Expected message handler, got nil\n") + } + message := Message{ + Type: SetDeliveryType, + Content: &messages.SetDelivery{ + Provider: "test", + Items: []int64{1, 2}, + }, + } + var b bytes.Buffer + err = h.Write(&message, &b) + if err != nil { + t.Errorf("Error writing message: %v\n", err) + } + result, err := h.Read(b.Bytes()) + if err != nil { + t.Errorf("Error reading message: %v\n", err) + } + if result == nil { + t.Errorf("Expected result, got nil\n") + } + r, ok := result.(*messages.SetDelivery) + if !ok { + t.Errorf("Expected AddRequest, got %T\n", result) + } + if len(r.Items) != 2 { + t.Errorf("Expected 2 items, got %d\n", len(r.Items)) + } + if r.Provider != "test" { + t.Errorf("Expected provider 'test', got %s\n", r.Provider) + } +} diff --git a/message-types.go b/message-types.go index 6253949..98506fc 100644 --- a/message-types.go +++ b/message-types.go @@ -1,9 +1,9 @@ package main const ( - AddRequestType = 1 - AddItemType = 2 - AddDeliveryType = 3 + AddRequestType = 1 + AddItemType = 2 + //AddDeliveryType = 3 RemoveItemType = 4 RemoveDeliveryType = 5 ChangeQuantityType = 6