From 6c44a03dd1338d4d3aad656a4f670225e8e36487 Mon Sep 17 00:00:00 2001 From: matst80 Date: Tue, 14 Oct 2025 09:10:01 +0200 Subject: [PATCH] test add vouchers and shared service --- cmd/cart/cart-grain.go | 24 +++++++------ cmd/cart/main.go | 10 +++++- cmd/cart/mutation_add_voucher.go | 26 ++++++++++++++ cmd/cart/pool-server.go | 15 ++++++++ pkg/messages/messages.pb.go | 59 ++++++++++++++++++++++++++++---- pkg/voucher/service.go | 32 +++++++++++++++++ proto/messages.proto | 4 +++ 7 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 cmd/cart/mutation_add_voucher.go create mode 100644 pkg/voucher/service.go diff --git a/cmd/cart/cart-grain.go b/cmd/cart/cart-grain.go index ca4faca..41fd0ab 100644 --- a/cmd/cart/cart-grain.go +++ b/cmd/cart/cart-grain.go @@ -8,6 +8,7 @@ import ( "time" messages "git.tornberg.me/go-cart-actor/pkg/messages" + "git.tornberg.me/go-cart-actor/pkg/voucher" ) // Legacy padded [16]byte CartId and its helper methods removed. @@ -63,17 +64,18 @@ type CartGrain struct { lastItemId int lastDeliveryId int lastAccess time.Time - lastChange time.Time // unix seconds of last successful mutation (replay sets from event ts) - Id CartId `json:"id"` - Items []*CartItem `json:"items"` - TotalPrice int64 `json:"totalPrice"` - TotalTax int64 `json:"totalTax"` - TotalDiscount int64 `json:"totalDiscount"` - Deliveries []*CartDelivery `json:"deliveries,omitempty"` - Processing bool `json:"processing"` - PaymentInProgress bool `json:"paymentInProgress"` - OrderReference string `json:"orderReference,omitempty"` - PaymentStatus string `json:"paymentStatus,omitempty"` + lastChange time.Time // unix seconds of last successful mutation (replay sets from event ts) + Id CartId `json:"id"` + Items []*CartItem `json:"items"` + TotalPrice int64 `json:"totalPrice"` + TotalTax int64 `json:"totalTax"` + TotalDiscount int64 `json:"totalDiscount"` + Deliveries []*CartDelivery `json:"deliveries,omitempty"` + Processing bool `json:"processing"` + PaymentInProgress bool `json:"paymentInProgress"` + OrderReference string `json:"orderReference,omitempty"` + PaymentStatus string `json:"paymentStatus,omitempty"` + Vouchers []*voucher.Voucher `json:"vouchers,omitempty"` } func (c *CartGrain) GetId() uint64 { diff --git a/cmd/cart/main.go b/cmd/cart/main.go index 8135bce..b452330 100644 --- a/cmd/cart/main.go +++ b/cmd/cart/main.go @@ -16,6 +16,7 @@ import ( "git.tornberg.me/go-cart-actor/pkg/discovery" messages "git.tornberg.me/go-cart-actor/pkg/messages" "git.tornberg.me/go-cart-actor/pkg/proxy" + "git.tornberg.me/go-cart-actor/pkg/voucher" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -92,10 +93,14 @@ func GetDiscovery() discovery.Discovery { return discovery.NewK8sDiscovery(client) } +type MutationContext struct { + VoucherService voucher.Service +} + func main() { controlPlaneConfig := actor.DefaultServerConfig() - + ctx := MutationContext{} reg := actor.NewMutationRegistry() reg.RegisterMutations( actor.NewMutation(AddItem, func() *messages.AddItem { @@ -125,6 +130,9 @@ func main() { actor.NewMutation(ClearCart, func() *messages.ClearCartRequest { return &messages.ClearCartRequest{} }), + actor.NewMutation(ctx.AddVoucher, func() *messages.AddVoucher { + return &messages.AddVoucher{} + }), ) diskStorage := actor.NewDiskStorage[CartGrain]("data", reg) poolConfig := actor.GrainPoolConfig[CartGrain]{ diff --git a/cmd/cart/mutation_add_voucher.go b/cmd/cart/mutation_add_voucher.go new file mode 100644 index 0000000..0c24f9a --- /dev/null +++ b/cmd/cart/mutation_add_voucher.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + + "git.tornberg.me/go-cart-actor/pkg/messages" +) + +func (ctx *MutationContext) AddVoucher(g *CartGrain, m *messages.AddVoucher) error { + if m == nil { + return fmt.Errorf("AddVoucher: nil payload") + } + + voucher, err := ctx.VoucherService.GetVoucher(m.Code) + if err != nil { + return fmt.Errorf("AddVoucher: %w", err) + } + + if voucher == nil { + return nil + } + + g.Vouchers = append(g.Vouchers, voucher) + g.UpdateTotals() + return nil +} diff --git a/cmd/cart/pool-server.go b/cmd/cart/pool-server.go index 6d84e0f..fa6fd45 100644 --- a/cmd/cart/pool-server.go +++ b/cmd/cart/pool-server.go @@ -437,6 +437,19 @@ func (s *PoolServer) ProxyHandler(fn func(w http.ResponseWriter, r *http.Request } } +func (s *PoolServer) AddVoucherHandler(w http.ResponseWriter, r *http.Request, cartId CartId) error { + msg := &messages.AddVoucher{} + json.NewDecoder(r.Body).Decode(msg) + reply, err := s.Apply(uint64(cartId), msg) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return err + } + s.WriteResult(w, reply) + return nil +} + func (s *PoolServer) Serve() *http.ServeMux { mux := http.NewServeMux() @@ -458,6 +471,8 @@ func (s *PoolServer) Serve() *http.ServeMux { mux.HandleFunc("POST /delivery", CookieCartIdHandler(s.ProxyHandler(s.SetDeliveryHandler))) mux.HandleFunc("DELETE /delivery/{deliveryId}", CookieCartIdHandler(s.ProxyHandler(s.RemoveDeliveryHandler))) mux.HandleFunc("PUT /delivery/{deliveryId}/pickupPoint", CookieCartIdHandler(s.ProxyHandler(s.SetPickupPointHandler))) + mux.HandleFunc("PUT /voucher", CookieCartIdHandler(s.ProxyHandler(s.AddVoucherHandler))) + //mux.HandleFunc("GET /checkout", CookieCartIdHandler(s.ProxyHandler(s.HandleCheckout))) //mux.HandleFunc("GET /confirmation/{orderId}", CookieCartIdHandler(s.ProxyHandler(s.HandleConfirmation))) diff --git a/pkg/messages/messages.pb.go b/pkg/messages/messages.pb.go index 5c8d1f8..b88f5a2 100644 --- a/pkg/messages/messages.pb.go +++ b/pkg/messages/messages.pb.go @@ -977,6 +977,50 @@ func (x *InitializeCheckout) GetPaymentInProgress() bool { return false } +type AddVoucher struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddVoucher) Reset() { + *x = AddVoucher{} + mi := &file_messages_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddVoucher) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddVoucher) ProtoMessage() {} + +func (x *AddVoucher) ProtoReflect() protoreflect.Message { + mi := &file_messages_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddVoucher.ProtoReflect.Descriptor instead. +func (*AddVoucher) Descriptor() ([]byte, []int) { + return file_messages_proto_rawDescGZIP(), []int{13} +} + +func (x *AddVoucher) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + var File_messages_proto protoreflect.FileDescriptor var file_messages_proto_rawDesc = string([]byte{ @@ -1107,10 +1151,12 @@ var file_messages_proto_rawDesc = string([]byte{ 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x2e, 0x74, 0x6f, 0x72, 0x6e, 0x62, - 0x65, 0x72, 0x67, 0x2e, 0x6d, 0x65, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x61, 0x72, 0x74, 0x2d, 0x61, - 0x63, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x73, 0x22, 0x20, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x56, 0x6f, 0x75, 0x63, 0x68, 0x65, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x2e, 0x74, 0x6f, 0x72, + 0x6e, 0x62, 0x65, 0x72, 0x67, 0x2e, 0x6d, 0x65, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x61, 0x72, 0x74, + 0x2d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -1125,7 +1171,7 @@ func file_messages_proto_rawDescGZIP() []byte { return file_messages_proto_rawDescData } -var file_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 14) var file_messages_proto_goTypes = []any{ (*AddRequest)(nil), // 0: messages.AddRequest (*ClearCartRequest)(nil), // 1: messages.ClearCartRequest @@ -1140,6 +1186,7 @@ var file_messages_proto_goTypes = []any{ (*OrderCreated)(nil), // 10: messages.OrderCreated (*Noop)(nil), // 11: messages.Noop (*InitializeCheckout)(nil), // 12: messages.InitializeCheckout + (*AddVoucher)(nil), // 13: messages.AddVoucher } var file_messages_proto_depIdxs = []int32{ 7, // 0: messages.SetDelivery.pickupPoint:type_name -> messages.PickupPoint @@ -1166,7 +1213,7 @@ func file_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_messages_proto_rawDesc), len(file_messages_proto_rawDesc)), NumEnums: 0, - NumMessages: 13, + NumMessages: 14, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/voucher/service.go b/pkg/voucher/service.go new file mode 100644 index 0000000..ab6f16d --- /dev/null +++ b/pkg/voucher/service.go @@ -0,0 +1,32 @@ +package voucher + +import "math" + +type Rule struct { + Type string `json:"type"` + Value int64 `json:"value"` +} + +type Voucher struct { + Code string `json:"code"` + Value int64 `json:"discount"` + TaxValue int64 `json:"taxValue"` + TaxRate int `json:"taxRate"` + rules []Rule `json:"rules"` +} + +type Service struct { + // Add fields here + +} + +func (s *Service) GetVoucher(code string) (*Voucher, error) { + value := int64(math.Round(100 * math.Pow(10, 2))) + return &Voucher{ + Code: code, + Value: value, + TaxValue: int64(float64(value) * 0.2), + TaxRate: 2500, + rules: nil, + }, nil +} diff --git a/proto/messages.proto b/proto/messages.proto index 1640d81..cefa63b 100644 --- a/proto/messages.proto +++ b/proto/messages.proto @@ -103,3 +103,7 @@ message InitializeCheckout { string status = 2; bool paymentInProgress = 3; } + +message AddVoucher { + string code = 1; +}