init mongo
This commit is contained in:
parent
69746285ae
commit
9e667c83f3
|
@ -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
|
|
@ -4,3 +4,26 @@ Etcd:
|
||||||
Hosts:
|
Hosts:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
Key: trade.rpc
|
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
|
||||||
|
|
17
go.mod
17
go.mod
|
@ -3,7 +3,12 @@ module app-cloudep-trade-service
|
||||||
go 1.22.3
|
go 1.22.3
|
||||||
|
|
||||||
require (
|
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
|
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/grpc v1.67.1
|
||||||
google.golang.org/protobuf v1.35.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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||||
github.com/fatih/color v1.17.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/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||||
github.com/go-openapi/swag v0.22.4 // 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/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // 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/gnostic-models v0.6.8 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.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/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.17.9 // 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/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // 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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // 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/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // 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/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.7.0 // indirect
|
github.com/redis/go-redis/v9 v9.7.0 // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.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/api/v3 v3.5.15 // indirect
|
||||||
go.etcd.io/etcd/client/pkg/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
|
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/automaxprocs v1.6.0 // indirect
|
||||||
go.uber.org/multierr v1.9.0 // indirect
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
go.uber.org/zap v1.24.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/net v0.30.0 // indirect
|
||||||
golang.org/x/oauth2 v0.22.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/sys v0.26.0 // indirect
|
||||||
golang.org/x/term v0.25.0 // indirect
|
golang.org/x/term v0.25.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.19.0 // indirect
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/zeromicro/go-zero/zrpc"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/zrpc"
|
||||||
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
zrpc.RpcServerConf
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
|
@ -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")
|
||||||
|
)
|
|
@ -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),
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"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"
|
"app-cloudep-trade-service/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"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"
|
"app-cloudep-trade-service/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"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"
|
"app-cloudep-trade-service/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"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"
|
"app-cloudep-trade-service/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"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"
|
"app-cloudep-trade-service/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"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"
|
"app-cloudep-trade-service/internal/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,13 +1,30 @@
|
||||||
package svc
|
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 {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
|
Validate vi.Validate
|
||||||
|
OrderModel model.OrderModel
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
|
// TODO 改成 Trade
|
||||||
|
ers.Scope = code.CloudEPOrder
|
||||||
|
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
|
Validate: vi.MustValidator(
|
||||||
|
WithDecimalGt(),
|
||||||
|
WithDecimalGte(),
|
||||||
|
),
|
||||||
|
OrderModel: MustOrderModel(c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
5
trade.go
5
trade.go
|
@ -2,7 +2,8 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
|
||||||
"app-cloudep-trade-service/gen_result/pb/trade"
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
"app-cloudep-trade-service/internal/config"
|
"app-cloudep-trade-service/internal/config"
|
||||||
|
@ -44,6 +45,6 @@ func main() {
|
||||||
})
|
})
|
||||||
defer s.Stop()
|
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()
|
s.Start()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue