From 6b648c4f4856140cf3da9888bd669d22208713cd Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 7 Jul 2023 01:57:06 +0000 Subject: [PATCH] ci: set broker ip --- .env.test | 28 +- README.md | 3 + deployments/dev/.env.dev | 23 -- deployments/dev/docker-compose.yaml | 3 + deployments/staging/docker-compose.yaml | 3 + go.mod | 4 + go.sum | 8 + internal/app/app.go | 27 +- internal/initialize/api_test.go | 7 + internal/initialize/brokers.go | 30 ++ internal/initialize/brokers_test.go | 27 ++ internal/initialize/config.go | 2 + internal/initialize/config_test.go | 7 + internal/initialize/controllers_test.go | 7 + internal/initialize/services.go | 23 +- internal/initialize/services_test.go | 8 + internal/interface/broker/tariff/consumer.go | 65 +++++ internal/interface/broker/tariff/producer.go | 61 ++++ .../interface/controller/rest/cart/cart.go | 9 +- internal/models/config.go | 10 + internal/models/tariff.go | 18 +- internal/proto/broker/models.pb.go | 247 ++++++++++++++++ internal/proto/discount/discount.model.pb.go | 273 +++++++++--------- internal/proto/discount/service.pb.go | 76 ++--- internal/service/broker/tariff/tariff.go | 90 ++++++ internal/service/cart/cart.go | 83 ++++-- internal/service/wallet/wallet.go | 25 +- internal/utils/transfer/privilege.go | 53 ++++ internal/utils/transfer/privilege_test.go | 112 +++++++ internal/utils/transfer/tariff.go | 22 +- internal/utils/transfer/tariff_test.go | 80 +++++ pkg/closer/closer.go | 13 + pkg/kafka/kafka.go | 83 ++++++ proto/broker/models.proto | 17 ++ proto/discount/audit.model.proto | 34 +-- proto/discount/discount.model.proto | 175 +++++------ proto/discount/service.proto | 189 ++++++------ 37 files changed, 1465 insertions(+), 480 deletions(-) create mode 100644 internal/initialize/brokers.go create mode 100644 internal/initialize/brokers_test.go create mode 100644 internal/interface/broker/tariff/consumer.go create mode 100644 internal/interface/broker/tariff/producer.go create mode 100644 internal/proto/broker/models.pb.go create mode 100644 internal/service/broker/tariff/tariff.go create mode 100644 internal/utils/transfer/privilege.go create mode 100644 internal/utils/transfer/privilege_test.go create mode 100644 pkg/kafka/kafka.go create mode 100644 proto/broker/models.proto diff --git a/.env.test b/.env.test index 1cb9f58..f6d855c 100644 --- a/.env.test +++ b/.env.test @@ -1,25 +1,25 @@ -# HTTP settings HTTP_HOST=0.0.0.0 -HTTP_PORT=8080 +HTTP_PORT=8082 -# MONGO settings -MONGO_HOST=localhost +GRPC_HOST=0.0.0.0 +GRPC_PORT=9082 +GRPC_DOMEN=customer-app:9082 + +MONGO_HOST=mongo MONGO_PORT=27017 MONGO_USER=test MONGO_PASSWORD=test -MONGO_AUTH=admin MONGO_DB_NAME=admin +MONGO_AUTH=admin -# Auth Microservice settings -AUTH_MICROSERVICE_USER_URL=http://localhost:8000/user +AUTH_MICROSERVICE_USER_URL=http://pena-auth-service:8000/user +HUBADMIN_MICROSERVICE_TARIFF_URL=http://hub-admin-service:8010/tariff +CURRENCY_MICROSERVICE_TRANSLATE_URL=http://cbrf-service:8020/translate +DISCOUNT_MICROSERVICE_GRPC_HOST=discount-service:9040 +PAYMENT_MICROSERVICE_GRPC_HOST=treasurer-service:9085 -# Hub Admin Microservice settings -HUBADMIN_MICROSERVICE_TARIFF_URL=http://localhost:8001/tariff - -# Currency Microservice settings -CURRENCY_MICROSERVICE_TRANSLATE_URL=http://localhost:8002/change - -# Admin +KAFKA_BROKERS=localhost:8080,localhost:1111 +KAFKA_TOPIC_TARIFF=tariff # JWT settings JWT_ISSUER="pena-auth-service" diff --git a/README.md b/README.md index a59416a..cd2a5a4 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,9 @@ PAYMENT_MICROSERVICE_GRPC_HOST - хост микросервиса payment (GRPC JWT_PUBLIC_KEY - публичный ключ для верификации jwt токена JWT_ISSUER - издатель токена JWT_AUDIENCE - аудитория, которая может верифицировать токен + +KAFKA_BROKERS - массив брокеров (localhost:8888,localhost:1111) +KAFKA_TOPIC_TARIFF - название топика для сообщений тарифа ``` ## Полезные ссылки: diff --git a/deployments/dev/.env.dev b/deployments/dev/.env.dev index 1cb9f58..6ed8cbb 100644 --- a/deployments/dev/.env.dev +++ b/deployments/dev/.env.dev @@ -1,26 +1,3 @@ -# HTTP settings -HTTP_HOST=0.0.0.0 -HTTP_PORT=8080 - -# MONGO settings -MONGO_HOST=localhost -MONGO_PORT=27017 -MONGO_USER=test -MONGO_PASSWORD=test -MONGO_AUTH=admin -MONGO_DB_NAME=admin - -# Auth Microservice settings -AUTH_MICROSERVICE_USER_URL=http://localhost:8000/user - -# Hub Admin Microservice settings -HUBADMIN_MICROSERVICE_TARIFF_URL=http://localhost:8001/tariff - -# Currency Microservice settings -CURRENCY_MICROSERVICE_TRANSLATE_URL=http://localhost:8002/change - -# Admin - # JWT settings JWT_ISSUER="pena-auth-service" JWT_AUDIENCE="pena" diff --git a/deployments/dev/docker-compose.yaml b/deployments/dev/docker-compose.yaml index bb66281..2dd96e5 100644 --- a/deployments/dev/docker-compose.yaml +++ b/deployments/dev/docker-compose.yaml @@ -25,6 +25,9 @@ services: - MONGO_DB_NAME=admin - MONGO_AUTH=admin + - KAFKA_BROKERS=localhost:8080,localhost:1111 + - KAFKA_TOPIC_TARIFF=tariff + - JWT_ISSUER=pena-auth-service - JWT_AUDIENCE=pena diff --git a/deployments/staging/docker-compose.yaml b/deployments/staging/docker-compose.yaml index 209aba3..479614e 100644 --- a/deployments/staging/docker-compose.yaml +++ b/deployments/staging/docker-compose.yaml @@ -21,6 +21,9 @@ services: - MONGO_DB_NAME=customer - MONGO_AUTH=customer + - KAFKA_BROKERS=10.6.0.11:9092 + - KAFKA_TOPIC_TARIFF=tariffs + - AUTH_MICROSERVICE_USER_URL=https://admin.pena.digital/user - HUBADMIN_MICROSERVICE_TARIFF_URL=https://admin.pena.digital/strator/tariff - CURRENCY_MICROSERVICE_TRANSLATE_URL=http://10.6.0.11:3131/change diff --git a/go.mod b/go.mod index f1c8b7a..a38f4c9 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,8 @@ require ( github.com/labstack/echo/v4 v4.10.2 github.com/sethvargo/go-envconfig v0.9.0 github.com/stretchr/testify v1.8.2 + github.com/twmb/franz-go v1.13.6 + github.com/twmb/franz-go/pkg/kadm v1.8.1 go.mongodb.org/mongo-driver v1.11.4 go.uber.org/zap v1.24.0 google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 @@ -42,8 +44,10 @@ require ( github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/perimeterx/marshmallow v1.1.4 // indirect + github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/twmb/franz-go/pkg/kmsg v1.4.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect diff --git a/go.sum b/go.sum index 01c1d0f..c156146 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,8 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= +github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -135,6 +137,12 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/twmb/franz-go v1.13.6 h1:DRh06Hy3GthZuA+fQhDo+IMV+QUZHQfS2TIiWf/rCw8= +github.com/twmb/franz-go v1.13.6/go.mod h1:jm/FtYxmhxDTN0gNSb26XaJY0irdSVcsckLiR5tQNMk= +github.com/twmb/franz-go/pkg/kadm v1.8.1 h1:SrzL855I7gQTGdMtOYGTHhebs7TPgPN29FPtjusqwlE= +github.com/twmb/franz-go/pkg/kadm v1.8.1/go.mod h1:qUSM7pxoMCU1UNu5H4USE64ODcVmeG9LS96mysv1nu8= +github.com/twmb/franz-go/pkg/kmsg v1.4.0 h1:tbp9hxU6m8qZhQTlpGiaIJOm4BXix5lsuEZ7K00dF0s= +github.com/twmb/franz-go/pkg/kmsg v1.4.0/go.mod h1:SxG/xJKhgPu25SamAq0rrucfp7lbzCpEXOC+vH/ELrY= github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= diff --git a/internal/app/app.go b/internal/app/app.go index 8d63084..5507b6a 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -8,6 +8,7 @@ import ( "syscall" "time" + "github.com/twmb/franz-go/pkg/kgo" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger" @@ -15,6 +16,7 @@ import ( "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/server" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils" "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/closer" + "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/kafka" "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo" ) @@ -30,10 +32,16 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) { } }() + closer := closer.New() + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() - closer := closer.New() + if err := kafka.Initialize(ctx, config.Service.Kafka.Brokers, []string{ + config.Service.Kafka.Tariff.Topic, + }); err != nil { + return err + } mongoDB, err := mongo.Connect(ctx, &mongo.ConnectDeps{ Configuration: &config.Database, @@ -43,6 +51,21 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) { return fmt.Errorf("failed connection to db: %w", err) } + kafkaTariffClient, err := kgo.NewClient( + kgo.SeedBrokers(config.Service.Kafka.Brokers...), + kgo.ConsumeResetOffset(kgo.NewOffset().AtStart()), + kgo.DefaultProduceTopic(config.Service.Kafka.Tariff.Topic), + kgo.ConsumeTopics(config.Service.Kafka.Tariff.Topic), + ) + if err != nil { + return err + } + + brokers := initialize.NewBrokers(initialize.BrokersDeps{ + Logger: logger, + TariffClient: kafkaTariffClient, + }) + clients := initialize.NewClients(initialize.ClientsDeps{ Logger: logger, AuthURL: &config.Service.AuthMicroservice.URL, @@ -62,6 +85,7 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) { Repositories: repositories, Clients: clients, ConfigurationGRPC: &config.GRPC, + Brokers: brokers, }) controllers := initialize.NewControllers(initialize.ControllersDeps{ @@ -99,6 +123,7 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) { closer.Add(mongoDB.Client().Disconnect) closer.Add(serverHTTP.Stop) closer.Add(serverGRPC.Stop) + closer.Add(closer.Wrap(kafkaTariffClient.Close)) <-ctx.Done() diff --git a/internal/initialize/api_test.go b/internal/initialize/api_test.go index a2b4bcd..9772184 100644 --- a/internal/initialize/api_test.go +++ b/internal/initialize/api_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/twmb/franz-go/pkg/kgo" "go.mongodb.org/mongo-driver/mongo/integration/mtest" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize" @@ -31,11 +32,17 @@ func TestNewAPI(t *testing.T) { PaymentServiceConfiguration: &models.PaymentMicroserviceConfiguration{HostGRPC: "host"}, }) + brokers := initialize.NewBrokers(initialize.BrokersDeps{ + Logger: logger, + TariffClient: &kgo.Client{}, + }) + services := initialize.NewServices(initialize.ServicesDeps{ Logger: logger, Repositories: repositories, Clients: clients, ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "domen"}, + Brokers: brokers, }) controllers := initialize.NewControllers(initialize.ControllersDeps{ diff --git a/internal/initialize/brokers.go b/internal/initialize/brokers.go new file mode 100644 index 0000000..d041459 --- /dev/null +++ b/internal/initialize/brokers.go @@ -0,0 +1,30 @@ +package initialize + +import ( + "github.com/twmb/franz-go/pkg/kgo" + "go.uber.org/zap" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/broker/tariff" +) + +type BrokersDeps struct { + Logger *zap.Logger + TariffClient *kgo.Client +} + +type Brokers struct { + TariffConsumer *tariff.Consumer + TariffProducer *tariff.Producer +} + +func NewBrokers(deps BrokersDeps) *Brokers { + return &Brokers{ + TariffConsumer: tariff.NewConsumer(tariff.ConsumerDeps{ + Logger: deps.Logger, + Client: deps.TariffClient, + }), + TariffProducer: tariff.NewProducer(tariff.ProducerDeps{ + Logger: deps.Logger, + Client: deps.TariffClient, + }), + } +} diff --git a/internal/initialize/brokers_test.go b/internal/initialize/brokers_test.go new file mode 100644 index 0000000..d6ca211 --- /dev/null +++ b/internal/initialize/brokers_test.go @@ -0,0 +1,27 @@ +package initialize_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/twmb/franz-go/pkg/kgo" + "go.uber.org/zap" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize" +) + +func TestNewBrokers(t *testing.T) { + t.Run("Брокеры должны успешно инициализироваться", func(t *testing.T) { + logger := zap.New(zap.L().Core()) + + assert.NotPanics(t, func() { + brokers := initialize.NewBrokers(initialize.BrokersDeps{ + Logger: logger, + TariffClient: &kgo.Client{}, + }) + + assert.NotNil(t, brokers) + assert.NotNil(t, brokers.TariffConsumer) + assert.NotNil(t, brokers.TariffProducer) + }) + }) +} diff --git a/internal/initialize/config.go b/internal/initialize/config.go index c021baf..d36cecf 100644 --- a/internal/initialize/config.go +++ b/internal/initialize/config.go @@ -9,6 +9,8 @@ import ( "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/env" ) +// TODO: обработать возможность читать конфиги ещё по json + func Configuration(path string) (*models.Config, error) { config, err := env.Parse[models.Config](path) if err != nil { diff --git a/internal/initialize/config_test.go b/internal/initialize/config_test.go index 1345ed2..2f1fb60 100644 --- a/internal/initialize/config_test.go +++ b/internal/initialize/config_test.go @@ -74,6 +74,10 @@ func setDefaultTestingENV(t *testing.T) *models.Config { AuthMicroservice: models.AuthMicroserviceConfiguration{ URL: defaultAuthURL, }, + Kafka: models.KafkaConfiguration{ + Tariff: models.TariffKafkaConfiguration{Topic: "topic"}, + Brokers: []string{"localhost:8080", "localhost:8081"}, + }, HubadminMicroservice: models.HubadminMicroserviceConfiguration{ URL: defaultHubAdminURL, }, @@ -114,6 +118,9 @@ func setDefaultTestingENV(t *testing.T) *models.Config { t.Setenv("JWT_ISSUER", defaultConfiguration.Service.JWT.Issuer) t.Setenv("JWT_AUDIENCE", defaultConfiguration.Service.JWT.Audience) + t.Setenv("KAFKA_BROKERS", "localhost:8080,localhost:8081") + t.Setenv("KAFKA_TOPIC_TARIFF", defaultConfiguration.Service.Kafka.Tariff.Topic) + t.Setenv("AUTH_MICROSERVICE_USER_URL", defaultConfiguration.Service.AuthMicroservice.URL.User) t.Setenv("HUBADMIN_MICROSERVICE_TARIFF_URL", defaultConfiguration.Service.HubadminMicroservice.URL.Tariff) t.Setenv("CURRENCY_MICROSERVICE_TRANSLATE_URL", defaultConfiguration.Service.CurrencyMicroservice.URL.Translate) diff --git a/internal/initialize/controllers_test.go b/internal/initialize/controllers_test.go index 3d299e9..ed0a658 100644 --- a/internal/initialize/controllers_test.go +++ b/internal/initialize/controllers_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/twmb/franz-go/pkg/kgo" "go.mongodb.org/mongo-driver/mongo/integration/mtest" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize" @@ -31,10 +32,16 @@ func TestNewControllers(t *testing.T) { MongoDB: t.Client.Database("test"), }) + brokers := initialize.NewBrokers(initialize.BrokersDeps{ + Logger: logger, + TariffClient: &kgo.Client{}, + }) + services := initialize.NewServices(initialize.ServicesDeps{ Logger: logger, Clients: clients, Repositories: repositories, + Brokers: brokers, ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "http://test:8080"}, }) diff --git a/internal/initialize/services.go b/internal/initialize/services.go index e8f6162..3ae1e6a 100644 --- a/internal/initialize/services.go +++ b/internal/initialize/services.go @@ -4,6 +4,7 @@ import ( "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/account" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/broker/tariff" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/callback" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/cart" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/currency" @@ -16,6 +17,7 @@ type ServicesDeps struct { Logger *zap.Logger Repositories *Repositories Clients *Clients + Brokers *Brokers ConfigurationGRPC *models.ConfigurationGRPC } @@ -27,6 +29,7 @@ type Services struct { WalletService *wallet.Service PaymentService *payment.Service PaymentCallbackService *callback.PaymentCallbackService + TariffBrokerService *tariff.Service } func NewServices(deps ServicesDeps) *Services { @@ -42,6 +45,12 @@ func NewServices(deps ServicesDeps) *Services { HistoryService: historyService, }) + tariffBrokerService := tariff.New(tariff.Deps{ + Logger: deps.Logger, + Consumer: deps.Brokers.TariffConsumer, + Producer: deps.Brokers.TariffProducer, + }) + return &Services{ WalletService: walletService, HistoryService: historyService, @@ -55,12 +64,13 @@ func NewServices(deps ServicesDeps) *Services { Repository: deps.Repositories.CurrencyRepository, }), CartService: cart.New(cart.Deps{ - Logger: deps.Logger, - Repository: deps.Repositories.AccountRepository, - HubadminClient: deps.Clients.HubadminClient, - DiscountClient: deps.Clients.DiscountClient, - WalletService: walletService, - HistoryService: historyService, + Logger: deps.Logger, + Repository: deps.Repositories.AccountRepository, + HubadminClient: deps.Clients.HubadminClient, + DiscountClient: deps.Clients.DiscountClient, + WalletService: walletService, + HistoryService: historyService, + TariffBrokerService: tariffBrokerService, }), PaymentService: payment.New(payment.Deps{ Logger: deps.Logger, @@ -74,5 +84,6 @@ func NewServices(deps ServicesDeps) *Services { WalletService: walletService, HistoryService: historyService, }), + TariffBrokerService: tariffBrokerService, } } diff --git a/internal/initialize/services_test.go b/internal/initialize/services_test.go index 8de4726..503b0e8 100644 --- a/internal/initialize/services_test.go +++ b/internal/initialize/services_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/twmb/franz-go/pkg/kgo" "go.mongodb.org/mongo-driver/mongo/integration/mtest" "go.uber.org/zap" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize" @@ -26,6 +27,11 @@ func TestNewServices(t *testing.T) { PaymentServiceConfiguration: &models.PaymentMicroserviceConfiguration{HostGRPC: "host"}, }) + brokers := initialize.NewBrokers(initialize.BrokersDeps{ + Logger: logger, + TariffClient: &kgo.Client{}, + }) + repositories := initialize.NewRepositories(initialize.RepositoriesDeps{ Logger: logger, MongoDB: t.Client.Database("test"), @@ -35,6 +41,7 @@ func TestNewServices(t *testing.T) { Logger: logger, Clients: clients, Repositories: repositories, + Brokers: brokers, ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "http://test:8080"}, }) @@ -46,6 +53,7 @@ func TestNewServices(t *testing.T) { assert.NotNil(t, services.WalletService) assert.NotNil(t, services.PaymentService) assert.NotNil(t, services.PaymentCallbackService) + assert.NotNil(t, services.TariffBrokerService) }) }) } diff --git a/internal/interface/broker/tariff/consumer.go b/internal/interface/broker/tariff/consumer.go new file mode 100644 index 0000000..ab16351 --- /dev/null +++ b/internal/interface/broker/tariff/consumer.go @@ -0,0 +1,65 @@ +package tariff + +import ( + "context" + "fmt" + "log" + + "github.com/twmb/franz-go/pkg/kgo" + "go.uber.org/zap" + "google.golang.org/protobuf/proto" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/broker" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils/transfer" +) + +type ConsumerDeps struct { + Logger *zap.Logger + Client *kgo.Client +} + +type Consumer struct { + logger *zap.Logger + client *kgo.Client +} + +func NewConsumer(deps ConsumerDeps) *Consumer { + if deps.Logger == nil { + log.Panicln("logger is nil on ") + } + + if deps.Client == nil { + log.Panicln("Kafka client is nil on ") + } + + return &Consumer{ + logger: deps.Logger, + client: deps.Client, + } +} + +func (receiver *Consumer) FetchPrivileges(ctx context.Context) []models.Privilege { + fetches := receiver.client.PollFetches(ctx) + iter := fetches.RecordIter() + + tariffs := make([]models.Tariff, 0) + privileges := make([]models.Privilege, 0) + + for !iter.Done() { + record := iter.Next() + tariff := broker.TariffMessage{} + + if err := proto.Unmarshal(record.Value, &tariff); err != nil { + receiver.logger.Error(fmt.Sprintf("error decoding message: %v\n", err)) + continue + } + + tariffs = append(tariffs, *transfer.TariffMessageProtoToTariffModel(&tariff)) + } + + for _, tariff := range tariffs { + privileges = append(privileges, tariff.Privileges...) + } + + return privileges +} diff --git a/internal/interface/broker/tariff/producer.go b/internal/interface/broker/tariff/producer.go new file mode 100644 index 0000000..0a9ea21 --- /dev/null +++ b/internal/interface/broker/tariff/producer.go @@ -0,0 +1,61 @@ +package tariff + +import ( + "context" + "fmt" + "log" + + "github.com/twmb/franz-go/pkg/kgo" + "go.uber.org/zap" + "google.golang.org/protobuf/proto" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils/transfer" +) + +type ProducerDeps struct { + Logger *zap.Logger + Client *kgo.Client + Topic string +} + +type Producer struct { + logger *zap.Logger + client *kgo.Client + topic string +} + +func NewProducer(deps ProducerDeps) *Producer { + if deps.Logger == nil { + log.Panicln("logger is nil on ") + } + + if deps.Client == nil { + log.Panicln("Kafka client is nil on ") + } + + return &Producer{ + logger: deps.Logger, + client: deps.Client, + topic: deps.Topic, + } +} + +func (receiver *Producer) Send(ctx context.Context, userID string, tariff *models.Tariff) errors.Error { + bytes, err := proto.Marshal(transfer.TariffModelToProtoMessage(userID, tariff)) + if err != nil { + receiver.logger.Error("failed to marshal tariff model on of ") + return errors.New(fmt.Errorf("failed to marshal tariff: %w", err), errors.ErrInternalError) + } + + responses := receiver.client.ProduceSync(ctx, &kgo.Record{Value: bytes}) + + for _, response := range responses { + if response.Err != nil { + receiver.logger.Error("failed to send tariff on of ", zap.Error(response.Err)) + return errors.New(fmt.Errorf("failed to send tariff: %w", response.Err), errors.ErrInternalError) + } + } + + return nil +} diff --git a/internal/interface/controller/rest/cart/cart.go b/internal/interface/controller/rest/cart/cart.go index 5544ee1..71cd8fe 100644 --- a/internal/interface/controller/rest/cart/cart.go +++ b/internal/interface/controller/rest/cart/cart.go @@ -17,7 +17,7 @@ import ( type cartService interface { Remove(ctx context.Context, userID, itemID string) ([]string, errors.Error) Add(context.Context, *models.AddItemToCart) ([]string, errors.Error) - Pay(ctx context.Context, token, userID string) (link string, err errors.Error) + Pay(ctx context.Context, token, userID string) errors.Error } type Deps struct { @@ -114,15 +114,10 @@ func (receiver *Controller) Pay(ctx echo.Context) error { return errors.HTTP(ctx, errors.NewWithMessage("failed to convert access token payload to string", errors.ErrInvalidArgs)) } - link, err := receiver.cartService.Pay(ctx.Request().Context(), token, userID) - if err != nil { + if err := receiver.cartService.Pay(ctx.Request().Context(), token, userID); err != nil { receiver.logger.Error("failed to pay cart on of ", zap.Error(err)) return errors.HTTP(ctx, err) } - if !validate.IsStringEmpty(link) { - return ctx.Redirect(http.StatusTemporaryRedirect, link) - } - return ctx.JSON(http.StatusOK, true) } diff --git a/internal/models/config.go b/internal/models/config.go index 19ceec0..ef9a9b5 100644 --- a/internal/models/config.go +++ b/internal/models/config.go @@ -32,6 +32,16 @@ type ServiceConfiguration struct { DiscountMicroservice DiscountMicroserviceConfiguration PaymentMicroservice PaymentMicroserviceConfiguration JWT JWTConfiguration + Kafka KafkaConfiguration +} + +type KafkaConfiguration struct { + Tariff TariffKafkaConfiguration `json:"tariff"` + Brokers []string `json:"brokers" env:"KAFKA_BROKERS,required"` +} + +type TariffKafkaConfiguration struct { + Topic string `json:"topic" env:"KAFKA_TOPIC_TARIFF,required"` } type JWTConfiguration struct { diff --git a/internal/models/tariff.go b/internal/models/tariff.go index 12e86a4..79b2a22 100644 --- a/internal/models/tariff.go +++ b/internal/models/tariff.go @@ -3,15 +3,15 @@ package models import "time" type Tariff struct { - ID string `json:"_id"` - Name string `json:"name"` - Price int64 `json:"price"` - IsCustom bool `json:"isCustom"` - Privileges map[string]Privilege `json:"privileges"` - Deleted bool `json:"isDeleted"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt *time.Time `json:"deletedAt,omitempty"` + ID string `json:"_id"` + Name string `json:"name"` + Price int64 `json:"price"` + IsCustom bool `json:"isCustom"` + Privileges []Privilege `json:"privileges"` + Deleted bool `json:"isDeleted"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt,omitempty"` } type Privilege struct { diff --git a/internal/proto/broker/models.pb.go b/internal/proto/broker/models.pb.go new file mode 100644 index 0000000..55e57ed --- /dev/null +++ b/internal/proto/broker/models.pb.go @@ -0,0 +1,247 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc (unknown) +// source: broker/models.proto + +package broker + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PrivilegeMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PrivilegeID string `protobuf:"bytes,1,opt,name=PrivilegeID,proto3" json:"PrivilegeID,omitempty"` + ServiceKey string `protobuf:"bytes,2,opt,name=ServiceKey,proto3" json:"ServiceKey,omitempty"` + Type string `protobuf:"bytes,3,opt,name=Type,proto3" json:"Type,omitempty"` + Value string `protobuf:"bytes,4,opt,name=Value,proto3" json:"Value,omitempty"` +} + +func (x *PrivilegeMessage) Reset() { + *x = PrivilegeMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_broker_models_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PrivilegeMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrivilegeMessage) ProtoMessage() {} + +func (x *PrivilegeMessage) ProtoReflect() protoreflect.Message { + mi := &file_broker_models_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrivilegeMessage.ProtoReflect.Descriptor instead. +func (*PrivilegeMessage) Descriptor() ([]byte, []int) { + return file_broker_models_proto_rawDescGZIP(), []int{0} +} + +func (x *PrivilegeMessage) GetPrivilegeID() string { + if x != nil { + return x.PrivilegeID + } + return "" +} + +func (x *PrivilegeMessage) GetServiceKey() string { + if x != nil { + return x.ServiceKey + } + return "" +} + +func (x *PrivilegeMessage) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *PrivilegeMessage) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type TariffMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Privileges []*PrivilegeMessage `protobuf:"bytes,1,rep,name=Privileges,proto3" json:"Privileges,omitempty"` + UserID string `protobuf:"bytes,2,opt,name=UserID,proto3" json:"UserID,omitempty"` +} + +func (x *TariffMessage) Reset() { + *x = TariffMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_broker_models_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TariffMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TariffMessage) ProtoMessage() {} + +func (x *TariffMessage) ProtoReflect() protoreflect.Message { + mi := &file_broker_models_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TariffMessage.ProtoReflect.Descriptor instead. +func (*TariffMessage) Descriptor() ([]byte, []int) { + return file_broker_models_proto_rawDescGZIP(), []int{1} +} + +func (x *TariffMessage) GetPrivileges() []*PrivilegeMessage { + if x != nil { + return x.Privileges + } + return nil +} + +func (x *TariffMessage) GetUserID() string { + if x != nil { + return x.UserID + } + return "" +} + +var File_broker_models_proto protoreflect.FileDescriptor + +var file_broker_models_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x22, 0x7e, 0x0a, + 0x10, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x49, 0x44, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, + 0x65, 0x49, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x61, 0x0a, + 0x0d, 0x54, 0x61, 0x72, 0x69, 0x66, 0x66, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, + 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x76, + 0x69, 0x6c, 0x65, 0x67, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x50, 0x72, + 0x69, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, + 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_broker_models_proto_rawDescOnce sync.Once + file_broker_models_proto_rawDescData = file_broker_models_proto_rawDesc +) + +func file_broker_models_proto_rawDescGZIP() []byte { + file_broker_models_proto_rawDescOnce.Do(func() { + file_broker_models_proto_rawDescData = protoimpl.X.CompressGZIP(file_broker_models_proto_rawDescData) + }) + return file_broker_models_proto_rawDescData +} + +var file_broker_models_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_broker_models_proto_goTypes = []interface{}{ + (*PrivilegeMessage)(nil), // 0: broker.PrivilegeMessage + (*TariffMessage)(nil), // 1: broker.TariffMessage +} +var file_broker_models_proto_depIdxs = []int32{ + 0, // 0: broker.TariffMessage.Privileges:type_name -> broker.PrivilegeMessage + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_broker_models_proto_init() } +func file_broker_models_proto_init() { + if File_broker_models_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_broker_models_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PrivilegeMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_broker_models_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TariffMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_broker_models_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_broker_models_proto_goTypes, + DependencyIndexes: file_broker_models_proto_depIdxs, + MessageInfos: file_broker_models_proto_msgTypes, + }.Build() + File_broker_models_proto = out.File + file_broker_models_proto_rawDesc = nil + file_broker_models_proto_goTypes = nil + file_broker_models_proto_depIdxs = nil +} diff --git a/internal/proto/discount/discount.model.pb.go b/internal/proto/discount/discount.model.pb.go index 5a1ba58..a852324 100644 --- a/internal/proto/discount/discount.model.pb.go +++ b/internal/proto/discount/discount.model.pb.go @@ -83,6 +83,7 @@ type DiscountOptional struct { Description *string `protobuf:"bytes,4,opt,name=Description,proto3,oneof" json:"Description,omitempty"` Condition *DiscountCondition `protobuf:"bytes,5,opt,name=Condition,proto3,oneof" json:"Condition,omitempty"` Target *DiscountCalculationTarget `protobuf:"bytes,6,opt,name=Target,proto3,oneof" json:"Target,omitempty"` + Deprecated *bool `protobuf:"varint,7,opt,name=Deprecated,proto3,oneof" json:"Deprecated,omitempty"` } func (x *DiscountOptional) Reset() { @@ -159,6 +160,13 @@ func (x *DiscountOptional) GetTarget() *DiscountCalculationTarget { return nil } +func (x *DiscountOptional) GetDeprecated() bool { + if x != nil && x.Deprecated != nil { + return *x.Deprecated + } + return false +} + type Discounts struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -397,12 +405,12 @@ type DiscountCondition struct { User *string `protobuf:"bytes,2,opt,name=User,proto3,oneof" json:"User,omitempty"` UserType *string `protobuf:"bytes,3,opt,name=UserType,proto3,oneof" json:"UserType,omitempty"` Coupon *string `protobuf:"bytes,4,opt,name=Coupon,proto3,oneof" json:"Coupon,omitempty"` - PurchasesAmount *float64 `protobuf:"fixed64,5,opt,name=PurchasesAmount,proto3,oneof" json:"PurchasesAmount,omitempty"` - CartPurchasesAmount *float64 `protobuf:"fixed64,6,opt,name=CartPurchasesAmount,proto3,oneof" json:"CartPurchasesAmount,omitempty"` + PurchasesAmount *uint64 `protobuf:"varint,5,opt,name=PurchasesAmount,proto3,oneof" json:"PurchasesAmount,omitempty"` + CartPurchasesAmount *uint64 `protobuf:"varint,6,opt,name=CartPurchasesAmount,proto3,oneof" json:"CartPurchasesAmount,omitempty"` Product *string `protobuf:"bytes,7,opt,name=Product,proto3,oneof" json:"Product,omitempty"` Term *uint64 `protobuf:"varint,8,opt,name=Term,proto3,oneof" json:"Term,omitempty"` Usage *uint64 `protobuf:"varint,9,opt,name=Usage,proto3,oneof" json:"Usage,omitempty"` - PriceFrom *float64 `protobuf:"fixed64,10,opt,name=PriceFrom,proto3,oneof" json:"PriceFrom,omitempty"` + PriceFrom *uint64 `protobuf:"varint,10,opt,name=PriceFrom,proto3,oneof" json:"PriceFrom,omitempty"` Group *string `protobuf:"bytes,11,opt,name=Group,proto3,oneof" json:"Group,omitempty"` } @@ -466,14 +474,14 @@ func (x *DiscountCondition) GetCoupon() string { return "" } -func (x *DiscountCondition) GetPurchasesAmount() float64 { +func (x *DiscountCondition) GetPurchasesAmount() uint64 { if x != nil && x.PurchasesAmount != nil { return *x.PurchasesAmount } return 0 } -func (x *DiscountCondition) GetCartPurchasesAmount() float64 { +func (x *DiscountCondition) GetCartPurchasesAmount() uint64 { if x != nil && x.CartPurchasesAmount != nil { return *x.CartPurchasesAmount } @@ -501,7 +509,7 @@ func (x *DiscountCondition) GetUsage() uint64 { return 0 } -func (x *DiscountCondition) GetPriceFrom() float64 { +func (x *DiscountCondition) GetPriceFrom() uint64 { if x != nil && x.PriceFrom != nil { return *x.PriceFrom } @@ -638,10 +646,10 @@ type UserInformation struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` - Type string `protobuf:"bytes,2,opt,name=Type,proto3" json:"Type,omitempty"` - PurchasesAmount float64 `protobuf:"fixed64,3,opt,name=PurchasesAmount,proto3" json:"PurchasesAmount,omitempty"` - CartPurchasesAmount float64 `protobuf:"fixed64,4,opt,name=CartPurchasesAmount,proto3" json:"CartPurchasesAmount,omitempty"` + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + Type string `protobuf:"bytes,2,opt,name=Type,proto3" json:"Type,omitempty"` + PurchasesAmount uint64 `protobuf:"varint,3,opt,name=PurchasesAmount,proto3" json:"PurchasesAmount,omitempty"` + CartPurchasesAmount uint64 `protobuf:"varint,4,opt,name=CartPurchasesAmount,proto3" json:"CartPurchasesAmount,omitempty"` } func (x *UserInformation) Reset() { @@ -690,14 +698,14 @@ func (x *UserInformation) GetType() string { return "" } -func (x *UserInformation) GetPurchasesAmount() float64 { +func (x *UserInformation) GetPurchasesAmount() uint64 { if x != nil { return x.PurchasesAmount } return 0 } -func (x *UserInformation) GetCartPurchasesAmount() float64 { +func (x *UserInformation) GetCartPurchasesAmount() uint64 { if x != nil { return x.CartPurchasesAmount } @@ -710,7 +718,7 @@ type ProductInformation struct { unknownFields protoimpl.UnknownFields ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` - Price float64 `protobuf:"fixed64,2,opt,name=Price,proto3" json:"Price,omitempty"` + Price uint64 `protobuf:"varint,2,opt,name=Price,proto3" json:"Price,omitempty"` Term *uint64 `protobuf:"varint,3,opt,name=Term,proto3,oneof" json:"Term,omitempty"` Usage *uint64 `protobuf:"varint,4,opt,name=Usage,proto3,oneof" json:"Usage,omitempty"` Group *string `protobuf:"bytes,5,opt,name=Group,proto3,oneof" json:"Group,omitempty"` @@ -755,7 +763,7 @@ func (x *ProductInformation) GetID() string { return "" } -func (x *ProductInformation) GetPrice() float64 { +func (x *ProductInformation) GetPrice() uint64 { if x != nil { return x.Price } @@ -796,7 +804,7 @@ var file_discount_discount_model_proto_rawDesc = []byte{ 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xbb, 0x02, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x70, + 0x6f, 0x22, 0xef, 0x02, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x17, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, @@ -812,123 +820,126 @@ var file_discount_discount_model_proto_rawDesc = []byte{ 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x04, 0x52, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, - 0x5f, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, - 0x3d, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x09, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x09, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0xa5, - 0x02, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, - 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, - 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, - 0x25, 0x0a, 0x05, 0x41, 0x75, 0x64, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x52, - 0x05, 0x41, 0x75, 0x64, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x44, 0x65, 0x70, 0x72, - 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x9b, 0x02, 0x0a, 0x19, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x61, 0x63, - 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x46, 0x61, 0x63, 0x74, 0x6f, - 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x48, 0x00, 0x52, - 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, - 0x25, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, - 0x6c, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x08, 0x4f, 0x76, 0x65, 0x72, - 0x68, 0x65, 0x6c, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x4f, 0x76, 0x65, 0x72, - 0x68, 0x65, 0x6c, 0x6d, 0x22, 0xa8, 0x04, 0x0a, 0x11, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x06, 0x50, 0x65, - 0x72, 0x69, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x88, - 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x01, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x55, - 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, - 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, - 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x06, - 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x0f, 0x50, 0x75, 0x72, - 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x01, 0x48, 0x04, 0x52, 0x0f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x13, 0x43, 0x61, 0x72, 0x74, - 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x01, 0x48, 0x05, 0x52, 0x13, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, - 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, - 0x1d, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x06, 0x52, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x88, 0x01, 0x01, 0x12, 0x17, - 0x0a, 0x04, 0x54, 0x65, 0x72, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x48, 0x07, 0x52, 0x04, - 0x54, 0x65, 0x72, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48, 0x08, 0x52, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x88, - 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x50, 0x72, 0x69, 0x63, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x01, 0x48, 0x09, 0x52, 0x09, 0x50, 0x72, 0x69, 0x63, 0x65, 0x46, 0x72, - 0x6f, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x0a, 0x52, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x88, 0x01, 0x01, - 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x5f, - 0x55, 0x73, 0x65, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x55, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, - 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x42, 0x12, 0x0a, 0x10, - 0x5f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, - 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x50, 0x72, 0x6f, - 0x64, 0x75, 0x63, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x54, 0x65, 0x72, 0x6d, 0x42, 0x08, 0x0a, - 0x06, 0x5f, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x50, 0x72, 0x69, 0x63, - 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, - 0x65, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, - 0x12, 0x16, 0x0a, 0x06, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, - 0x52, 0x06, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x08, 0x4f, 0x76, 0x65, 0x72, - 0x68, 0x65, 0x6c, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x4f, 0x76, - 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x4f, 0x76, - 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x22, 0x6d, 0x0a, 0x0f, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, - 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x46, 0x72, 0x6f, - 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x04, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x2a, 0x0a, 0x02, 0x54, 0x6f, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x02, 0x54, 0x6f, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, - 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, + 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0a, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, 0x52, 0x0a, 0x44, 0x65, 0x70, 0x72, 0x65, + 0x63, 0x61, 0x74, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x4e, 0x61, 0x6d, + 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, + 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x22, 0x3d, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x12, 0x30, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x09, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, + 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09, 0x43, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x43, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x12, 0x25, 0x0a, 0x05, 0x41, 0x75, 0x64, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x75, + 0x64, 0x69, 0x74, 0x52, 0x05, 0x41, 0x75, 0x64, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x22, 0x9b, 0x02, 0x0a, 0x19, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x46, + 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x48, 0x00, 0x52, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, + 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x4f, 0x76, + 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x48, 0x02, 0x52, 0x08, + 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x0b, 0x0a, 0x09, 0x5f, + 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x22, 0xa8, 0x04, 0x0a, 0x11, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, + 0x0a, 0x06, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, + 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x50, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, + 0x1f, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x02, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, + 0x12, 0x1b, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x03, 0x52, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x0f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, - 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x13, 0x43, 0x61, 0x72, 0x74, 0x50, - 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x01, 0x52, 0x13, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, - 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x12, 0x50, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, - 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x54, 0x65, 0x72, 0x6d, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, 0x54, 0x65, 0x72, 0x6d, 0x88, 0x01, 0x01, 0x12, - 0x19, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, - 0x52, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x05, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x54, 0x65, 0x72, 0x6d, 0x42, 0x08, - 0x0a, 0x06, 0x5f, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x2a, 0x2b, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x63, 0x6f, 0x70, - 0x65, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x75, 0x6d, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x61, 0x63, 0x68, 0x10, 0x02, 0x42, - 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x48, 0x04, 0x52, 0x0f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, + 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x13, + 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x48, 0x05, 0x52, 0x13, 0x43, 0x61, 0x72, + 0x74, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x88, + 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x54, 0x65, 0x72, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, + 0x48, 0x07, 0x52, 0x04, 0x54, 0x65, 0x72, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48, 0x08, 0x52, 0x05, 0x55, 0x73, + 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x50, 0x72, 0x69, 0x63, 0x65, 0x46, + 0x72, 0x6f, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x48, 0x09, 0x52, 0x09, 0x50, 0x72, 0x69, + 0x63, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x0a, 0x52, 0x05, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x42, + 0x07, 0x0a, 0x05, 0x5f, 0x55, 0x73, 0x65, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x55, 0x73, 0x65, + 0x72, 0x54, 0x79, 0x70, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, + 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, + 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, + 0x5f, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x54, 0x65, 0x72, + 0x6d, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, + 0x50, 0x72, 0x69, 0x63, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x22, 0x65, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x08, + 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, + 0x52, 0x08, 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, + 0x09, 0x5f, 0x4f, 0x76, 0x65, 0x72, 0x68, 0x65, 0x6c, 0x6d, 0x22, 0x6d, 0x0a, 0x0f, 0x50, 0x65, + 0x72, 0x69, 0x6f, 0x64, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, + 0x04, 0x46, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x2a, 0x0a, + 0x02, 0x54, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x02, 0x54, 0x6f, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, + 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, + 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x50, 0x75, 0x72, 0x63, + 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x13, 0x43, + 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, + 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x73, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa6, 0x01, + 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x04, 0x54, 0x65, + 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, 0x54, 0x65, 0x72, 0x6d, + 0x88, 0x01, 0x01, 0x12, 0x19, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x48, 0x01, 0x52, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x19, + 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, + 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x54, 0x65, + 0x72, 0x6d, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x55, 0x73, 0x61, 0x67, 0x65, 0x42, 0x08, 0x0a, 0x06, + 0x5f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2a, 0x2b, 0x0a, 0x0b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x75, 0x6d, 0x10, 0x00, 0x12, 0x09, + 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x61, 0x63, + 0x68, 0x10, 0x02, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/proto/discount/service.pb.go b/internal/proto/discount/service.pb.go index 5152942..17cd2ef 100644 --- a/internal/proto/discount/service.pb.go +++ b/internal/proto/discount/service.pb.go @@ -146,7 +146,7 @@ type ApplyDiscountResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Price float64 `protobuf:"fixed64,1,opt,name=Price,proto3" json:"Price,omitempty"` + Price uint64 `protobuf:"varint,1,opt,name=Price,proto3" json:"Price,omitempty"` AppliedDiscounts []*Discount `protobuf:"bytes,2,rep,name=AppliedDiscounts,proto3" json:"AppliedDiscounts,omitempty"` } @@ -182,7 +182,7 @@ func (*ApplyDiscountResponse) Descriptor() ([]byte, []int) { return file_discount_service_proto_rawDescGZIP(), []int{2} } -func (x *ApplyDiscountResponse) GetPrice() float64 { +func (x *ApplyDiscountResponse) GetPrice() uint64 { if x != nil { return x.Price } @@ -307,7 +307,7 @@ var file_discount_service_proto_rawDesc = []byte{ 0x00, 0x52, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, @@ -327,44 +327,44 @@ var file_discount_service_proto_rawDesc = []byte{ 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x32, 0x80, 0x07, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, - 0x12, 0x0d, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x6c, 0x6c, 0x12, - 0x66, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x47, - 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x15, 0x12, 0x13, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x75, 0x73, - 0x65, 0x72, 0x2f, 0x7b, 0x49, 0x44, 0x7d, 0x12, 0x69, 0x0a, 0x12, 0x44, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, - 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x73, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x65, 0x12, 0x6d, 0x0a, 0x0e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, - 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, - 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a, - 0x22, 0x0f, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x70, 0x70, 0x6c, - 0x79, 0x12, 0x5f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x42, 0x79, 0x49, 0x44, 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, - 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x7b, 0x49, - 0x44, 0x7d, 0x12, 0x58, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x0b, 0x22, 0x09, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x0f, + 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, + 0x12, 0x0a, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x66, 0x0a, 0x10, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, + 0x13, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, + 0x7b, 0x49, 0x44, 0x7d, 0x12, 0x69, 0x0a, 0x12, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, + 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x12, + 0x6d, 0x0a, 0x0e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x73, 0x12, 0x1e, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a, 0x22, 0x0f, 0x2f, + 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x5f, + 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, + 0x44, 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, + 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, + 0x0e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x7b, 0x49, 0x44, 0x7d, 0x12, + 0x5b, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x14, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0e, 0x3a, 0x01, + 0x2a, 0x22, 0x09, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x1a, 0x12, 0x2e, 0x64, 0x69, diff --git a/internal/service/broker/tariff/tariff.go b/internal/service/broker/tariff/tariff.go new file mode 100644 index 0000000..c4bf330 --- /dev/null +++ b/internal/service/broker/tariff/tariff.go @@ -0,0 +1,90 @@ +package tariff + +import ( + "context" + "log" + "sync" + + "go.uber.org/zap" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" +) + +type consumer interface { + FetchPrivileges(context.Context) []models.Privilege +} + +type producer interface { + Send(ctx context.Context, userID string, tariff *models.Tariff) errors.Error +} + +type Deps struct { + Logger *zap.Logger + Consumer consumer + Producer producer +} + +type Service struct { + logger *zap.Logger + consumer consumer + producer producer +} + +func New(deps Deps) *Service { + if deps.Logger == nil { + log.Panicln("logger is nil on ") + } + + if deps.Consumer == nil { + log.Panicln("Consumer is nil on ") + } + + if deps.Producer == nil { + log.Panicln("Producer is nil on ") + } + + return &Service{ + logger: deps.Logger, + consumer: deps.Consumer, + producer: deps.Producer, + } +} + +func (receiver *Service) Send(ctx context.Context, userID string, tariff *models.Tariff) errors.Error { + if tariff == nil { + receiver.logger.Error("tarif is nil on of ") + return errors.NewWithMessage("tariff is nil", errors.ErrInvalidArgs) + } + + if err := receiver.producer.Send(ctx, userID, tariff); err != nil { + receiver.logger.Error("failed to send tariff on of ", zap.Error(err)) + return err + } + + return nil +} + +func (receiver *Service) SendMany(ctx context.Context, userID string, tariffs []models.Tariff) []errors.Error { + sendErrors := make([]errors.Error, 0) + waitGroup := sync.WaitGroup{} + + for _, tariff := range tariffs { + waitGroup.Add(1) + + go func(currentTariff models.Tariff) { + defer waitGroup.Done() + + if err := receiver.Send(ctx, userID, ¤tTariff); err != nil { + sendErrors = append(sendErrors, err) + } + }(tariff) + } + + waitGroup.Wait() + + return sendErrors +} + +func (receiver *Service) Read(ctx context.Context) []models.Privilege { + return receiver.consumer.FetchPrivileges(ctx) +} diff --git a/internal/service/cart/cart.go b/internal/service/cart/cart.go index 0988c23..a67b946 100644 --- a/internal/service/cart/cart.go +++ b/internal/service/cart/cart.go @@ -40,22 +40,28 @@ type historyService interface { CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error) } +type tariffBrokerService interface { + SendMany(ctx context.Context, userID string, tariffs []models.Tariff) []errors.Error +} + type Deps struct { - Logger *zap.Logger - Repository accountRepository - HubadminClient hubadminClient - DiscountClient discountClient - WalletService walletService - HistoryService historyService + Logger *zap.Logger + Repository accountRepository + HubadminClient hubadminClient + DiscountClient discountClient + WalletService walletService + HistoryService historyService + TariffBrokerService tariffBrokerService } type Service struct { - logger *zap.Logger - repository accountRepository - hubadminClient hubadminClient - discountClient discountClient - walletService walletService - historyService historyService + logger *zap.Logger + repository accountRepository + hubadminClient hubadminClient + discountClient discountClient + walletService walletService + historyService historyService + tariffBrokerService tariffBrokerService } func New(deps Deps) *Service { @@ -83,13 +89,18 @@ func New(deps Deps) *Service { log.Panicln("HistoryService is nil on ") } + if deps.TariffBrokerService == nil { + log.Panicln("TariffBrokerService is nil on ") + } + return &Service{ - logger: deps.Logger, - repository: deps.Repository, - hubadminClient: deps.HubadminClient, - discountClient: deps.DiscountClient, - walletService: deps.WalletService, - historyService: deps.HistoryService, + logger: deps.Logger, + repository: deps.Repository, + hubadminClient: deps.HubadminClient, + discountClient: deps.DiscountClient, + walletService: deps.WalletService, + historyService: deps.HistoryService, + tariffBrokerService: deps.TariffBrokerService, } } @@ -131,41 +142,39 @@ func (receiver *Service) Add(ctx context.Context, request *models.AddItemToCart) return account.Cart, nil } -func (receiver *Service) Pay(ctx context.Context, accessToken string, userID string) (string, errors.Error) { +func (receiver *Service) Pay(ctx context.Context, accessToken string, userID string) errors.Error { account, err := receiver.repository.FindByUserID(ctx, userID) if err != nil { receiver.logger.Error("failed to find account on of ", zap.String("userID", userID), zap.Error(err)) - return "", err + return err } tariffs, err := receiver.hubadminClient.GetTariffs(ctx, accessToken, account.Cart) if err != nil { receiver.logger.Error("failed to get tarrifs on of ", zap.Strings("cart", account.Cart), zap.Error(err)) - return "", err + return err } tariffsAmount := utils.CalculateCartPurchasesAmount(tariffs) - // TODO: убрать все конвертеры чисел: float64, int64 - response, err := receiver.discountClient.Apply(ctx, &discount.ApplyDiscountRequest{ UserInformation: &discount.UserInformation{ ID: account.UserID, Type: string(account.Status), - PurchasesAmount: float64(account.Wallet.PurchasesAmount), - CartPurchasesAmount: float64(tariffsAmount), + PurchasesAmount: uint64(account.Wallet.PurchasesAmount), + CartPurchasesAmount: uint64(tariffsAmount), }, Products: transfer.TariffsToProductInformations(tariffs), Date: timestamppb.New(time.Now()), }) if err != nil { receiver.logger.Error("failed to discount on of ", zap.Error(err)) - return "", err + return err } if account.Wallet.Money < int64(response.Price) { receiver.logger.Error("insufficient funds on of ") - return "", errors.New(fmt.Errorf("insufficient funds: %d", int64(response.Price)-account.Wallet.Money), errors.ErrInsufficientFunds) + return errors.New(fmt.Errorf("insufficient funds: %d", int64(response.Price)-account.Wallet.Money), errors.ErrInsufficientFunds) } if _, err := receiver.walletService.WithdrawAccountWalletMoney(ctx, &models.WithdrawAccountWallet{ @@ -173,7 +182,7 @@ func (receiver *Service) Pay(ctx context.Context, accessToken string, userID str Account: account, }); err != nil { receiver.logger.Error("failed to withdraw money on of ", zap.Error(err)) - return "", err + return err } if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{ @@ -184,10 +193,20 @@ func (receiver *Service) Pay(ctx context.Context, accessToken string, userID str receiver.logger.Error("failed to insert history on of ", zap.Error(historyErr)) } - if _, err := receiver.repository.ClearCart(ctx, account.UserID); err != nil { - receiver.logger.Error("failed to clear cart on of ", zap.Error(err)) - return "", err + // TODO: обработать ошибки при отправке сообщений + + if sendErrors := receiver.tariffBrokerService.SendMany(ctx, account.UserID, tariffs); len(sendErrors) > 0 { + for _, err := range sendErrors { + receiver.logger.Error("failed to send tariffs to broker on of ", zap.Error(err)) + } + + return errors.NewWithMessage("failed to send tariffs to broker", errors.ErrInternalError) } - return "", nil + if _, err := receiver.repository.ClearCart(ctx, account.UserID); err != nil { + receiver.logger.Error("failed to clear cart on of ", zap.Error(err)) + return err + } + + return nil } diff --git a/internal/service/wallet/wallet.go b/internal/service/wallet/wallet.go index e0c2f83..41444e6 100644 --- a/internal/service/wallet/wallet.go +++ b/internal/service/wallet/wallet.go @@ -80,10 +80,7 @@ func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *mo To: request.Account.Wallet.Currency, }) if translateErr != nil { - receiver.logger.Error("failed to translate cash on of ", - zap.Error(translateErr), - ) - + receiver.logger.Error("failed to translate cash on of ", zap.Error(translateErr)) return nil, translateErr } @@ -127,10 +124,7 @@ func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *mo To: models.InternalCurrencyKey, }) if err != nil { - receiver.logger.Error("failed to translate money on of ", - zap.Error(err), - ) - + receiver.logger.Error("failed to translate money on of ", zap.Error(err)) return nil, err } @@ -179,10 +173,7 @@ func (receiver *Service) WithdrawAccountWalletMoney(ctx context.Context, request To: request.Account.Wallet.Currency, }) if err != nil { - receiver.logger.Error("failed to translate money on of ", - zap.Error(err), - ) - + receiver.logger.Error("failed to translate money on of ", zap.Error(err)) return nil, err } @@ -225,10 +216,7 @@ func (receiver *Service) ChangeCurrency(ctx context.Context, userID string, curr To: currency, }) if err != nil { - receiver.logger.Error("failed to translate currency on of ", - zap.Error(err), - ) - + receiver.logger.Error("failed to translate currency on of ", zap.Error(err)) return nil, err } @@ -238,10 +226,7 @@ func (receiver *Service) ChangeCurrency(ctx context.Context, userID string, curr Money: account.Wallet.Money, }) if err != nil { - receiver.logger.Error("failed to update wallet on of ", - zap.Error(err), - ) - + receiver.logger.Error("failed to update wallet on of ", zap.Error(err)) return nil, err } diff --git a/internal/utils/transfer/privilege.go b/internal/utils/transfer/privilege.go new file mode 100644 index 0000000..5b02970 --- /dev/null +++ b/internal/utils/transfer/privilege.go @@ -0,0 +1,53 @@ +package transfer + +import ( + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/broker" +) + +func PrivilegeProtoToModel(privilege *broker.PrivilegeMessage) *models.Privilege { + if privilege == nil { + return &models.Privilege{} + } + + return &models.Privilege{ + PrivilegeID: privilege.GetPrivilegeID(), + ServiceKey: privilege.GetServiceKey(), + Type: privilege.GetType(), + Value: privilege.GetValue(), + } +} + +func PrivilegeArrayProtoToModel(privileges []*broker.PrivilegeMessage) []models.Privilege { + privilegesModel := make([]models.Privilege, len(privileges)) + + for index, privilege := range privileges { + privilegesModel[index] = *PrivilegeProtoToModel(privilege) + } + + return privilegesModel +} + +func PrivilegeModelToProto(privilege *models.Privilege) *broker.PrivilegeMessage { + if privilege == nil { + return &broker.PrivilegeMessage{} + } + + return &broker.PrivilegeMessage{ + PrivilegeID: privilege.PrivilegeID, + ServiceKey: privilege.ServiceKey, + Type: privilege.Type, + Value: privilege.Value, + } +} + +func PrivilegeArrayModelToProto(privileges []models.Privilege) []*broker.PrivilegeMessage { + privilegesProto := make([]*broker.PrivilegeMessage, len(privileges)) + + for index, privilege := range privileges { + privilegeCopy := privilege + privilegesProto[index] = PrivilegeModelToProto(&privilegeCopy) + } + + return privilegesProto +} diff --git a/internal/utils/transfer/privilege_test.go b/internal/utils/transfer/privilege_test.go new file mode 100644 index 0000000..81ada29 --- /dev/null +++ b/internal/utils/transfer/privilege_test.go @@ -0,0 +1,112 @@ +package transfer_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/broker" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils/transfer" +) + +func TestPrivilegeModelToProto(t *testing.T) { + t.Run("Успешный перевод модели привелегии в прото", func(t *testing.T) { + assert.Equal(t, + &broker.PrivilegeMessage{ + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + transfer.PrivilegeModelToProto(&models.Privilege{ + ID: "1", + Name: "name", + PrivilegeID: "12", + ServiceKey: "key-1", + Description: "description", + Type: "type", + Value: "12", + Price: 20, + }), + ) + }) + + t.Run("Успешный перевод nil модели привелегии в прото", func(t *testing.T) { + assert.Equal(t, &broker.PrivilegeMessage{}, transfer.PrivilegeModelToProto(nil)) + }) +} + +func TestPrivilegeArrayModelToProto(t *testing.T) { + t.Run("Успешный перевод массива модели привелегий в массив прото", func(t *testing.T) { + assert.Equal(t, + []*broker.PrivilegeMessage{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + }, + transfer.PrivilegeArrayModelToProto([]models.Privilege{ + { + ID: "1", + Name: "name", + PrivilegeID: "12", + ServiceKey: "key-1", + Description: "description", + Type: "type", + Value: "12", + Price: 20, + }, + }), + ) + }) +} + +func TestPrivilegeProtoToModel(t *testing.T) { + t.Run("Успешный перевод прото привелегии в модель", func(t *testing.T) { + assert.Equal(t, + &models.Privilege{ + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + transfer.PrivilegeProtoToModel(&broker.PrivilegeMessage{ + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }), + ) + }) + + t.Run("Успешный перевод nil прото привелегии в модель", func(t *testing.T) { + assert.Equal(t, &models.Privilege{}, transfer.PrivilegeProtoToModel(nil)) + }) +} + +func TestPrivilegeArrayProtoToModel(t *testing.T) { + t.Run("Успешный перевод массива прото привелегий в массив моделей", func(t *testing.T) { + assert.Equal(t, + []models.Privilege{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + {}, + }, + transfer.PrivilegeArrayProtoToModel([]*broker.PrivilegeMessage{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + nil, + }), + ) + }) +} diff --git a/internal/utils/transfer/tariff.go b/internal/utils/transfer/tariff.go index 0ad821e..958c5a3 100644 --- a/internal/utils/transfer/tariff.go +++ b/internal/utils/transfer/tariff.go @@ -2,6 +2,7 @@ package transfer import ( "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/broker" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/discount" ) @@ -18,6 +19,25 @@ func TariffsToProductInformations(tarrifs []models.Tariff) []*discount.ProductIn func TariffToProductInformation(tarrif models.Tariff) *discount.ProductInformation { return &discount.ProductInformation{ ID: tarrif.ID, - Price: float64(tarrif.Price), + Price: uint64(tarrif.Price), + } +} + +func TariffMessageProtoToTariffModel(tariff *broker.TariffMessage) *models.Tariff { + if tariff == nil { + return &models.Tariff{} + } + + return &models.Tariff{Privileges: PrivilegeArrayProtoToModel(tariff.Privileges)} +} + +func TariffModelToProtoMessage(userID string, tariffModel *models.Tariff) *broker.TariffMessage { + if tariffModel == nil { + return &broker.TariffMessage{} + } + + return &broker.TariffMessage{ + UserID: userID, + Privileges: PrivilegeArrayModelToProto(tariffModel.Privileges), } } diff --git a/internal/utils/transfer/tariff_test.go b/internal/utils/transfer/tariff_test.go index 0b1e45a..557d3e7 100644 --- a/internal/utils/transfer/tariff_test.go +++ b/internal/utils/transfer/tariff_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models" + "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/broker" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/discount" "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils/transfer" ) @@ -23,3 +24,82 @@ func TestTariffsToProductInformations(t *testing.T) { ) }) } + +func TestTariffToProductInformation(t *testing.T) { + t.Run("Успешный перевод модели тарифа в информацию о продукте", func(t *testing.T) { + assert.Equal(t, + &discount.ProductInformation{ + ID: "1", + Price: 20, + }, + transfer.TariffToProductInformation(models.Tariff{ + ID: "1", + Price: 20, + }), + ) + }) +} + +func TestTariffMessageProtoToTariffModel(t *testing.T) { + t.Run("Успешный перевод прото сообщения тарифа в модель", func(t *testing.T) { + assert.Equal(t, + &models.Tariff{ + Privileges: []models.Privilege{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + }, + }, + transfer.TariffMessageProtoToTariffModel(&broker.TariffMessage{ + UserID: "11", + Privileges: []*broker.PrivilegeMessage{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + }, + }), + ) + }) + + t.Run("Успешный перевод nil прото сообщения тарифа в модель", func(t *testing.T) { + assert.Equal(t, &models.Tariff{}, transfer.TariffMessageProtoToTariffModel(nil)) + }) +} + +func TestTariffModelToProtoMessage(t *testing.T) { + t.Run("Успешный перевод модели тарифа в прото сообщение", func(t *testing.T) { + assert.Equal(t, + &broker.TariffMessage{ + UserID: "1", + Privileges: []*broker.PrivilegeMessage{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + }, + }, + transfer.TariffModelToProtoMessage("1", &models.Tariff{ + Privileges: []models.Privilege{ + { + PrivilegeID: "12", + ServiceKey: "key-1", + Type: "type", + Value: "12", + }, + }, + }), + ) + }) + + t.Run("Успешный перевод nil модели тарифа в прото сообщение", func(t *testing.T) { + assert.Equal(t, &broker.TariffMessage{}, transfer.TariffModelToProtoMessage("1", nil)) + }) +} diff --git a/pkg/closer/closer.go b/pkg/closer/closer.go index 1e993e9..9df5737 100644 --- a/pkg/closer/closer.go +++ b/pkg/closer/closer.go @@ -8,6 +8,7 @@ import ( ) type Callback func(ctx context.Context) error +type EasyCallback func() type Closer struct { mutex sync.Mutex @@ -48,3 +49,15 @@ func (receiver *Closer) Close(ctx context.Context) error { return fmt.Errorf("shutdown cancelled: %v", ctx.Err()) } } + +func (receiver *Closer) Wrap(callback EasyCallback) Callback { + return Wrap(callback) +} + +func Wrap(callback EasyCallback) Callback { + return func(_ context.Context) error { + callback() + + return nil + } +} diff --git a/pkg/kafka/kafka.go b/pkg/kafka/kafka.go new file mode 100644 index 0000000..a95d32f --- /dev/null +++ b/pkg/kafka/kafka.go @@ -0,0 +1,83 @@ +package kafka + +import ( + "context" + "fmt" + + "github.com/twmb/franz-go/pkg/kadm" + "github.com/twmb/franz-go/pkg/kgo" +) + +type Deps struct { + Client *kadm.Client +} + +type Kafka struct { + client *kadm.Client +} + +func New(deps Deps) *Kafka { + return &Kafka{client: deps.Client} +} + +func (receiver *Kafka) TopicExists(ctx context.Context, topic string) (bool, error) { + topicsMetadata, err := receiver.client.ListTopics(ctx) + if err != nil { + return false, err + } + + for _, metadata := range topicsMetadata { + if metadata.Topic == topic { + return true, nil + } + } + + return false, nil +} + +func (receiver *Kafka) CreateTopic(ctx context.Context, topic string) error { + responses, err := receiver.client.CreateTopics(ctx, 1, 1, nil, topic) + if err != nil { + return err + } + + for _, response := range responses { + if response.Err != nil { + return err + } + } + + return nil +} + +// Initialize topics in brokers if not exist. Client connection closes self. +func Initialize(ctx context.Context, brokers, topics []string) error { + lastInitializeErr := error(nil) + + kafkaAdminClient, err := kgo.NewClient(kgo.SeedBrokers(brokers...)) + if err != nil { + return err + } + + defer kafkaAdminClient.Close() + + kafka := New(Deps{Client: kadm.NewClient(kafkaAdminClient)}) + + for _, topic := range topics { + isExist, err := kafka.TopicExists(ctx, topic) + if err != nil { + lastInitializeErr = err + continue + } + + if isExist { + continue + } + + if err := kafka.CreateTopic(ctx, topic); err != nil { + lastInitializeErr = fmt.Errorf("failed to create topic <%s> on of ", topic) + } + } + + return lastInitializeErr +} diff --git a/proto/broker/models.proto b/proto/broker/models.proto new file mode 100644 index 0000000..49440ee --- /dev/null +++ b/proto/broker/models.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package broker; + +option go_package = "./broker"; + +message PrivilegeMessage { + string PrivilegeID = 1; + string ServiceKey = 2; + string Type = 3; + string Value = 4; +} + +message TariffMessage { + repeated PrivilegeMessage Privileges = 1; + string UserID = 2; +} diff --git a/proto/discount/audit.model.proto b/proto/discount/audit.model.proto index 5c783a6..99a1d47 100644 --- a/proto/discount/audit.model.proto +++ b/proto/discount/audit.model.proto @@ -1,17 +1,17 @@ -syntax = "proto3"; - -package discount; - -import "google/api/annotations.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/empty.proto"; - -option go_package = "./discount"; - -message Audit { - google.protobuf.Timestamp UpdatedAt = 1; - google.protobuf.Timestamp CreatedAt = 2; - optional google.protobuf.Timestamp DeletedAt = 3; - bool Deleted = 4; -} - +syntax = "proto3"; + +package discount; + +import "google/api/annotations.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; + +option go_package = "./discount"; + +message Audit { + google.protobuf.Timestamp UpdatedAt = 1; + google.protobuf.Timestamp CreatedAt = 2; + optional google.protobuf.Timestamp DeletedAt = 3; + bool Deleted = 4; +} + diff --git a/proto/discount/discount.model.proto b/proto/discount/discount.model.proto index 54db7c9..6378c26 100644 --- a/proto/discount/discount.model.proto +++ b/proto/discount/discount.model.proto @@ -1,88 +1,89 @@ -syntax = "proto3"; - -package discount; - -import "google/api/annotations.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/empty.proto"; -import "discount/audit.model.proto"; - -option go_package = "./discount"; - -message DiscountOptional { - string ID = 1; - optional string Name = 2; - optional uint32 Layer = 3; - optional string Description = 4; - optional DiscountCondition Condition = 5; - optional DiscountCalculationTarget Target = 6; -} - -message Discounts { - repeated Discount Discounts = 1; -} - -message Discount { - string ID = 1; - string Name = 2; - uint32 Layer = 3; - string Description = 4; - DiscountCondition Condition = 5; - DiscountCalculationTarget Target = 6; - Audit Audit = 7; - bool Deprecated = 8; -} - -message DiscountCalculationTarget { - repeated ProductTarget Products = 1; - double Factor = 2; - optional TargetScope TargetScope = 3; - optional string TargetGroup = 4; - optional bool Overhelm = 5; -} - -message DiscountCondition { - optional PeriodCondition Period = 1; - optional string User = 2; - optional string UserType = 3; - optional string Coupon = 4; - optional double PurchasesAmount = 5; - optional double CartPurchasesAmount = 6; - optional string Product = 7; - optional uint64 Term = 8; - optional uint64 Usage = 9; - optional double PriceFrom = 10; - optional string Group = 11; -} - -message ProductTarget { - string ID = 1; - double Factor = 2; - optional bool Overhelm = 3; -} - -message PeriodCondition { - google.protobuf.Timestamp From = 1; - google.protobuf.Timestamp To = 2; -} - -message UserInformation { - string ID = 1; - string Type = 2; - double PurchasesAmount = 3; - double CartPurchasesAmount = 4; -} - -message ProductInformation { - string ID = 1; - double Price = 2; - optional uint64 Term = 3; - optional uint64 Usage = 4; - optional string Group = 5; -} - -enum TargetScope { - Sum = 0; - Group = 1; - Each = 2; +syntax = "proto3"; + +package discount; + +import "google/api/annotations.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; +import "discount/audit.model.proto"; + +option go_package = "./discount"; + +message DiscountOptional { + string ID = 1; + optional string Name = 2; + optional uint32 Layer = 3; + optional string Description = 4; + optional DiscountCondition Condition = 5; + optional DiscountCalculationTarget Target = 6; + optional bool Deprecated = 7; +} + +message Discounts { + repeated Discount Discounts = 1; +} + +message Discount { + string ID = 1; + string Name = 2; + uint32 Layer = 3; + string Description = 4; + DiscountCondition Condition = 5; + DiscountCalculationTarget Target = 6; + Audit Audit = 7; + bool Deprecated = 8; +} + +message DiscountCalculationTarget { + repeated ProductTarget Products = 1; + double Factor = 2; + optional TargetScope TargetScope = 3; + optional string TargetGroup = 4; + optional bool Overhelm = 5; +} + +message DiscountCondition { + optional PeriodCondition Period = 1; + optional string User = 2; + optional string UserType = 3; + optional string Coupon = 4; + optional uint64 PurchasesAmount = 5; + optional uint64 CartPurchasesAmount = 6; + optional string Product = 7; + optional uint64 Term = 8; + optional uint64 Usage = 9; + optional uint64 PriceFrom = 10; + optional string Group = 11; +} + +message ProductTarget { + string ID = 1; + double Factor = 2; + optional bool Overhelm = 3; +} + +message PeriodCondition { + google.protobuf.Timestamp From = 1; + google.protobuf.Timestamp To = 2; +} + +message UserInformation { + string ID = 1; + string Type = 2; + uint64 PurchasesAmount = 3; + uint64 CartPurchasesAmount = 4; +} + +message ProductInformation { + string ID = 1; + uint64 Price = 2; + optional uint64 Term = 3; + optional uint64 Usage = 4; + optional string Group = 5; +} + +enum TargetScope { + Sum = 0; + Group = 1; + Each = 2; } \ No newline at end of file diff --git a/proto/discount/service.proto b/proto/discount/service.proto index b8ff240..80b0f9c 100644 --- a/proto/discount/service.proto +++ b/proto/discount/service.proto @@ -1,94 +1,95 @@ -syntax = "proto3"; - -package discount; - -import "google/api/annotations.proto"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/empty.proto"; -import "discount/discount.model.proto"; - -option go_package = "./discount"; - -service DiscountService { - rpc GetAllDiscounts(google.protobuf.Empty) returns (Discounts) { - option (google.api.http) = { - get: "/discount/all" - }; - } - - rpc GetUserDiscounts(GetDiscountByIDRequest) returns (Discounts) { - option (google.api.http) = { - get: "/discount/user/{ID}" - }; - } - - rpc DetermineDiscounts(ApplyDiscountRequest) returns (Discounts) { - option (google.api.http) = { - post: "/discount/determine" - body: "*" - }; - } - - rpc ApplyDiscounts(ApplyDiscountRequest) returns (ApplyDiscountResponse) { - option (google.api.http) = { - post: "/discount/apply" - body: "*" - }; - } - - rpc GetDiscountByID(GetDiscountByIDRequest) returns (Discount) { - option (google.api.http) = { - get: "/discount/{ID}" - }; - } - - rpc CreateDiscount(CreateDiscountRequest) returns (Discount) { - option (google.api.http) = { - post: "/discount" - }; - } - - rpc ReplaceDiscount(DiscountOptional) returns (Discount) { - option (google.api.http) = { - put: "/discount/{ID}" - body: "*" - }; - } - - rpc UpdateDiscount(DiscountOptional) returns (Discount) { - option (google.api.http) = { - patch: "/discount/{ID}" - body: "*" - }; - } - - rpc DeleteDiscount(GetDiscountByIDRequest) returns (Discount) { - option (google.api.http) = { - delete: "/discount/{ID}" - }; - } -} - -message GetDiscountByIDRequest { - string ID = 1; -} - -message ApplyDiscountRequest { - UserInformation UserInformation = 1; - repeated ProductInformation Products = 2; - google.protobuf.Timestamp Date = 3; - optional string Coupon = 4; -} - -message ApplyDiscountResponse { - double Price = 1; - repeated Discount AppliedDiscounts = 2; -} - -message CreateDiscountRequest { - string Name = 1; - uint32 Layer = 2; - string Description = 3; - DiscountCondition Condition = 4; - DiscountCalculationTarget Target = 5; -} +syntax = "proto3"; + +package discount; + +import "google/api/annotations.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; +import "discount/discount.model.proto"; + +option go_package = "./discount"; + +service DiscountService { + rpc GetAllDiscounts(google.protobuf.Empty) returns (Discounts) { + option (google.api.http) = { + get: "/discounts" + }; + } + + rpc GetUserDiscounts(GetDiscountByIDRequest) returns (Discounts) { + option (google.api.http) = { + get: "/discount/user/{ID}" + }; + } + + rpc DetermineDiscounts(ApplyDiscountRequest) returns (Discounts) { + option (google.api.http) = { + post: "/discount/determine" + body: "*" + }; + } + + rpc ApplyDiscounts(ApplyDiscountRequest) returns (ApplyDiscountResponse) { + option (google.api.http) = { + post: "/discount/apply" + body: "*" + }; + } + + rpc GetDiscountByID(GetDiscountByIDRequest) returns (Discount) { + option (google.api.http) = { + get: "/discount/{ID}" + }; + } + + rpc CreateDiscount(CreateDiscountRequest) returns (Discount) { + option (google.api.http) = { + post: "/discount" + body: "*" + }; + } + + rpc ReplaceDiscount(DiscountOptional) returns (Discount) { + option (google.api.http) = { + put: "/discount/{ID}" + body: "*" + }; + } + + rpc UpdateDiscount(DiscountOptional) returns (Discount) { + option (google.api.http) = { + patch: "/discount/{ID}" + body: "*" + }; + } + + rpc DeleteDiscount(GetDiscountByIDRequest) returns (Discount) { + option (google.api.http) = { + delete: "/discount/{ID}" + }; + } +} + +message GetDiscountByIDRequest { + string ID = 1; +} + +message ApplyDiscountRequest { + UserInformation UserInformation = 1; + repeated ProductInformation Products = 2; + google.protobuf.Timestamp Date = 3; + optional string Coupon = 4; +} + +message ApplyDiscountResponse { + uint64 Price = 1; + repeated Discount AppliedDiscounts = 2; +} + +message CreateDiscountRequest { + string Name = 1; + uint32 Layer = 2; + string Description = 3; + DiscountCondition Condition = 4; + DiscountCalculationTarget Target = 5; +}