feat: overhelm

This commit is contained in:
Mikhail 2023-07-04 04:04:31 +00:00 committed by Kirill
parent e15242a2b8
commit 01dce42f5c
112 changed files with 9154 additions and 7750 deletions

@ -1,8 +1,31 @@
stages:
- lint
- test
- clean
- build
- deploy
lint:
image: golangci/golangci-lint:v1.51-alpine
stage: lint
script:
- go generate ./internal/...
- golangci-lint version
- golangci-lint run --disable-all --enable=vet --enable=golint ./...
test:
image: golang:1.20-alpine
stage: test
coverage: /\(statements\)(?:\s+)?(\d+(?:\.\d+)?%)/
script:
- CGO_ENABLED=0 go test ./internal/... -coverprofile=coverage.out
- go tool cover -html=coverage.out -o coverage.html
- go tool cover -func coverage.out
artifacts:
expire_in: "3 days"
paths:
- coverage.html
clean-old:
stage: clean
image:

164
.golangci.yaml Normal file

@ -0,0 +1,164 @@
run:
timeout: 5m
skip-files:
- \.pb\.go$
- .pb.go
- \.pb\.validate\.go$
- \.pb\.gw\.go$
- .pb.gw.go
- \.gen\.go$
skip-dirs:
- mocks
linters:
disable-all: true
enable:
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- dogsled
- dupword
- durationcheck
- errcheck
- errchkjson
- exportloopref
- goconst
- gocritic
- godot
- gofmt
- gci
- goprintffuncname
- gosec
- gosimple
- govet
- importas
- ineffassign
- misspell
- nakedret
- nilerr
- noctx
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- revive
- rowserrcheck
- staticcheck
- stylecheck
- thelper
- typecheck
- unconvert
- unparam
- unused
- usestdlibvars
- whitespace
linters-settings:
errcheck:
exclude-functions:
- (io.Closer).Close
govet:
check-shadowing: true
gci:
custom-order: false
section-separators:
- newLine
sections:
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
- blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled.
- dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled.
importas:
no-unaliased: true
alias:
# Foundation libraries
- pkg: git.sbercloud.tech/products/paas/shared/foundation/management-server
alias: mgmtserver
maligned:
suggest-new: true
goconst:
min-len: 2
min-occurrences: 2
lll:
line-length: 140
revive:
rules:
# The following rules are recommended https://github.com/mgechev/revive#recommended-configuration
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
# - name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
# - name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id
#
# Rules in addition to the recommended configuration above.
#
- name: bool-literal-in-expr
- name: constant-logical-expr
gosec:
excludes:
- G307 # Deferring unsafe method "Close" on type "\*os.File"
- G108 # Profiling endpoint is automatically exposed on /debug/pprof
gocritic:
enabled-tags:
- diagnostic
- experimental
- performance
disabled-checks:
- appendAssign
- dupImport # https://github.com/go-critic/go-critic/issues/845
- evalOrder
- ifElseChain
- octalLiteral
- regexpSimplify
- sloppyReassign
- truncateCmp
- typeDefFirst
- unnamedResult
- unnecessaryDefer
- whyNoLint
- wrapperFunc
- rangeValCopy
- hugeParam
issues:
exclude-rules:
- text: "at least one file in a package should have a package comment"
linters:
- stylecheck
- text: "should have a package comment, unless it's in another file for this package"
linters:
- golint
- text: "should have comment or be unexported"
linters:
- golint
- path: _test\.go
linters:
- gosec
- dupl
exclude-use-default: false
output:
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
format: colored-line-number
print-linter-name: true

6
.mockery.yaml Normal file

@ -0,0 +1,6 @@
exported: True
inpackage: False
keeptree: True
case: underscore
with-expecter: True
inpackage-suffix: True

@ -8,11 +8,11 @@ help: ## show this help
install: ## install all go dependencies
go install \
github.com/bufbuild/buf/cmd/buf \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
google.golang.org/grpc/cmd/protoc-gen-go-grpc \
google.golang.org/protobuf/cmd/protoc-gen-go
github.com/bufbuild/buf/cmd/buf@v1.23.1 \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest \
google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest \
google.golang.org/protobuf/cmd/protoc-gen-go@latest
generate: ## generate grpc proto for golang
buf generate --path ./proto/${SERVICE_NAME}

@ -1,4 +1,4 @@
version: v1beta1
version: v1
plugins:
- name: go
out: internal/proto
@ -6,7 +6,3 @@ plugins:
out: internal/proto
opt:
- require_unimplemented_servers=false
- name: grpc-gateway
out: internal/proto
- name: openapiv2
out: internal/proto

3
buf.work.yaml Normal file

@ -0,0 +1,3 @@
version: v1
directories:
- proto

@ -1,7 +1,4 @@
version: v1beta1
build:
roots:
- proto
version: v1
lint:
use:
- DEFAULT

@ -8,7 +8,6 @@ import (
formatter "github.com/antonfisher/nested-logrus-formatter"
"github.com/sirupsen/logrus"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/app"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"

82
go.mod

@ -5,37 +5,89 @@ go 1.20
require (
github.com/antonfisher/nested-logrus-formatter v1.3.1
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
github.com/joho/godotenv v1.4.0
github.com/sethvargo/go-envconfig v0.8.3
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.1
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
go.mongodb.org/mongo-driver v1.11.1
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
google.golang.org/genproto v0.0.0-20230119192704-9d59e20e5cd1
google.golang.org/grpc v1.52.0
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e
google.golang.org/grpc v1.55.0
google.golang.org/protobuf v1.31.0
)
require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/bufbuild/buf v1.23.1 // indirect
github.com/bufbuild/connect-go v1.8.0 // indirect
github.com/bufbuild/connect-opentelemetry-go v0.3.0 // indirect
github.com/bufbuild/protocompile v0.5.1 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/docker/cli v24.0.2+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/go-chi/chi/v5 v5.0.8 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gofrs/uuid/v5 v5.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/google/go-containerregistry v0.15.2 // indirect
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect
github.com/klauspost/compress v1.16.6 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/profile v1.7.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/cors v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tetratelabs/wazero v1.2.1 // indirect
github.com/vbatts/tar-split v0.11.3 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/net v0.4.0 // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.5.0 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.11.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/tools v0.10.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

149
go.sum

@ -1,25 +1,70 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ=
github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
github.com/bufbuild/buf v1.23.1 h1:BeMkA3+e9XTFEZPDlAI7cydFKlq24wwYiOHp8CvsRzc=
github.com/bufbuild/buf v1.23.1/go.mod h1:ERFRzJiIjAOzUSJ3vz1zoI7XfxlBnCwZEyL+NJm4pko=
github.com/bufbuild/connect-go v1.8.0 h1:srluNkFkZBfSfg9Qb6DrO+5nMaxix//h2ctrHZhMGKc=
github.com/bufbuild/connect-go v1.8.0/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk=
github.com/bufbuild/connect-opentelemetry-go v0.3.0 h1:AuZi3asTDKmjGtd2aqpyP4p5QvBFG/YEaHopViLatnk=
github.com/bufbuild/connect-opentelemetry-go v0.3.0/go.mod h1:r1ppyTtu1EWeRodk4Q/JbyQhIWtO7eR3GoRDzjeEcNU=
github.com/bufbuild/protocompile v0.5.1 h1:mixz5lJX4Hiz4FpqFREJHIXLfaLBntfaJv1h+/jS+Qg=
github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM=
github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg=
github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -27,6 +72,8 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@ -34,39 +81,84 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs=
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 h1:1JYBfzqrWPcCclBwxFCPAou9n+q86mfnu7NAeHfte7A=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0/go.mod h1:YDZoGHuwE+ov0c8smSH49WLF3F2LaWnYYuDVd+EWrc0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 h1:2uT3aivO7NVpUPGcQX7RbHijHMyWix/yCnIrCWc+5co=
github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
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=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE=
github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sethvargo/go-envconfig v0.8.3 h1:dXyUrDCJvCm3ybP7yNpiux93qoSORvuH23bdsgFfiJ0=
github.com/sethvargo/go-envconfig v0.8.3/go.mod h1:Iz1Gy1Sf3T64TQlJSvee81qDhf7YIlt8GMUX6yyNFs0=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@ -79,8 +171,15 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tetratelabs/wazero v1.2.1 h1:J4X2hrGzJvt+wqltuvcSjHQ7ujQxA9gb6PeMs4qlUWs=
github.com/tetratelabs/wazero v1.2.1/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
@ -93,22 +192,42 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8=
go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -120,6 +239,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -129,6 +250,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -137,16 +260,26 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -155,6 +288,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -166,6 +301,12 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20230119192704-9d59e20e5cd1 h1:wSjSSQW7LuPdv3m1IrSN33nVxH/kID6OIKy+FMwGB2k=
google.golang.org/genproto v0.0.0-20230119192704-9d59e20e5cd1/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw=
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@ -173,15 +314,23 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

@ -2,18 +2,27 @@ package app
import (
"context"
"os/signal"
"syscall"
"time"
"github.com/sirupsen/logrus"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/server"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/closer"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/mongo"
)
const (
shutdownTimeout = 5 * time.Second
)
func Run(config *core.Config, logger *logrus.Logger) {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
closer := closer.New()
database, err := mongo.Connect(ctx, &mongo.ConnectDeps{
Configuration: &config.Database.Connection,
@ -31,7 +40,7 @@ func Run(config *core.Config, logger *logrus.Logger) {
services := initialize.NewServices(&initialize.ServicesDeps{
Logger: logger,
Respositories: repositories,
Repositories: repositories,
})
controllers := initialize.NewControllers(&initialize.ControllersDeps{
@ -45,9 +54,18 @@ func Run(config *core.Config, logger *logrus.Logger) {
go serverGRPC.Run(&config.GRPC)
go serverHTTP.Run(&config.HTTP)
gracefulShutdown(ctx, &gracefulShutdownDeps{
serverGRPC: serverGRPC,
database: database.Client(),
cancel: cancel,
})
closer.Add(database.Client().Disconnect)
closer.Add(serverGRPC.Stop)
<-ctx.Done()
logger.Info("shutting down app gracefully")
shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
defer cancel()
if err := closer.Close(shutdownCtx); err != nil {
logger.Errorf("failed to close with graceful shutdown: %v", err)
}
}

@ -1,29 +0,0 @@
package app
import (
"context"
"os"
"os/signal"
"syscall"
"go.mongodb.org/mongo-driver/mongo"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/server"
)
type gracefulShutdownDeps struct {
serverGRPC *server.GRPC
database *mongo.Client
cancel context.CancelFunc
}
func gracefulShutdown(ctx context.Context, deps *gracefulShutdownDeps) {
defer deps.serverGRPC.Stop()
defer deps.database.Disconnect(ctx)
defer deps.cancel()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT)
<-quit
}

@ -5,7 +5,6 @@ import (
"github.com/sirupsen/logrus"
"google.golang.org/protobuf/types/known/emptypb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/transfer"

@ -14,14 +14,14 @@ type CommonDiscountCondition struct {
User string `json:"user"`
UserType string `json:"userType"`
Coupon *string `json:"coupon"`
PurchasesAmount float64 `json:"purchasesAmount"`
CartPurchasesAmount float64 `json:"cartPurchasesAmount"`
PurchasesAmount uint64 `json:"purchasesAmount"`
CartPurchasesAmount uint64 `json:"cartPurchasesAmount"`
}
type OptionalDiscounCondition struct {
Product *string `json:"product"`
Group *string `json:"group"`
PriceFrom *float64 `json:"priceFrom"`
PriceFrom *uint64 `json:"priceFrom"`
/* Срок использования (количество дней использования) */
Term *uint64 `json:"term"`

@ -3,7 +3,6 @@ package initialize
import (
"github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/mongo"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/repository"
)

@ -7,7 +7,7 @@ import (
type ServicesDeps struct {
Logger *logrus.Logger
Respositories *Repositories
Repositories *Repositories
}
type Services struct {
@ -18,7 +18,7 @@ func NewServices(deps *ServicesDeps) *Services {
return &Services{
DiscountService: service.NewDiscountService(&service.DiscountServiceDeps{
Logger: deps.Logger,
DiscountRepository: deps.Respositories.DiscountRepository,
DiscountRepository: deps.Repositories.DiscountRepository,
}),
}
}

@ -36,19 +36,19 @@ type DiscountCalculationTarget struct {
type DiscountCondition struct {
Period *PeriodCondition `json:"period,omitempty" bson:"period,omitempty"`
Product *string `json:"product,omitempty" bson:"product,omitempty"`
PriceFrom *float64 `json:"priceFrom,omitempty" bson:"priceFrom,omitempty"`
PriceFrom *uint64 `json:"priceFrom,omitempty" bson:"priceFrom,omitempty"`
Group *string `json:"group,omitempty" bson:"group,omitempty"`
User *string `json:"user,omitempty" bson:"user,omitempty"`
UserType *string `json:"userType,omitempty" bson:"userType,omitempty"`
Coupon *string `json:"coupon,omitempty" bson:"coupon,omitempty"`
PurchasesAmount *float64 `json:"purchasesAmount,omitempty" bson:"purchasesAmount,omitempty"`
CartPurchasesAmount *float64 `json:"cartPurchasesAmount,omitempty" bson:"cartPurchasesAmount,omitempty"`
PurchasesAmount *uint64 `json:"purchasesAmount,omitempty" bson:"purchasesAmount,omitempty"`
CartPurchasesAmount *uint64 `json:"cartPurchasesAmount,omitempty" bson:"cartPurchasesAmount,omitempty"`
/* Срок использования (количество дней использования) */
Term *uint64 `json:"term,omitempty" bson:"term,omitempty"`
Term *uint64 `json:"term" bson:"term"`
/* Количество использований (количество попыток) */
Usage *uint64 `json:"usage,omitempty" bson:"usage,omitempty"`
Usage *uint64 `json:"usage" bson:"usage,omitempty"`
}
type ProductTarget struct {
@ -65,8 +65,13 @@ type PeriodCondition struct {
type TargetScope string
const (
// TargetSum тип скидки, применяющийся на финальную сформированную сумму всех товаров.
TargetSum TargetScope = "sum"
// TargetGroup тип скидки, применяющийся на сумму товаров определённой группы.
TargetGroup TargetScope = "group"
// TargetEach тип скидки, применяющийся на определённый товар.
TargetEach TargetScope = "each"
)

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: discount/audit.model.proto

@ -34,6 +34,7 @@
"details": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/protobufAny"
}
}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: discount/discount.model.proto
@ -397,12 +397,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 +466,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 +501,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
}
@ -640,8 +640,8 @@ type UserInformation struct {
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"`
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 +690,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 +710,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 +755,7 @@ func (x *ProductInformation) GetID() string {
return ""
}
func (x *ProductInformation) GetPrice() float64 {
func (x *ProductInformation) GetPrice() uint64 {
if x != nil {
return x.Price
}
@ -868,10 +868,10 @@ var file_discount_discount_model_proto_rawDesc = []byte{
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,
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, 0x01, 0x48, 0x05, 0x52, 0x13, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72,
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,
@ -879,7 +879,7 @@ var file_discount_discount_model_proto_rawDesc = []byte{
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,
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,
@ -909,14 +909,14 @@ var file_discount_discount_model_proto_rawDesc = []byte{
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, 0x01, 0x52, 0x0f, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65,
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, 0x01, 0x52, 0x13, 0x43, 0x61, 0x72, 0x74, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61,
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, 0x01, 0x52,
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,

@ -34,6 +34,7 @@
"details": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/protobufAny"
}
}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: discount/service.proto
@ -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,

@ -681,7 +681,7 @@ func RegisterDiscountServiceHandlerServer(ctx context.Context, mux *runtime.Serv
// RegisterDiscountServiceHandlerFromEndpoint is same as RegisterDiscountServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterDiscountServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
conn, err := grpc.DialContext(ctx, endpoint, opts...)
if err != nil {
return err
}

@ -341,6 +341,7 @@
"Products": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/discountProductInformation"
}
},
@ -363,6 +364,7 @@
"AppliedDiscounts": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/discountDiscount"
}
}
@ -445,6 +447,7 @@
"Products": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/discountProductTarget"
}
},
@ -512,6 +515,7 @@
"Discounts": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/discountDiscount"
}
}
@ -618,6 +622,7 @@
"details": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/protobufAny"
}
}

@ -1,4 +1,8 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc (unknown)
// source: discount/service.proto
package discount
@ -15,6 +19,18 @@ import (
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
DiscountService_GetAllDiscounts_FullMethodName = "/discount.DiscountService/GetAllDiscounts"
DiscountService_GetUserDiscounts_FullMethodName = "/discount.DiscountService/GetUserDiscounts"
DiscountService_DetermineDiscounts_FullMethodName = "/discount.DiscountService/DetermineDiscounts"
DiscountService_ApplyDiscounts_FullMethodName = "/discount.DiscountService/ApplyDiscounts"
DiscountService_GetDiscountByID_FullMethodName = "/discount.DiscountService/GetDiscountByID"
DiscountService_CreateDiscount_FullMethodName = "/discount.DiscountService/CreateDiscount"
DiscountService_ReplaceDiscount_FullMethodName = "/discount.DiscountService/ReplaceDiscount"
DiscountService_UpdateDiscount_FullMethodName = "/discount.DiscountService/UpdateDiscount"
DiscountService_DeleteDiscount_FullMethodName = "/discount.DiscountService/DeleteDiscount"
)
// DiscountServiceClient is the client API for DiscountService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
@ -40,7 +56,7 @@ func NewDiscountServiceClient(cc grpc.ClientConnInterface) DiscountServiceClient
func (c *discountServiceClient) GetAllDiscounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Discounts, error) {
out := new(Discounts)
err := c.cc.Invoke(ctx, "/discount.DiscountService/GetAllDiscounts", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_GetAllDiscounts_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -49,7 +65,7 @@ func (c *discountServiceClient) GetAllDiscounts(ctx context.Context, in *emptypb
func (c *discountServiceClient) GetUserDiscounts(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discounts, error) {
out := new(Discounts)
err := c.cc.Invoke(ctx, "/discount.DiscountService/GetUserDiscounts", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_GetUserDiscounts_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -58,7 +74,7 @@ func (c *discountServiceClient) GetUserDiscounts(ctx context.Context, in *GetDis
func (c *discountServiceClient) DetermineDiscounts(ctx context.Context, in *ApplyDiscountRequest, opts ...grpc.CallOption) (*Discounts, error) {
out := new(Discounts)
err := c.cc.Invoke(ctx, "/discount.DiscountService/DetermineDiscounts", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_DetermineDiscounts_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -67,7 +83,7 @@ func (c *discountServiceClient) DetermineDiscounts(ctx context.Context, in *Appl
func (c *discountServiceClient) ApplyDiscounts(ctx context.Context, in *ApplyDiscountRequest, opts ...grpc.CallOption) (*ApplyDiscountResponse, error) {
out := new(ApplyDiscountResponse)
err := c.cc.Invoke(ctx, "/discount.DiscountService/ApplyDiscounts", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_ApplyDiscounts_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -76,7 +92,7 @@ func (c *discountServiceClient) ApplyDiscounts(ctx context.Context, in *ApplyDis
func (c *discountServiceClient) GetDiscountByID(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/GetDiscountByID", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_GetDiscountByID_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -85,7 +101,7 @@ func (c *discountServiceClient) GetDiscountByID(ctx context.Context, in *GetDisc
func (c *discountServiceClient) CreateDiscount(ctx context.Context, in *CreateDiscountRequest, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/CreateDiscount", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_CreateDiscount_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -94,7 +110,7 @@ func (c *discountServiceClient) CreateDiscount(ctx context.Context, in *CreateDi
func (c *discountServiceClient) ReplaceDiscount(ctx context.Context, in *DiscountOptional, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/ReplaceDiscount", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_ReplaceDiscount_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -103,7 +119,7 @@ func (c *discountServiceClient) ReplaceDiscount(ctx context.Context, in *Discoun
func (c *discountServiceClient) UpdateDiscount(ctx context.Context, in *DiscountOptional, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/UpdateDiscount", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_UpdateDiscount_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -112,7 +128,7 @@ func (c *discountServiceClient) UpdateDiscount(ctx context.Context, in *Discount
func (c *discountServiceClient) DeleteDiscount(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/DeleteDiscount", in, out, opts...)
err := c.cc.Invoke(ctx, DiscountService_DeleteDiscount_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@ -187,7 +203,7 @@ func _DiscountService_GetAllDiscounts_Handler(srv interface{}, ctx context.Conte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/GetAllDiscounts",
FullMethod: DiscountService_GetAllDiscounts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).GetAllDiscounts(ctx, req.(*emptypb.Empty))
@ -205,7 +221,7 @@ func _DiscountService_GetUserDiscounts_Handler(srv interface{}, ctx context.Cont
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/GetUserDiscounts",
FullMethod: DiscountService_GetUserDiscounts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).GetUserDiscounts(ctx, req.(*GetDiscountByIDRequest))
@ -223,7 +239,7 @@ func _DiscountService_DetermineDiscounts_Handler(srv interface{}, ctx context.Co
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/DetermineDiscounts",
FullMethod: DiscountService_DetermineDiscounts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).DetermineDiscounts(ctx, req.(*ApplyDiscountRequest))
@ -241,7 +257,7 @@ func _DiscountService_ApplyDiscounts_Handler(srv interface{}, ctx context.Contex
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/ApplyDiscounts",
FullMethod: DiscountService_ApplyDiscounts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).ApplyDiscounts(ctx, req.(*ApplyDiscountRequest))
@ -259,7 +275,7 @@ func _DiscountService_GetDiscountByID_Handler(srv interface{}, ctx context.Conte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/GetDiscountByID",
FullMethod: DiscountService_GetDiscountByID_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).GetDiscountByID(ctx, req.(*GetDiscountByIDRequest))
@ -277,7 +293,7 @@ func _DiscountService_CreateDiscount_Handler(srv interface{}, ctx context.Contex
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/CreateDiscount",
FullMethod: DiscountService_CreateDiscount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).CreateDiscount(ctx, req.(*CreateDiscountRequest))
@ -295,7 +311,7 @@ func _DiscountService_ReplaceDiscount_Handler(srv interface{}, ctx context.Conte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/ReplaceDiscount",
FullMethod: DiscountService_ReplaceDiscount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).ReplaceDiscount(ctx, req.(*DiscountOptional))
@ -313,7 +329,7 @@ func _DiscountService_UpdateDiscount_Handler(srv interface{}, ctx context.Contex
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/UpdateDiscount",
FullMethod: DiscountService_UpdateDiscount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).UpdateDiscount(ctx, req.(*DiscountOptional))
@ -331,7 +347,7 @@ func _DiscountService_DeleteDiscount_Handler(srv interface{}, ctx context.Contex
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/DeleteDiscount",
FullMethod: DiscountService_DeleteDiscount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).DeleteDiscount(ctx, req.(*GetDiscountByIDRequest))

@ -11,7 +11,6 @@ import (
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readconcern"
"go.mongodb.org/mongo-driver/mongo/writeconcern"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
@ -184,7 +183,9 @@ func (receiver *DiscountRepository) UpdateMany(ctx context.Context, updates []co
if _, transactionError := session.WithTransaction(ctx, func(sessionContext mongo.SessionContext) (interface{}, error) {
for _, update := range updates {
if err := receiver.UpdateOne(sessionContext, &update); err != nil {
updateCopy := update
if err := receiver.UpdateOne(sessionContext, &updateCopy); err != nil {
receiver.logger.Errorf("failed to update <%s> in transaction on <UpdateMany> of <DiscountRepository>: %v", update.ID, err)
return nil, err
}

@ -1,6 +1,7 @@
package server
import (
"context"
"fmt"
"net"
@ -60,14 +61,12 @@ func (receiver *GRPC) listen(address string) error {
return err
}
if err := receiver.grpc.Serve(listener); err != nil {
return err
return receiver.grpc.Serve(listener)
}
func (receiver *GRPC) Stop(_ context.Context) error {
receiver.grpc.GracefulStop()
receiver.logger.Infoln("Shutting down GRPC server...")
return nil
}
func (receiver *GRPC) Stop() {
receiver.grpc.GracefulStop()
receiver.logger.Infoln("Shutting down GRPC server...")
}

@ -4,18 +4,19 @@ import (
"context"
"fmt"
"net/http"
"time"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
)
type HTTP struct {
logger *logrus.Logger
server *http.Server
mux *runtime.ServeMux
}
@ -23,6 +24,12 @@ func NewHTTP(logger *logrus.Logger) *HTTP {
return &HTTP{
logger: logger,
mux: runtime.NewServeMux(),
server: &http.Server{
MaxHeaderBytes: 1 << 20,
ReadTimeout: 20 * time.Second,
WriteTimeout: 20 * time.Second,
IdleTimeout: 20 * time.Second,
},
}
}
@ -38,12 +45,19 @@ func (receiver *HTTP) Register(ctx context.Context, config *core.GRPCConfigurati
return receiver
}
func (receiver *HTTP) Listen(address string) error {
receiver.server.Addr = address
receiver.server.Handler = receiver.mux
return receiver.server.ListenAndServe()
}
func (receiver *HTTP) Run(config *core.HTTPConfiguration) {
endpoint := fmt.Sprintf(":%s", config.Port)
receiver.logger.Infof("HTTP server started on: <%s>", endpoint)
if err := http.ListenAndServe(endpoint, receiver.mux); err != nil && err != http.ErrServerClosed {
if err := receiver.Listen(endpoint); err != nil && err != http.ErrServerClosed {
receiver.logger.Errorf("HTTP listen error: %v", err)
panic(err)
}

@ -4,12 +4,11 @@ import (
"context"
"github.com/sirupsen/logrus"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/calculate"
discountUtils "penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/transfer"
)
@ -70,7 +69,7 @@ func (receiver *DiscountService) ApplyDiscounts(ctx context.Context, request *di
products := transfer.ProductsProtoToCore(request.Products)
return &discount.ApplyDiscountResponse{
Price: calculate.Discount(products, filteredDiscounts),
Price: discountUtils.Calculate(products, filteredDiscounts),
AppliedDiscounts: transfer.DiscountsModelToProto(filteredDiscounts).Discounts,
}, nil
}

@ -1,52 +0,0 @@
package calculate
import (
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/convert"
)
/*
TODO:
1) Рефактор всех приватных утилит
2) Покрытие тестами всех утилит
3) Уточнить систему overhelm при высчитывании
*/
func Discount(products []core.Product, discounts []models.Discount) float64 {
if len(products) < 1 {
return 0
}
price := calculateProducts(products)
if len(discounts) < 1 {
return price
}
discountTargets := constituteDiscountTargets(divideDiscounts(discounts))
productsMap := convert.ArrayToMap(products, func(product core.Product) string {
return product.ID
})
if eachTarget, ok := discountTargets[models.TargetEach]; ok {
productsMap = calculateEachProduct(productsMap, eachTarget)
price = calculateProductsMap(productsMap)
}
if groupTarget, ok := discountTargets[models.TargetGroup]; ok {
productGroups := convert.MapToMapArray(productsMap, func(product core.Product) string {
return product.Group
})
pricesGroup := calculateGroupProducts(productGroups, groupTarget)
price = calculatePricesGroup(pricesGroup)
}
if sumTarget, ok := discountTargets[models.TargetSum]; ok {
price = price * sumTarget.Factor
}
return price
}

@ -1,94 +0,0 @@
package calculate
import (
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
)
func calculateProducts(products []core.Product) float64 {
productsPrice := float64(0)
for _, product := range products {
productsPrice = productsPrice + product.Price
}
return productsPrice
}
func calculateProductsMap(products map[string]core.Product) float64 {
productsPrice := float64(0)
for _, product := range products {
productsPrice = productsPrice + product.Price
}
return productsPrice
}
func calculatePricesGroup(pricesGroup map[string]float64) float64 {
finalPrice := float64(0)
for _, price := range pricesGroup {
finalPrice = finalPrice + price
}
return finalPrice
}
func calculateEachProduct(products map[string]core.Product, target models.DiscountCalculationTarget) map[string]core.Product {
if target.Products == nil && target.Factor == 0 {
return products
}
if target.Products == nil {
for key, product := range products {
products[key] = core.Product{
ID: key,
Price: product.Price * target.Factor,
}
}
return products
}
for _, productTarget := range target.Products {
product, ok := products[productTarget.ID]
if !ok {
continue
}
if productTarget.Factor != 0 {
products[product.ID] = core.Product{
ID: product.ID,
Price: product.Price * productTarget.Factor,
}
continue
}
products[product.ID] = core.Product{
ID: product.ID,
Price: product.Price * target.Factor,
}
}
return products
}
func calculateGroupProducts(productsGroup map[string][]core.Product, target models.DiscountCalculationTarget) map[string]float64 {
pricesGroup := make(map[string]float64)
if target.TargetGroup == "" && target.Factor == 0 {
for group, products := range productsGroup {
pricesGroup[group] = calculateProducts(products)
}
return pricesGroup
}
for group, products := range productsGroup {
pricesGroup[group] = calculateProducts(products) * target.Factor
}
return pricesGroup
}

@ -1,92 +0,0 @@
package calculate
import (
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/convert"
)
func constituteDiscountTargets(dividedDiscounts map[models.TargetScope][]models.Discount) map[models.TargetScope]models.DiscountCalculationTarget {
discountTargets := make(map[models.TargetScope]models.DiscountCalculationTarget, 3)
for group, discounts := range dividedDiscounts {
switch group {
case models.TargetEach:
discountTargets[group] = models.DiscountCalculationTarget{
Products: sumEachFactor(discounts),
}
case models.TargetGroup, models.TargetSum:
discountTargets[group] = models.DiscountCalculationTarget{
Factor: sumCommonFactor(discounts),
}
}
}
return discountTargets
}
func divideDiscounts(discounts []models.Discount) map[models.TargetScope][]models.Discount {
dividedDiscounts := make(map[models.TargetScope][]models.Discount, 3)
for _, discount := range discounts {
if len(discount.Target.Products) > 0 {
dividedDiscounts[models.TargetEach] = append(dividedDiscounts[models.TargetEach], discount)
continue
}
if discount.Target.TargetScope == "" && len(discount.Target.Products) < 1 {
dividedDiscounts[models.TargetSum] = append(dividedDiscounts[models.TargetSum], discount)
continue
}
if discount.Target.TargetScope == "" {
continue
}
dividedDiscounts[discount.Target.TargetScope] = append(dividedDiscounts[discount.Target.TargetScope], discount)
}
return dividedDiscounts
}
func sumCommonFactor(discounts []models.Discount) float64 {
sum := float64(1)
for _, discount := range discounts {
if discount.Target.Overhelm {
sum = discount.Target.Factor
break
}
sum = sum * discount.Target.Factor
}
return sum
}
func sumEachFactor(discounts []models.Discount) []models.ProductTarget {
productTargetsMap := make(map[string]models.ProductTarget)
for _, discount := range discounts {
for _, productTarget := range discount.Target.Products {
if productTargetsMap[productTarget.ID].Overhelm {
continue
}
if productTargetsMap[productTarget.ID].Factor > 0 {
productTargetsMap[productTarget.ID] = models.ProductTarget{
ID: productTarget.ID,
Factor: productTargetsMap[productTarget.ID].Factor * productTarget.Factor,
Overhelm: productTargetsMap[productTarget.ID].Overhelm,
}
continue
}
productTargetsMap[productTarget.ID] = models.ProductTarget{
ID: productTarget.ID,
Factor: 1 * productTarget.Factor,
Overhelm: productTargetsMap[productTarget.ID].Overhelm,
}
}
}
return convert.MapToArray(productTargetsMap)
}

@ -38,7 +38,7 @@ func ConstituteConditions(request *discount.ApplyDiscountRequest) (*core.Discoun
Term: product.Term,
Usage: product.Usage,
}
optionalConditionsIndex = optionalConditionsIndex + 2
optionalConditionsIndex += 2
}
return &core.DiscountConditions{

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
@ -16,17 +15,17 @@ import (
func TestConstituteConditions(t *testing.T) {
userID := "1"
userType := "nkvo"
purchasesAmount := float64(100000)
cartPurchasesAmount := float64(5000)
purchasesAmount := uint64(100000)
cartPurchasesAmount := uint64(5000)
productsGroup := "group"
productID1 := "1"
productID2 := "2"
productID3 := "3"
productID4 := "4"
productPrice1 := float64(1000)
productPrice2 := float64(6000)
productPrice3 := float64(10000)
productPrice4 := float64(4000)
productPrice1 := uint64(1000)
productPrice2 := uint64(6000)
productPrice3 := uint64(10000)
productPrice4 := uint64(4000)
productTerm1 := uint64(14)
productTerm2 := uint64(16)
productUsage1 := uint64(24)

@ -0,0 +1,144 @@
package discount
import (
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/convert"
)
/*
TODO:
1) Рефактор всех приватных утилит
2) Покрытие тестами всех утилит
*/
func Calculate(products []core.Product, discounts []models.Discount) uint64 {
if len(products) < 1 {
return 0
}
price := calculateProducts(products)
if len(discounts) < 1 {
return convert.FloatToUint64(price)
}
discountTargetsMap := SortOverhelmingDiscounts(discounts)
productsMap := convert.ArrayToMap(products, func(product core.Product) string {
return product.ID
})
if targetsEach, ok := discountTargetsMap[models.TargetEach]; ok {
for _, target := range targetsEach {
productsMap = calculateEachProductWithTarget(productsMap, target)
}
price = calculateProductsMap(productsMap)
}
if targetsGroup, ok := discountTargetsMap[models.TargetGroup]; ok {
productGroups := convert.MapToMapArray(productsMap, func(product core.Product) string {
return product.Group
})
pricesGroup := calculateProductsGroup(productGroups)
for _, target := range targetsGroup {
pricesGroup[target.TargetGroup] *= target.Factor
}
price = calculatePricesGroupSum(pricesGroup)
}
if targetsSum, ok := discountTargetsMap[models.TargetSum]; ok {
for _, target := range targetsSum {
price *= target.Factor
}
}
return convert.FloatToUint64(price)
}
func calculateProducts(products []core.Product) float64 {
productsPrice := float64(0)
for _, product := range products {
productsPrice += product.Price
}
return productsPrice
}
func calculateProductsMap(products map[string]core.Product) float64 {
productsPrice := float64(0)
for _, product := range products {
productsPrice += product.Price
}
return productsPrice
}
func calculatePricesGroupSum(pricesGroup map[string]float64) float64 {
finalPrice := float64(0)
for _, price := range pricesGroup {
finalPrice += price
}
return finalPrice
}
func calculateEachProductWithTarget(products map[string]core.Product, target models.DiscountCalculationTarget) map[string]core.Product {
if target.Products == nil && target.Factor == 0 {
return products
}
if target.Products == nil {
for key, product := range products {
products[key] = core.Product{
ID: key,
Price: product.Price * target.Factor,
Group: product.Group,
}
}
return products
}
for _, productTarget := range target.Products {
product, ok := products[productTarget.ID]
if !ok {
continue
}
if productTarget.Factor != 0 {
products[product.ID] = core.Product{
ID: product.ID,
Price: product.Price * productTarget.Factor,
Group: product.Group,
}
continue
}
products[product.ID] = core.Product{
ID: product.ID,
Price: product.Price * target.Factor,
Group: product.Group,
}
}
return products
}
func calculateProductsGroup(productsGroup map[string][]core.Product) map[string]float64 {
pricesGroup := make(map[string]float64)
for group, products := range productsGroup {
pricesGroup[group] = calculateProducts(products)
}
return pricesGroup
}

@ -1,31 +1,30 @@
package calculate_test
package discount_test
import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/calculate"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/discount"
)
func TestCalculate(t *testing.T) {
t.Run("Покупка продуктов в количестве не больше 1 при отсутствии скидок", func(t *testing.T) {
assert.Equal(t, 3.0, calculate.Discount(
assert.Equal(t, uint64(3), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 1.0},
{ID: "p2", Price: 2.0},
{ID: "p1", Price: 1},
{ID: "p2", Price: 2},
},
[]models.Discount{},
))
})
t.Run("Сумма корзины достигла 5к", func(t *testing.T) {
assert.Equal(t, 4925.0, calculate.Discount(
assert.Equal(t, uint64(4925), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 2000.0},
{ID: "p2", Price: 3000.0},
{ID: "p1", Price: 2000},
{ID: "p2", Price: 3000},
},
[]models.Discount{
{
@ -36,10 +35,10 @@ func TestCalculate(t *testing.T) {
},
},
))
assert.Equal(t, 4925.0, calculate.Discount(
assert.Equal(t, uint64(4925), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 2000.0},
{ID: "p2", Price: 3000.0},
{ID: "p1", Price: 2000},
{ID: "p2", Price: 3000},
},
[]models.Discount{
{
@ -52,11 +51,11 @@ func TestCalculate(t *testing.T) {
})
t.Run("Наложение несколько скидок разного формата", func(t *testing.T) {
assert.InEpsilon(t, 5025.32, calculate.Discount(
assert.Equal(t, uint64(5025), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 2000.0},
{ID: "p2", Price: 3000.0},
{ID: "p3", Price: 105.0},
{ID: "p1", Price: 2000},
{ID: "p2", Price: 3000},
{ID: "p3", Price: 105},
},
[]models.Discount{
{
@ -71,16 +70,16 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.001)
))
})
t.Run("Наложение несколько скидок разного формата с несколькими таргетами", func(t *testing.T) {
assert.InEpsilon(t, 5223.89, calculate.Discount(
assert.Equal(t, uint64(5223), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 2000.0},
{ID: "p2", Price: 3000.0},
{ID: "p3", Price: 105.0},
{ID: "p4", Price: 210.0},
{ID: "p1", Price: 2000},
{ID: "p2", Price: 3000},
{ID: "p3", Price: 105},
{ID: "p4", Price: 210},
},
[]models.Discount{
{
@ -98,16 +97,16 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.001)
))
})
t.Run("Наложение несколько скидок с наличием скидки на лояльность", func(t *testing.T) {
assert.InEpsilon(t, 5171.66, calculate.Discount(
assert.Equal(t, uint64(5171), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 2000.0},
{ID: "p2", Price: 3000.0},
{ID: "p3", Price: 105.0},
{ID: "p4", Price: 210.0},
{ID: "p1", Price: 2000},
{ID: "p2", Price: 3000},
{ID: "p3", Price: 105},
{ID: "p4", Price: 210},
},
[]models.Discount{
{
@ -135,7 +134,7 @@ func TestCalculate(t *testing.T) {
})
t.Run("Наложение несколько скидок на привелегии", func(t *testing.T) {
assert.InEpsilon(t, 422.28, calculate.Discount(
assert.Equal(t, uint64(422), discount.Calculate(
[]core.Product{
{ID: "p5", Price: 30},
{ID: "p6", Price: 70},
@ -164,11 +163,11 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.001)
))
})
t.Run("Наложение несколько скидок на привелегии без лояльности", func(t *testing.T) {
assert.InEpsilon(t, 426.55, calculate.Discount(
assert.Equal(t, uint64(426), discount.Calculate(
[]core.Product{
{ID: "p5", Price: 30},
{ID: "p6", Price: 70},
@ -185,11 +184,11 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.001)
))
})
t.Run("Вычисление скидки за привелегии и сервис", func(t *testing.T) {
assert.InEpsilon(t, 743.45, calculate.Discount(
assert.Equal(t, uint64(743), discount.Calculate(
[]core.Product{
{ID: "p5", Price: 30, Group: "dwarfener"},
{ID: "p6", Price: 70, Group: "dwarfener"},
@ -218,11 +217,11 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.001)
))
})
t.Run("Наложение скидок на несколько сервисов", func(t *testing.T) {
assert.InEpsilon(t, 2398.5, calculate.Discount(
assert.Equal(t, uint64(2398), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 1500, Group: "templategen"},
{ID: "p2", Price: 300, Group: "templategen"},
@ -262,11 +261,11 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.01)
))
})
t.Run("Наложение скидок с промокодом", func(t *testing.T) {
assert.InEpsilon(t, 2368.68, calculate.Discount(
assert.Equal(t, uint64(2368), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 1500, Group: "templategen"},
{ID: "p2", Price: 300, Group: "templategen"},
@ -287,6 +286,7 @@ func TestCalculate(t *testing.T) {
},
},
{
Layer: 2,
Target: models.DiscountCalculationTarget{
Products: []models.ProductTarget{
{ID: "p6", Factor: 0.5, Overhelm: true},
@ -299,6 +299,8 @@ func TestCalculate(t *testing.T) {
},
},
{
ID: "2",
Layer: 2,
Target: models.DiscountCalculationTarget{
Factor: 0.99,
Overhelm: true,
@ -319,11 +321,11 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.01)
))
})
t.Run("Наложение скидок по типу пользователя", func(t *testing.T) {
assert.InEpsilon(t, 540, calculate.Discount(
assert.Equal(t, uint64(540), discount.Calculate(
[]core.Product{
{ID: "p1", Price: 1500, Group: "templategen"},
{ID: "p2", Price: 300, Group: "templategen"},
@ -339,6 +341,6 @@ func TestCalculate(t *testing.T) {
},
},
},
), 0.01)
))
})
}

@ -0,0 +1,147 @@
package discount
import (
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
)
func SortOverhelmingDiscounts(discounts []models.Discount) map[models.TargetScope][]models.DiscountCalculationTarget {
dividedDiscounts := divideDiscountsByScope(discounts)
return map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: sortOverhelmingDiscountsEach(dividedDiscounts[models.TargetEach]),
models.TargetGroup: sortOverhelmingDiscounts(dividedDiscounts[models.TargetGroup]),
models.TargetSum: sortOverhelmingDiscounts(dividedDiscounts[models.TargetSum]),
}
}
func constituteOverhelmingProductTargetLayersMap(discounts []models.Discount) map[string]uint32 {
overhelmingProductTargetLayers := make(map[string]uint32)
for _, discount := range discounts {
for _, productTarget := range discount.Target.Products {
if existingLayer, ok := overhelmingProductTargetLayers[productTarget.ID]; ok {
if productTarget.Overhelm && existingLayer < discount.Layer {
overhelmingProductTargetLayers[productTarget.ID] = discount.Layer
}
continue
}
if productTarget.Overhelm {
overhelmingProductTargetLayers[productTarget.ID] = discount.Layer
}
}
}
return overhelmingProductTargetLayers
}
func constituteOverhelmingDiscountLayer(discounts []models.Discount) uint32 {
overhelmingDiscountLayer := uint32(0)
for _, discount := range discounts {
if discount.Target.Overhelm && overhelmingDiscountLayer < discount.Layer {
overhelmingDiscountLayer = discount.Layer
}
}
return overhelmingDiscountLayer
}
func sortOverhelmingDiscountsEach(discounts []models.Discount) []models.DiscountCalculationTarget {
if len(discounts) < 1 {
return []models.DiscountCalculationTarget{}
}
sortedDiscountCalculationTargetsEach := make([]models.DiscountCalculationTarget, 0, len(discounts))
overhelmingProductTargetLayers := constituteOverhelmingProductTargetLayersMap(discounts)
overhelmingDiscountLayer := constituteOverhelmingDiscountLayer(discounts)
for _, discount := range discounts {
if overhelmingDiscountLayer > discount.Layer {
continue
}
updatedProductTargets := make([]models.ProductTarget, 0, len(discount.Target.Products))
for _, productTarget := range discount.Target.Products {
if overhelmingProductTarget, ok := overhelmingProductTargetLayers[productTarget.ID]; ok && overhelmingProductTarget > discount.Layer {
continue
}
updatedProductTargets = append(updatedProductTargets, models.ProductTarget{
ID: productTarget.ID,
Factor: productTarget.Factor,
})
}
sortedDiscountCalculationTargetsEach = append(sortedDiscountCalculationTargetsEach, models.DiscountCalculationTarget{
Products: updatedProductTargets,
Factor: discount.Target.Factor,
TargetScope: discount.Target.TargetScope,
TargetGroup: discount.Target.TargetGroup,
})
}
return sortedDiscountCalculationTargetsEach
}
func sortOverhelmingDiscounts(discounts []models.Discount) []models.DiscountCalculationTarget {
if len(discounts) < 1 {
return []models.DiscountCalculationTarget{}
}
sortedDiscountCalculationTargets := make([]models.DiscountCalculationTarget, 0, len(discounts))
overhelmingDiscountLayer := constituteOverhelmingDiscountLayer(discounts)
for _, discount := range discounts {
if overhelmingDiscountLayer > discount.Layer {
continue
}
sortedDiscountCalculationTargets = append(sortedDiscountCalculationTargets, models.DiscountCalculationTarget{
Factor: discount.Target.Factor,
TargetScope: discount.Target.TargetScope,
TargetGroup: discount.Target.TargetGroup,
})
}
return sortedDiscountCalculationTargets
}
func divideDiscountsByScope(discounts []models.Discount) map[models.TargetScope][]models.Discount {
dividedTargets := make(map[models.TargetScope][]models.Discount, 3)
for _, discount := range discounts {
if discount.Target.TargetScope == "" && len(discount.Target.Products) > 0 {
dividedTargets[models.TargetEach] = append(dividedTargets[models.TargetEach], models.Discount{
Layer: discount.Layer,
Target: models.DiscountCalculationTarget{
Products: discount.Target.Products,
Factor: discount.Target.Factor,
TargetScope: models.TargetEach,
Overhelm: discount.Target.Overhelm,
},
})
continue
}
if discount.Target.TargetScope == "" && len(discount.Target.Products) < 1 {
dividedTargets[models.TargetSum] = append(dividedTargets[models.TargetSum], models.Discount{
Layer: discount.Layer,
Target: models.DiscountCalculationTarget{
Factor: discount.Target.Factor,
TargetScope: models.TargetSum,
Overhelm: discount.Target.Overhelm,
},
})
continue
}
dividedTargets[discount.Target.TargetScope] = append(dividedTargets[discount.Target.TargetScope], discount)
}
return dividedTargets
}

@ -0,0 +1,743 @@
package discount_test
import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/discount"
)
func TestSortOverhelmingDiscounts(t *testing.T) {
t.Run("Успешная сортировка скидок по каждому продукту при наличии перекрывающией скидки на каждый продукт и на определённый продукт", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
{
TargetScope: models.TargetEach,
Factor: 0.8,
Products: []models.ProductTarget{
{ID: "p6", Factor: 0.5},
},
},
},
models.TargetGroup: {},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "1",
Layer: 1,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.94},
},
},
},
{
ID: "2",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91},
},
},
},
{
ID: "3",
Layer: 3,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p6", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
},
{
ID: "4",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.8,
Products: []models.ProductTarget{
{ID: "p6", Factor: 0.5, Overhelm: true},
},
},
},
}),
)
})
t.Run("Успешная сортировка скидок по каждому продукту при наличии самой перекрывающей скидки", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
},
models.TargetGroup: {},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "5",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
},
{
ID: "6",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91, Overhelm: true},
},
},
},
{
ID: "7",
Layer: 3,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p6", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
},
{
ID: "8",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.8,
Products: []models.ProductTarget{
{ID: "p6", Factor: 0.5, Overhelm: true},
},
},
},
}),
)
})
t.Run("Успешная сортировка скидок по каждому продукту при наличии скидок с одинаковым значением слоя", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91},
},
},
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p6", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
},
models.TargetGroup: {},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "9",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
},
{
ID: "1",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91, Overhelm: true},
},
},
},
{
ID: "2",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p6", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
},
{
ID: "3",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.8,
Products: []models.ProductTarget{
{ID: "p6", Factor: 0.5, Overhelm: true},
},
},
},
}),
)
})
t.Run("Успешная сортировка скидок по каждому продукту при наличии скидок с одинаковым значением слоя и полностью перекрывающими другие", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {
{
Factor: 0.92,
TargetScope: models.TargetEach,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
{
Factor: 0.92,
TargetScope: models.TargetEach,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91},
},
},
},
models.TargetGroup: {},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "4",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
},
{
ID: "7",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91, Overhelm: true},
},
},
},
{
ID: "4",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.8,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.5, Overhelm: true},
},
},
},
}),
)
})
t.Run("Успешная сортировка скидок по каждому продукту при наличии скидок, где одна полностью перекрывает продукты другой", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {
{
TargetScope: models.TargetEach,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
{
Factor: 0.92,
TargetScope: models.TargetEach,
Products: []models.ProductTarget{},
},
},
models.TargetGroup: {},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "5",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94, Overhelm: true},
},
},
},
{
ID: "6",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.5, Overhelm: true},
},
},
},
}),
)
})
t.Run("Успешная сортировка скидок по группе продуктов при наличии перекрывающих скидок", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {},
models.TargetGroup: {
{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.92,
},
},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "7",
Layer: 6,
Target: models.DiscountCalculationTarget{
Overhelm: true,
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.92,
},
},
{
ID: "8",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.96,
},
},
{
ID: "9",
Layer: 3,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.91,
},
},
}),
)
})
t.Run("Успешная сортировка скидок по группе продуктов при наличии перекрывающих скидок и разных групп", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {},
models.TargetGroup: {
{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.92,
},
},
models.TargetSum: {},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "1",
Layer: 6,
Target: models.DiscountCalculationTarget{
Overhelm: true,
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.92,
},
},
{
ID: "2",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.42,
},
},
{
ID: "3",
Layer: 5,
Target: models.DiscountCalculationTarget{
Overhelm: true,
TargetScope: models.TargetGroup,
TargetGroup: "111",
Factor: 0.9,
},
},
{
ID: "4",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetGroup,
TargetGroup: "111",
Factor: 0.8,
},
},
}),
)
})
t.Run("Успешная сортировка скидок по сумме при наличии скидки, перекрывающая все остальные", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {},
models.TargetGroup: {},
models.TargetSum: {
{
TargetScope: models.TargetSum,
Factor: 0.92,
},
},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "1",
Layer: 6,
Target: models.DiscountCalculationTarget{
Overhelm: true,
TargetScope: models.TargetSum,
Factor: 0.92,
},
},
{
ID: "2",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.42,
},
},
{
ID: "3",
Layer: 5,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Overhelm: true,
Factor: 0.9,
},
},
{
ID: "4",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.8,
},
},
}),
)
})
t.Run("Успешная сортировка скидок по сумме при наличии перекрывающей скидки", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {},
models.TargetGroup: {},
models.TargetSum: {
{
TargetScope: models.TargetSum,
Factor: 0.92,
},
{
TargetScope: models.TargetSum,
Factor: 0.42,
},
{
TargetScope: models.TargetSum,
Factor: 0.9,
},
},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "1",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.92,
},
},
{
ID: "2",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Overhelm: true,
Factor: 0.42,
},
},
{
ID: "3",
Layer: 5,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.9,
},
},
{
ID: "4",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.8,
},
},
}),
)
})
t.Run("Успешная сортировка смешанных скидок при наличии перекрывающих", func(t *testing.T) {
assert.Equal(t,
map[models.TargetScope][]models.DiscountCalculationTarget{
models.TargetEach: {
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91},
},
},
{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p6", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
},
models.TargetGroup: {
{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.92,
},
},
models.TargetSum: {
{
TargetScope: models.TargetSum,
Factor: 0.92,
},
{
TargetScope: models.TargetSum,
Factor: 0.42,
},
{
TargetScope: models.TargetSum,
Factor: 0.9,
},
},
},
discount.SortOverhelmingDiscounts([]models.Discount{
{
ID: "1",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.92,
},
},
{
ID: "2",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Overhelm: true,
Factor: 0.42,
},
},
{
ID: "3",
Layer: 5,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.9,
},
},
{
ID: "4",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetSum,
Factor: 0.8,
},
},
{
ID: "5",
Layer: 6,
Target: models.DiscountCalculationTarget{
Overhelm: true,
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.92,
},
},
{
ID: "6",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetGroup,
TargetGroup: "123",
Factor: 0.42,
},
},
{
ID: "7",
Layer: 5,
Target: models.DiscountCalculationTarget{
Overhelm: true,
TargetScope: models.TargetGroup,
TargetGroup: "111",
Factor: 0.9,
},
},
{
ID: "8",
Layer: 2,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetGroup,
TargetGroup: "111",
Factor: 0.8,
},
},
{
ID: "9",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p2", Factor: 0.94},
},
},
},
{
ID: "10",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Products: []models.ProductTarget{
{ID: "p7", Factor: 0.91, Overhelm: true},
},
},
},
{
ID: "11",
Layer: 6,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.92,
Overhelm: true,
Products: []models.ProductTarget{
{ID: "p1", Factor: 0.93},
{ID: "p2", Factor: 0.945},
{ID: "p5", Factor: 0.97},
{ID: "p6", Factor: 0.97},
{ID: "p7", Factor: 0.83},
},
},
},
{
ID: "12",
Layer: 4,
Target: models.DiscountCalculationTarget{
TargetScope: models.TargetEach,
Factor: 0.8,
Products: []models.ProductTarget{
{ID: "p6", Factor: 0.5, Overhelm: true},
},
},
},
}),
)
})
}

@ -4,7 +4,6 @@ import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"golang.org/x/exp/constraints"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
)

@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/expression"
@ -52,7 +51,6 @@ func TestGetValueConditionBSON(t *testing.T) {
}
func TestGetPerionConditionBSON(t *testing.T) {
t.Run("Получение bson условия периода с заполненными данными", func(t *testing.T) {
assert.Equal(t,
[]bson.M{

@ -2,7 +2,6 @@ package discount
import (
"go.mongodb.org/mongo-driver/bson"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/expression"
@ -41,7 +40,7 @@ func ConstituteOptionalConditions(conditions *core.OptionalDiscounCondition) []b
{"$or": expression.GetValueConditionBSON(fields.DiscountCondition.Product, defaults.GetDefaultValue(conditions.Product, ""))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.Term, defaults.GetDefaultValue(conditions.Term, uint64(0)))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.Usage, defaults.GetDefaultValue(conditions.Usage, uint64(0)))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.PriceFrom, defaults.GetDefaultValue(conditions.PriceFrom, float64(0)))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.PriceFrom, defaults.GetDefaultValue(conditions.PriceFrom, uint64(0)))},
{"$or": expression.GetValueConditionBSON(fields.DiscountCondition.Group, defaults.GetDefaultValue(conditions.Group, ""))},
}
}

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
@ -15,11 +14,11 @@ import (
)
func TestConstituteCommonConditions(t *testing.T) {
userID := "user1"
userType := "nkvo"
coupon := "coupon"
purchasesAmount := float64(10000)
cartPurchasesAmount := float64(20000)
userID := "user12"
userType := "nkvo9"
coupon := "coupon11"
purchasesAmount := uint64(10000)
cartPurchasesAmount := uint64(20000)
t.Run("Формирование фильтра общих условий поиска с nil", func(t *testing.T) {
assert.Equal(t, []bson.M{}, discount.ConstituteCommonConditions(nil))
@ -96,11 +95,11 @@ func TestConstituteCommonConditions(t *testing.T) {
}
func TestConstituteOptionalConditions(t *testing.T) {
productID := "product1"
productID := "productgg1"
term := uint64(14)
usage := uint64(10)
priceFrom := float64(13000)
group := "group"
priceFrom := uint64(13000)
group := "group888"
t.Run("Формирование фильтра опциональных условий поиска и nil", func(t *testing.T) {
assert.Equal(t, []bson.M{}, discount.ConstituteOptionalConditions(nil))
@ -131,7 +130,7 @@ func TestConstituteOptionalConditions(t *testing.T) {
{"$or": expression.GetValueConditionBSON(fields.DiscountCondition.Product, "")},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.Term, uint64(0))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.Usage, uint64(0))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.PriceFrom, float64(0))},
{"$or": expression.GetAscRangeConditionBSON(fields.DiscountCondition.PriceFrom, uint64(0))},
{"$or": expression.GetValueConditionBSON(fields.DiscountCondition.Group, "")},
},
discount.ConstituteOptionalConditions(&core.OptionalDiscounCondition{}),

@ -2,7 +2,6 @@ package discount
import (
"go.mongodb.org/mongo-driver/bson"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
)
@ -22,7 +21,8 @@ func ConditionFilter(conditions *core.DiscountConditions) *bson.M {
}
for _, expression := range conditions.Optionals {
optionalExpressions := ConstituteOptionalConditions(&expression)
expressionCopy := expression
optionalExpressions := ConstituteOptionalConditions(&expressionCopy)
expressions = append(expressions, bson.M{
"$and": append([]bson.M{}, append(commonExpressions, optionalExpressions...)...),
})

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/expression/discount"
@ -17,13 +16,13 @@ func TestConditionFilter(t *testing.T) {
productID2 := "product2"
term := uint64(14)
usage := uint64(10)
priceFrom := float64(13000)
group := "group"
priceFrom := uint64(13000)
group := "groupopo"
userID := "user1"
userType := "nkvo"
userType := "nkvo01001"
coupon := "coupon"
purchasesAmount := float64(10000)
cartPurchasesAmount := float64(20000)
purchasesAmount := uint64(10000)
cartPurchasesAmount := uint64(20000)
t.Run("Формирование фильтра условий поиска с пустыми условиями", func(t *testing.T) {
assert.NotNil(t, discount.ConditionFilter(&core.DiscountConditions{}))

@ -3,7 +3,6 @@ package discount
import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/utils"

@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
@ -16,22 +15,22 @@ import (
func TestGetDiscountExpression(t *testing.T) {
id := "id1"
name := "discount"
name := "discount1oo"
description := ""
layer := uint32(3)
deprecated := false
user := "testUser"
userType := "nkvo"
coupon := "coupon1"
product := "p1"
priceFrom := float64(200)
cartPurchasesAmount := float64(20000)
purchasesAmount := float64(10000)
user := "testUser3"
userType := "nkvo090909"
coupon := "coupon14"
product := "p12"
priceFrom := uint64(200)
cartPurchasesAmount := uint64(20000)
purchasesAmount := uint64(10000)
usage := uint64(20)
term := uint64(40)
factor := 0.95
targetScope := models.TargetSum
targetGroup := "group"
targetGroup := "groupffffff"
overhelm := true
condition := models.DiscountCondition{
User: &user,

@ -2,7 +2,6 @@ package discount
import (
"go.mongodb.org/mongo-driver/bson"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/convert"
)

@ -7,7 +7,6 @@ import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
@ -23,9 +22,9 @@ func TestGetUpdateDiscountExpression(t *testing.T) {
userType := "nkvo"
coupon := "coupon1"
product := "p1"
priceFrom := float64(200)
cartPurchasesAmount := float64(20000)
purchasesAmount := float64(10000)
priceFrom := uint64(200)
cartPurchasesAmount := uint64(20000)
purchasesAmount := uint64(10000)
usage := uint64(20)
term := uint64(40)
factor := 0.95

@ -10,6 +10,7 @@ func FilterCouponDiscounts(discounts []models.Discount) ([]models.Discount, *mod
}
var couponDiscount *models.Discount
notCouponDiscount := make([]models.Discount, 0, len(discounts))
for _, discount := range discounts {
@ -19,6 +20,7 @@ func FilterCouponDiscounts(discounts []models.Discount) ([]models.Discount, *mod
if isCouponDiscount && couponDiscount != nil {
continue
}
if isCouponDiscount && couponDiscount == nil {
couponDiscount = &currentDiscount
}

@ -4,7 +4,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils"
)

@ -2,7 +2,6 @@ package transfer
import (
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
)

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/transfer"

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/transfer"
@ -14,15 +13,15 @@ import (
func TestDiscountConditionProtoToModel(t *testing.T) {
userID := "1"
userType := "nkvo"
coupon := "test"
product := "product1"
purchasesAmount := float64(20000)
cartPurchasesAmount := float64(20000)
userType := "nkvo11"
coupon := "test22"
product := "product13"
purchasesAmount := uint64(20000)
cartPurchasesAmount := uint64(20000)
term := uint64(20)
usage := uint64(20)
priceFrom := float64(20000)
group := "testGroup"
priceFrom := uint64(20000)
group := "testGroupo"
t.Run("Перевод не до конца заполненных условий скидок с proto в модель", func(t *testing.T) {
assert.Equal(t,
@ -86,12 +85,12 @@ func TestDiscountConditionModelToProto(t *testing.T) {
userType := "nkvo"
coupon := "test"
product := "product1"
purchasesAmount := float64(20000)
cartPurchasesAmount := float64(20000)
purchasesAmount := uint64(20000)
cartPurchasesAmount := uint64(20000)
term := uint64(20)
usage := uint64(20)
priceFrom := float64(20000)
group := "testGroup"
priceFrom := uint64(20000)
group := "testGroupbgfbgbgb"
t.Run("Перевод условий скидки с модели в proto", func(t *testing.T) {
assert.Equal(t,

@ -6,15 +6,14 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/transfer"
)
func TestDiscountsProtoToModel(t *testing.T) {
cartPurchasesAmount := float64(20000)
purchasesAmount := float64(20000)
cartPurchasesAmount := uint64(20000)
purchasesAmount := uint64(20000)
userID := string("13")
userType := string("type")
coupon := string("coupon1")
@ -88,7 +87,7 @@ func TestDiscountsProtoToModel(t *testing.T) {
}
func TestDiscountProtoToModel(t *testing.T) {
cartPurchasesAmount := float64(20000)
cartPurchasesAmount := uint64(20000)
deletedAtModel := time.Unix(1674546287, 0).UTC()
deletedAtProto := timestamppb.Timestamp{Seconds: 1674546287}
@ -143,7 +142,7 @@ func TestDiscountProtoToModel(t *testing.T) {
}
func TestDiscountsModelToProto(t *testing.T) {
cartPurchasesAmount := float64(20000)
cartPurchasesAmount := uint64(20000)
deletedAtModel := time.Unix(1674546287, 0).UTC()
deletedAtProto := timestamppb.Timestamp{Seconds: 1674546287}
@ -200,7 +199,7 @@ func TestDiscountsModelToProto(t *testing.T) {
}
func TestDiscountModelToProto(t *testing.T) {
cartPurchasesAmount := float64(20000)
cartPurchasesAmount := uint64(20000)
t.Run("Перевод скидки из модели в proto", func(t *testing.T) {
assert.Equal(t,

@ -2,7 +2,6 @@ package transfer
import (
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
proto "penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
)

@ -6,7 +6,6 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/utils/transfer"

@ -76,7 +76,7 @@ func ProductsProtoToCore(productInformations []*proto.ProductInformation) []core
products[index] = core.Product{
ID: product.ID,
Price: product.Price,
Price: float64(product.Price),
Group: receiveGroup(product),
}
}

@ -4,7 +4,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"

@ -17,11 +17,11 @@ func TestContains(t *testing.T) {
}{
{
name: "Проверка наличие строк по значению",
inputArray: []any{"test1", "test2"},
inputArray: []any{"test1245", "test2"},
inputCallback: func(element any, index int, array []any) bool {
assert.Equal(t, array, []any{"test1", "test2"})
assert.Equal(t, array, []any{"test1245", "test2"})
return element == "test1"
return element == "test1245"
},
expect: true,
},
@ -31,7 +31,7 @@ func TestContains(t *testing.T) {
inputCallback: func(element any, index int, array []any) bool {
assert.Equal(t, array, []any{"test1", "test2"})
return element == "tttt"
return element == "fdadadfadfadf"
},
expect: false,
},
@ -108,16 +108,16 @@ func TestContains(t *testing.T) {
{
name: "Проверка наличие объектов по значению поля",
inputArray: []struct{ Name string }{
{Name: "test1"},
{Name: "test19999"},
{Name: "test2"},
},
inputCallback: func(element struct{ Name string }, index int, array []struct{ Name string }) bool {
assert.Equal(t, array, []struct{ Name string }{
{Name: "test1"},
{Name: "test19999"},
{Name: "test2"},
})
return element.Name == "test1"
return element.Name == "test19999"
},
expect: true,
},

@ -11,4 +11,3 @@ func Filter[T any](array []T, callback func(T, int, []T) bool) []T {
return filteredArray
}

@ -17,13 +17,13 @@ func TestFilter(t *testing.T) {
}{
{
name: "Фильтрация массива строк по значению",
inputArray: []any{"test1", "test2"},
inputArray: []any{"test10130153", "test2"},
inputCallback: func(element any, index int, array []any) bool {
assert.Equal(t, array, []any{"test1", "test2"})
assert.Equal(t, array, []any{"test10130153", "test2"})
return element == "test1"
return element == "test10130153"
},
expect: []any{"test1"},
expect: []any{"test10130153"},
},
{
name: "Фильтрация массива строк по индексу",
@ -84,19 +84,19 @@ func TestFilter(t *testing.T) {
{
name: "Фильтрация массива объектов по значению поля",
inputArray: []struct{ Name string }{
{Name: "test1"},
{Name: "test5313131"},
{Name: "test2"},
},
inputCallback: func(element struct{ Name string }, index int, array []struct{ Name string }) bool {
assert.Equal(t, array, []struct{ Name string }{
{Name: "test1"},
{Name: "test5313131"},
{Name: "test2"},
})
return element.Name == "test1"
return element.Name == "test5313131"
},
expect: []struct{ Name string }{
{Name: "test1"},
{Name: "test5313131"},
},
},
{

11
pkg/array/find.go Normal file

@ -0,0 +1,11 @@
package array
func Find[T any](array []T, callback func(T, int, []T) bool) *T {
for index, element := range array {
if callback(element, index, array) {
return &element
}
}
return nil
}

32
pkg/array/find_test.go Normal file

@ -0,0 +1,32 @@
package array_test
import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/array"
)
func TestFind(t *testing.T) {
t.Run("Find element in array (success)", func(t *testing.T) {
result := "test1"
callback := func(element string, index int, array []string) bool {
assert.Equal(t, array, []string{"test1", "test2"})
return element == result
}
assert.Equal(t, &result, array.Find([]string{"test1", "test2"}, callback))
})
t.Run("Find element in array (failure)", func(t *testing.T) {
result := "test"
callback := func(element string, index int, array []string) bool {
assert.Equal(t, array, []string{"test1", "test2"})
return element == result
}
assert.Nil(t, array.Find([]string{"test1", "test2"}, callback))
})
}

50
pkg/closer/closer.go Normal file

@ -0,0 +1,50 @@
package closer
import (
"context"
"fmt"
"log"
"sync"
)
type Callback func(ctx context.Context) error
type Closer struct {
mutex sync.Mutex
callbacks []Callback
}
func New() *Closer {
return &Closer{}
}
func (receiver *Closer) Add(callback Callback) {
receiver.mutex.Lock()
defer receiver.mutex.Unlock()
receiver.callbacks = append(receiver.callbacks, callback)
}
func (receiver *Closer) Close(ctx context.Context) error {
receiver.mutex.Lock()
defer receiver.mutex.Unlock()
complete := make(chan struct{}, 1)
go func() {
for index, callback := range receiver.callbacks {
if err := callback(ctx); err != nil {
log.Printf("[! (%d)] %v", index, err)
}
}
complete <- struct{}{}
}()
select {
case <-complete:
return nil
case <-ctx.Done():
return fmt.Errorf("shutdown cancelled: %v", ctx.Err())
}
}

74
pkg/convert/map_test.go Normal file

@ -0,0 +1,74 @@
package convert_test
import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/convert"
)
func TestArrayToMap(t *testing.T) {
type Product struct {
ID string
Price float64
Group string
}
t.Run("Успешная конвертация массива в карту по ID", func(t *testing.T) {
products := []Product{
{ID: "p1", Price: 1500, Group: "templategen"},
{ID: "p2", Price: 300, Group: "templategen"},
{ID: "p5", Price: 30, Group: "dwarfener"},
{ID: "p6", Price: 70, Group: "dwarfener"},
{ID: "p7", Price: 800, Group: "dwarfener"},
}
assert.Equal(t,
map[string]Product{
"p1": {ID: "p1", Price: 1500, Group: "templategen"},
"p2": {ID: "p2", Price: 300, Group: "templategen"},
"p5": {ID: "p5", Price: 30, Group: "dwarfener"},
"p6": {ID: "p6", Price: 70, Group: "dwarfener"},
"p7": {ID: "p7", Price: 800, Group: "dwarfener"},
},
convert.ArrayToMap(products, func(product Product) string {
return product.ID
}),
)
})
}
func TestMapToMapArray(t *testing.T) {
type Product struct {
ID string
Price float64
Group string
}
t.Run("Успешная конвертация массива в карту из массивов", func(t *testing.T) {
productsMap := map[string]Product{
"p1": {ID: "p1", Price: 1500, Group: "templategen"},
"p2": {ID: "p2", Price: 300, Group: "templategen"},
"p5": {ID: "p5", Price: 30, Group: "dwarfener"},
"p6": {ID: "p6", Price: 70, Group: "dwarfener"},
"p7": {ID: "p7", Price: 800, Group: "dwarfener"},
}
assert.EqualValues(t,
map[string][]Product{
"templategen": {
{ID: "p1", Price: 1500, Group: "templategen"},
{ID: "p2", Price: 300, Group: "templategen"},
},
"dwarfener": {
{ID: "p5", Price: 30, Group: "dwarfener"},
{ID: "p6", Price: 70, Group: "dwarfener"},
{ID: "p7", Price: 800, Group: "dwarfener"},
},
},
convert.MapToMapArray(productsMap, func(product Product) string {
return product.Group
}),
)
})
}

@ -50,10 +50,8 @@ func ObjectToStringMap(object interface{}, tagName string) (map[string]string, e
mapString := make(map[string]string, len(mapObject))
for key, value := range mapObject {
strKey := fmt.Sprintf("%v", key)
strValue := fmt.Sprintf("%v", value)
mapString[strKey] = strValue
mapString[key] = strValue
}
return mapString, nil

11
pkg/convert/uint.go Normal file

@ -0,0 +1,11 @@
package convert
import (
"math"
"golang.org/x/exp/constraints"
)
func FloatToUint64[T constraints.Float](number T) uint64 {
return uint64(math.Floor(float64(number)))
}

22
pkg/convert/uint_test.go Normal file

@ -0,0 +1,22 @@
package convert_test
import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/convert"
)
func TestFloatToUint64(t *testing.T) {
t.Run("Успешная конвертация float32 в uint32", func(t *testing.T) {
assert.Equal(t, uint64(10), convert.FloatToUint64(float32(10.6)))
})
t.Run("Успешная конвертация float64 в uint32", func(t *testing.T) {
assert.Equal(t, uint64(10), convert.FloatToUint64(float64(10.6)))
})
t.Run("Успешная конвертация float64 в uint32 (2)", func(t *testing.T) {
assert.Equal(t, uint64(10), convert.FloatToUint64(float64(10)))
})
}

@ -8,7 +8,6 @@ import (
)
func TestGetDefaultValue(t *testing.T) {
t.Run("Стандартное значение nil", func(t *testing.T) {
assert.Equal(t, 0, defaults.GetDefaultValue(nil, 0))
})

2
pkg/env/parse.go vendored

@ -9,7 +9,7 @@ import (
envParser "github.com/sethvargo/go-envconfig"
)
// Parsing default env file or env context and returns struct pointer by generic
// Parse parsing default env file or env context and returns struct pointer by generic.
func Parse[T interface{}](envFilePath string) (*T, error) {
var configuration T

@ -65,7 +65,9 @@ func Connect(ctx context.Context, deps *ConnectDeps) (*mongo.Database, error) {
log.Printf("failed to connect to db <%s>: %s", mongoURI.String(), err.Error())
case <-timeoutExceeded:
return nil, fmt.Errorf("db connection <%s> failed after %d timeout", mongoURI, deps.Timeout)
return nil, fmt.Errorf("db connection <%s> failed after %d timeout", mongoURI.String(), deps.Timeout)
default:
time.Sleep(1 * time.Second)
}
}
}

@ -2,10 +2,9 @@ package mongo
import (
"context"
"log"
)
func Find[T any](ctx context.Context, settings *RequestSettings) ([]T, error) {
if settings == nil {
return []T{}, ErrEmptyArgs
@ -13,12 +12,16 @@ func Find[T any](ctx context.Context, settings *RequestSettings) ([]T, error) {
results := make([]T, 0)
cursor, err := settings.Driver.Find(ctx, settings.Filter)
cursor, err := settings.Driver.Find(ctx, settings.Filter, settings.Options)
if err != nil {
return []T{}, err
}
defer cursor.Close(ctx)
defer func() {
if err := cursor.Close(ctx); err != nil {
log.Printf("failed to close cursor: %v", err)
}
}()
for cursor.Next(ctx) {
result := new(T)

@ -4,7 +4,6 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/utils"
)

@ -46,12 +46,12 @@ message DiscountCondition {
optional string User = 2;
optional string UserType = 3;
optional string Coupon = 4;
optional double PurchasesAmount = 5;
optional double CartPurchasesAmount = 6;
optional uint64 PurchasesAmount = 5;
optional uint64 CartPurchasesAmount = 6;
optional string Product = 7;
optional uint64 Term = 8;
optional uint64 Usage = 9;
optional double PriceFrom = 10;
optional uint64 PriceFrom = 10;
optional string Group = 11;
}
@ -69,13 +69,13 @@ message PeriodCondition {
message UserInformation {
string ID = 1;
string Type = 2;
double PurchasesAmount = 3;
double CartPurchasesAmount = 4;
uint64 PurchasesAmount = 3;
uint64 CartPurchasesAmount = 4;
}
message ProductInformation {
string ID = 1;
double Price = 2;
uint64 Price = 2;
optional uint64 Term = 3;
optional uint64 Usage = 4;
optional string Group = 5;

@ -82,7 +82,7 @@ message ApplyDiscountRequest {
}
message ApplyDiscountResponse {
double Price = 1;
uint64 Price = 1;
repeated Discount AppliedDiscounts = 2;
}

@ -1,5 +1,3 @@
//go:build integration
package integration_test
import (
@ -9,11 +7,10 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/parse"
)
func TestCreateDiscount(t *testing.T) {
@ -24,7 +21,7 @@ func TestCreateDiscount(t *testing.T) {
discountClientConnection, err := grpc.Dial(
fmt.Sprintf("%s:%s", config.GRPC.Host, config.GRPC.Port),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
assert.NoError(t, err)
@ -32,7 +29,7 @@ func TestCreateDiscount(t *testing.T) {
discountClient := discount.NewDiscountServiceClient(discountClientConnection)
t.Run("Создание скидки", func(t *testing.T) {
productID := "p1"
productID := "p1000"
term := uint64(40)
createdDiscount, err := discountClient.CreateDiscount(
@ -63,7 +60,24 @@ func TestCreateDiscount(t *testing.T) {
isNotNil := assert.NotNil(t, findedDiscount)
if isNoError && isNotNil {
assert.Equal(t, parse.Discount(createdDiscount), parse.Discount(findedDiscount))
assert.Equal(t,
discount.Discount{
ID: createdDiscount.ID,
Name: createdDiscount.Name,
Layer: createdDiscount.Layer,
Description: createdDiscount.Description,
Condition: createdDiscount.Condition,
Deprecated: createdDiscount.Deprecated,
},
discount.Discount{
ID: findedDiscount.ID,
Name: findedDiscount.Name,
Layer: findedDiscount.Layer,
Description: findedDiscount.Description,
Condition: findedDiscount.Condition,
Deprecated: findedDiscount.Deprecated,
},
)
}
}
})

@ -1,5 +1,3 @@
//go:build integration
package integration_test
import (
@ -9,11 +7,10 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/parse"
)
func TestDeleteDiscount(t *testing.T) {
@ -24,7 +21,7 @@ func TestDeleteDiscount(t *testing.T) {
discountClientConnection, err := grpc.Dial(
fmt.Sprintf("%s:%s", config.GRPC.Host, config.GRPC.Port),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
assert.NoError(t, err)
@ -63,7 +60,24 @@ func TestDeleteDiscount(t *testing.T) {
isNotNil := assert.NotNil(t, deletedDiscount)
if isNoError && isNotNil {
assert.Equal(t, parse.Discount(createdDiscount), parse.Discount(deletedDiscount))
assert.Equal(t,
discount.Discount{
ID: createdDiscount.ID,
Name: createdDiscount.Name,
Layer: createdDiscount.Layer,
Description: createdDiscount.Description,
Condition: createdDiscount.Condition,
Deprecated: createdDiscount.Deprecated,
},
discount.Discount{
ID: deletedDiscount.ID,
Name: deletedDiscount.Name,
Layer: deletedDiscount.Layer,
Description: deletedDiscount.Description,
Condition: deletedDiscount.Condition,
Deprecated: deletedDiscount.Deprecated,
},
)
findedDiscount, err := discountClient.GetDiscountByID(context.Background(), &discount.GetDiscountByIDRequest{
ID: createdDiscount.ID,

@ -1,5 +1,3 @@
//go:build integration
package integration_test
import (
@ -9,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"
@ -32,7 +30,7 @@ func TestApplyDiscount(t *testing.T) {
discountClientConnection, err := grpc.Dial(
fmt.Sprintf("%s:%s", config.GRPC.Host, config.GRPC.Port),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
assert.NoError(t, err)
@ -69,7 +67,7 @@ func TestApplyDiscount(t *testing.T) {
utils.CleanDiscountsIDs(response.AppliedDiscounts)
assert.Equal(t, []*discount.Discount{data.DiscountID4}, response.AppliedDiscounts)
assert.InEpsilon(t, 4925.0, response.Price, 0.001)
assert.Equal(t, uint64(4925), response.Price)
}
})
@ -110,7 +108,7 @@ func TestApplyDiscount(t *testing.T) {
utils.CleanDiscountsIDs(response.AppliedDiscounts)
assert.Equal(t, []*discount.Discount{data.DiscountID4, data.DiscountID22}, response.AppliedDiscounts)
assert.InEpsilon(t, 5025.32, response.Price, 0.001)
assert.Equal(t, uint64(5025), response.Price)
}
})
}

@ -9,9 +9,9 @@ var (
varFalse = false
varTrue = true
cartPurchasesAmounts = []float64{5000, 50000}
purchasesAmounts = []float64{10000, 25000, 50000}
priceFroms = []float64{1000, 5000, 2000, 6000, 500, 2500}
cartPurchasesAmounts = []uint64{5000, 50000}
purchasesAmounts = []uint64{10000, 25000, 50000}
priceFroms = []uint64{1000, 5000, 2000, 6000, 500, 2500}
terms = []uint64{30, 90, 180}
usages = []uint64{100, 350, 500}

@ -1,5 +1,3 @@
//go:build integration
package integration_test
import (
@ -9,13 +7,12 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/protobuf/types/known/emptypb"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/data"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/parse"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/utils"
)
@ -27,7 +24,7 @@ func TestGetAllDiscounts(t *testing.T) {
discountClientConnection, err := grpc.Dial(
fmt.Sprintf("%s:%s", config.GRPC.Host, config.GRPC.Port),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
assert.NoError(t, err)
@ -42,7 +39,7 @@ func TestGetAllDiscounts(t *testing.T) {
if isNotNil && isNoError {
utils.CleanDiscountsIDs(response.Discounts)
assert.Equal(t, data.Discounts, parse.Discounts(response))
assert.Equal(t, data.Discounts, response)
}
})
}

@ -1,5 +1,3 @@
//go:build integration
package integration_test
import (
@ -9,12 +7,11 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/data"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/parse"
)
func TestGetDiscountByID(t *testing.T) {
@ -25,7 +22,7 @@ func TestGetDiscountByID(t *testing.T) {
discountClientConnection, err := grpc.Dial(
fmt.Sprintf("%s:%s", config.GRPC.Host, config.GRPC.Port),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
assert.NoError(t, err)
@ -41,7 +38,24 @@ func TestGetDiscountByID(t *testing.T) {
isNotNil := assert.NotNil(t, findedDiscount)
if isNoError && isNotNil {
assert.Equal(t, data.DiscountID22, parse.Discount(findedDiscount))
assert.Equal(t,
discount.Discount{
ID: data.DiscountID22.ID,
Name: data.DiscountID22.Name,
Layer: data.DiscountID22.Layer,
Description: data.DiscountID22.Description,
Condition: data.DiscountID22.Condition,
Deprecated: data.DiscountID22.Deprecated,
},
discount.Discount{
ID: findedDiscount.ID,
Name: findedDiscount.Name,
Layer: findedDiscount.Layer,
Description: findedDiscount.Description,
Condition: findedDiscount.Condition,
Deprecated: findedDiscount.Deprecated,
},
)
}
})

@ -1,5 +1,3 @@
//go:build integration
package integration_test
import (
@ -9,12 +7,11 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/core"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/pkg/env"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/data"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/parse"
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/tests/integration/utils"
)
@ -26,7 +23,7 @@ func TestGetUserDiscounts(t *testing.T) {
discountClientConnection, err := grpc.Dial(
fmt.Sprintf("%s:%s", config.GRPC.Host, config.GRPC.Port),
grpc.WithInsecure(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
assert.NoError(t, err)
@ -43,7 +40,7 @@ func TestGetUserDiscounts(t *testing.T) {
if isNotNil && isNoError {
utils.CleanDiscountsIDs(response.Discounts)
assert.Equal(t, data.User1Discounts, parse.Discounts(response))
assert.Equal(t, data.User1Discounts, response)
}
})
}

@ -1,28 +0,0 @@
package parse
import (
"penahub.gitlab.yandexcloud.net/pena-services/accruals-service/internal/proto/discount"
)
func Discount(discountToParse *discount.Discount) *discount.Discount {
return &discount.Discount{
ID: discountToParse.GetID(),
Name: discountToParse.GetName(),
Layer: discountToParse.GetLayer(),
Description: discountToParse.GetDescription(),
Condition: discountToParse.GetCondition(),
Target: discountToParse.GetTarget(),
Audit: discountToParse.GetAudit(),
Deprecated: discountToParse.GetDeprecated(),
}
}
func Discounts(discountsToParse *discount.Discounts) []*discount.Discount {
parsedDiscounts := make([]*discount.Discount, len(discountsToParse.Discounts))
for index, discountToParse := range discountsToParse.Discounts {
parsedDiscounts[index] = Discount(discountToParse)
}
return parsedDiscounts
}