diff --git a/README.md b/README.md index 5fa0634..e0a00a1 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,5 @@ # Go Cart Actor -## Migration Notes (Ring-based Ownership Transition) - -This release removes the legacy ConfirmOwner ownership negotiation RPC in favor of deterministic ownership via the consistent hashing ring. - -Summary of changes: -- ConfirmOwner RPC removed from the ControlPlane service. -- OwnerChangeRequest message removed (was only used by ConfirmOwner). -- OwnerChangeAck retained solely as the response type for the Closing RPC. -- SyncedPool now relies exclusively on the ring for ownership (no quorum negotiation). -- Remote proxy creation includes a bounded readiness retry to reduce first-call failures. -- New Prometheus ring metrics: - - cart_ring_epoch - - cart_ring_hosts - - cart_ring_vnodes - - cart_ring_host_share{host} - - cart_ring_lookup_local_total - - cart_ring_lookup_remote_total - -Action required for consumers: -1. Regenerate protobuf code after pulling (requires protoc-gen-go and protoc-gen-go-grpc installed). -2. Remove any client code or automation invoking ConfirmOwner (calls will now return UNIMPLEMENTED if using stale generated stubs). -3. Update monitoring/alerts that referenced ConfirmOwner or ownership quorum failures—use ring metrics instead. -4. If you previously interpreted “ownership flapping” via ConfirmOwner logs, now check for: - - Rapid changes in ring epoch (cart_ring_epoch) - - Host churn (cart_ring_hosts) - - Imbalance in vnode distribution (cart_ring_host_share) - -No data migration is necessary; cart IDs and grain state are unaffected. - ---- - A distributed cart management system using the actor model pattern. ## Prerequisites diff --git a/cmd/cart/pool-server.go b/cmd/cart/pool-server.go index fae39e4..b1be858 100644 --- a/cmd/cart/pool-server.go +++ b/cmd/cart/pool-server.go @@ -470,6 +470,24 @@ func (s *PoolServer) AddVoucherHandler(w http.ResponseWriter, r *http.Request, c return nil } +func (s *PoolServer) SubscriptionDetailsHandler(w http.ResponseWriter, r *http.Request, cartId cart.CartId) error { + data := &messages.UpsertSubscriptionDetails{} + err := json.NewDecoder(r.Body).Decode(data) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return err + } + reply, err := s.ApplyLocal(cartId, data) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return err + } + s.WriteResult(w, reply) + return nil +} + func (s *PoolServer) RemoveVoucherHandler(w http.ResponseWriter, r *http.Request, cartId cart.CartId) error { idStr := r.PathValue("voucherId") @@ -511,6 +529,7 @@ func (s *PoolServer) Serve() *http.ServeMux { 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("PUT /subscription-details", CookieCartIdHandler(s.ProxyHandler(s.SubscriptionDetailsHandler))) mux.HandleFunc("DELETE /voucher/{voucherId}", CookieCartIdHandler(s.ProxyHandler(s.RemoveVoucherHandler))) //mux.HandleFunc("GET /checkout", CookieCartIdHandler(s.ProxyHandler(s.HandleCheckout))) diff --git a/pkg/actor/mutation_registry.go b/pkg/actor/mutation_registry.go index 8b3d59d..72b7f91 100644 --- a/pkg/actor/mutation_registry.go +++ b/pkg/actor/mutation_registry.go @@ -171,11 +171,21 @@ func (r *ProtoMutationRegistry) Apply(grain any, msg ...proto.Message) ([]ApplyR if grain == nil { return results, fmt.Errorf("nil grain") } + // Nil slice of mutations still treated as an error (call contract violation). if msg == nil { return results, fmt.Errorf("nil mutation message") } for _, m := range msg { + // Ignore nil mutation elements (untyped or typed nil pointers) silently; they carry no data. + if m == nil { + continue + } + // Typed nil: interface holds concrete proto message type whose pointer value is nil. + rv := reflect.ValueOf(m) + if rv.Kind() == reflect.Ptr && rv.IsNil() { + continue + } rt := indirectType(reflect.TypeOf(m)) r.mutationRegistryMu.RLock() entry, ok := r.mutationRegistry[rt] @@ -188,10 +198,6 @@ func (r *ProtoMutationRegistry) Apply(grain any, msg ...proto.Message) ([]ApplyR results = append(results, ApplyResult{Error: err, Type: rt.Name(), Mutation: m}) } - // if entry.updateTotals { - // grain.UpdateTotals() - // } - return results, nil } diff --git a/pkg/cart/cart-grain.go b/pkg/cart/cart-grain.go index 85aaed1..373a9f9 100644 --- a/pkg/cart/cart-grain.go +++ b/pkg/cart/cart-grain.go @@ -61,25 +61,33 @@ type CartNotification struct { Content string `json:"content"` } +type SubscriptionDetails struct { + Id string `json:"id"` + OfferingCode string `json:"offeringCode,omitempty"` + SigningType string `json:"signingType,omitempty"` + Meta json.RawMessage `json:"data,omitempty"` +} + type CartGrain struct { - mu sync.RWMutex - lastItemId uint32 - lastDeliveryId uint32 - lastVoucherId uint32 - lastAccess time.Time - lastChange time.Time // unix seconds of last successful mutation (replay sets from event ts) - userId string - Id CartId `json:"id"` - Items []*CartItem `json:"items"` - TotalPrice *Price `json:"totalPrice"` - TotalDiscount *Price `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 `json:"vouchers,omitempty"` - Notifications []CartNotification `json:"cartNotification,omitempty"` + mu sync.RWMutex + lastItemId uint32 + lastDeliveryId uint32 + lastVoucherId uint32 + lastAccess time.Time + lastChange time.Time // unix seconds of last successful mutation (replay sets from event ts) + userId string + Id CartId `json:"id"` + Items []*CartItem `json:"items"` + TotalPrice *Price `json:"totalPrice"` + TotalDiscount *Price `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 `json:"vouchers,omitempty"` + Notifications []CartNotification `json:"cartNotification,omitempty"` + SubscriptionDetails map[string]*SubscriptionDetails `json:"subscriptionDetails,omitempty"` } type Voucher struct { @@ -139,17 +147,18 @@ func (v *Voucher) AppliesTo(cart *CartGrain) ([]*CartItem, bool) { func NewCartGrain(id uint64, ts time.Time) *CartGrain { return &CartGrain{ - lastItemId: 0, - lastDeliveryId: 0, - lastVoucherId: 0, - lastAccess: ts, - lastChange: ts, - TotalDiscount: NewPrice(), - Vouchers: []*Voucher{}, - Deliveries: []*CartDelivery{}, - Id: CartId(id), - Items: []*CartItem{}, - TotalPrice: NewPrice(), + lastItemId: 0, + lastDeliveryId: 0, + lastVoucherId: 0, + lastAccess: ts, + lastChange: ts, + TotalDiscount: NewPrice(), + Vouchers: []*Voucher{}, + Deliveries: []*CartDelivery{}, + Id: CartId(id), + Items: []*CartItem{}, + TotalPrice: NewPrice(), + SubscriptionDetails: make(map[string]*SubscriptionDetails), } } diff --git a/pkg/cart/cart-mutation-helper.go b/pkg/cart/cart-mutation-helper.go index 891f9e1..69035bf 100644 --- a/pkg/cart/cart-mutation-helper.go +++ b/pkg/cart/cart-mutation-helper.go @@ -42,6 +42,9 @@ func NewCartMultationRegistry() actor.MutationRegistry { actor.NewMutation(RemoveVoucher, func() *messages.RemoveVoucher { return &messages.RemoveVoucher{} }), + actor.NewMutation(UpsertSubscriptionDetails, func() *messages.UpsertSubscriptionDetails { + return &messages.UpsertSubscriptionDetails{} + }), ) return reg diff --git a/pkg/cart/mutation_add_item.go b/pkg/cart/mutation_add_item.go index 9a3a092..e6172cd 100644 --- a/pkg/cart/mutation_add_item.go +++ b/pkg/cart/mutation_add_item.go @@ -28,14 +28,23 @@ func AddItem(g *CartGrain, m *messages.AddItem) error { return fmt.Errorf("AddItem: invalid quantity %d", m.Quantity) } - // Fast path: merge with existing item having same SKU - if existing, found := g.FindItemWithSku(m.Sku); found { - if existing.StoreId == m.StoreId { - existing.Quantity += int(m.Quantity) - existing.Stock = StockStatus(m.Stock) - existing.StoreId = m.StoreId - return nil + // 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() diff --git a/pkg/cart/mutation_test.go b/pkg/cart/mutation_test.go new file mode 100644 index 0000000..68c37a2 --- /dev/null +++ b/pkg/cart/mutation_test.go @@ -0,0 +1,520 @@ +package cart + +import ( + "reflect" + "slices" + "strings" + "testing" + "time" + + "github.com/gogo/protobuf/proto" + anypb "google.golang.org/protobuf/types/known/anypb" + + "git.tornberg.me/go-cart-actor/pkg/actor" + messages "git.tornberg.me/go-cart-actor/pkg/messages" +) + +// ---------------------- +// Helper constructors +// ---------------------- + +func newTestGrain() *CartGrain { + return NewCartGrain(123, time.Now()) +} + +func newRegistry() actor.MutationRegistry { + return NewCartMultationRegistry() +} + +func msgAddItem(sku string, price int64, qty int32, storePtr *string) *messages.AddItem { + return &messages.AddItem{ + Sku: sku, + Price: price, + Quantity: qty, + // Tax left 0 -> handler uses default 25% + StoreId: storePtr, + } +} + +func msgChangeQty(id uint32, qty int32) *messages.ChangeQuantity { + return &messages.ChangeQuantity{Id: id, Quantity: qty} +} + +func msgRemoveItem(id uint32) *messages.RemoveItem { + return &messages.RemoveItem{Id: id} +} + +func msgSetDelivery(provider string, items ...uint32) *messages.SetDelivery { + uitems := make([]uint32, len(items)) + copy(uitems, items) + return &messages.SetDelivery{Provider: provider, Items: uitems} +} + +func msgSetPickupPoint(deliveryId uint32, id string) *messages.SetPickupPoint { + return &messages.SetPickupPoint{ + DeliveryId: deliveryId, + Id: id, + Name: ptr("Pickup"), + Address: ptr("Street 1"), + City: ptr("Town"), + Zip: ptr("12345"), + Country: ptr("SE"), + } +} + +func msgClearCart() *messages.ClearCartRequest { + return &messages.ClearCartRequest{} +} + +func msgAddVoucher(code string, value int64, rules ...*messages.VoucherRule) *messages.AddVoucher { + return &messages.AddVoucher{Code: code, Value: value, VoucherRules: rules} +} + +func msgRemoveVoucher(id uint32) *messages.RemoveVoucher { + return &messages.RemoveVoucher{Id: id} +} + +func msgInitializeCheckout(orderId, status string, inProgress bool) *messages.InitializeCheckout { + return &messages.InitializeCheckout{OrderId: orderId, Status: status, PaymentInProgress: inProgress} +} + +func msgOrderCreated(orderId, status string) *messages.OrderCreated { + return &messages.OrderCreated{OrderId: orderId, Status: status} +} + +func ptr[T any](v T) *T { return &v } + +// ---------------------- +// Apply helpers +// ---------------------- + +func applyOne(t *testing.T, reg actor.MutationRegistry, g *CartGrain, msg proto.Message) actor.ApplyResult { + t.Helper() + results, err := reg.Apply(g, msg) + if err != nil { + t.Fatalf("unexpected registry-level error applying %T: %v", msg, err) + } + if len(results) != 1 { + t.Fatalf("expected exactly one ApplyResult, got %d", len(results)) + } + return results[0] +} + +// Expect success (nil error inside ApplyResult). +func applyOK(t *testing.T, reg actor.MutationRegistry, g *CartGrain, msg proto.Message) { + t.Helper() + res := applyOne(t, reg, g, msg) + if res.Error != nil { + t.Fatalf("expected mutation %s (%T) to succeed, got error: %v", res.Type, msg, res.Error) + } +} + +// Expect an error matching substring. +func applyErrorContains(t *testing.T, reg actor.MutationRegistry, g *CartGrain, msg proto.Message, substr string) { + t.Helper() + res := applyOne(t, reg, g, msg) + if res.Error == nil { + t.Fatalf("expected error applying %T, got nil", msg) + } + if substr != "" && !strings.Contains(res.Error.Error(), substr) { + t.Fatalf("error mismatch, want substring %q got %q", substr, res.Error.Error()) + } +} + +// ---------------------- +// Tests +// ---------------------- + +func TestMutationRegistryCoverage(t *testing.T) { + reg := newRegistry() + + expected := []string{ + "AddItem", + "ChangeQuantity", + "RemoveItem", + "InitializeCheckout", + "OrderCreated", + "RemoveDelivery", + "SetDelivery", + "SetPickupPoint", + "ClearCartRequest", + "AddVoucher", + "RemoveVoucher", + "UpsertSubscriptionDetails", + } + + names := reg.(*actor.ProtoMutationRegistry).RegisteredMutations() + for _, want := range expected { + if !slices.Contains(names, want) { + t.Fatalf("registry missing mutation %s; got %v", want, names) + } + } + + // Create() by name returns correct concrete type. + for _, name := range expected { + msg, ok := reg.Create(name) + if !ok { + t.Fatalf("Create failed for %s", name) + } + rt := reflect.TypeOf(msg) + if rt.Kind() == reflect.Ptr { + rt = rt.Elem() + } + if rt.Name() != name { + t.Fatalf("Create(%s) returned wrong type %s", name, rt.Name()) + } + } + + // Unregistered create + if m, ok := reg.Create("DoesNotExist"); ok || m != nil { + t.Fatalf("Create should fail for unknown; got (%T,%v)", m, ok) + } + + // GetTypeName sanity + add := &messages.AddItem{} + nm, ok := reg.GetTypeName(add) + if !ok || nm != "AddItem" { + t.Fatalf("GetTypeName failed for AddItem, got (%q,%v)", nm, ok) + } + + // Apply unregistered message -> result should contain ErrMutationNotRegistered, no top-level error + results, err := reg.Apply(newTestGrain(), &messages.Noop{}) + if err != nil { + t.Fatalf("unexpected top-level error applying unregistered mutation: %v", err) + } + if len(results) != 1 || results[0].Error == nil || results[0].Error != actor.ErrMutationNotRegistered { + t.Fatalf("expected ApplyResult with ErrMutationNotRegistered, got %#v", results) + } +} + +func TestAddItemAndMerging(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + // Merge scenario (same SKU + same store pointer) + add1 := msgAddItem("SKU-1", 1000, 2, nil) + applyOK(t, reg, g, add1) + + if len(g.Items) != 1 || g.Items[0].Quantity != 2 { + t.Fatalf("expected first item added; items=%d qty=%d", len(g.Items), g.Items[0].Quantity) + } + + applyOK(t, reg, g, msgAddItem("SKU-1", 1000, 3, nil)) // should merge + if len(g.Items) != 1 || g.Items[0].Quantity != 5 { + t.Fatalf("expected merge quantity=5 items=%d qty=%d", len(g.Items), g.Items[0].Quantity) + } + + // Different store pointer -> new line + store := "S1" + applyOK(t, reg, g, msgAddItem("SKU-1", 1000, 1, &store)) + if len(g.Items) != 2 { + t.Fatalf("expected second line for different store pointer; items=%d", len(g.Items)) + } + + // Same store pointer & SKU -> merge with second line + applyOK(t, reg, g, msgAddItem("SKU-1", 1000, 4, &store)) + if len(g.Items) != 2 || g.Items[1].Quantity != 5 { + t.Fatalf("expected merge on second line; items=%d second.qty=%d", len(g.Items), g.Items[1].Quantity) + } + + // Invalid quantity + applyErrorContains(t, reg, g, msgAddItem("BAD", 1000, 0, nil), "invalid quantity") +} + +func TestChangeQuantityBehavior(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + applyOK(t, reg, g, msgAddItem("A", 1500, 2, nil)) + id := g.Items[0].Id + + // Increase quantity + applyOK(t, reg, g, msgChangeQty(id, 5)) + if g.Items[0].Quantity != 5 { + t.Fatalf("quantity not updated expected=5 got=%d", g.Items[0].Quantity) + } + + // Remove item by setting <=0 + applyOK(t, reg, g, msgChangeQty(id, 0)) + if len(g.Items) != 0 { + t.Fatalf("expected item removed; items=%d", len(g.Items)) + } + + // Not found + applyErrorContains(t, reg, g, msgChangeQty(9999, 1), "not found") +} + +func TestRemoveItemBehavior(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + applyOK(t, reg, g, msgAddItem("X", 1200, 1, nil)) + id := g.Items[0].Id + + applyOK(t, reg, g, msgRemoveItem(id)) + if len(g.Items) != 0 { + t.Fatalf("expected item removed; items=%d", len(g.Items)) + } + + applyErrorContains(t, reg, g, msgRemoveItem(id), "not found") +} + +func TestDeliveryMutations(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + applyOK(t, reg, g, msgAddItem("D1", 1000, 1, nil)) + applyOK(t, reg, g, msgAddItem("D2", 2000, 1, nil)) + i1 := g.Items[0].Id + + // Explicit items + applyOK(t, reg, g, msgSetDelivery("POSTNORD", i1)) + if len(g.Deliveries) != 1 || len(g.Deliveries[0].Items) != 1 || g.Deliveries[0].Items[0] != i1 { + t.Fatalf("delivery not created as expected: %+v", g.Deliveries) + } + + // Attempt to attach an already-delivered item + applyErrorContains(t, reg, g, msgSetDelivery("POSTNORD", i1), "already has a delivery") + + // Attach remaining item via empty list (auto include items without delivery) + applyOK(t, reg, g, msgSetDelivery("DHL")) + if len(g.Deliveries) != 2 { + t.Fatalf("expected second delivery; deliveries=%d", len(g.Deliveries)) + } + + // Non-existent item + applyErrorContains(t, reg, g, msgSetDelivery("UPS", 99999), "not found") + + // No eligible items left + applyErrorContains(t, reg, g, msgSetDelivery("UPS"), "no eligible items") + + // Set pickup point on first delivery + did := g.Deliveries[0].Id + applyOK(t, reg, g, msgSetPickupPoint(did, "PP1")) + if g.Deliveries[0].PickupPoint == nil || g.Deliveries[0].PickupPoint.Id != "PP1" { + t.Fatalf("pickup point not set correctly: %+v", g.Deliveries[0].PickupPoint) + } + + // Bad delivery id + applyErrorContains(t, reg, g, msgSetPickupPoint(9999, "PPX"), "delivery id") + + // Remove delivery + applyOK(t, reg, g, &messages.RemoveDelivery{Id: did}) + if len(g.Deliveries) != 1 || g.Deliveries[0].Id == did { + t.Fatalf("expected first delivery removed, remaining: %+v", g.Deliveries) + } + + // Remove delivery not found + applyErrorContains(t, reg, g, &messages.RemoveDelivery{Id: did}, "not found") +} + +func TestClearCart(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + applyOK(t, reg, g, msgAddItem("X", 1000, 2, nil)) + applyOK(t, reg, g, msgSetDelivery("P", g.Items[0].Id)) + + applyOK(t, reg, g, msgClearCart()) + + if len(g.Items) != 0 || len(g.Deliveries) != 0 { + t.Fatalf("expected cart cleared; items=%d deliveries=%d", len(g.Items), len(g.Deliveries)) + } +} + +func TestVoucherMutations(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + applyOK(t, reg, g, msgAddItem("VOUCH", 10000, 1, nil)) + applyOK(t, reg, g, msgAddVoucher("PROMO", 5000)) + + if len(g.Vouchers) != 1 { + t.Fatalf("voucher not stored") + } + if g.TotalDiscount.IncVat != 5000 { + t.Fatalf("expected discount 5000 got %d", g.TotalDiscount.IncVat) + } + if g.TotalPrice.IncVat != 5000 { + t.Fatalf("expected total price 5000 got %d", g.TotalPrice.IncVat) + } + + // Duplicate voucher code + applyErrorContains(t, reg, g, msgAddVoucher("PROMO", 1000), "already applied") + + // Add a large voucher (should not apply because value > total price) + applyOK(t, reg, g, msgAddVoucher("BIG", 100000)) + if len(g.Vouchers) != 2 { + t.Fatalf("expected second voucher stored") + } + if g.TotalDiscount.IncVat != 5000 || g.TotalPrice.IncVat != 5000 { + t.Fatalf("large voucher incorrectly applied discount=%d total=%d", + g.TotalDiscount.IncVat, g.TotalPrice.IncVat) + } + + // Remove existing voucher + firstId := g.Vouchers[0].Id + applyOK(t, reg, g, msgRemoveVoucher(firstId)) + + if slices.ContainsFunc(g.Vouchers, func(v *Voucher) bool { return v.Id == firstId }) { + t.Fatalf("voucher id %d not removed", firstId) + } + // After removing PROMO, BIG remains but is not applied (exceeds price) + if g.TotalDiscount.IncVat != 0 || g.TotalPrice.IncVat != 10000 { + t.Fatalf("totals incorrect after removal discount=%d total=%d", + g.TotalDiscount.IncVat, g.TotalPrice.IncVat) + } + + // Remove not applied + applyErrorContains(t, reg, g, msgRemoveVoucher(firstId), "not applied") +} + +func TestCheckoutMutations(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + applyOK(t, reg, g, msgInitializeCheckout("ORD-1", "PENDING", true)) + if g.OrderReference != "ORD-1" || g.PaymentStatus != "PENDING" || !g.PaymentInProgress { + t.Fatalf("initialize checkout failed: ref=%s status=%s inProgress=%v", + g.OrderReference, g.PaymentStatus, g.PaymentInProgress) + } + + applyOK(t, reg, g, msgOrderCreated("ORD-1", "COMPLETED")) + if g.OrderReference != "ORD-1" || g.PaymentStatus != "COMPLETED" || g.PaymentInProgress { + t.Fatalf("order created mutation failed: ref=%s status=%s inProgress=%v", + g.OrderReference, g.PaymentStatus, g.PaymentInProgress) + } + + applyErrorContains(t, reg, g, msgInitializeCheckout("", "X", true), "missing orderId") + applyErrorContains(t, reg, g, msgOrderCreated("", "X"), "missing orderId") +} + +func TestSubscriptionDetailsMutation(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + // Upsert new (Id == nil) + msgNew := &messages.UpsertSubscriptionDetails{ + OfferingCode: "OFF1", + SigningType: "TYPE1", + } + applyOK(t, reg, g, msgNew) + if len(g.SubscriptionDetails) != 1 { + t.Fatalf("expected one subscription detail; got=%d", len(g.SubscriptionDetails)) + } + + // Capture created id + var createdId string + for k := range g.SubscriptionDetails { + createdId = k + } + + // Update existing + msgUpdate := &messages.UpsertSubscriptionDetails{ + Id: &createdId, + OfferingCode: "OFF2", + SigningType: "TYPE2", + } + applyOK(t, reg, g, msgUpdate) + if g.SubscriptionDetails[createdId].OfferingCode != "OFF2" || + g.SubscriptionDetails[createdId].SigningType != "TYPE2" { + t.Fatalf("subscription details not updated: %+v", g.SubscriptionDetails[createdId]) + } + + // Update non-existent + badId := "NON_EXISTENT" + applyErrorContains(t, reg, g, &messages.UpsertSubscriptionDetails{Id: &badId}, "not found") + + // Nil mutation should be ignored and produce zero results. + resultsNil, errNil := reg.Apply(g, (*messages.UpsertSubscriptionDetails)(nil)) + if errNil != nil { + t.Fatalf("unexpected error for nil mutation element: %v", errNil) + } + if len(resultsNil) != 0 { + t.Fatalf("expected zero results for nil mutation, got %d", len(resultsNil)) + } +} + +// Ensure registry Apply handles nil grain and nil message defensive errors consistently. +func TestRegistryDefensiveErrors(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + // Nil grain + results, err := reg.Apply(nil, &messages.AddItem{}) + if err == nil { + t.Fatalf("expected error for nil grain") + } + if len(results) != 0 { + t.Fatalf("expected no results for nil grain") + } + + // Nil message slice + results, _ = reg.Apply(g, nil) + + if len(results) != 0 { + t.Fatalf("expected no results when message slice nil") + } +} +func TestSubscriptionDetailsJSONValidation(t *testing.T) { + reg := newRegistry() + g := newTestGrain() + + // Valid JSON on create + validCreate := &messages.UpsertSubscriptionDetails{ + OfferingCode: "OFFJSON", + SigningType: "TYPEJSON", + Data: &anypb.Any{Value: []byte(`{"ok":true}`)}, + } + applyOK(t, reg, g, validCreate) + if len(g.SubscriptionDetails) != 1 { + t.Fatalf("expected one subscription detail after valid create, got %d", len(g.SubscriptionDetails)) + } + var id string + for k := range g.SubscriptionDetails { + id = k + } + if string(g.SubscriptionDetails[id].Meta) != `{"ok":true}` { + t.Fatalf("expected meta stored as valid json, got %s", string(g.SubscriptionDetails[id].Meta)) + } + + // Update with valid JSON replaces meta + updateValid := &messages.UpsertSubscriptionDetails{ + Id: &id, + Data: &anypb.Any{Value: []byte(`{"changed":123}`)}, + } + applyOK(t, reg, g, updateValid) + if string(g.SubscriptionDetails[id].Meta) != `{"changed":123}` { + t.Fatalf("expected meta updated to new json, got %s", string(g.SubscriptionDetails[id].Meta)) + } + + // Invalid JSON on create + invalidCreate := &messages.UpsertSubscriptionDetails{ + OfferingCode: "BAD", + Data: &anypb.Any{Value: []byte(`{"broken":}`)}, + } + res := applyOne(t, reg, g, invalidCreate) + if res.Error == nil || !strings.Contains(res.Error.Error(), "invalid json") { + t.Fatalf("expected invalid json error on create, got %v", res.Error) + } + + // Invalid JSON on update + badUpdate := &messages.UpsertSubscriptionDetails{ + Id: &id, + Data: &anypb.Any{Value: []byte(`{oops`)}, + } + res2 := applyOne(t, reg, g, badUpdate) + if res2.Error == nil || !strings.Contains(res2.Error.Error(), "invalid json") { + t.Fatalf("expected invalid json error on update, got %v", res2.Error) + } + + // Empty Data.Value should not overwrite existing meta + emptyUpdate := &messages.UpsertSubscriptionDetails{ + Id: &id, + Data: &anypb.Any{Value: []byte{}}, + } + applyOK(t, reg, g, emptyUpdate) + if string(g.SubscriptionDetails[id].Meta) != `{"changed":123}` { + t.Fatalf("empty update should not change meta, got %s", string(g.SubscriptionDetails[id].Meta)) + } +} diff --git a/pkg/cart/mutation_upsert_subscriptiondetails.go b/pkg/cart/mutation_upsert_subscriptiondetails.go new file mode 100644 index 0000000..1e438bd --- /dev/null +++ b/pkg/cart/mutation_upsert_subscriptiondetails.go @@ -0,0 +1,57 @@ +package cart + +import ( + "encoding/json" + "fmt" + + messages "git.tornberg.me/go-cart-actor/pkg/messages" +) + +func UpsertSubscriptionDetails(g *CartGrain, m *messages.UpsertSubscriptionDetails) error { + if m == nil { + return nil + } + + // Create new subscription details when Id is nil. + if m.Id == nil { + // Validate JSON if provided. + var meta json.RawMessage + if m.Data != nil && len(m.Data.Value) > 0 { + if !json.Valid(m.Data.Value) { + return fmt.Errorf("subscription details invalid json") + } + meta = json.RawMessage(m.Data.Value) + } + + id := MustNewCartId().String() + g.SubscriptionDetails[id] = &SubscriptionDetails{ + Id: id, + OfferingCode: m.OfferingCode, + SigningType: m.SigningType, + Meta: meta, + } + return nil + } + + // Update existing entry. + existing, ok := g.SubscriptionDetails[*m.Id] + if !ok { + return fmt.Errorf("subscription details not found") + } + if m.OfferingCode != "" { + existing.OfferingCode = m.OfferingCode + } + if m.SigningType != "" { + existing.SigningType = m.SigningType + } + if m.Data != nil { + // Only validate & assign if there is content; empty -> leave as-is. + if len(m.Data.Value) > 0 { + if !json.Valid(m.Data.Value) { + return fmt.Errorf("subscription details invalid json") + } + existing.Meta = m.Data.Value + } + } + return nil +} diff --git a/cmd/cart/price_test.go b/pkg/cart/price_test.go similarity index 96% rename from cmd/cart/price_test.go rename to pkg/cart/price_test.go index b7d697a..285424b 100644 --- a/cmd/cart/price_test.go +++ b/pkg/cart/price_test.go @@ -1,4 +1,4 @@ -package main +package cart import ( "encoding/json" @@ -33,14 +33,14 @@ func TestPriceMarshalJSON(t *testing.T) { } func TestNewPriceFromIncVat(t *testing.T) { - p := NewPriceFromIncVat(1000, 0.25) - if p.IncVat != 1000 { - t.Fatalf("expected IncVat %d got %d", 1000, p.IncVat) + p := NewPriceFromIncVat(1250, 25) + if p.IncVat != 1250 { + t.Fatalf("expected IncVat %d got %d", 1250, p.IncVat) } if p.VatRates[25] != 250 { t.Fatalf("expected VAT 25 rate %d got %d", 250, p.VatRates[25]) } - if p.ValueExVat() != 750 { + if p.ValueExVat() != 1000 { t.Fatalf("expected exVat %d got %d", 750, p.ValueExVat()) } } diff --git a/pkg/messages/control_plane.pb.go b/pkg/messages/control_plane.pb.go index 95aed7d..cf6eeae 100644 --- a/pkg/messages/control_plane.pb.go +++ b/pkg/messages/control_plane.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.5 -// protoc v5.29.3 +// protoc-gen-go v1.36.10 +// protoc v6.32.0 // source: control_plane.proto package messages @@ -453,65 +453,38 @@ func (x *ExpiryAnnounce) GetIds() []uint64 { var File_control_plane_proto protoreflect.FileDescriptor -var file_control_plane_proto_rawDesc = string([]byte{ - 0x0a, 0x13, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, - 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3c, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x6e, 0x69, - 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x75, 0x6e, - 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x33, 0x0a, 0x10, 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x6e, - 0x6f, 0x77, 0x6e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x22, 0x26, 0x0a, 0x0e, 0x4e, - 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x68, 0x6f, - 0x73, 0x74, 0x73, 0x22, 0x21, 0x0a, 0x0d, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x73, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x46, 0x0a, 0x0e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, - 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, - 0x70, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x23, - 0x0a, 0x0d, 0x43, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, - 0x6f, 0x73, 0x74, 0x22, 0x39, 0x0a, 0x11, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x36, - 0x0a, 0x0e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x68, 0x6f, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x03, 0x69, 0x64, 0x73, 0x32, 0x8d, 0x03, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, - 0x0f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x13, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x50, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x41, 0x0a, 0x09, 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, - 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x4e, 0x65, - 0x67, 0x6f, 0x74, 0x69, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x67, 0x6f, 0x74, 0x69, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3c, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x73, 0x12, 0x0f, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x64, - 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x4a, 0x0a, 0x11, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, - 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x1b, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, - 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x1a, 0x18, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, - 0x63, 0x6b, 0x12, 0x44, 0x0a, 0x0e, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x45, 0x78, - 0x70, 0x69, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, - 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x1a, 0x18, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x63, 0x6b, 0x12, 0x3c, 0x0a, 0x07, 0x43, 0x6c, 0x6f, 0x73, - 0x69, 0x6e, 0x67, 0x12, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x43, - 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x1a, 0x18, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x41, 0x63, 0x6b, 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, -}) +const file_control_plane_proto_rawDesc = "" + + "\n" + + "\x13control_plane.proto\x12\bmessages\"\a\n" + + "\x05Empty\"<\n" + + "\tPingReply\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12\x1b\n" + + "\tunix_time\x18\x02 \x01(\x03R\bunixTime\"3\n" + + "\x10NegotiateRequest\x12\x1f\n" + + "\vknown_hosts\x18\x01 \x03(\tR\n" + + "knownHosts\"&\n" + + "\x0eNegotiateReply\x12\x14\n" + + "\x05hosts\x18\x01 \x03(\tR\x05hosts\"!\n" + + "\rActorIdsReply\x12\x10\n" + + "\x03ids\x18\x01 \x03(\x04R\x03ids\"F\n" + + "\x0eOwnerChangeAck\x12\x1a\n" + + "\baccepted\x18\x01 \x01(\bR\baccepted\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage\"#\n" + + "\rClosingNotice\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\"9\n" + + "\x11OwnershipAnnounce\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12\x10\n" + + "\x03ids\x18\x02 \x03(\x04R\x03ids\"6\n" + + "\x0eExpiryAnnounce\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12\x10\n" + + "\x03ids\x18\x02 \x03(\x04R\x03ids2\x8d\x03\n" + + "\fControlPlane\x12,\n" + + "\x04Ping\x12\x0f.messages.Empty\x1a\x13.messages.PingReply\x12A\n" + + "\tNegotiate\x12\x1a.messages.NegotiateRequest\x1a\x18.messages.NegotiateReply\x12<\n" + + "\x10GetLocalActorIds\x12\x0f.messages.Empty\x1a\x17.messages.ActorIdsReply\x12J\n" + + "\x11AnnounceOwnership\x12\x1b.messages.OwnershipAnnounce\x1a\x18.messages.OwnerChangeAck\x12D\n" + + "\x0eAnnounceExpiry\x12\x18.messages.ExpiryAnnounce\x1a\x18.messages.OwnerChangeAck\x12<\n" + + "\aClosing\x12\x17.messages.ClosingNotice\x1a\x18.messages.OwnerChangeAckB.Z,git.tornberg.me/go-cart-actor/proto;messagesb\x06proto3" var ( file_control_plane_proto_rawDescOnce sync.Once diff --git a/pkg/messages/control_plane_grpc.pb.go b/pkg/messages/control_plane_grpc.pb.go index d0c9cf5..f95afab 100644 --- a/pkg/messages/control_plane_grpc.pb.go +++ b/pkg/messages/control_plane_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.29.3 +// - protoc v6.32.0 // source: control_plane.proto package messages diff --git a/pkg/messages/messages.pb.go b/pkg/messages/messages.pb.go index e6e6da1..3e49955 100644 --- a/pkg/messages/messages.pb.go +++ b/pkg/messages/messages.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.5 -// protoc v5.29.3 +// protoc-gen-go v1.36.10 +// protoc v6.32.0 // source: messages.proto package messages @@ -9,6 +9,7 @@ package messages import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" reflect "reflect" sync "sync" unsafe "unsafe" @@ -1089,153 +1090,199 @@ func (x *RemoveVoucher) GetId() uint32 { return 0 } +type UpsertSubscriptionDetails struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"` + OfferingCode string `protobuf:"bytes,2,opt,name=offeringCode,proto3" json:"offeringCode,omitempty"` + SigningType string `protobuf:"bytes,3,opt,name=signingType,proto3" json:"signingType,omitempty"` + Data *anypb.Any `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpsertSubscriptionDetails) Reset() { + *x = UpsertSubscriptionDetails{} + mi := &file_messages_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpsertSubscriptionDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpsertSubscriptionDetails) ProtoMessage() {} + +func (x *UpsertSubscriptionDetails) ProtoReflect() protoreflect.Message { + mi := &file_messages_proto_msgTypes[15] + 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 UpsertSubscriptionDetails.ProtoReflect.Descriptor instead. +func (*UpsertSubscriptionDetails) Descriptor() ([]byte, []int) { + return file_messages_proto_rawDescGZIP(), []int{15} +} + +func (x *UpsertSubscriptionDetails) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + +func (x *UpsertSubscriptionDetails) GetOfferingCode() string { + if x != nil { + return x.OfferingCode + } + return "" +} + +func (x *UpsertSubscriptionDetails) GetSigningType() string { + if x != nil { + return x.SigningType + } + return "" +} + +func (x *UpsertSubscriptionDetails) GetData() *anypb.Any { + if x != nil { + return x.Data + } + return nil +} + var File_messages_proto protoreflect.FileDescriptor -var file_messages_proto_rawDesc = string([]byte{ - 0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x12, 0x0a, 0x10, 0x43, 0x6c, - 0x65, 0x61, 0x72, 0x43, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x97, - 0x05, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x74, - 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x69, 0x74, 0x65, - 0x6d, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, - 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x72, 0x67, 0x50, 0x72, 0x69, 0x63, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x72, 0x67, 0x50, 0x72, 0x69, 0x63, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x6b, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x73, 0x6b, 0x75, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, - 0x6f, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x03, 0x74, 0x61, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, - 0x6f, 0x72, 0x79, 0x32, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x32, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x33, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x33, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x34, - 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, - 0x34, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x35, 0x18, 0x12, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x35, 0x12, - 0x1e, 0x0a, 0x0a, 0x64, 0x69, 0x73, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x72, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x69, 0x73, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x72, 0x12, - 0x20, 0x0a, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x18, 0x13, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, - 0x0a, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x6c, 0x65, - 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x6c, 0x65, - 0x74, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x49, 0x64, 0x18, - 0x16, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x49, 0x64, - 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x18, - 0x17, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x02, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6f, 0x75, 0x74, 0x6c, 0x65, 0x74, 0x42, - 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x49, 0x64, 0x42, 0x0b, 0x0a, 0x09, 0x5f, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x1c, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x02, 0x49, 0x64, 0x22, 0x3c, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x22, 0x86, 0x02, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x69, - 0x76, 0x65, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x12, 0x14, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, - 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x3c, 0x0a, 0x0b, 0x70, 0x69, 0x63, 0x6b, 0x75, 0x70, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x50, 0x69, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x69, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x7a, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x7a, 0x69, 0x70, - 0x12, 0x1d, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x01, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, - 0x17, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, - 0x04, 0x63, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x70, 0x69, 0x63, - 0x6b, 0x75, 0x70, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x63, 0x69, 0x74, 0x79, 0x22, 0xf9, 0x01, - 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x50, 0x69, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x49, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x49, 0x64, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x88, 0x01, - 0x01, 0x12, 0x15, 0x0a, 0x03, 0x7a, 0x69, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, - 0x52, 0x03, 0x7a, 0x69, 0x70, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x07, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x72, 0x79, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x07, 0x0a, 0x05, - 0x5f, 0x63, 0x69, 0x74, 0x79, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x7a, 0x69, 0x70, 0x42, 0x0a, 0x0a, - 0x08, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xd6, 0x01, 0x0a, 0x0b, 0x50, 0x69, - 0x63, 0x6b, 0x75, 0x70, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, - 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, - 0x01, 0x12, 0x17, 0x0a, 0x04, 0x63, 0x69, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x02, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x12, 0x15, 0x0a, 0x03, 0x7a, 0x69, - 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x03, 0x7a, 0x69, 0x70, 0x88, 0x01, - 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x04, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x88, 0x01, 0x01, - 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x63, 0x69, 0x74, 0x79, 0x42, 0x06, - 0x0a, 0x04, 0x5f, 0x7a, 0x69, 0x70, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x72, 0x79, 0x22, 0x20, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x65, 0x6c, 0x69, - 0x76, 0x65, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x02, 0x69, 0x64, 0x22, 0xb9, 0x01, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, - 0x74, 0x65, 0x72, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x65, 0x72, - 0x6d, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x12, 0x22, - 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x75, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x70, 0x75, 0x73, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, - 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x22, 0x40, 0x0a, 0x0c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x06, 0x0a, 0x04, 0x4e, 0x6f, 0x6f, 0x70, 0x22, 0x74, 0x0a, 0x12, 0x49, 0x6e, - 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, - 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 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, - 0x22, 0x79, 0x0a, 0x0b, 0x56, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x71, 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, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x52, 0x75, - 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x2e, 0x56, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x52, 0x75, 0x6c, 0x65, - 0x52, 0x0c, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x1f, - 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x56, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 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, -}) +const file_messages_proto_rawDesc = "" + + "\n" + + "\x0emessages.proto\x12\bmessages\x1a\x19google/protobuf/any.proto\"\x12\n" + + "\x10ClearCartRequest\"\x97\x05\n" + + "\aAddItem\x12\x17\n" + + "\aitem_id\x18\x01 \x01(\rR\x06itemId\x12\x1a\n" + + "\bquantity\x18\x02 \x01(\x05R\bquantity\x12\x14\n" + + "\x05price\x18\x03 \x01(\x03R\x05price\x12\x1a\n" + + "\borgPrice\x18\t \x01(\x03R\borgPrice\x12\x10\n" + + "\x03sku\x18\x04 \x01(\tR\x03sku\x12\x12\n" + + "\x04name\x18\x05 \x01(\tR\x04name\x12\x14\n" + + "\x05image\x18\x06 \x01(\tR\x05image\x12\x14\n" + + "\x05stock\x18\a \x01(\x05R\x05stock\x12\x10\n" + + "\x03tax\x18\b \x01(\x05R\x03tax\x12\x14\n" + + "\x05brand\x18\r \x01(\tR\x05brand\x12\x1a\n" + + "\bcategory\x18\x0e \x01(\tR\bcategory\x12\x1c\n" + + "\tcategory2\x18\x0f \x01(\tR\tcategory2\x12\x1c\n" + + "\tcategory3\x18\x10 \x01(\tR\tcategory3\x12\x1c\n" + + "\tcategory4\x18\x11 \x01(\tR\tcategory4\x12\x1c\n" + + "\tcategory5\x18\x12 \x01(\tR\tcategory5\x12\x1e\n" + + "\n" + + "disclaimer\x18\n" + + " \x01(\tR\n" + + "disclaimer\x12 \n" + + "\varticleType\x18\v \x01(\tR\varticleType\x12\x1a\n" + + "\bsellerId\x18\x13 \x01(\tR\bsellerId\x12\x1e\n" + + "\n" + + "sellerName\x18\x14 \x01(\tR\n" + + "sellerName\x12\x18\n" + + "\acountry\x18\x15 \x01(\tR\acountry\x12\x1b\n" + + "\x06outlet\x18\f \x01(\tH\x00R\x06outlet\x88\x01\x01\x12\x1d\n" + + "\astoreId\x18\x16 \x01(\tH\x01R\astoreId\x88\x01\x01\x12\x1f\n" + + "\bparentId\x18\x17 \x01(\rH\x02R\bparentId\x88\x01\x01B\t\n" + + "\a_outletB\n" + + "\n" + + "\b_storeIdB\v\n" + + "\t_parentId\"\x1c\n" + + "\n" + + "RemoveItem\x12\x0e\n" + + "\x02Id\x18\x01 \x01(\rR\x02Id\"<\n" + + "\x0eChangeQuantity\x12\x0e\n" + + "\x02Id\x18\x01 \x01(\rR\x02Id\x12\x1a\n" + + "\bquantity\x18\x02 \x01(\x05R\bquantity\"\x86\x02\n" + + "\vSetDelivery\x12\x1a\n" + + "\bprovider\x18\x01 \x01(\tR\bprovider\x12\x14\n" + + "\x05items\x18\x02 \x03(\rR\x05items\x12<\n" + + "\vpickupPoint\x18\x03 \x01(\v2\x15.messages.PickupPointH\x00R\vpickupPoint\x88\x01\x01\x12\x18\n" + + "\acountry\x18\x04 \x01(\tR\acountry\x12\x10\n" + + "\x03zip\x18\x05 \x01(\tR\x03zip\x12\x1d\n" + + "\aaddress\x18\x06 \x01(\tH\x01R\aaddress\x88\x01\x01\x12\x17\n" + + "\x04city\x18\a \x01(\tH\x02R\x04city\x88\x01\x01B\x0e\n" + + "\f_pickupPointB\n" + + "\n" + + "\b_addressB\a\n" + + "\x05_city\"\xf9\x01\n" + + "\x0eSetPickupPoint\x12\x1e\n" + + "\n" + + "deliveryId\x18\x01 \x01(\rR\n" + + "deliveryId\x12\x0e\n" + + "\x02id\x18\x02 \x01(\tR\x02id\x12\x17\n" + + "\x04name\x18\x03 \x01(\tH\x00R\x04name\x88\x01\x01\x12\x1d\n" + + "\aaddress\x18\x04 \x01(\tH\x01R\aaddress\x88\x01\x01\x12\x17\n" + + "\x04city\x18\x05 \x01(\tH\x02R\x04city\x88\x01\x01\x12\x15\n" + + "\x03zip\x18\x06 \x01(\tH\x03R\x03zip\x88\x01\x01\x12\x1d\n" + + "\acountry\x18\a \x01(\tH\x04R\acountry\x88\x01\x01B\a\n" + + "\x05_nameB\n" + + "\n" + + "\b_addressB\a\n" + + "\x05_cityB\x06\n" + + "\x04_zipB\n" + + "\n" + + "\b_country\"\xd6\x01\n" + + "\vPickupPoint\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x17\n" + + "\x04name\x18\x02 \x01(\tH\x00R\x04name\x88\x01\x01\x12\x1d\n" + + "\aaddress\x18\x03 \x01(\tH\x01R\aaddress\x88\x01\x01\x12\x17\n" + + "\x04city\x18\x04 \x01(\tH\x02R\x04city\x88\x01\x01\x12\x15\n" + + "\x03zip\x18\x05 \x01(\tH\x03R\x03zip\x88\x01\x01\x12\x1d\n" + + "\acountry\x18\x06 \x01(\tH\x04R\acountry\x88\x01\x01B\a\n" + + "\x05_nameB\n" + + "\n" + + "\b_addressB\a\n" + + "\x05_cityB\x06\n" + + "\x04_zipB\n" + + "\n" + + "\b_country\" \n" + + "\x0eRemoveDelivery\x12\x0e\n" + + "\x02id\x18\x01 \x01(\rR\x02id\"\xb9\x01\n" + + "\x13CreateCheckoutOrder\x12\x14\n" + + "\x05terms\x18\x01 \x01(\tR\x05terms\x12\x1a\n" + + "\bcheckout\x18\x02 \x01(\tR\bcheckout\x12\"\n" + + "\fconfirmation\x18\x03 \x01(\tR\fconfirmation\x12\x12\n" + + "\x04push\x18\x04 \x01(\tR\x04push\x12\x1e\n" + + "\n" + + "validation\x18\x05 \x01(\tR\n" + + "validation\x12\x18\n" + + "\acountry\x18\x06 \x01(\tR\acountry\"@\n" + + "\fOrderCreated\x12\x18\n" + + "\aorderId\x18\x01 \x01(\tR\aorderId\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\"\x06\n" + + "\x04Noop\"t\n" + + "\x12InitializeCheckout\x12\x18\n" + + "\aorderId\x18\x01 \x01(\tR\aorderId\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12,\n" + + "\x11paymentInProgress\x18\x03 \x01(\bR\x11paymentInProgress\"y\n" + + "\vVoucherRule\x12\x12\n" + + "\x04type\x18\x02 \x01(\tR\x04type\x12 \n" + + "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x1c\n" + + "\tcondition\x18\x04 \x01(\tR\tcondition\x12\x16\n" + + "\x06action\x18\x05 \x01(\tR\x06action\"q\n" + + "\n" + + "AddVoucher\x12\x12\n" + + "\x04code\x18\x01 \x01(\tR\x04code\x12\x14\n" + + "\x05value\x18\x02 \x01(\x03R\x05value\x129\n" + + "\fvoucherRules\x18\x03 \x03(\v2\x15.messages.VoucherRuleR\fvoucherRules\"\x1f\n" + + "\rRemoveVoucher\x12\x0e\n" + + "\x02id\x18\x01 \x01(\rR\x02id\"\xa7\x01\n" + + "\x19UpsertSubscriptionDetails\x12\x13\n" + + "\x02id\x18\x01 \x01(\tH\x00R\x02id\x88\x01\x01\x12\"\n" + + "\fofferingCode\x18\x02 \x01(\tR\fofferingCode\x12 \n" + + "\vsigningType\x18\x03 \x01(\tR\vsigningType\x12(\n" + + "\x04data\x18\x04 \x01(\v2\x14.google.protobuf.AnyR\x04dataB\x05\n" + + "\x03_idB.Z,git.tornberg.me/go-cart-actor/proto;messagesb\x06proto3" var ( file_messages_proto_rawDescOnce sync.Once @@ -1249,32 +1296,35 @@ func file_messages_proto_rawDescGZIP() []byte { return file_messages_proto_rawDescData } -var file_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_messages_proto_goTypes = []any{ - (*ClearCartRequest)(nil), // 0: messages.ClearCartRequest - (*AddItem)(nil), // 1: messages.AddItem - (*RemoveItem)(nil), // 2: messages.RemoveItem - (*ChangeQuantity)(nil), // 3: messages.ChangeQuantity - (*SetDelivery)(nil), // 4: messages.SetDelivery - (*SetPickupPoint)(nil), // 5: messages.SetPickupPoint - (*PickupPoint)(nil), // 6: messages.PickupPoint - (*RemoveDelivery)(nil), // 7: messages.RemoveDelivery - (*CreateCheckoutOrder)(nil), // 8: messages.CreateCheckoutOrder - (*OrderCreated)(nil), // 9: messages.OrderCreated - (*Noop)(nil), // 10: messages.Noop - (*InitializeCheckout)(nil), // 11: messages.InitializeCheckout - (*VoucherRule)(nil), // 12: messages.VoucherRule - (*AddVoucher)(nil), // 13: messages.AddVoucher - (*RemoveVoucher)(nil), // 14: messages.RemoveVoucher + (*ClearCartRequest)(nil), // 0: messages.ClearCartRequest + (*AddItem)(nil), // 1: messages.AddItem + (*RemoveItem)(nil), // 2: messages.RemoveItem + (*ChangeQuantity)(nil), // 3: messages.ChangeQuantity + (*SetDelivery)(nil), // 4: messages.SetDelivery + (*SetPickupPoint)(nil), // 5: messages.SetPickupPoint + (*PickupPoint)(nil), // 6: messages.PickupPoint + (*RemoveDelivery)(nil), // 7: messages.RemoveDelivery + (*CreateCheckoutOrder)(nil), // 8: messages.CreateCheckoutOrder + (*OrderCreated)(nil), // 9: messages.OrderCreated + (*Noop)(nil), // 10: messages.Noop + (*InitializeCheckout)(nil), // 11: messages.InitializeCheckout + (*VoucherRule)(nil), // 12: messages.VoucherRule + (*AddVoucher)(nil), // 13: messages.AddVoucher + (*RemoveVoucher)(nil), // 14: messages.RemoveVoucher + (*UpsertSubscriptionDetails)(nil), // 15: messages.UpsertSubscriptionDetails + (*anypb.Any)(nil), // 16: google.protobuf.Any } var file_messages_proto_depIdxs = []int32{ 6, // 0: messages.SetDelivery.pickupPoint:type_name -> messages.PickupPoint 12, // 1: messages.AddVoucher.voucherRules:type_name -> messages.VoucherRule - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 16, // 2: messages.UpsertSubscriptionDetails.data:type_name -> google.protobuf.Any + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_messages_proto_init() } @@ -1286,13 +1336,14 @@ func file_messages_proto_init() { file_messages_proto_msgTypes[4].OneofWrappers = []any{} file_messages_proto_msgTypes[5].OneofWrappers = []any{} file_messages_proto_msgTypes[6].OneofWrappers = []any{} + file_messages_proto_msgTypes[15].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_messages_proto_rawDesc), len(file_messages_proto_rawDesc)), NumEnums: 0, - NumMessages: 15, + NumMessages: 16, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/messages.proto b/proto/messages.proto index 42a94ac..009fcf2 100644 --- a/proto/messages.proto +++ b/proto/messages.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package messages; option go_package = "git.tornberg.me/go-cart-actor/proto;messages"; +import "google/protobuf/any.proto"; + message ClearCartRequest { } @@ -114,3 +116,12 @@ message AddVoucher { message RemoveVoucher { uint32 id = 1; } + +message UpsertSubscriptionDetails { + + optional string id = 1; + string offeringCode = 2; + string signingType = 3; + google.protobuf.Any data = 4; + +}