diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..c9726ca --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,148 @@ +run: + timeout: 3m + # Exit code when at least one issue was found. + # Default: 1 + issues-exit-code: 2 + # Include test files or not. + # Default: true + tests: false + +# Reference URL: https://golangci-lint.run/usage/linters/ +linters: + # Disable everything by default so upgrades to not include new - default + # enabled- linters. + disable-all: true + # Specifically enable linters we want to use. + enable: + # - depguard + - errcheck + # - godot + - gofmt + - goimports + - gosimple + - govet + - ineffassign + - misspell + - revive + # - staticcheck + - typecheck + - unused + # - wsl + - asasalint + - asciicheck + - bidichk + - bodyclose + # - containedctx + - contextcheck + # - cyclop + # - varnamelen + # - gci + - wastedassign + - whitespace + # - wrapcheck + - thelper + - tparallel + - unconvert + - unparam + - usestdlibvars + - tenv + - testableexamples + - stylecheck + - sqlclosecheck + - nosprintfhostport + - paralleltest + - prealloc + - predeclared + - promlinter + - reassign + - rowserrcheck + - nakedret + - nestif + - nilerr + - nilnil + - nlreturn + - noctx + - nolintlint + - nonamedreturns + - decorder + - dogsled + # - dupl + - dupword + - durationcheck + - errchkjson + - errname + - errorlint + # - execinquery + - exhaustive + - exportloopref + - forbidigo + - forcetypeassert + # - gochecknoglobals + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + # - godox + # - goerr113 + # - gofumpt + - goheader + - gomoddirectives + # - gomodguard always failed + - goprintffuncname + - gosec + - grouper + - importas + - interfacebloat + # - ireturn + - lll + - loggercheck + - maintidx + - makezero + +issues: + exclude-rules: + - path: _test\.go + linters: + - funlen + - goconst + - interfacer + - dupl + - lll + - goerr113 + - errcheck + - gocritic + - cyclop + - wrapcheck + - gocognit + - contextcheck + + exclude-dirs: + - internal/model + + exclude-files: + - .*_test.go + + + +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + gocognit: + # Minimal code complexity to report. + # Default: 30 (but we recommend 10-20) + min-complexity: 40 + nestif: + # Minimal complexity of if statements to report. + # Default: 5 + min-complexity: 10 + lll: + # Max line length, lines longer will be reported. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option. + # Default: 120. + line-length: 200 + # Tab width in spaces. + # Default: 1 + tab-width: 1 diff --git a/etc/trade.yaml b/etc/trade.yaml index b6ca0b5..595e41c 100644 --- a/etc/trade.yaml +++ b/etc/trade.yaml @@ -4,3 +4,26 @@ Etcd: Hosts: - 127.0.0.1:2379 Key: trade.rpc + +mongodb: + hosts: [ 127.0.0.1:27017 ] + username: + password: + databaseName: "cnx_commission" + minPoolSize: 10 + maxPoolSize: 30 + maxConnIdleTime: 30m + replicaName: "" + +Mongo: + Schema: mongodb + Host: 127.0.0.1 + User: "" + Password: "" + Port: "27017" + Database: digimon_order + ReplicaName: "order" + MaxStaleness: 30m + MaxPoolSize: 30 + MinPoolSize: 10 + MaxConnIdleTime: 30m diff --git a/go.mod b/go.mod index eb744f6..aff2a09 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,12 @@ module app-cloudep-trade-service go 1.22.3 require ( + code.30cm.net/digimon/library-go/errs v1.2.5 + code.30cm.net/digimon/library-go/validator v1.0.0 + github.com/go-playground/validator/v10 v10.22.0 + github.com/shopspring/decimal v1.4.0 github.com/zeromicro/go-zero v1.7.3 + go.mongodb.org/mongo-driver v1.17.1 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 ) @@ -18,14 +23,18 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/fatih/color v1.17.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -34,11 +43,13 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.9 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect @@ -48,6 +59,10 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/redis/go-redis/v9 v9.7.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect go.etcd.io/etcd/api/v3 v3.5.15 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect go.etcd.io/etcd/client/v3 v3.5.15 // indirect @@ -66,8 +81,10 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.25.0 // indirect golang.org/x/text v0.19.0 // indirect diff --git a/internal/config/config.go b/internal/config/config.go index c1f85b9..516850b 100755 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,7 +1,27 @@ package config -import "github.com/zeromicro/go-zero/zrpc" +import ( + "time" + + "github.com/zeromicro/go-zero/zrpc" +) type Config struct { zrpc.RpcServerConf + + Mongo struct { + Schema string + User string + Password string + Host string + Port string + Database string + ReplicaName string + MaxStaleness time.Duration + MaxPoolSize uint64 + MinPoolSize uint64 + MaxConnIdleTime time.Duration + // Compressors []string + // EnableStandardReadWriteSplitMode bool + } } diff --git a/internal/lib/mongo/custom_mongo_decimal.go b/internal/lib/mongo/custom_mongo_decimal.go new file mode 100644 index 0000000..6b56811 --- /dev/null +++ b/internal/lib/mongo/custom_mongo_decimal.go @@ -0,0 +1,52 @@ +package mongo + +import ( + "fmt" + "reflect" + + "github.com/shopspring/decimal" + "go.mongodb.org/mongo-driver/bson/bsoncodec" + "go.mongodb.org/mongo-driver/bson/bsonrw" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +type MgoDecimal struct{} + +var ( + _ bsoncodec.ValueEncoder = &MgoDecimal{} + _ bsoncodec.ValueDecoder = &MgoDecimal{} +) + +func (dc *MgoDecimal) EncodeValue(_ bsoncodec.EncodeContext, w bsonrw.ValueWriter, value reflect.Value) error { + // TODO 待確認是否有非decimal.Decimal type而導致error的場景 + dec, ok := value.Interface().(decimal.Decimal) + if !ok { + return fmt.Errorf("value %v to encode is not of type decimal.Decimal", value) + } + + // Convert decimal.Decimal to primitive.Decimal128. + primDec, err := primitive.ParseDecimal128(dec.String()) + if err != nil { + return fmt.Errorf("converting decimal.Decimal %v to primitive.Decimal128 error: %w", dec, err) + } + + return w.WriteDecimal128(primDec) +} + +func (dc *MgoDecimal) DecodeValue(_ bsoncodec.DecodeContext, r bsonrw.ValueReader, value reflect.Value) error { + primDec, err := r.ReadDecimal128() + if err != nil { + return fmt.Errorf("reading primitive.Decimal128 from ValueReader error: %w", err) + } + + // Convert primitive.Decimal128 to decimal.Decimal. + dec, err := decimal.NewFromString(primDec.String()) + if err != nil { + return fmt.Errorf("converting primitive.Decimal128 %v to decimal.Decimal error: %w", primDec, err) + } + + // set as decimal.Decimal type + value.Set(reflect.ValueOf(dec)) + + return nil +} diff --git a/internal/lib/mongo/init_mongodb.go b/internal/lib/mongo/init_mongodb.go new file mode 100644 index 0000000..64f8315 --- /dev/null +++ b/internal/lib/mongo/init_mongodb.go @@ -0,0 +1,14 @@ +package mongo + +import ( + "app-cloudep-trade-service/internal/config" + "fmt" +) + +func MustMongoConnectURL(c config.Config) string { + return fmt.Sprintf("%s://%s:%s", + c.Mongo.Schema, + c.Mongo.Host, + c.Mongo.Port, + ) +} diff --git a/internal/lib/mongo/option.go b/internal/lib/mongo/option.go new file mode 100644 index 0000000..bcefdc6 --- /dev/null +++ b/internal/lib/mongo/option.go @@ -0,0 +1,51 @@ +package mongo + +import ( + "app-cloudep-trade-service/internal/config" + "reflect" + + "github.com/shopspring/decimal" + "github.com/zeromicro/go-zero/core/stores/mon" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/bsoncodec" + "go.mongodb.org/mongo-driver/mongo/options" +) + +type TypeCodec struct { + ValueType reflect.Type + Encoder bsoncodec.ValueEncoder + Decoder bsoncodec.ValueDecoder +} + +// WithTypeCodec registers TypeCodecs to convert custom types. +func WithTypeCodec(typeCodecs ...TypeCodec) mon.Option { + return func(c *options.ClientOptions) { + registry := bson.NewRegistry() + for _, v := range typeCodecs { + registry.RegisterTypeEncoder(v.ValueType, v.Encoder) + registry.RegisterTypeDecoder(v.ValueType, v.Decoder) + } + c.SetRegistry(registry) + } +} + +// SetCustomDecimalType force convert primitive.Decimal128 to decimal.Decimal. +func SetCustomDecimalType() mon.Option { + return WithTypeCodec(TypeCodec{ + ValueType: reflect.TypeOf(decimal.Decimal{}), + Encoder: &MgoDecimal{}, + Decoder: &MgoDecimal{}, + }) +} + +func InitMongoOptions(cfg config.Config) mon.Option { + return func(opts *options.ClientOptions) { + opts.SetMaxPoolSize(cfg.Mongo.MaxPoolSize) + opts.SetMinPoolSize(cfg.Mongo.MinPoolSize) + opts.SetMaxConnIdleTime(cfg.Mongo.MaxConnIdleTime) + opts.SetCompressors([]string{"snappy"}) + // opts.SetReplicaSet(cfg.Mongo.ReplicaName) + // opts.SetWriteConcern(writeconcern.W1()) + // opts.SetReadPreference(readpref.Primary()) + } +} diff --git a/internal/model/mongo/error.go b/internal/model/mongo/error.go new file mode 100644 index 0000000..27d9244 --- /dev/null +++ b/internal/model/mongo/error.go @@ -0,0 +1,12 @@ +package model + +import ( + "errors" + + "github.com/zeromicro/go-zero/core/stores/mon" +) + +var ( + ErrNotFound = mon.ErrNotFound + ErrInvalidObjectId = errors.New("invalid objectId") +) diff --git a/internal/model/mongo/order_model.go b/internal/model/mongo/order_model.go new file mode 100644 index 0000000..c7a7662 --- /dev/null +++ b/internal/model/mongo/order_model.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/mon" +) + +var _ OrderModel = (*customOrderModel)(nil) + +type ( + // OrderModel is an interface to be customized, add more methods here, + // and implement the added methods in customOrderModel. + OrderModel interface { + orderModel + } + + customOrderModel struct { + *defaultOrderModel + } +) + +// NewOrderModel returns a model for the mongo. +func NewOrderModel(url, db, collection string, opts ...mon.Option) OrderModel { + conn := mon.MustNewModel(url, db, collection, opts...) + return &customOrderModel{ + defaultOrderModel: newDefaultOrderModel(conn), + } +} diff --git a/internal/model/mongo/order_model_gen.go b/internal/model/mongo/order_model_gen.go new file mode 100644 index 0000000..0d9f599 --- /dev/null +++ b/internal/model/mongo/order_model_gen.go @@ -0,0 +1,74 @@ +// Code generated by goctl. DO NOT EDIT. +package model + +import ( + "context" + "time" + + "github.com/zeromicro/go-zero/core/stores/mon" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" +) + +type orderModel interface { + Insert(ctx context.Context, data *Order) error + FindOne(ctx context.Context, id string) (*Order, error) + Update(ctx context.Context, data *Order) (*mongo.UpdateResult, error) + Delete(ctx context.Context, id string) (int64, error) +} + +type defaultOrderModel struct { + conn *mon.Model +} + +func newDefaultOrderModel(conn *mon.Model) *defaultOrderModel { + return &defaultOrderModel{conn: conn} +} + +func (m *defaultOrderModel) Insert(ctx context.Context, data *Order) error { + if data.ID.IsZero() { + data.ID = primitive.NewObjectID() + data.CreateAt = time.Now() + data.UpdateAt = time.Now() + } + + _, err := m.conn.InsertOne(ctx, data) + return err +} + +func (m *defaultOrderModel) FindOne(ctx context.Context, id string) (*Order, error) { + oid, err := primitive.ObjectIDFromHex(id) + if err != nil { + return nil, ErrInvalidObjectId + } + + var data Order + + err = m.conn.FindOne(ctx, &data, bson.M{"_id": oid}) + switch err { + case nil: + return &data, nil + case mon.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultOrderModel) Update(ctx context.Context, data *Order) (*mongo.UpdateResult, error) { + data.UpdateAt = time.Now() + + res, err := m.conn.UpdateOne(ctx, bson.M{"_id": data.ID}, bson.M{"$set": data}) + return res, err +} + +func (m *defaultOrderModel) Delete(ctx context.Context, id string) (int64, error) { + oid, err := primitive.ObjectIDFromHex(id) + if err != nil { + return 0, ErrInvalidObjectId + } + + res, err := m.conn.DeleteOne(ctx, bson.M{"_id": oid}) + return res, err +} diff --git a/internal/model/mongo/order_types.go b/internal/model/mongo/order_types.go new file mode 100644 index 0000000..07c1fdf --- /dev/null +++ b/internal/model/mongo/order_types.go @@ -0,0 +1,18 @@ +package model + +import ( + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" +) + +type Order struct { + ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"` + // TODO: Fill your own fields + UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"` + CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"` +} + +func (p *Order) CollectionName() string { + return "order" +} diff --git a/internal/server/couponservice/coupon_service_server.go b/internal/server/couponservice/coupon_service_server.go index ae08579..948ec75 100644 --- a/internal/server/couponservice/coupon_service_server.go +++ b/internal/server/couponservice/coupon_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-trade-service/gen_result/pb/trade" - "app-cloudep-trade-service/internal/logic/couponservice" + couponservicelogic "app-cloudep-trade-service/internal/logic/couponservice" "app-cloudep-trade-service/internal/svc" ) diff --git a/internal/server/inventoryservice/inventory_service_server.go b/internal/server/inventoryservice/inventory_service_server.go index 8419076..beb685f 100644 --- a/internal/server/inventoryservice/inventory_service_server.go +++ b/internal/server/inventoryservice/inventory_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-trade-service/gen_result/pb/trade" - "app-cloudep-trade-service/internal/logic/inventoryservice" + inventoryservicelogic "app-cloudep-trade-service/internal/logic/inventoryservice" "app-cloudep-trade-service/internal/svc" ) diff --git a/internal/server/orderservice/order_service_server.go b/internal/server/orderservice/order_service_server.go index 8771b43..94d7ec1 100644 --- a/internal/server/orderservice/order_service_server.go +++ b/internal/server/orderservice/order_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-trade-service/gen_result/pb/trade" - "app-cloudep-trade-service/internal/logic/orderservice" + orderservicelogic "app-cloudep-trade-service/internal/logic/orderservice" "app-cloudep-trade-service/internal/svc" ) diff --git a/internal/server/productservice/product_service_server.go b/internal/server/productservice/product_service_server.go index abc38bc..c0b552e 100644 --- a/internal/server/productservice/product_service_server.go +++ b/internal/server/productservice/product_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-trade-service/gen_result/pb/trade" - "app-cloudep-trade-service/internal/logic/productservice" + productservicelogic "app-cloudep-trade-service/internal/logic/productservice" "app-cloudep-trade-service/internal/svc" ) diff --git a/internal/server/subscriptionservice/subscription_service_server.go b/internal/server/subscriptionservice/subscription_service_server.go index edf4f02..c864be2 100644 --- a/internal/server/subscriptionservice/subscription_service_server.go +++ b/internal/server/subscriptionservice/subscription_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-trade-service/gen_result/pb/trade" - "app-cloudep-trade-service/internal/logic/subscriptionservice" + subscriptionservicelogic "app-cloudep-trade-service/internal/logic/subscriptionservice" "app-cloudep-trade-service/internal/svc" ) diff --git a/internal/server/walletservice/wallet_service_server.go b/internal/server/walletservice/wallet_service_server.go index 43e3670..4f0f60a 100644 --- a/internal/server/walletservice/wallet_service_server.go +++ b/internal/server/walletservice/wallet_service_server.go @@ -7,7 +7,7 @@ import ( "context" "app-cloudep-trade-service/gen_result/pb/trade" - "app-cloudep-trade-service/internal/logic/walletservice" + walletservicelogic "app-cloudep-trade-service/internal/logic/walletservice" "app-cloudep-trade-service/internal/svc" ) diff --git a/internal/svc/inject_mongo.go b/internal/svc/inject_mongo.go new file mode 100644 index 0000000..addbcc3 --- /dev/null +++ b/internal/svc/inject_mongo.go @@ -0,0 +1,20 @@ +package svc + +import ( + "app-cloudep-trade-service/internal/config" + mgo "app-cloudep-trade-service/internal/lib/mongo" + model "app-cloudep-trade-service/internal/model/mongo" +) + +// MustOrderModel 連線 order mongo 時 +func MustOrderModel(c config.Config) model.OrderModel { + orderCollection := model.Order{} + + return model.NewOrderModel( + mgo.MustMongoConnectURL(c), + c.Mongo.Database, + orderCollection.CollectionName(), + mgo.SetCustomDecimalType(), + mgo.InitMongoOptions(c), + ) +} diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index fa78db1..18b1085 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -1,13 +1,30 @@ package svc -import "app-cloudep-trade-service/internal/config" +import ( + "app-cloudep-trade-service/internal/config" + model "app-cloudep-trade-service/internal/model/mongo" + + ers "code.30cm.net/digimon/library-go/errs" + "code.30cm.net/digimon/library-go/errs/code" + vi "code.30cm.net/digimon/library-go/validator" +) type ServiceContext struct { - Config config.Config + Config config.Config + Validate vi.Validate + OrderModel model.OrderModel } func NewServiceContext(c config.Config) *ServiceContext { + // TODO 改成 Trade + ers.Scope = code.CloudEPOrder + return &ServiceContext{ Config: c, + Validate: vi.MustValidator( + WithDecimalGt(), + WithDecimalGte(), + ), + OrderModel: MustOrderModel(c), } } diff --git a/internal/svc/validator.go b/internal/svc/validator.go new file mode 100644 index 0000000..f5104d5 --- /dev/null +++ b/internal/svc/validator.go @@ -0,0 +1,55 @@ +package svc + +import ( + vi "code.30cm.net/digimon/library-go/validator" + "github.com/go-playground/validator/v10" + "github.com/shopspring/decimal" +) + +// WithDecimalGt 是否大於等於 +func WithDecimalGt() vi.Option { + return vi.Option{ + ValidatorName: "decimalGt", + ValidatorFunc: func(fl validator.FieldLevel) bool { + if val, ok := fl.Field().Interface().(string); ok { + value, err := decimal.NewFromString(val) + if err != nil { + return false + } + + conditionValue, err := decimal.NewFromString(fl.Param()) + if err != nil { + return false + } + + return value.GreaterThan(conditionValue) + } + + return true + }, + } +} + +// WithDecimalGte 是否大於等於 +func WithDecimalGte() vi.Option { + return vi.Option{ + ValidatorName: "decimalGte", + ValidatorFunc: func(fl validator.FieldLevel) bool { + if val, ok := fl.Field().Interface().(string); ok { + value, err := decimal.NewFromString(val) + if err != nil { + return false + } + + conditionValue, err := decimal.NewFromString(fl.Param()) + if err != nil { + return false + } + + return value.GreaterThanOrEqual(conditionValue) + } + + return true + }, + } +} diff --git a/internal/svc/validator_test.go b/internal/svc/validator_test.go new file mode 100644 index 0000000..6b14b07 --- /dev/null +++ b/internal/svc/validator_test.go @@ -0,0 +1,106 @@ +package svc + +import ( + "testing" + + vi "code.30cm.net/digimon/library-go/validator" +) + +func TestWithDecimalGte(t *testing.T) { + validate := vi.MustValidator(WithDecimalGt(), WithDecimalGte()) + + type TestStruct struct { + Value string `validate:"decimalGte=10.50"` + } + + tests := []struct { + name string + input TestStruct + wantErr bool + }{ + { + name: "valid - equal", + input: TestStruct{Value: "10.50"}, + wantErr: false, + }, + { + name: "valid - greater", + input: TestStruct{Value: "15.00"}, + wantErr: false, + }, + { + name: "invalid - less", + input: TestStruct{Value: "9.99"}, + wantErr: true, + }, + { + name: "invalid - not a decimal", + input: TestStruct{Value: "abc"}, + wantErr: true, + }, + { + name: "valid - empty string", + input: TestStruct{Value: ""}, + wantErr: true, // Assuming empty string is valid + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validate.ValidateAll(tt.input) + + if (err != nil) != tt.wantErr { + t.Errorf("TestWithDecimalGte() %s = error %v, wantErr %v", tt.name, err, tt.wantErr) + } + }) + } +} + +func TestWithDecimalGt(t *testing.T) { + validate := vi.MustValidator(WithDecimalGt(), WithDecimalGt()) + + type TestStruct struct { + Value string `validate:"decimalGt=10.50"` + } + + tests := []struct { + name string + input TestStruct + wantErr bool + }{ + { + name: "valid - greater", + input: TestStruct{Value: "10.51"}, + wantErr: false, + }, + { + name: "invalid - equal", + input: TestStruct{Value: "10.50"}, + wantErr: true, // should fail because the value is equal to the condition + }, + { + name: "invalid - less", + input: TestStruct{Value: "9.99"}, + wantErr: true, + }, + { + name: "invalid - not a decimal", + input: TestStruct{Value: "abc"}, + wantErr: true, + }, + { + name: "valid - empty string", + input: TestStruct{Value: ""}, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validate.ValidateAll(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("TestWithDecimalGt() %s = error %v, wantErr %v", tt.name, err, tt.wantErr) + } + }) + } +} diff --git a/trade.go b/trade.go index 9a123cb..6f262a4 100644 --- a/trade.go +++ b/trade.go @@ -2,7 +2,8 @@ package main import ( "flag" - "fmt" + + "github.com/zeromicro/go-zero/core/logx" "app-cloudep-trade-service/gen_result/pb/trade" "app-cloudep-trade-service/internal/config" @@ -44,6 +45,6 @@ func main() { }) defer s.Stop() - fmt.Printf("Starting rpc server at %s...\n", c.ListenOn) + logx.Infof("Starting rpc server at %s...\n", c.ListenOn) s.Start() }