feature/order_service (#1)
Co-authored-by: daniel.w <daniel.w@intteam.net> Reviewed-on: #1
This commit is contained in:
parent
a575e4fc42
commit
47a38526b1
|
@ -0,0 +1,153 @@
|
||||||
|
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
|
||||||
|
- internal/logic/couponservice
|
||||||
|
- internal/logic/inventoryservice
|
||||||
|
- internal/logic/productservice
|
||||||
|
- internal/logic/subscriptionservice
|
||||||
|
- internal/logic/walletservice
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,64 @@
|
||||||
|
GO_CTL_NAME=goctl
|
||||||
|
|
||||||
|
# go-zero 生成風格
|
||||||
|
GO_ZERO_STYLE=go_zero
|
||||||
|
|
||||||
|
GO ?= go
|
||||||
|
GOFMT ?= gofmt "-s"
|
||||||
|
GOFILES := $(shell find . -name "*.go")
|
||||||
|
LDFLAGS := -s -w
|
||||||
|
VERSION="v1.0.1"
|
||||||
|
DOCKER_REPO="igs170911/feed"
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: # 進行測試
|
||||||
|
go test -v --cover ./...
|
||||||
|
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt: # 格式優化
|
||||||
|
$(GOFMT) -w $(GOFILES)
|
||||||
|
goimports -w ./
|
||||||
|
golangci-lint run
|
||||||
|
|
||||||
|
.PHONY: gen-rpc
|
||||||
|
gen-rpc: # 建立 rpc code
|
||||||
|
$(GO_CTL_NAME) rpc protoc ./generate/protobuf/trade.proto -m --style=$(GO_ZERO_STYLE) --go_out=./gen_result/pb --go-grpc_out=./gen_result/pb --zrpc_out=.
|
||||||
|
go mod tidy
|
||||||
|
@echo "Generate core-api files successfully"
|
||||||
|
|
||||||
|
.PHONY: gen-clean
|
||||||
|
gen-clean: # 建立 rpc code
|
||||||
|
rm -rf ./client
|
||||||
|
rm -rf ./etc
|
||||||
|
rm -rf ./gen_result
|
||||||
|
rm -rf ./internal
|
||||||
|
rm -rf go.mod
|
||||||
|
rm -rf go.sum
|
||||||
|
rm -rf order.go
|
||||||
|
@echo "Generate core-api files successfully"
|
||||||
|
|
||||||
|
.PHONY: run-docker
|
||||||
|
run-docker: # 建立 rpc code
|
||||||
|
docker run --platform=linux/arm64/v8 -p 8080:8080 $(DOCKER_REPO):$(VERSION)
|
||||||
|
|
||||||
|
.PHONY: build-docker
|
||||||
|
build-docker:
|
||||||
|
cp ./build/Dockerfile Dockerfile
|
||||||
|
docker buildx build -t $(DOCKER_REPO):$(VERSION) --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/ed_25519)" .
|
||||||
|
rm -rf Dockerfile
|
||||||
|
@echo "Generate core-api files successfully"
|
||||||
|
|
||||||
|
gen-mongo-model: # 建立 rpc 資料庫
|
||||||
|
# 只產生 Model 剩下的要自己撰寫,連欄位名稱也是
|
||||||
|
goctl model mongo -t order --dir ./internal/model/mongo --style $(GO_ZERO_STYLE)
|
||||||
|
@echo "Generate mongo model files successfully"
|
||||||
|
|
||||||
|
.PHONY: mock-gen
|
||||||
|
mock-gen: # 建立 mock 資料
|
||||||
|
mockgen -source=./internal/model/mongo/order_model_gen.go -destination=./internal/mock/model/order_model_gen.go -package=mock
|
||||||
|
mockgen -source=./internal/model/mongo/order_model.go -destination=./internal/mock/model/order_model.go -package=mock
|
||||||
|
@echo "Generate mock files successfully"
|
||||||
|
|
||||||
|
.PHONY: migrate-database
|
||||||
|
migrate-database:
|
||||||
|
migrate -source file://generate/database/mongodb -database 'mongodb://127.0.0.1:27017/digimon_order' up
|
|
@ -0,0 +1,29 @@
|
||||||
|
Name: trade.rpc
|
||||||
|
ListenOn: 0.0.0.0:8080
|
||||||
|
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
|
|
@ -0,0 +1,108 @@
|
||||||
|
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/assert/v2 v2.2.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
|
||||||
|
go.uber.org/mock v0.5.0
|
||||||
|
google.golang.org/grpc v1.67.1
|
||||||
|
google.golang.org/protobuf v1.35.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/coreos/go-semver v0.3.1 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
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
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||||
|
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
|
||||||
|
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||||
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
|
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
|
||||||
|
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/exporters/zipkin v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||||
|
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||||
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
|
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
|
||||||
|
golang.org/x/time v0.7.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
k8s.io/api v0.29.3 // indirect
|
||||||
|
k8s.io/apimachinery v0.29.4 // indirect
|
||||||
|
k8s.io/client-go v0.29.3 // indirect
|
||||||
|
k8s.io/klog/v2 v2.110.1 // indirect
|
||||||
|
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
|
||||||
|
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||||
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
|
)
|
|
@ -0,0 +1,27 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
"code.30cm.net/digimon/library-go/errs/code"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ErrorCode uint32
|
||||||
|
|
||||||
|
func (e ErrorCode) ToUint32() uint32 {
|
||||||
|
return uint32(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error Code 統一這邊改
|
||||||
|
const (
|
||||||
|
_ = iota
|
||||||
|
CreateOrderErrorCode ErrorCode = iota
|
||||||
|
CancelOrderErrorCode
|
||||||
|
ModifyOrderErrorCode
|
||||||
|
TimeoutOrderErrorCode
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ ErrorCode = 10 + iota
|
||||||
|
DataNotFoundErrorCode
|
||||||
|
)
|
||||||
|
|
||||||
|
func CommentError(ec ErrorCode, s ...string) *ers.LibError {
|
||||||
|
return ers.NewError(code.CloudEPOrder, code.DBError, ec.ToUint32(), strings.Join(s, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommentErrorL(ec ErrorCode,
|
||||||
|
l logx.Logger, filed []logx.LogField, s ...string) *ers.LibError {
|
||||||
|
e := CommentError(ec, s...)
|
||||||
|
l.WithCallerSkip(1).WithFields(filed...).Error(e.Error())
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotFoundError(ec ErrorCode, s ...string) *ers.LibError {
|
||||||
|
return ers.NewError(code.CloudEPOrder, code.ResourceNotFound, ec.ToUint32(), strings.Join(s, " "))
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
type OrderStatus int64
|
||||||
|
|
||||||
|
func (o *OrderStatus) ToInt64() int64 {
|
||||||
|
return int64(*o)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderStatusCreated OrderStatus = 0 // 建立訂單
|
||||||
|
OrderStatusFailed OrderStatus = 1 // 建單失敗
|
||||||
|
OrderStatusReviewing OrderStatus = 2 // 審核中
|
||||||
|
OrderStatusPaying OrderStatus = 3 // 付款中
|
||||||
|
OrderStatusPaid OrderStatus = 4 // 已付款
|
||||||
|
OrderStatusPendingTransfer OrderStatus = 5 // 已付款待轉帳
|
||||||
|
OrderStatusDisputing OrderStatus = 6 // 申訴中
|
||||||
|
OrderStatusCompleted OrderStatus = 7 // 交易完成
|
||||||
|
OrderStatusFailedTrade OrderStatus = 8 // 交易失敗
|
||||||
|
OrderStatusCancelled OrderStatus = 9 // 交易取消
|
||||||
|
OrderStatusAbnormal OrderStatus = 10 // 交易異常
|
||||||
|
OrderStatusTimeout OrderStatus = 11 // 交易超時
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderType int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
OrderTypeTest OrderType = 0 // 測試訂單
|
||||||
|
)
|
||||||
|
|
||||||
|
func (o *OrderType) ToInt() int {
|
||||||
|
return int(*o)
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderUseCase interface {
|
||||||
|
// CreateOrder 建立訂單,不另外做 struct 直接用 model.Order
|
||||||
|
// 考量底層已經寫完,如有額外需求需要在這邊用轉的
|
||||||
|
CreateOrder(ctx context.Context, param CreateOrderReq) error
|
||||||
|
// CancelOrder 取消訂單
|
||||||
|
CancelOrder(ctx context.Context, param CancelOrderQuery) error
|
||||||
|
// DeleteOrder 刪除訂單(軟刪除)
|
||||||
|
DeleteOrder(ctx context.Context, param DeleteOrderQuery) error
|
||||||
|
// GetOrder 取得訂單資料
|
||||||
|
GetOrder(ctx context.Context, param GetOrderQuery) (*GetOrderResp, error)
|
||||||
|
// ListOrder 取得資料列表
|
||||||
|
ListOrder(ctx context.Context, param GetOrderListReq) (*ListOrderResp, error)
|
||||||
|
// ModifyOrderStatus 更新資料
|
||||||
|
ModifyOrderStatus(ctx context.Context, param *ModifyOrderQuery) error
|
||||||
|
// OrderStatusTimeout 訂單超時任務/cron/order-status/timeout
|
||||||
|
OrderStatusTimeout(ctx context.Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyOrderQuery
|
||||||
|
// 0.建立訂單 1.建單失敗 2.審核中 3.付款中 4.已付款
|
||||||
|
// 5.已付款待轉帳 6.申訴中 7.交易完成
|
||||||
|
// 8.交易失敗 9.交易取消 10.交易異常 11.交易超時
|
||||||
|
|
||||||
|
type ModifyOrderQuery struct {
|
||||||
|
BusinessID string `json:"business_id" validate:"required"`
|
||||||
|
Status int64 `json:"status" validate:"required,oneof=2 3 4 5 6 7 8 11"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrderQuery 1.建單失敗 9.交易取消 10.交易異常
|
||||||
|
type CancelOrderQuery struct {
|
||||||
|
BusinessID string
|
||||||
|
Status domain.OrderStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrderQuery 刪除訂單(軟刪除)
|
||||||
|
type DeleteOrderQuery struct {
|
||||||
|
BusinessID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrderQuery 取得訂單
|
||||||
|
type GetOrderQuery struct {
|
||||||
|
BusinessID string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetOrderResp struct {
|
||||||
|
BusinessID string // 訂單業務流水號
|
||||||
|
OrderType domain.OrderType `json:"order_type"` // 訂單類型
|
||||||
|
OrderStatus domain.OrderStatus `json:"order_status"` // 訂單狀態
|
||||||
|
Brand string `json:"brand"` // 下單平台
|
||||||
|
OrderUID string `json:"order_uid"` // 下單用戶 UID
|
||||||
|
ReferenceID string `json:"reference_id"` // 訂單來源
|
||||||
|
Count string `json:"count"` // 訂單數量 (decimal to string)
|
||||||
|
OrderFee string `json:"order_fee"` // 訂單手續費 (decimal to string)
|
||||||
|
Amount string `json:"amount"` // 單價 (decimal to string)
|
||||||
|
ReferenceBrand *string `json:"reference_brand,omitempty"` // 訂單來源平台
|
||||||
|
ReferenceUID *string `json:"reference_uid,omitempty"` // 訂單來源用戶 UID
|
||||||
|
WalletStatus *int64 `json:"wallet_status,omitempty"` // 交易金額狀態
|
||||||
|
ThreePartyStatus *int64 `json:"three_party_status,omitempty"` // 三方請求狀態
|
||||||
|
DirectionType *int64 `json:"direction_type,omitempty"` // 交易方向
|
||||||
|
CryptoType *string `json:"crypto_type,omitempty"` // 交易幣種
|
||||||
|
ThirdPartyFee *string `json:"third_party_fee,omitempty"` // 第三方手續費 (decimal to string)
|
||||||
|
CryptoToUsdtRate *string `json:"crypto_to_usdt_rate,omitempty"` // 交易幣種對 USDT 匯率 (decimal to string)
|
||||||
|
FiatToUsdRate *string `json:"fiat_to_usd_rate,omitempty"` // 法幣對 USD 匯率 (decimal to string)
|
||||||
|
FeeCryptoToUsdtRate *string `json:"fee_crypto_to_usdt_rate,omitempty"` // 手續費幣種對 USDT 匯率 (decimal to string)
|
||||||
|
UsdtToCryptoTypeRate *string `json:"usdt_to_crypto_type_rate,omitempty"` // USDT 對交易幣種匯率 (decimal to string)
|
||||||
|
PaymentFiat *string `json:"payment_fiat,omitempty"` // 支付法幣
|
||||||
|
PaymentUnitPrice *string `json:"payment_unit_price,omitempty"` // crypto 單價 (decimal to string)
|
||||||
|
PaymentTemplateID *string `json:"payment_template_id,omitempty"` // 支付方式配置 ID
|
||||||
|
OrderArrivalTime *int64 `json:"order_arrival_time,omitempty"` // 訂單到帳時間
|
||||||
|
OrderPaymentTime *int64 `json:"order_payment_time,omitempty"` // 訂單付款時間
|
||||||
|
UnpaidTimeoutSecond *int64 `json:"unpaid_timeout_second,omitempty"` // 支付期限秒數
|
||||||
|
ChainType *string `json:"chain_type,omitempty"` // 主網類型
|
||||||
|
TxHash *string `json:"tx_hash,omitempty,omitempty"` // 交易哈希
|
||||||
|
FromAddress *string `json:"from_address,omitempty,omitempty"` // 來源地址
|
||||||
|
ToAddress *string `json:"to_address,omitempty,omitempty"` // 目標地址
|
||||||
|
ChainFee *string `json:"chain_fee,omitempty"` // 鏈上交易手續費 (decimal to string)
|
||||||
|
ChainFeeCrypto *string `json:"chain_fee_crypto,omitempty"` // 鏈上手續費使用幣別
|
||||||
|
Memo *string `json:"memo,omitempty"` // 鏈上備註
|
||||||
|
OrderNote *string `json:"order_note,omitempty"` // 訂單交易備註
|
||||||
|
CreateTime int64 `json:"create_time,omitempty"` // 建立時間
|
||||||
|
UpdateTime int64 `json:"update_time,omitempty"` // 更新時間
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetOrderListReq struct {
|
||||||
|
PageIndex int64
|
||||||
|
PageSize int64
|
||||||
|
|
||||||
|
ReferenceID string
|
||||||
|
ReferenceUID string
|
||||||
|
BusinessID string
|
||||||
|
UID string
|
||||||
|
OrderType domain.OrderType
|
||||||
|
DirectionType []int64
|
||||||
|
OrderStatus []int64
|
||||||
|
|
||||||
|
StartCreateTime int64
|
||||||
|
EndCreateTime int64
|
||||||
|
StartUpdateTime int64
|
||||||
|
EndUpdateTime int64
|
||||||
|
StartOrderArrivalTime int64
|
||||||
|
EndOrderArrivalTime int64
|
||||||
|
StartOrderPaymentTime int64
|
||||||
|
EndOrderPaymentTime int64
|
||||||
|
|
||||||
|
CryptoType string
|
||||||
|
TxHash string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pager struct {
|
||||||
|
Index int64
|
||||||
|
Size int64
|
||||||
|
Total int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListOrderResp struct {
|
||||||
|
Data []*GetOrderResp `json:"data"` // 訂單列表
|
||||||
|
Page *Pager `json:"page"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateOrderReq struct {
|
||||||
|
BusinessID string
|
||||||
|
OrderType domain.OrderType // 訂單類型
|
||||||
|
OrderStatus domain.OrderStatus // 訂單狀態
|
||||||
|
Brand string // 下單平台
|
||||||
|
OrderUID string // 下單用戶 UID
|
||||||
|
ReferenceID string // 訂單來源
|
||||||
|
Count decimal.Decimal // 訂單數量
|
||||||
|
OrderFee decimal.Decimal // 訂單手續費
|
||||||
|
Amount decimal.Decimal // 單價
|
||||||
|
WalletStatus int64 // 交易金額狀態
|
||||||
|
DirectionType int64 // 交易方向
|
||||||
|
// 以上為必要欄位,下面是區塊鏈時才需要
|
||||||
|
ReferenceBrand *string // 訂單來源平台
|
||||||
|
ReferenceUID *string // 訂單來源用戶 UID
|
||||||
|
ThreePartyStatus *int64 // 三方請求狀態
|
||||||
|
CryptoType *string // 交易幣種
|
||||||
|
ThirdPartyFee *decimal.Decimal // 第三方手續費
|
||||||
|
CryptoToUSDTRate *decimal.Decimal // 加密貨幣對 USDT 匯率
|
||||||
|
FiatToUSDRate *decimal.Decimal // 法幣對 USD 匯率
|
||||||
|
FeeCryptoToUSDTRate *decimal.Decimal // 手續費加密貨幣對 USDT 匯率
|
||||||
|
USDTToCryptoTypeRate *decimal.Decimal // USDT 對加密貨幣匯率
|
||||||
|
PaymentFiat *string // 支付法幣
|
||||||
|
PaymentUnitPrice *decimal.Decimal // 加密貨幣單價
|
||||||
|
PaymentTemplateID *string // 支付方式配置 ID
|
||||||
|
OrderArrivalTime *int64 // 訂單到帳時間
|
||||||
|
OrderPaymentTime *int64 // 訂單付款時間
|
||||||
|
UnpaidTimeoutSecond *int64 // 支付期限秒數
|
||||||
|
ChainType *string // 主網類型
|
||||||
|
TxHash *string // 交易哈希
|
||||||
|
FromAddress *string // 來源地址
|
||||||
|
ToAddress *string // 目標地址
|
||||||
|
ChainFee *decimal.Decimal // 鏈上交易手續費
|
||||||
|
ChainFeeCrypto *string // 鏈上手續費使用幣別
|
||||||
|
Memo *string // 鏈上備註
|
||||||
|
OrderNote *string // 訂單交易備註
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
type WalletStatus int64
|
||||||
|
|
||||||
|
func (o *WalletStatus) ToInt() int {
|
||||||
|
return int(*o)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThreePartyStatus int64
|
||||||
|
|
||||||
|
func (o *ThreePartyStatus) ToInt() int {
|
||||||
|
return int(*o)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectionType int64
|
||||||
|
|
||||||
|
func (o *DirectionType) ToInt() int {
|
||||||
|
return int(*o)
|
||||||
|
}
|
|
@ -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,31 @@
|
||||||
|
package couponservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateCouponLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateCouponLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateCouponLogic {
|
||||||
|
return &CreateCouponLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateCoupon 創建優惠券
|
||||||
|
func (l *CreateCouponLogic) CreateCoupon(in *trade.CreateCouponReq) (*trade.CouponResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.CouponResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package couponservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteCouponLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeleteCouponLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCouponLogic {
|
||||||
|
return &DeleteCouponLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCoupon 刪除優惠券
|
||||||
|
func (l *DeleteCouponLogic) DeleteCoupon(in *trade.CouponQueryReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package couponservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListCouponsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListCouponsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListCouponsLogic {
|
||||||
|
return &ListCouponsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCoupons列出所有優惠券
|
||||||
|
func (l *ListCouponsLogic) ListCoupons(in *trade.CouponListReq) (*trade.CouponListResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.CouponListResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package couponservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QueryCouponLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryCouponLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryCouponLogic {
|
||||||
|
return &QueryCouponLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryCoupon查詢優惠券
|
||||||
|
func (l *QueryCouponLogic) QueryCoupon(in *trade.CouponQueryReq) (*trade.CouponResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.CouponResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package couponservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateCouponLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateCouponLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateCouponLogic {
|
||||||
|
return &UpdateCouponLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCoupon更新優惠券
|
||||||
|
func (l *UpdateCouponLogic) UpdateCoupon(in *trade.UpdateCouponReq) (*trade.CouponResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.CouponResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package couponservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidateCouponLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewValidateCouponLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ValidateCouponLogic {
|
||||||
|
return &ValidateCouponLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateCoupon 驗證優惠券 (在下單或支付時使用)
|
||||||
|
func (l *ValidateCouponLogic) ValidateCoupon(in *trade.ValidateCouponReq) (*trade.CouponValidationResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.CouponValidationResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AddStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAddStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddStockLogic {
|
||||||
|
return &AddStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStock 增加庫存
|
||||||
|
func (l *AddStockLogic) AddStock(in *trade.StockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AdjustStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAdjustStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdjustStockLogic {
|
||||||
|
return &AdjustStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustStock 調整庫存 (批量修改庫存,用於大批商品更新)
|
||||||
|
func (l *AdjustStockLogic) AdjustStock(in *trade.BatchStockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateStockLogic {
|
||||||
|
return &CreateStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStock 建立庫存品項
|
||||||
|
func (l *CreateStockLogic) CreateStock(in *trade.StockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListAllStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListAllStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListAllStockLogic {
|
||||||
|
return &ListAllStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllStock 查詢所有商品的庫存狀況
|
||||||
|
func (l *ListAllStockLogic) ListAllStock(in *trade.StockListReq) (*trade.StockListResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.StockListResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QueryStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryStockLogic {
|
||||||
|
return &QueryStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStock 查詢單一商品的庫存
|
||||||
|
func (l *QueryStockLogic) QueryStock(in *trade.StockQueryReq) (*trade.StockResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.StockResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReduceStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReduceStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ReduceStockLogic {
|
||||||
|
return &ReduceStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReduceStock 減少庫存
|
||||||
|
func (l *ReduceStockLogic) ReduceStock(in *trade.StockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReleaseReservedStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReleaseReservedStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ReleaseReservedStockLogic {
|
||||||
|
return &ReleaseReservedStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReleaseReservedStock 釋放預留庫存 (取消或失效的訂單)
|
||||||
|
func (l *ReleaseReservedStockLogic) ReleaseReservedStock(in *trade.StockReservationReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package inventoryservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReserveStockLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReserveStockLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ReserveStockLogic {
|
||||||
|
return &ReserveStockLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReserveStock 預留庫存 (用於未完成的訂單)
|
||||||
|
func (l *ReserveStockLogic) ReserveStock(in *trade.StockReservationReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CancelOrderLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCancelOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CancelOrderLogic {
|
||||||
|
return &CancelOrderLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrderQuery 1.建單失敗 9.交易取消 10.交易異常
|
||||||
|
type CancelOrderQuery struct {
|
||||||
|
BusinessID string `json:"business_id" validate:"required"`
|
||||||
|
Status int64 `json:"status" validate:"required,oneof=1 9 10"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrder 取消訂單
|
||||||
|
func (l *CancelOrderLogic) CancelOrder(in *trade.CancelOrderReq) (*trade.OKResp, error) {
|
||||||
|
// 驗證資料
|
||||||
|
if err := l.svcCtx.Validate.ValidateAll(&CancelOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
Status: in.GetStatus(),
|
||||||
|
}); err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.svcCtx.OrderUseCase.CancelOrder(l.ctx, usecase.CancelOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
Status: domain.OrderStatus(in.GetStatus()),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
"context"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateOrderLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic {
|
||||||
|
return &CreateOrderLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type createOrderReq struct { // 訂單ID
|
||||||
|
BusinessID string `json:"business_id" validate:"required"` // 訂單業務流水號
|
||||||
|
OrderType int8 `json:"order_type" validate:"required"` // 訂單類型
|
||||||
|
OrderStatus int8 `json:"order_status" validate:"oneof=0 1 2 3 4 5 6 7 8 9 10 11"` // 訂單狀態
|
||||||
|
Brand string `json:"brand" validate:"required"` // 下單平台
|
||||||
|
OrderUID string `json:"order_uid" validate:"required"` // 下單用戶 UID
|
||||||
|
ReferenceID string `json:"reference_id" validate:"required"` // 訂單來源
|
||||||
|
Count string `json:"count" validate:"required,decimalGt=0"` // 訂單數量
|
||||||
|
OrderFee string `json:"order_fee" validate:"required,decimalGte=0"` // 訂單手續費
|
||||||
|
Amount string `json:"amount" validate:"required,decimalGte=0"` // 單價
|
||||||
|
ReferenceBrand *string `json:"reference_brand,omitempty" validate:"omitempty"` // 訂單來源平台
|
||||||
|
ReferenceUID *string `json:"reference_uid,omitempty" validate:"omitempty"` // 訂單來源用戶 UID
|
||||||
|
WalletStatus *int64 `json:"wallet_status,omitempty" validate:"omitempty,oneof=1 2 3 4 5 6 7"` // 交易金額狀態
|
||||||
|
ThreePartyStatus *int64 `json:"three_party_status,omitempty" validate:"omitempty,oneof=1 2 3"` // 三方請求狀態
|
||||||
|
DirectionType *int64 `json:"direction_type,omitempty" validate:"omitempty,oneof=1 2"` // 交易方向
|
||||||
|
CryptoType *string `json:"crypto_type,omitempty" validate:"omitempty"` // 交易幣種
|
||||||
|
ThirdPartyFee *string `json:"third_party_fee,omitempty" validate:"omitempty,decimalGte=0"` // 第三方手續費
|
||||||
|
CryptoToUSDTRate *string `json:"crypto_to_usdt_rate,omitempty" validate:"omitempty,decimalGte=0"` // 交易幣種對 USDT 匯率
|
||||||
|
FiatToUSDRate *string `json:"fiat_to_usd_rate,omitempty" validate:"omitempty,decimalGte=0"` // 法幣對 USD 匯率
|
||||||
|
FeeCryptoToUSDTRate *string `json:"fee_crypto_to_usdt_rate,omitempty" validate:"omitempty,decimalGte=0"` // 手續費幣種對 USDT 匯率
|
||||||
|
USDTToCryptoTypeRate *string `json:"usdt_to_crypto_type_rate,omitempty" validate:"omitempty,decimalGte=0"` // USDT 對交易幣種匯率
|
||||||
|
PaymentFiat *string `json:"payment_fiat,omitempty" validate:"omitempty"` // 支付法幣
|
||||||
|
PaymentUnitPrice *string `json:"payment_unit_price,omitempty" validate:"omitempty,decimalGte=0"` // crypto 單價
|
||||||
|
PaymentTemplateID *string `json:"payment_template_id,omitempty" validate:"omitempty"` // 支付方式配置 ID
|
||||||
|
OrderArrivalTime *int64 `json:"order_arrival_time,omitempty" validate:"omitempty,gt=1"` // 訂單到帳時間
|
||||||
|
OrderPaymentTime *int64 `json:"order_payment_time,omitempty" validate:"omitempty,gt=1"` // 訂單付款時間
|
||||||
|
UnpaidTimeoutSecond *int64 `json:"unpaid_timeout_second,omitempty" validate:"omitempty,gt=1"` // 支付期限秒數
|
||||||
|
ChainType *string `json:"chain_type,omitempty" validate:"omitempty"` // 主網類型
|
||||||
|
TxHash *string `json:"tx_hash,omitempty" validate:"omitempty"` // 交易哈希
|
||||||
|
FromAddress *string `json:"from_address,omitempty" validate:"omitempty"` // 來源地址
|
||||||
|
ToAddress *string `json:"to_address,omitempty" validate:"omitempty"` // 目標地址
|
||||||
|
ChainFee *string `json:"chain_fee,omitempty" validate:"omitempty,decimalGte=0"` // 鏈上交易手續費
|
||||||
|
ChainFeeCrypto *string `json:"chain_fee_crypto,omitempty" validate:"omitempty"` // 鏈上手續費使用幣別
|
||||||
|
Memo *string `json:"memo,omitempty" validate:"omitempty"` // 鏈上備註
|
||||||
|
OrderNote *string `json:"order_note,omitempty" validate:"omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo,gocognit
|
||||||
|
func buildCreateOrderReq(in *trade.CreateOrderReq) (*createOrderReq, error) {
|
||||||
|
createOrderReq := &createOrderReq{
|
||||||
|
BusinessID: in.BusinessId,
|
||||||
|
OrderType: int8(in.OrderType),
|
||||||
|
OrderStatus: int8(in.OrderStatus),
|
||||||
|
Brand: in.Brand,
|
||||||
|
OrderUID: in.OrderUid,
|
||||||
|
ReferenceID: in.ReferenceId,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有當 Count, OrderFee, Amount 不為空時才進行轉換和設置
|
||||||
|
if in.Count != "" {
|
||||||
|
createOrderReq.Count = in.Count
|
||||||
|
}
|
||||||
|
if in.OrderFee != "" {
|
||||||
|
createOrderReq.OrderFee = in.OrderFee
|
||||||
|
}
|
||||||
|
if in.Amount != "" {
|
||||||
|
createOrderReq.Amount = in.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判斷可選字段,只有不為 nil 才設置
|
||||||
|
if in.ReferenceBrand != nil {
|
||||||
|
createOrderReq.ReferenceBrand = in.ReferenceBrand
|
||||||
|
}
|
||||||
|
if in.ReferenceUid != nil {
|
||||||
|
createOrderReq.ReferenceUID = in.ReferenceUid
|
||||||
|
}
|
||||||
|
if in.WalletStatus != nil {
|
||||||
|
createOrderReq.WalletStatus = in.WalletStatus
|
||||||
|
}
|
||||||
|
if in.ThreePartyStatus != nil {
|
||||||
|
createOrderReq.ThreePartyStatus = in.ThreePartyStatus
|
||||||
|
}
|
||||||
|
if in.DirectionType != nil {
|
||||||
|
createOrderReq.DirectionType = in.DirectionType
|
||||||
|
}
|
||||||
|
if in.CryptoType != nil {
|
||||||
|
createOrderReq.CryptoType = in.CryptoType
|
||||||
|
}
|
||||||
|
if in.ThirdPartyFee != nil && *in.ThirdPartyFee != "" {
|
||||||
|
createOrderReq.ThirdPartyFee = in.ThirdPartyFee
|
||||||
|
}
|
||||||
|
if in.CryptoToUsdtRate != nil && *in.CryptoToUsdtRate != "" {
|
||||||
|
createOrderReq.CryptoToUSDTRate = in.CryptoToUsdtRate
|
||||||
|
}
|
||||||
|
if in.FiatToUsdRate != nil && *in.FiatToUsdRate != "" {
|
||||||
|
createOrderReq.FiatToUSDRate = in.FiatToUsdRate
|
||||||
|
}
|
||||||
|
if in.FeeCryptoToUsdtRate != nil && *in.FeeCryptoToUsdtRate != "" {
|
||||||
|
createOrderReq.FeeCryptoToUSDTRate = in.FeeCryptoToUsdtRate
|
||||||
|
}
|
||||||
|
if in.UsdtToCryptoTypeRate != nil && *in.UsdtToCryptoTypeRate != "" {
|
||||||
|
createOrderReq.USDTToCryptoTypeRate = in.UsdtToCryptoTypeRate
|
||||||
|
}
|
||||||
|
if in.PaymentFiat != nil {
|
||||||
|
createOrderReq.PaymentFiat = in.PaymentFiat
|
||||||
|
}
|
||||||
|
if in.PaymentUnitPrice != nil && *in.PaymentUnitPrice != "" {
|
||||||
|
createOrderReq.PaymentUnitPrice = in.PaymentUnitPrice
|
||||||
|
}
|
||||||
|
if in.PaymentTemplateId != nil {
|
||||||
|
createOrderReq.PaymentTemplateID = in.PaymentTemplateId
|
||||||
|
}
|
||||||
|
if in.OrderArrivalTime != nil {
|
||||||
|
createOrderReq.OrderArrivalTime = in.OrderArrivalTime
|
||||||
|
}
|
||||||
|
if in.OrderPaymentTime != nil {
|
||||||
|
createOrderReq.OrderPaymentTime = in.OrderPaymentTime
|
||||||
|
}
|
||||||
|
if in.UnpaidTimeoutSecond != nil {
|
||||||
|
createOrderReq.UnpaidTimeoutSecond = in.UnpaidTimeoutSecond
|
||||||
|
}
|
||||||
|
if in.ChainType != nil {
|
||||||
|
createOrderReq.ChainType = in.ChainType
|
||||||
|
}
|
||||||
|
if in.TxHash != nil {
|
||||||
|
createOrderReq.TxHash = in.TxHash
|
||||||
|
}
|
||||||
|
if in.FromAddress != nil {
|
||||||
|
createOrderReq.FromAddress = in.FromAddress
|
||||||
|
}
|
||||||
|
if in.ToAddress != nil {
|
||||||
|
createOrderReq.ToAddress = in.ToAddress
|
||||||
|
}
|
||||||
|
if in.ChainFee != nil && *in.ChainFee != "" {
|
||||||
|
createOrderReq.ChainFee = in.ChainFee
|
||||||
|
}
|
||||||
|
if in.ChainFeeCrypto != nil {
|
||||||
|
createOrderReq.ChainFeeCrypto = in.ChainFeeCrypto
|
||||||
|
}
|
||||||
|
if in.Memo != nil {
|
||||||
|
createOrderReq.Memo = in.Memo
|
||||||
|
}
|
||||||
|
if in.OrderNote != nil {
|
||||||
|
createOrderReq.OrderNote = in.OrderNote
|
||||||
|
}
|
||||||
|
|
||||||
|
return createOrderReq, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toCreateOrderReq 將 createOrderReq 轉換為 CreateOrderReq
|
||||||
|
// toCreateOrderUseCase 將 createOrderReq 轉換為 CreateOrderReq
|
||||||
|
func toCreateOrderUseCase(req *createOrderReq) usecase.CreateOrderReq {
|
||||||
|
return usecase.CreateOrderReq{
|
||||||
|
BusinessID: req.BusinessID,
|
||||||
|
OrderType: domain.OrderType(req.OrderType),
|
||||||
|
OrderStatus: domain.OrderStatus(req.OrderStatus),
|
||||||
|
Brand: req.Brand,
|
||||||
|
OrderUID: req.OrderUID,
|
||||||
|
ReferenceID: req.ReferenceID,
|
||||||
|
Count: *stringToDecimalPtr(&req.Count),
|
||||||
|
OrderFee: *stringToDecimalPtr(&req.OrderFee),
|
||||||
|
Amount: *stringToDecimalPtr(&req.Amount),
|
||||||
|
WalletStatus: getInt64Value(req.WalletStatus),
|
||||||
|
DirectionType: getInt64Value(req.DirectionType),
|
||||||
|
ReferenceBrand: req.ReferenceBrand,
|
||||||
|
ReferenceUID: req.ReferenceUID,
|
||||||
|
ThreePartyStatus: req.ThreePartyStatus,
|
||||||
|
CryptoType: req.CryptoType,
|
||||||
|
ThirdPartyFee: stringToDecimalPtr(req.ThirdPartyFee),
|
||||||
|
CryptoToUSDTRate: stringToDecimalPtr(req.CryptoToUSDTRate),
|
||||||
|
FiatToUSDRate: stringToDecimalPtr(req.FiatToUSDRate),
|
||||||
|
FeeCryptoToUSDTRate: stringToDecimalPtr(req.FeeCryptoToUSDTRate),
|
||||||
|
USDTToCryptoTypeRate: stringToDecimalPtr(req.USDTToCryptoTypeRate),
|
||||||
|
PaymentFiat: req.PaymentFiat,
|
||||||
|
PaymentUnitPrice: stringToDecimalPtr(req.PaymentUnitPrice),
|
||||||
|
PaymentTemplateID: req.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: req.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: req.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: req.UnpaidTimeoutSecond,
|
||||||
|
ChainType: req.ChainType,
|
||||||
|
TxHash: req.TxHash,
|
||||||
|
FromAddress: req.FromAddress,
|
||||||
|
ToAddress: req.ToAddress,
|
||||||
|
ChainFee: stringToDecimalPtr(req.ChainFee),
|
||||||
|
ChainFeeCrypto: req.ChainFeeCrypto,
|
||||||
|
Memo: req.Memo,
|
||||||
|
OrderNote: req.OrderNote,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrder 建立訂單
|
||||||
|
func (l *CreateOrderLogic) CreateOrder(in *trade.CreateOrderReq) (*trade.OKResp, error) {
|
||||||
|
|
||||||
|
req, err := buildCreateOrderReq(in)
|
||||||
|
if err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驗證資料
|
||||||
|
if err := l.svcCtx.Validate.ValidateAll(req); err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.svcCtx.OrderUseCase.CreateOrder(l.ctx, toCreateOrderUseCase(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteOrderLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeleteOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteOrderLogic {
|
||||||
|
return &DeleteOrderLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrderQuery 刪除訂單(軟刪除)
|
||||||
|
type DeleteOrderQuery struct {
|
||||||
|
BusinessID string `json:"business_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrder 刪除訂單(軟刪除)
|
||||||
|
func (l *DeleteOrderLogic) DeleteOrder(in *trade.DeleteOrderReq) (*trade.OKResp, error) {
|
||||||
|
// 驗證資料
|
||||||
|
if err := l.svcCtx.Validate.ValidateAll(&DeleteOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
}); err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.svcCtx.OrderUseCase.DeleteOrder(l.ctx, usecase.DeleteOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetOrderLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderLogic {
|
||||||
|
return &GetOrderLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetOrderQuery struct {
|
||||||
|
BusinessID string `json:"business_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrder 取得訂單詳情
|
||||||
|
func (l *GetOrderLogic) GetOrder(in *trade.GetOrderReq) (*trade.GetOrderResp, error) {
|
||||||
|
// 驗證資料
|
||||||
|
if err := l.svcCtx.Validate.ValidateAll(&GetOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
}); err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
o, err := l.svcCtx.OrderUseCase.GetOrder(l.ctx, usecase.GetOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.GetOrderResp{
|
||||||
|
UpdateTime: o.UpdateTime,
|
||||||
|
CreateTime: o.CreateTime,
|
||||||
|
BusinessId: o.BusinessID,
|
||||||
|
OrderType: int32(o.OrderType),
|
||||||
|
OrderStatus: int32(o.OrderStatus),
|
||||||
|
Brand: o.Brand,
|
||||||
|
OrderUid: o.OrderUID,
|
||||||
|
ReferenceId: o.ReferenceID,
|
||||||
|
Count: o.Count,
|
||||||
|
OrderFee: o.OrderFee,
|
||||||
|
Amount: o.Amount,
|
||||||
|
// 下面的為未來擴充用的欄位
|
||||||
|
ReferenceBrand: o.ReferenceBrand,
|
||||||
|
ReferenceUid: o.ReferenceUID,
|
||||||
|
WalletStatus: o.WalletStatus,
|
||||||
|
ThreePartyStatus: o.ThreePartyStatus,
|
||||||
|
DirectionType: o.DirectionType,
|
||||||
|
CryptoType: o.CryptoType,
|
||||||
|
ThirdPartyFee: o.ThirdPartyFee,
|
||||||
|
CryptoToUsdtRate: o.CryptoToUsdtRate,
|
||||||
|
FiatToUsdRate: o.FiatToUsdRate,
|
||||||
|
FeeCryptoToUsdtRate: o.FeeCryptoToUsdtRate,
|
||||||
|
UsdtToCryptoTypeRate: o.UsdtToCryptoTypeRate,
|
||||||
|
PaymentFiat: o.PaymentFiat,
|
||||||
|
PaymentUnitPrice: o.PaymentUnitPrice,
|
||||||
|
PaymentTemplateId: o.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: o.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: o.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: o.UnpaidTimeoutSecond,
|
||||||
|
ChainType: o.ChainType,
|
||||||
|
TxHash: o.TxHash,
|
||||||
|
FromAddress: o.FromAddress,
|
||||||
|
ToAddress: o.ToAddress,
|
||||||
|
ChainFee: o.ChainFee,
|
||||||
|
ChainFeeCrypto: o.ChainFeeCrypto,
|
||||||
|
Memo: o.Memo,
|
||||||
|
OrderNote: o.OrderNote,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListOrderLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListOrderLogic {
|
||||||
|
return &ListOrderLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetOrderListReq struct {
|
||||||
|
PageIndex int64 `json:"page_index" validate:"required"`
|
||||||
|
PageSize int64 `json:"page_size" validate:"required"`
|
||||||
|
|
||||||
|
ReferenceID string `json:"reference_id"`
|
||||||
|
ReferenceUID string `json:"reference_uid"`
|
||||||
|
BusinessID string `json:"business_id"`
|
||||||
|
UID string `json:"uid"`
|
||||||
|
OrderType int `json:"order_type"`
|
||||||
|
DirectionType []int64 `json:"direction_type"`
|
||||||
|
OrderStatus []int64 `json:"order_status"`
|
||||||
|
|
||||||
|
StartCreateTime int64 `json:"start_create_time"`
|
||||||
|
EndCreateTime int64 `json:"end_create_time"`
|
||||||
|
StartUpdateTime int64 `json:"start_update_time"`
|
||||||
|
EndUpdateTime int64 `json:"end_update_time"`
|
||||||
|
StartOrderArrivalTime int64 `json:"start_order_arrival_time"`
|
||||||
|
EndOrderArrivalTime int64 `json:"end_order_arrival_time"`
|
||||||
|
StartOrderPaymentTime int64 `json:"start_order_payment_time"`
|
||||||
|
EndOrderPaymentTime int64 `json:"end_order_payment_time"`
|
||||||
|
|
||||||
|
CryptoType string `json:"crypto_type"`
|
||||||
|
TxHash string `json:"tx_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// toGetOrderListReq 將 JSON 標籤結構轉換為無 JSON 標籤結構
|
||||||
|
func toGetOrderListReq(req *trade.ListOrderReq) usecase.GetOrderListReq {
|
||||||
|
return usecase.GetOrderListReq{
|
||||||
|
PageIndex: req.PageIndex,
|
||||||
|
PageSize: req.PageSize,
|
||||||
|
ReferenceID: req.ReferenceId,
|
||||||
|
ReferenceUID: req.ReferenceUid,
|
||||||
|
BusinessID: req.BusinessId,
|
||||||
|
UID: req.Uid,
|
||||||
|
OrderType: domain.OrderType(req.OrderType),
|
||||||
|
DirectionType: i32To64(req.DirectionType),
|
||||||
|
OrderStatus: i32To64(req.OrderStatus),
|
||||||
|
StartCreateTime: req.StartCreateTime,
|
||||||
|
EndCreateTime: req.EndCreateTime,
|
||||||
|
StartUpdateTime: req.StartUpdateTime,
|
||||||
|
EndUpdateTime: req.EndUpdateTime,
|
||||||
|
StartOrderArrivalTime: req.StartOrderArrivalTime,
|
||||||
|
EndOrderArrivalTime: req.EndOrderArrivalTime,
|
||||||
|
StartOrderPaymentTime: req.StartOrderPaymentTime,
|
||||||
|
EndOrderPaymentTime: req.EndOrderPaymentTime,
|
||||||
|
CryptoType: req.CryptoType,
|
||||||
|
TxHash: req.TxHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func i32To64(i []int32) []int64 {
|
||||||
|
if len(i) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
result := make([]int64, 0, len(i))
|
||||||
|
for item := range i {
|
||||||
|
result = append(result, int64(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrder 取得訂單列表
|
||||||
|
func (l *ListOrderLogic) ListOrder(in *trade.ListOrderReq) (*trade.ListOrderResp, error) {
|
||||||
|
// 驗證資料
|
||||||
|
if err := l.svcCtx.Validate.ValidateAll(&GetOrderListReq{
|
||||||
|
PageIndex: in.GetPageIndex(),
|
||||||
|
PageSize: in.GetPageSize(),
|
||||||
|
}); err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
order, err := l.svcCtx.OrderUseCase.ListOrder(l.ctx, toGetOrderListReq(in))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]*trade.GetOrderResp, 0, len(order.Data))
|
||||||
|
for _, item := range order.Data {
|
||||||
|
data = append(data, &trade.GetOrderResp{
|
||||||
|
BusinessId: item.BusinessID,
|
||||||
|
OrderType: int32(item.OrderType),
|
||||||
|
OrderStatus: int32(item.OrderStatus),
|
||||||
|
Brand: item.Brand,
|
||||||
|
OrderUid: item.OrderUID,
|
||||||
|
ReferenceId: item.ReferenceID,
|
||||||
|
Count: item.Count,
|
||||||
|
OrderFee: item.OrderFee,
|
||||||
|
Amount: item.Amount,
|
||||||
|
ReferenceBrand: item.ReferenceBrand,
|
||||||
|
ReferenceUid: item.ReferenceUID,
|
||||||
|
WalletStatus: item.WalletStatus,
|
||||||
|
ThreePartyStatus: item.ThreePartyStatus,
|
||||||
|
DirectionType: item.DirectionType,
|
||||||
|
CryptoType: item.CryptoType,
|
||||||
|
ThirdPartyFee: item.ThirdPartyFee,
|
||||||
|
CryptoToUsdtRate: item.CryptoToUsdtRate,
|
||||||
|
FiatToUsdRate: item.FiatToUsdRate,
|
||||||
|
FeeCryptoToUsdtRate: item.FeeCryptoToUsdtRate,
|
||||||
|
UsdtToCryptoTypeRate: item.UsdtToCryptoTypeRate,
|
||||||
|
PaymentFiat: item.PaymentFiat,
|
||||||
|
PaymentUnitPrice: item.PaymentUnitPrice,
|
||||||
|
PaymentTemplateId: item.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: item.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: item.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: item.UnpaidTimeoutSecond,
|
||||||
|
ChainType: item.ChainType,
|
||||||
|
TxHash: item.TxHash,
|
||||||
|
FromAddress: item.FromAddress,
|
||||||
|
ToAddress: item.ToAddress,
|
||||||
|
ChainFee: item.ChainFee,
|
||||||
|
ChainFeeCrypto: item.ChainFeeCrypto,
|
||||||
|
Memo: item.Memo,
|
||||||
|
OrderNote: item.OrderNote,
|
||||||
|
CreateTime: item.CreateTime,
|
||||||
|
UpdateTime: item.UpdateTime,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.ListOrderResp{
|
||||||
|
Data: data,
|
||||||
|
Page: &trade.Pager{
|
||||||
|
Index: order.Page.Index,
|
||||||
|
Size: order.Page.Size,
|
||||||
|
Total: order.Page.Total,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"context"
|
||||||
|
|
||||||
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ModifyOrderStatusLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewModifyOrderStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyOrderStatusLogic {
|
||||||
|
return &ModifyOrderStatusLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyOrderQuery
|
||||||
|
// 0.建立訂單 1.建單失敗 2.審核中 3.付款中 4.已付款
|
||||||
|
// 5.已付款待轉帳 6.申訴中 7.交易完成
|
||||||
|
// 8.交易失敗 9.交易取消 10.交易異常 11.交易超時
|
||||||
|
|
||||||
|
type ModifyOrderQuery struct {
|
||||||
|
BusinessID string `json:"business_id" validate:"required"`
|
||||||
|
Status int64 `json:"status" validate:"required,oneof=2 3 4 5 6 7 8 11"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyOrderStatus 修改訂單狀態
|
||||||
|
func (l *ModifyOrderStatusLogic) ModifyOrderStatus(in *trade.ModifyOrderStatusReq) (*trade.OKResp, error) {
|
||||||
|
// 驗證資料
|
||||||
|
if err := l.svcCtx.Validate.ValidateAll(&ModifyOrderQuery{
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
Status: in.GetStatus(),
|
||||||
|
}); err != nil {
|
||||||
|
// 錯誤代碼 06-011-00
|
||||||
|
return nil, ers.InvalidFormat(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.svcCtx.OrderUseCase.ModifyOrderStatus(l.ctx, &usecase.ModifyOrderQuery{
|
||||||
|
Status: in.GetStatus(),
|
||||||
|
BusinessID: in.GetBusinessId(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderStatusTimeoutLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrderStatusTimeoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OrderStatusTimeoutLogic {
|
||||||
|
return &OrderStatusTimeoutLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrderStatusTimeout 訂單超時任務/cron/order-status/timeout
|
||||||
|
func (l *OrderStatusTimeoutLogic) OrderStatusTimeout(_ *trade.OrderStatusTimeoutReq) (*trade.OKResp, error) {
|
||||||
|
err := l.svcCtx.OrderUseCase.OrderStatusTimeout(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package orderservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func decimalPtrFromString(val string) *decimal.Decimal {
|
||||||
|
if val == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dec, err := decimal.NewFromString(val)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("Failed to convert string to decimal: %v", err)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dec
|
||||||
|
}
|
||||||
|
|
||||||
|
// getInt64Value 將 *int64 的值返回,如果為 nil 則返回 0
|
||||||
|
func getInt64Value(val *int64) int64 {
|
||||||
|
if val == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return *val
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringToDecimalPtr 將 *string 轉換為 *decimal.Decimal,如果解析失敗或值為 nil 則返回 nil
|
||||||
|
func stringToDecimalPtr(s *string) *decimal.Decimal {
|
||||||
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dec, err := decimal.NewFromString(*s)
|
||||||
|
if err != nil {
|
||||||
|
return nil // 解析失敗時返回 nil,或根據需求記錄錯誤
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dec
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package productservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateProductLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateProductLogic {
|
||||||
|
return &CreateProductLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateProduct 新增商品
|
||||||
|
func (l *CreateProductLogic) CreateProduct(in *trade.ProductCreateReq) (*trade.ProductResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.ProductResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package productservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteProductLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeleteProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteProductLogic {
|
||||||
|
return &DeleteProductLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteProduct 刪除商品
|
||||||
|
func (l *DeleteProductLogic) DeleteProduct(in *trade.ProductDeleteReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package productservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListAllProductsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListAllProductsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListAllProductsLogic {
|
||||||
|
return &ListAllProductsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllProducts 查詢所有商品資訊
|
||||||
|
func (l *ListAllProductsLogic) ListAllProducts(in *trade.ProductListReq) (*trade.ProductListResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.ProductListResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package productservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QueryProductLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryProductLogic {
|
||||||
|
return &QueryProductLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryProduct 查詢單一商品資訊
|
||||||
|
func (l *QueryProductLogic) QueryProduct(in *trade.ProductQueryReq) (*trade.ProductResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.ProductResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package productservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateProductLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateProductLogic {
|
||||||
|
return &UpdateProductLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateProduct 更新商品資訊
|
||||||
|
func (l *UpdateProductLogic) UpdateProduct(in *trade.ProductUpdateReq) (*trade.ProductResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.ProductResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CancelSubscriptionLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCancelSubscriptionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CancelSubscriptionLogic {
|
||||||
|
return &CancelSubscriptionLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelSubscription 取消訂閱
|
||||||
|
func (l *CancelSubscriptionLogic) CancelSubscription(in *trade.SubscriptionCancelReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CheckSubscriptionStatusLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCheckSubscriptionStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CheckSubscriptionStatusLogic {
|
||||||
|
return &CheckSubscriptionStatusLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckSubscriptionStatus 查詢訂閱狀態 (啟用/過期/取消)
|
||||||
|
func (l *CheckSubscriptionStatusLogic) CheckSubscriptionStatus(in *trade.SubscriptionStatusQueryReq) (*trade.SubscriptionStatusResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.SubscriptionStatusResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateSubscriptionLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateSubscriptionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateSubscriptionLogic {
|
||||||
|
return &CreateSubscriptionLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSubscription 建立訂閱
|
||||||
|
func (l *CreateSubscriptionLogic) CreateSubscription(in *trade.SubscriptionCreateReq) (*trade.SubscriptionResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.SubscriptionResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListSubscriptionsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListSubscriptionsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListSubscriptionsLogic {
|
||||||
|
return &ListSubscriptionsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSubscriptions 查詢所有訂閱 (用於管理和監控)
|
||||||
|
func (l *ListSubscriptionsLogic) ListSubscriptions(in *trade.ListSubscriptionsReq) (*trade.SubscriptionListResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.SubscriptionListResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QuerySubscriptionLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQuerySubscriptionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QuerySubscriptionLogic {
|
||||||
|
return &QuerySubscriptionLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuerySubscription 查詢單一訂閱資訊
|
||||||
|
func (l *QuerySubscriptionLogic) QuerySubscription(in *trade.SubscriptionQueryReq) (*trade.SubscriptionResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.SubscriptionResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RefreshSubscriptionStatusLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRefreshSubscriptionStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshSubscriptionStatusLogic {
|
||||||
|
return &RefreshSubscriptionStatusLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshSubscriptionStatus cron 改變訂閱的狀態(時間到了要過期,需要續約自動續約),每 5 分鐘執行一次
|
||||||
|
func (l *RefreshSubscriptionStatusLogic) RefreshSubscriptionStatus(in *trade.NoneReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RenewSubscriptionLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRenewSubscriptionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RenewSubscriptionLogic {
|
||||||
|
return &RenewSubscriptionLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenewSubscription 續訂訂閱
|
||||||
|
func (l *RenewSubscriptionLogic) RenewSubscription(in *trade.SubscriptionRenewReq) (*trade.SubscriptionResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.SubscriptionResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package subscriptionservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateSubscriptionLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateSubscriptionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateSubscriptionLogic {
|
||||||
|
return &UpdateSubscriptionLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSubscription 更新訂閱設定
|
||||||
|
func (l *UpdateSubscriptionLogic) UpdateSubscription(in *trade.SubscriptionUpdateReq) (*trade.SubscriptionResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.SubscriptionResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppendToFreezeLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAppendToFreezeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AppendToFreezeLogic {
|
||||||
|
return &AppendToFreezeLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendToFreeze 追加凍結 - 減少可用餘額,追加到現有的 [凍結餘額] (基於原order_id)
|
||||||
|
func (l *AppendToFreezeLogic) AppendToFreeze(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CancelFreezeLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCancelFreezeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CancelFreezeLogic {
|
||||||
|
return &CancelFreezeLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelFreeze 取消凍結 - 減少 [凍結餘額],加回 [可用餘額],可指定金額
|
||||||
|
func (l *CancelFreezeLogic) CancelFreeze(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateWalletLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateWalletLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateWalletLogic {
|
||||||
|
return &CreateWalletLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWallet 建立錢包
|
||||||
|
func (l *CreateWalletLogic) CreateWallet(in *trade.CreateWalletReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DepositFundsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDepositFundsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DepositFundsLogic {
|
||||||
|
return &DepositFundsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DepositFunds 充值 - 增加 [可用餘額] 或 [限制餘額]
|
||||||
|
func (l *DepositFundsLogic) DepositFunds(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FreezeFundsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFreezeFundsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FreezeFundsLogic {
|
||||||
|
return &FreezeFundsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FreezeFunds 凍結 - 將 [可用餘額] 減少,加到 [凍結餘額]
|
||||||
|
func (l *FreezeFundsLogic) FreezeFunds(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type QueryBalanceLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryBalanceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryBalanceLogic {
|
||||||
|
return &QueryBalanceLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryBalance 餘額查詢 -> 依照日期查詢
|
||||||
|
func (l *QueryBalanceLogic) QueryBalance(in *trade.QueryBalanceByDateReq) (*trade.QueryBalanceByDateResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.QueryBalanceByDateResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RollbackFreezeLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRollbackFreezeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RollbackFreezeLogic {
|
||||||
|
return &RollbackFreezeLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RollbackFreeze 凍結回滾 - 減少 [凍結餘額],加回 [可用餘額],不可指定金額,整筆訂單的凍結金額加回 [可用餘額]
|
||||||
|
func (l *RollbackFreezeLogic) RollbackFreeze(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SettleRestrictedFundsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSettleRestrictedFundsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SettleRestrictedFundsLogic {
|
||||||
|
return &SettleRestrictedFundsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SettleRestrictedFunds 結算限制餘額 - 限制餘額在 T+N 天後自動失效,每日只能執行一次
|
||||||
|
func (l *SettleRestrictedFundsLogic) SettleRestrictedFunds(in *trade.NoneReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TransferToRestrictedFundsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTransferToRestrictedFundsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TransferToRestrictedFundsLogic {
|
||||||
|
return &TransferToRestrictedFundsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransferToRestrictedFunds 限制 - 減少 [凍結餘額],轉移到另一個使用者的 [限制餘額]
|
||||||
|
func (l *TransferToRestrictedFundsLogic) TransferToRestrictedFunds(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UnfreezeFundsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnfreezeFundsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UnfreezeFundsLogic {
|
||||||
|
return &UnfreezeFundsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnfreezeFunds 解凍 - 減少 [凍結餘額]
|
||||||
|
func (l *UnfreezeFundsLogic) UnfreezeFunds(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package walletservicelogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WithdrawFundsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWithdrawFundsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WithdrawFundsLogic {
|
||||||
|
return &WithdrawFundsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithdrawFunds 提現 - 減少 [可用餘額]
|
||||||
|
func (l *WithdrawFundsLogic) WithdrawFunds(in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return &trade.OKResp{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: ./validate.go
|
||||||
|
//
|
||||||
|
// Generated by this command:
|
||||||
|
//
|
||||||
|
// mockgen -source=./validate.go -destination=../../mock/lib/validate.go -package=lib
|
||||||
|
//
|
||||||
|
|
||||||
|
// Package lib is a generated GoMock package.
|
||||||
|
package lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
required "code.30cm.net/digimon/library-go/validator"
|
||||||
|
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockValidate is a mock of Validate interface.
|
||||||
|
type MockValidate struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockValidateMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockValidateMockRecorder is the mock recorder for MockValidate.
|
||||||
|
type MockValidateMockRecorder struct {
|
||||||
|
mock *MockValidate
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockValidate creates a new mock instance.
|
||||||
|
func NewMockValidate(ctrl *gomock.Controller) *MockValidate {
|
||||||
|
mock := &MockValidate{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockValidateMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockValidate) EXPECT() *MockValidateMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindToValidator mocks base method.
|
||||||
|
func (m *MockValidate) BindToValidator(opts ...required.Option) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []any{}
|
||||||
|
for _, a := range opts {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "BindToValidator", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindToValidator indicates an expected call of BindToValidator.
|
||||||
|
func (mr *MockValidateMockRecorder) BindToValidator(opts ...any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BindToValidator", reflect.TypeOf((*MockValidate)(nil).BindToValidator), opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAll mocks base method.
|
||||||
|
func (m *MockValidate) ValidateAll(obj any) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ValidateAll", obj)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAll indicates an expected call of ValidateAll.
|
||||||
|
func (mr *MockValidateMockRecorder) ValidateAll(obj any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAll", reflect.TypeOf((*MockValidate)(nil).ValidateAll), obj)
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: ./internal/model/mongo/order_model.go
|
||||||
|
//
|
||||||
|
// Generated by this command:
|
||||||
|
//
|
||||||
|
// mockgen -source=./internal/model/mongo/order_model.go -destination=./internal/mock/model/order_model.go -package=mock
|
||||||
|
//
|
||||||
|
|
||||||
|
// Package mock is a generated GoMock package.
|
||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
mongo "app-cloudep-trade-service/internal/model/mongo"
|
||||||
|
context "context"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
mongo0 "go.mongodb.org/mongo-driver/mongo"
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockOrderModel is a mock of OrderModel interface.
|
||||||
|
type MockOrderModel struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockOrderModelMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockOrderModelMockRecorder is the mock recorder for MockOrderModel.
|
||||||
|
type MockOrderModelMockRecorder struct {
|
||||||
|
mock *MockOrderModel
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockOrderModel creates a new mock instance.
|
||||||
|
func NewMockOrderModel(ctrl *gomock.Controller) *MockOrderModel {
|
||||||
|
mock := &MockOrderModel{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockOrderModelMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockOrderModel) EXPECT() *MockOrderModelMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete mocks base method.
|
||||||
|
func (m *MockOrderModel) Delete(ctx context.Context, id string) (int64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Delete", ctx, id)
|
||||||
|
ret0, _ := ret[0].(int64)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete indicates an expected call of Delete.
|
||||||
|
func (mr *MockOrderModelMockRecorder) Delete(ctx, id any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockOrderModel)(nil).Delete), ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByBusinessID mocks base method.
|
||||||
|
func (m *MockOrderModel) DeleteByBusinessID(ctx context.Context, id string) (*mongo0.UpdateResult, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "DeleteByBusinessID", ctx, id)
|
||||||
|
ret0, _ := ret[0].(*mongo0.UpdateResult)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByBusinessID indicates an expected call of DeleteByBusinessID.
|
||||||
|
func (mr *MockOrderModelMockRecorder) DeleteByBusinessID(ctx, id any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByBusinessID", reflect.TypeOf((*MockOrderModel)(nil).DeleteByBusinessID), ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne mocks base method.
|
||||||
|
func (m *MockOrderModel) FindOne(ctx context.Context, id string) (*mongo.Order, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FindOne", ctx, id)
|
||||||
|
ret0, _ := ret[0].(*mongo.Order)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne indicates an expected call of FindOne.
|
||||||
|
func (mr *MockOrderModelMockRecorder) FindOne(ctx, id any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockOrderModel)(nil).FindOne), ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOneBusinessID mocks base method.
|
||||||
|
func (m *MockOrderModel) FindOneBusinessID(ctx context.Context, id string) (*mongo.Order, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FindOneBusinessID", ctx, id)
|
||||||
|
ret0, _ := ret[0].(*mongo.Order)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOneBusinessID indicates an expected call of FindOneBusinessID.
|
||||||
|
func (mr *MockOrderModelMockRecorder) FindOneBusinessID(ctx, id any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOneBusinessID", reflect.TypeOf((*MockOrderModel)(nil).FindOneBusinessID), ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert mocks base method.
|
||||||
|
func (m *MockOrderModel) Insert(ctx context.Context, data *mongo.Order) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Insert", ctx, data)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert indicates an expected call of Insert.
|
||||||
|
func (mr *MockOrderModelMockRecorder) Insert(ctx, data any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockOrderModel)(nil).Insert), ctx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrder mocks base method.
|
||||||
|
func (m *MockOrderModel) ListOrder(ctx context.Context, req mongo.GetOrderListReq) ([]mongo.Order, int64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ListOrder", ctx, req)
|
||||||
|
ret0, _ := ret[0].([]mongo.Order)
|
||||||
|
ret1, _ := ret[1].(int64)
|
||||||
|
ret2, _ := ret[2].(error)
|
||||||
|
return ret0, ret1, ret2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrder indicates an expected call of ListOrder.
|
||||||
|
func (mr *MockOrderModelMockRecorder) ListOrder(ctx, req any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListOrder", reflect.TypeOf((*MockOrderModel)(nil).ListOrder), ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update mocks base method.
|
||||||
|
func (m *MockOrderModel) Update(ctx context.Context, data *mongo.Order) (*mongo0.UpdateResult, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Update", ctx, data)
|
||||||
|
ret0, _ := ret[0].(*mongo0.UpdateResult)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update indicates an expected call of Update.
|
||||||
|
func (mr *MockOrderModelMockRecorder) Update(ctx, data any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockOrderModel)(nil).Update), ctx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateStatus mocks base method.
|
||||||
|
func (m *MockOrderModel) UpdateStatus(ctx context.Context, data mongo.UpdateStatusReq) (*mongo0.UpdateResult, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "UpdateStatus", ctx, data)
|
||||||
|
ret0, _ := ret[0].(*mongo0.UpdateResult)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateStatus indicates an expected call of UpdateStatus.
|
||||||
|
func (mr *MockOrderModelMockRecorder) UpdateStatus(ctx, data any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockOrderModel)(nil).UpdateStatus), ctx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateTimeoutOrder mocks base method.
|
||||||
|
func (m *MockOrderModel) UpdateTimeoutOrder(ctx context.Context, req mongo.UpdateTimeoutReq) (*mongo0.UpdateResult, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "UpdateTimeoutOrder", ctx, req)
|
||||||
|
ret0, _ := ret[0].(*mongo0.UpdateResult)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateTimeoutOrder indicates an expected call of UpdateTimeoutOrder.
|
||||||
|
func (mr *MockOrderModelMockRecorder) UpdateTimeoutOrder(ctx, req any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTimeoutOrder", reflect.TypeOf((*MockOrderModel)(nil).UpdateTimeoutOrder), ctx, req)
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: ./internal/model/mongo/order_model_gen.go
|
||||||
|
//
|
||||||
|
// Generated by this command:
|
||||||
|
//
|
||||||
|
// mockgen -source=./internal/model/mongo/order_model_gen.go -destination=./internal/mock/model/order_model_gen.go -package=mock
|
||||||
|
//
|
||||||
|
|
||||||
|
// Package mock is a generated GoMock package.
|
||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
mongo "app-cloudep-trade-service/internal/model/mongo"
|
||||||
|
context "context"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
mongo0 "go.mongodb.org/mongo-driver/mongo"
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockorderModel is a mock of orderModel interface.
|
||||||
|
type MockorderModel struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockorderModelMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockorderModelMockRecorder is the mock recorder for MockorderModel.
|
||||||
|
type MockorderModelMockRecorder struct {
|
||||||
|
mock *MockorderModel
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockorderModel creates a new mock instance.
|
||||||
|
func NewMockorderModel(ctrl *gomock.Controller) *MockorderModel {
|
||||||
|
mock := &MockorderModel{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockorderModelMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockorderModel) EXPECT() *MockorderModelMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete mocks base method.
|
||||||
|
func (m *MockorderModel) Delete(ctx context.Context, id string) (int64, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Delete", ctx, id)
|
||||||
|
ret0, _ := ret[0].(int64)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete indicates an expected call of Delete.
|
||||||
|
func (mr *MockorderModelMockRecorder) Delete(ctx, id any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockorderModel)(nil).Delete), ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne mocks base method.
|
||||||
|
func (m *MockorderModel) FindOne(ctx context.Context, id string) (*mongo.Order, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "FindOne", ctx, id)
|
||||||
|
ret0, _ := ret[0].(*mongo.Order)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne indicates an expected call of FindOne.
|
||||||
|
func (mr *MockorderModelMockRecorder) FindOne(ctx, id any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockorderModel)(nil).FindOne), ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert mocks base method.
|
||||||
|
func (m *MockorderModel) Insert(ctx context.Context, data *mongo.Order) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Insert", ctx, data)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert indicates an expected call of Insert.
|
||||||
|
func (mr *MockorderModelMockRecorder) Insert(ctx, data any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockorderModel)(nil).Insert), ctx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update mocks base method.
|
||||||
|
func (m *MockorderModel) Update(ctx context.Context, data *mongo.Order) (*mongo0.UpdateResult, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Update", ctx, data)
|
||||||
|
ret0, _ := ret[0].(*mongo0.UpdateResult)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update indicates an expected call of Update.
|
||||||
|
func (mr *MockorderModelMockRecorder) Update(ctx, data any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockorderModel)(nil).Update), ctx, data)
|
||||||
|
}
|
|
@ -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,238 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
UpdateStatus(ctx context.Context, data UpdateStatusReq) (*mongo.UpdateResult, error)
|
||||||
|
UpdateTimeoutOrder(ctx context.Context, req UpdateTimeoutReq) (*mongo.UpdateResult, error)
|
||||||
|
DeleteByBusinessID(ctx context.Context, id string) (*mongo.UpdateResult, error)
|
||||||
|
FindOneBusinessID(ctx context.Context, id string) (*Order, error)
|
||||||
|
ListOrder(ctx context.Context, req GetOrderListReq) ([]Order, int64, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
customOrderModel struct {
|
||||||
|
*defaultOrderModel
|
||||||
|
}
|
||||||
|
UpdateStatusReq struct {
|
||||||
|
BusinessID string
|
||||||
|
Status int64
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTimeoutReq struct {
|
||||||
|
CreateTimeBefore int64
|
||||||
|
}
|
||||||
|
|
||||||
|
GetOrderListReq struct {
|
||||||
|
PageIndex int64 `json:"page_index" validate:"required"`
|
||||||
|
PageSize int64 `json:"page_size" validate:"required"`
|
||||||
|
|
||||||
|
ReferenceID string `json:"reference_id"`
|
||||||
|
ReferenceUID string `json:"reference_uid"`
|
||||||
|
BusinessID string `json:"business_id"`
|
||||||
|
UID string `json:"uid"`
|
||||||
|
OrderType int `json:"order_type"`
|
||||||
|
DirectionType []int64 `json:"direction_type"`
|
||||||
|
OrderStatus []int64 `json:"order_status"`
|
||||||
|
|
||||||
|
StartCreateTime int64 `json:"start_create_time"`
|
||||||
|
EndCreateTime int64 `json:"end_create_time"`
|
||||||
|
StartUpdateTime int64 `json:"start_update_time"`
|
||||||
|
EndUpdateTime int64 `json:"end_update_time"`
|
||||||
|
StartOrderArrivalTime int64 `json:"start_order_arrival_time"`
|
||||||
|
EndOrderArrivalTime int64 `json:"end_order_arrival_time"`
|
||||||
|
StartOrderPaymentTime int64 `json:"start_order_payment_time"`
|
||||||
|
EndOrderPaymentTime int64 `json:"end_order_payment_time"`
|
||||||
|
|
||||||
|
CryptoType string `json:"crypto_type"`
|
||||||
|
TxHash string `json:"tx_hash"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customOrderModel) UpdateStatus(ctx context.Context, data UpdateStatusReq) (*mongo.UpdateResult, error) {
|
||||||
|
// 初始化 updates map
|
||||||
|
updates := make(map[string]any)
|
||||||
|
|
||||||
|
// 更新 update_time 和 status
|
||||||
|
updates["update_time"] = time.Now().UTC().UnixNano()
|
||||||
|
updates["order_status"] = data.Status
|
||||||
|
|
||||||
|
// 使用 updates map 作為 $set 的內容
|
||||||
|
res, err := m.conn.UpdateOne(ctx,
|
||||||
|
bson.M{
|
||||||
|
"business_id": data.BusinessID,
|
||||||
|
"$or": []bson.M{
|
||||||
|
{"delete_time": bson.M{"$exists": false}},
|
||||||
|
{"delete_time": 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bson.M{"$set": updates}, // 使用 updates 而不是整個 data
|
||||||
|
)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customOrderModel) UpdateTimeoutOrder(ctx context.Context, req UpdateTimeoutReq) (*mongo.UpdateResult, error) {
|
||||||
|
// 構建過濾條件,選擇創建時間在指定時間之前且狀態為 0 (創建) 的項目
|
||||||
|
filter := bson.M{
|
||||||
|
"create_time": bson.M{"$lt": req.CreateTimeBefore},
|
||||||
|
"status": domain.OrderStatusCreated,
|
||||||
|
"$or": []bson.M{
|
||||||
|
{"delete_time": bson.M{"$exists": false}},
|
||||||
|
{"delete_time": 0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新內容,將狀態設置為 11,並更新 update_time
|
||||||
|
updates := bson.M{
|
||||||
|
"$set": bson.M{
|
||||||
|
"status": domain.OrderStatusTimeout,
|
||||||
|
"update_time": time.Now().UTC().UnixNano(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 執行更新操作
|
||||||
|
res, err := m.conn.UpdateOne(ctx, filter, updates)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customOrderModel) DeleteByBusinessID(ctx context.Context, id string) (*mongo.UpdateResult, error) {
|
||||||
|
filter := bson.M{
|
||||||
|
"business_id": id,
|
||||||
|
"$or": []bson.M{
|
||||||
|
{"delete_time": bson.M{"$exists": false}},
|
||||||
|
{"delete_time": 0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
updates := bson.M{
|
||||||
|
"$set": bson.M{
|
||||||
|
"delete_time": time.Now().UTC().UnixNano(),
|
||||||
|
"update_time": time.Now().UTC().UnixNano(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// 執行更新操作
|
||||||
|
res, err := m.conn.UpdateOne(ctx, filter, updates)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultOrderModel) FindOneBusinessID(ctx context.Context, id string) (*Order, error) {
|
||||||
|
var data Order
|
||||||
|
filter := bson.M{"delete_time": bson.M{"$in": []any{0, nil}}}
|
||||||
|
filter["business_id"] = id
|
||||||
|
|
||||||
|
err := m.conn.FindOne(ctx, &data, filter)
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
return &data, nil
|
||||||
|
case errors.Is(err, mon.ErrNotFound):
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customOrderModel) ListOrder(ctx context.Context, req GetOrderListReq) ([]Order, int64, error) {
|
||||||
|
// 定義查詢過濾器
|
||||||
|
filter := bson.M{
|
||||||
|
"delete_time": bson.M{"$in": []any{0, nil}},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加查詢條件
|
||||||
|
if req.ReferenceID != "" {
|
||||||
|
filter["reference_id"] = req.ReferenceID
|
||||||
|
}
|
||||||
|
if req.ReferenceUID != "" {
|
||||||
|
filter["reference_uid"] = req.ReferenceUID
|
||||||
|
}
|
||||||
|
if req.BusinessID != "" {
|
||||||
|
filter["business_id"] = req.BusinessID
|
||||||
|
}
|
||||||
|
if req.UID != "" {
|
||||||
|
filter["order_uid"] = req.UID
|
||||||
|
}
|
||||||
|
if req.OrderType != 0 {
|
||||||
|
filter["order_type"] = req.OrderType
|
||||||
|
}
|
||||||
|
if len(req.DirectionType) > 0 {
|
||||||
|
filter["direction_type"] = bson.M{"$in": req.DirectionType}
|
||||||
|
}
|
||||||
|
if len(req.OrderStatus) > 0 {
|
||||||
|
filter["order_status"] = bson.M{"$in": req.OrderStatus}
|
||||||
|
}
|
||||||
|
// 處理時間範圍
|
||||||
|
if req.StartCreateTime != 0 {
|
||||||
|
filter["create_time"] = bson.M{"$gte": req.StartCreateTime}
|
||||||
|
}
|
||||||
|
if req.EndCreateTime != 0 {
|
||||||
|
filter["create_time"] = bson.M{"$lte": req.EndCreateTime}
|
||||||
|
}
|
||||||
|
if req.StartUpdateTime != 0 {
|
||||||
|
filter["update_time"] = bson.M{"$gte": req.StartUpdateTime}
|
||||||
|
}
|
||||||
|
if req.EndUpdateTime != 0 {
|
||||||
|
filter["update_time"] = bson.M{"$lte": req.EndUpdateTime}
|
||||||
|
}
|
||||||
|
if req.StartOrderArrivalTime != 0 {
|
||||||
|
filter["order_arrival_time"] = bson.M{"$gte": req.StartOrderArrivalTime}
|
||||||
|
}
|
||||||
|
if req.EndOrderArrivalTime != 0 {
|
||||||
|
filter["order_arrival_time"] = bson.M{"$lte": req.EndOrderArrivalTime}
|
||||||
|
}
|
||||||
|
if req.StartOrderPaymentTime != 0 {
|
||||||
|
filter["order_payment_time"] = bson.M{"$gte": req.StartOrderPaymentTime}
|
||||||
|
}
|
||||||
|
if req.EndOrderPaymentTime != 0 {
|
||||||
|
filter["order_payment_time"] = bson.M{"$lte": req.EndOrderPaymentTime}
|
||||||
|
}
|
||||||
|
if req.CryptoType != "" {
|
||||||
|
filter["crypto_type"] = req.CryptoType
|
||||||
|
}
|
||||||
|
if req.TxHash != "" {
|
||||||
|
filter["tx_hash"] = req.TxHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// 計算符合條件的總數量
|
||||||
|
totalCount, err := m.conn.CountDocuments(ctx, filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 設定查詢選項,包含分頁
|
||||||
|
findOptions := options.Find()
|
||||||
|
findOptions.SetSkip((req.PageIndex - 1) * req.PageSize)
|
||||||
|
findOptions.SetLimit(req.PageSize)
|
||||||
|
|
||||||
|
// 執行查詢
|
||||||
|
var orders []Order
|
||||||
|
err = m.conn.Find(ctx, &orders, filter, findOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return orders, totalCount, nil
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
// 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() {
|
||||||
|
now := time.Now().UTC().UnixNano()
|
||||||
|
data.ID = primitive.NewObjectID()
|
||||||
|
data.CreateTime = now
|
||||||
|
data.UpdateTime = 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.UpdateTime = time.Now().UTC().UnixNano()
|
||||||
|
|
||||||
|
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,53 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Order struct {
|
||||||
|
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
|
||||||
|
UpdateTime int64 `bson:"update_time"`
|
||||||
|
CreateTime int64 `bson:"create_time"`
|
||||||
|
BusinessID string `bson:"business_id"` // 訂單業務流水號
|
||||||
|
OrderType domain.OrderType `bson:"order_type"` // 訂單類型
|
||||||
|
OrderStatus domain.OrderStatus `bson:"order_status"` // 訂單狀態
|
||||||
|
Brand string `bson:"brand"` // 下單平台
|
||||||
|
OrderUID string `bson:"order_uid"` // 下單用戶 UID
|
||||||
|
ReferenceID string `bson:"reference_id"` // 訂單來源
|
||||||
|
Count decimal.Decimal `bson:"count"` // 訂單數量
|
||||||
|
OrderFee decimal.Decimal `bson:"order_fee"` // 訂單手續費
|
||||||
|
Amount decimal.Decimal `bson:"amount"` // 單價
|
||||||
|
WalletStatus int64 `bson:"wallet_status,omitempty"` // 交易金額狀態
|
||||||
|
DirectionType int64 `bson:"direction_type,omitempty"` // 交易方向
|
||||||
|
// 以上為必要欄位,下面是區塊鏈時才需要
|
||||||
|
ReferenceBrand *string `bson:"reference_brand,omitempty"` // 訂單來源平台
|
||||||
|
ReferenceUID *string `bson:"reference_uid,omitempty"` // 訂單來源用戶 UID
|
||||||
|
ThreePartyStatus *int64 `bson:"three_party_status,omitempty"` // 三方請求狀態
|
||||||
|
CryptoType *string `bson:"crypto_type,omitempty"` // 交易幣種
|
||||||
|
ThirdPartyFee *decimal.Decimal `bson:"third_party_fee,omitempty"` // 第三方手續費
|
||||||
|
CryptoToUSDTRate *decimal.Decimal `bson:"crypto_to_usdt_rate,omitempty"` // 加密貨幣對 USDT 匯率
|
||||||
|
FiatToUSDRate *decimal.Decimal `bson:"fiat_to_usd_rate,omitempty"` // 法幣對 USD 匯率
|
||||||
|
FeeCryptoToUSDTRate *decimal.Decimal `bson:"fee_crypto_to_usdt_rate,omitempty"` // 手續費加密貨幣對 USDT 匯率
|
||||||
|
USDTToCryptoTypeRate *decimal.Decimal `bson:"usdt_to_crypto_type_rate,omitempty"` // USDT 對加密貨幣匯率
|
||||||
|
PaymentFiat *string `bson:"payment_fiat,omitempty"` // 支付法幣
|
||||||
|
PaymentUnitPrice *decimal.Decimal `bson:"payment_unit_price,omitempty"` // 加密貨幣單價
|
||||||
|
PaymentTemplateID *string `bson:"payment_template_id,omitempty"` // 支付方式配置 ID
|
||||||
|
OrderArrivalTime *int64 `bson:"order_arrival_time,omitempty"` // 訂單到帳時間
|
||||||
|
OrderPaymentTime *int64 `bson:"order_payment_time,omitempty"` // 訂單付款時間
|
||||||
|
UnpaidTimeoutSecond *int64 `bson:"unpaid_timeout_second,omitempty"` // 支付期限秒數
|
||||||
|
ChainType *string `bson:"chain_type,omitempty"` // 主網類型
|
||||||
|
TxHash *string `bson:"tx_hash,omitempty"` // 交易哈希
|
||||||
|
FromAddress *string `bson:"from_address,omitempty"` // 來源地址
|
||||||
|
ToAddress *string `bson:"to_address,omitempty"` // 目標地址
|
||||||
|
ChainFee *decimal.Decimal `bson:"chain_fee,omitempty"` // 鏈上交易手續費
|
||||||
|
ChainFeeCrypto *string `bson:"chain_fee_crypto,omitempty"` // 鏈上手續費使用幣別
|
||||||
|
Memo *string `bson:"memo,omitempty"` // 鏈上備註
|
||||||
|
OrderNote *string `bson:"order_note,omitempty"` // 訂單交易備註
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Order) CollectionName() string {
|
||||||
|
return "order"
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// Source: trade.proto
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
couponservicelogic "app-cloudep-trade-service/internal/logic/couponservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CouponServiceServer struct {
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
trade.UnimplementedCouponServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCouponServiceServer(svcCtx *svc.ServiceContext) *CouponServiceServer {
|
||||||
|
return &CouponServiceServer{
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateCoupon 創建優惠券
|
||||||
|
func (s *CouponServiceServer) CreateCoupon(ctx context.Context, in *trade.CreateCouponReq) (*trade.CouponResp, error) {
|
||||||
|
l := couponservicelogic.NewCreateCouponLogic(ctx, s.svcCtx)
|
||||||
|
return l.CreateCoupon(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateCoupon更新優惠券
|
||||||
|
func (s *CouponServiceServer) UpdateCoupon(ctx context.Context, in *trade.UpdateCouponReq) (*trade.CouponResp, error) {
|
||||||
|
l := couponservicelogic.NewUpdateCouponLogic(ctx, s.svcCtx)
|
||||||
|
return l.UpdateCoupon(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryCoupon查詢優惠券
|
||||||
|
func (s *CouponServiceServer) QueryCoupon(ctx context.Context, in *trade.CouponQueryReq) (*trade.CouponResp, error) {
|
||||||
|
l := couponservicelogic.NewQueryCouponLogic(ctx, s.svcCtx)
|
||||||
|
return l.QueryCoupon(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCoupon 刪除優惠券
|
||||||
|
func (s *CouponServiceServer) DeleteCoupon(ctx context.Context, in *trade.CouponQueryReq) (*trade.OKResp, error) {
|
||||||
|
l := couponservicelogic.NewDeleteCouponLogic(ctx, s.svcCtx)
|
||||||
|
return l.DeleteCoupon(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListCoupons列出所有優惠券
|
||||||
|
func (s *CouponServiceServer) ListCoupons(ctx context.Context, in *trade.CouponListReq) (*trade.CouponListResp, error) {
|
||||||
|
l := couponservicelogic.NewListCouponsLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListCoupons(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateCoupon 驗證優惠券 (在下單或支付時使用)
|
||||||
|
func (s *CouponServiceServer) ValidateCoupon(ctx context.Context, in *trade.ValidateCouponReq) (*trade.CouponValidationResp, error) {
|
||||||
|
l := couponservicelogic.NewValidateCouponLogic(ctx, s.svcCtx)
|
||||||
|
return l.ValidateCoupon(in)
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// Source: trade.proto
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
inventoryservicelogic "app-cloudep-trade-service/internal/logic/inventoryservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InventoryServiceServer struct {
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
trade.UnimplementedInventoryServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInventoryServiceServer(svcCtx *svc.ServiceContext) *InventoryServiceServer {
|
||||||
|
return &InventoryServiceServer{
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateStock 建立庫存品項
|
||||||
|
func (s *InventoryServiceServer) CreateStock(ctx context.Context, in *trade.StockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
l := inventoryservicelogic.NewCreateStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.CreateStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStock 增加庫存
|
||||||
|
func (s *InventoryServiceServer) AddStock(ctx context.Context, in *trade.StockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
l := inventoryservicelogic.NewAddStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.AddStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReduceStock 減少庫存
|
||||||
|
func (s *InventoryServiceServer) ReduceStock(ctx context.Context, in *trade.StockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
l := inventoryservicelogic.NewReduceStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.ReduceStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryStock 查詢單一商品的庫存
|
||||||
|
func (s *InventoryServiceServer) QueryStock(ctx context.Context, in *trade.StockQueryReq) (*trade.StockResp, error) {
|
||||||
|
l := inventoryservicelogic.NewQueryStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.QueryStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllStock 查詢所有商品的庫存狀況
|
||||||
|
func (s *InventoryServiceServer) ListAllStock(ctx context.Context, in *trade.StockListReq) (*trade.StockListResp, error) {
|
||||||
|
l := inventoryservicelogic.NewListAllStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListAllStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReserveStock 預留庫存 (用於未完成的訂單)
|
||||||
|
func (s *InventoryServiceServer) ReserveStock(ctx context.Context, in *trade.StockReservationReq) (*trade.OKResp, error) {
|
||||||
|
l := inventoryservicelogic.NewReserveStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.ReserveStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReleaseReservedStock 釋放預留庫存 (取消或失效的訂單)
|
||||||
|
func (s *InventoryServiceServer) ReleaseReservedStock(ctx context.Context, in *trade.StockReservationReq) (*trade.OKResp, error) {
|
||||||
|
l := inventoryservicelogic.NewReleaseReservedStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.ReleaseReservedStock(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustStock 調整庫存 (批量修改庫存,用於大批商品更新)
|
||||||
|
func (s *InventoryServiceServer) AdjustStock(ctx context.Context, in *trade.BatchStockAdjustmentReq) (*trade.OKResp, error) {
|
||||||
|
l := inventoryservicelogic.NewAdjustStockLogic(ctx, s.svcCtx)
|
||||||
|
return l.AdjustStock(in)
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// Source: trade.proto
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
orderservicelogic "app-cloudep-trade-service/internal/logic/orderservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderServiceServer struct {
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
trade.UnimplementedOrderServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrderServiceServer(svcCtx *svc.ServiceContext) *OrderServiceServer {
|
||||||
|
return &OrderServiceServer{
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrder 建立訂單
|
||||||
|
func (s *OrderServiceServer) CreateOrder(ctx context.Context, in *trade.CreateOrderReq) (*trade.OKResp, error) {
|
||||||
|
l := orderservicelogic.NewCreateOrderLogic(ctx, s.svcCtx)
|
||||||
|
return l.CreateOrder(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelOrder 取消訂單
|
||||||
|
func (s *OrderServiceServer) CancelOrder(ctx context.Context, in *trade.CancelOrderReq) (*trade.OKResp, error) {
|
||||||
|
l := orderservicelogic.NewCancelOrderLogic(ctx, s.svcCtx)
|
||||||
|
return l.CancelOrder(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyOrderStatus 修改訂單狀態
|
||||||
|
func (s *OrderServiceServer) ModifyOrderStatus(ctx context.Context, in *trade.ModifyOrderStatusReq) (*trade.OKResp, error) {
|
||||||
|
l := orderservicelogic.NewModifyOrderStatusLogic(ctx, s.svcCtx)
|
||||||
|
return l.ModifyOrderStatus(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteOrder 刪除訂單(軟刪除)
|
||||||
|
func (s *OrderServiceServer) DeleteOrder(ctx context.Context, in *trade.DeleteOrderReq) (*trade.OKResp, error) {
|
||||||
|
l := orderservicelogic.NewDeleteOrderLogic(ctx, s.svcCtx)
|
||||||
|
return l.DeleteOrder(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrder 取得訂單詳情
|
||||||
|
func (s *OrderServiceServer) GetOrder(ctx context.Context, in *trade.GetOrderReq) (*trade.GetOrderResp, error) {
|
||||||
|
l := orderservicelogic.NewGetOrderLogic(ctx, s.svcCtx)
|
||||||
|
return l.GetOrder(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrder 取得訂單列表
|
||||||
|
func (s *OrderServiceServer) ListOrder(ctx context.Context, in *trade.ListOrderReq) (*trade.ListOrderResp, error) {
|
||||||
|
l := orderservicelogic.NewListOrderLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListOrder(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrderStatusTimeout 訂單超時任務/cron/order-status/timeout
|
||||||
|
func (s *OrderServiceServer) OrderStatusTimeout(ctx context.Context, in *trade.OrderStatusTimeoutReq) (*trade.OKResp, error) {
|
||||||
|
l := orderservicelogic.NewOrderStatusTimeoutLogic(ctx, s.svcCtx)
|
||||||
|
return l.OrderStatusTimeout(in)
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// Source: trade.proto
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
productservicelogic "app-cloudep-trade-service/internal/logic/productservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProductServiceServer struct {
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
trade.UnimplementedProductServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProductServiceServer(svcCtx *svc.ServiceContext) *ProductServiceServer {
|
||||||
|
return &ProductServiceServer{
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateProduct 新增商品
|
||||||
|
func (s *ProductServiceServer) CreateProduct(ctx context.Context, in *trade.ProductCreateReq) (*trade.ProductResp, error) {
|
||||||
|
l := productservicelogic.NewCreateProductLogic(ctx, s.svcCtx)
|
||||||
|
return l.CreateProduct(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateProduct 更新商品資訊
|
||||||
|
func (s *ProductServiceServer) UpdateProduct(ctx context.Context, in *trade.ProductUpdateReq) (*trade.ProductResp, error) {
|
||||||
|
l := productservicelogic.NewUpdateProductLogic(ctx, s.svcCtx)
|
||||||
|
return l.UpdateProduct(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteProduct 刪除商品
|
||||||
|
func (s *ProductServiceServer) DeleteProduct(ctx context.Context, in *trade.ProductDeleteReq) (*trade.OKResp, error) {
|
||||||
|
l := productservicelogic.NewDeleteProductLogic(ctx, s.svcCtx)
|
||||||
|
return l.DeleteProduct(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryProduct 查詢單一商品資訊
|
||||||
|
func (s *ProductServiceServer) QueryProduct(ctx context.Context, in *trade.ProductQueryReq) (*trade.ProductResp, error) {
|
||||||
|
l := productservicelogic.NewQueryProductLogic(ctx, s.svcCtx)
|
||||||
|
return l.QueryProduct(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAllProducts 查詢所有商品資訊
|
||||||
|
func (s *ProductServiceServer) ListAllProducts(ctx context.Context, in *trade.ProductListReq) (*trade.ProductListResp, error) {
|
||||||
|
l := productservicelogic.NewListAllProductsLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListAllProducts(in)
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// Source: trade.proto
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
subscriptionservicelogic "app-cloudep-trade-service/internal/logic/subscriptionservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubscriptionServiceServer struct {
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
trade.UnimplementedSubscriptionServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSubscriptionServiceServer(svcCtx *svc.ServiceContext) *SubscriptionServiceServer {
|
||||||
|
return &SubscriptionServiceServer{
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSubscription 建立訂閱
|
||||||
|
func (s *SubscriptionServiceServer) CreateSubscription(ctx context.Context, in *trade.SubscriptionCreateReq) (*trade.SubscriptionResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewCreateSubscriptionLogic(ctx, s.svcCtx)
|
||||||
|
return l.CreateSubscription(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSubscription 更新訂閱設定
|
||||||
|
func (s *SubscriptionServiceServer) UpdateSubscription(ctx context.Context, in *trade.SubscriptionUpdateReq) (*trade.SubscriptionResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewUpdateSubscriptionLogic(ctx, s.svcCtx)
|
||||||
|
return l.UpdateSubscription(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelSubscription 取消訂閱
|
||||||
|
func (s *SubscriptionServiceServer) CancelSubscription(ctx context.Context, in *trade.SubscriptionCancelReq) (*trade.OKResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewCancelSubscriptionLogic(ctx, s.svcCtx)
|
||||||
|
return l.CancelSubscription(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuerySubscription 查詢單一訂閱資訊
|
||||||
|
func (s *SubscriptionServiceServer) QuerySubscription(ctx context.Context, in *trade.SubscriptionQueryReq) (*trade.SubscriptionResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewQuerySubscriptionLogic(ctx, s.svcCtx)
|
||||||
|
return l.QuerySubscription(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSubscriptions 查詢所有訂閱 (用於管理和監控)
|
||||||
|
func (s *SubscriptionServiceServer) ListSubscriptions(ctx context.Context, in *trade.ListSubscriptionsReq) (*trade.SubscriptionListResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewListSubscriptionsLogic(ctx, s.svcCtx)
|
||||||
|
return l.ListSubscriptions(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenewSubscription 續訂訂閱
|
||||||
|
func (s *SubscriptionServiceServer) RenewSubscription(ctx context.Context, in *trade.SubscriptionRenewReq) (*trade.SubscriptionResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewRenewSubscriptionLogic(ctx, s.svcCtx)
|
||||||
|
return l.RenewSubscription(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckSubscriptionStatus 查詢訂閱狀態 (啟用/過期/取消)
|
||||||
|
func (s *SubscriptionServiceServer) CheckSubscriptionStatus(ctx context.Context, in *trade.SubscriptionStatusQueryReq) (*trade.SubscriptionStatusResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewCheckSubscriptionStatusLogic(ctx, s.svcCtx)
|
||||||
|
return l.CheckSubscriptionStatus(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshSubscriptionStatus cron 改變訂閱的狀態(時間到了要過期,需要續約自動續約),每 5 分鐘執行一次
|
||||||
|
func (s *SubscriptionServiceServer) RefreshSubscriptionStatus(ctx context.Context, in *trade.NoneReq) (*trade.OKResp, error) {
|
||||||
|
l := subscriptionservicelogic.NewRefreshSubscriptionStatusLogic(ctx, s.svcCtx)
|
||||||
|
return l.RefreshSubscriptionStatus(in)
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// Source: trade.proto
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
walletservicelogic "app-cloudep-trade-service/internal/logic/walletservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WalletServiceServer struct {
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
trade.UnimplementedWalletServiceServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWalletServiceServer(svcCtx *svc.ServiceContext) *WalletServiceServer {
|
||||||
|
return &WalletServiceServer{
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWallet 建立錢包
|
||||||
|
func (s *WalletServiceServer) CreateWallet(ctx context.Context, in *trade.CreateWalletReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewCreateWalletLogic(ctx, s.svcCtx)
|
||||||
|
return l.CreateWallet(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DepositFunds 充值 - 增加 [可用餘額] 或 [限制餘額]
|
||||||
|
func (s *WalletServiceServer) DepositFunds(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewDepositFundsLogic(ctx, s.svcCtx)
|
||||||
|
return l.DepositFunds(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithdrawFunds 提現 - 減少 [可用餘額]
|
||||||
|
func (s *WalletServiceServer) WithdrawFunds(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewWithdrawFundsLogic(ctx, s.svcCtx)
|
||||||
|
return l.WithdrawFunds(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FreezeFunds 凍結 - 將 [可用餘額] 減少,加到 [凍結餘額]
|
||||||
|
func (s *WalletServiceServer) FreezeFunds(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewFreezeFundsLogic(ctx, s.svcCtx)
|
||||||
|
return l.FreezeFunds(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnfreezeFunds 解凍 - 減少 [凍結餘額]
|
||||||
|
func (s *WalletServiceServer) UnfreezeFunds(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewUnfreezeFundsLogic(ctx, s.svcCtx)
|
||||||
|
return l.UnfreezeFunds(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendToFreeze 追加凍結 - 減少可用餘額,追加到現有的 [凍結餘額] (基於原order_id)
|
||||||
|
func (s *WalletServiceServer) AppendToFreeze(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewAppendToFreezeLogic(ctx, s.svcCtx)
|
||||||
|
return l.AppendToFreeze(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RollbackFreeze 凍結回滾 - 減少 [凍結餘額],加回 [可用餘額],不可指定金額,整筆訂單的凍結金額加回 [可用餘額]
|
||||||
|
func (s *WalletServiceServer) RollbackFreeze(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewRollbackFreezeLogic(ctx, s.svcCtx)
|
||||||
|
return l.RollbackFreeze(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelFreeze 取消凍結 - 減少 [凍結餘額],加回 [可用餘額],可指定金額
|
||||||
|
func (s *WalletServiceServer) CancelFreeze(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewCancelFreezeLogic(ctx, s.svcCtx)
|
||||||
|
return l.CancelFreeze(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransferToRestrictedFunds 限制 - 減少 [凍結餘額],轉移到另一個使用者的 [限制餘額]
|
||||||
|
func (s *WalletServiceServer) TransferToRestrictedFunds(ctx context.Context, in *trade.WalletTransactionReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewTransferToRestrictedFundsLogic(ctx, s.svcCtx)
|
||||||
|
return l.TransferToRestrictedFunds(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SettleRestrictedFunds 結算限制餘額 - 限制餘額在 T+N 天後自動失效,每日只能執行一次
|
||||||
|
func (s *WalletServiceServer) SettleRestrictedFunds(ctx context.Context, in *trade.NoneReq) (*trade.OKResp, error) {
|
||||||
|
l := walletservicelogic.NewSettleRestrictedFundsLogic(ctx, s.svcCtx)
|
||||||
|
return l.SettleRestrictedFunds(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryBalance 餘額查詢 -> 依照日期查詢
|
||||||
|
func (s *WalletServiceServer) QueryBalance(ctx context.Context, in *trade.QueryBalanceByDateReq) (*trade.QueryBalanceByDateResp, error) {
|
||||||
|
l := walletservicelogic.NewQueryBalanceLogic(ctx, s.svcCtx)
|
||||||
|
return l.QueryBalance(in)
|
||||||
|
}
|
|
@ -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),
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package svc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/config"
|
||||||
|
duc "app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"app-cloudep-trade-service/internal/usecase"
|
||||||
|
|
||||||
|
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
|
||||||
|
Validate vi.Validate
|
||||||
|
|
||||||
|
OrderUseCase duc.OrderUseCase
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
|
// TODO 改成 Trade
|
||||||
|
ers.Scope = code.CloudEPOrder
|
||||||
|
|
||||||
|
om := MustOrderModel(c)
|
||||||
|
orderUseCase := usecase.NewOrderUseCase(usecase.OrderUseCaseParam{
|
||||||
|
OrderModel: om,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &ServiceContext{
|
||||||
|
Config: c,
|
||||||
|
Validate: vi.MustValidator(
|
||||||
|
WithDecimalGt(),
|
||||||
|
WithDecimalGte(),
|
||||||
|
),
|
||||||
|
|
||||||
|
OrderUseCase: orderUseCase,
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,310 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
model "app-cloudep-trade-service/internal/model/mongo"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderUseCaseParam struct {
|
||||||
|
OrderModel model.OrderModel
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderUseCase struct {
|
||||||
|
OrderModel model.OrderModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrderUseCase(param OrderUseCaseParam) usecase.OrderUseCase {
|
||||||
|
return &OrderUseCase{
|
||||||
|
OrderModel: param.OrderModel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) CreateOrder(ctx context.Context, param usecase.CreateOrderReq) error {
|
||||||
|
now := time.Now().UTC().UnixNano()
|
||||||
|
// 插入資料庫
|
||||||
|
order := &model.Order{
|
||||||
|
UpdateTime: now,
|
||||||
|
CreateTime: now,
|
||||||
|
BusinessID: param.BusinessID,
|
||||||
|
OrderType: param.OrderType,
|
||||||
|
OrderStatus: param.OrderStatus,
|
||||||
|
Brand: param.Brand,
|
||||||
|
OrderUID: param.OrderUID,
|
||||||
|
ReferenceID: param.ReferenceID,
|
||||||
|
Count: param.Count,
|
||||||
|
OrderFee: param.OrderFee,
|
||||||
|
Amount: param.Amount,
|
||||||
|
ReferenceBrand: param.ReferenceBrand,
|
||||||
|
ReferenceUID: param.ReferenceUID,
|
||||||
|
WalletStatus: param.WalletStatus,
|
||||||
|
ThreePartyStatus: param.ThreePartyStatus,
|
||||||
|
DirectionType: param.DirectionType,
|
||||||
|
CryptoType: param.CryptoType,
|
||||||
|
ThirdPartyFee: param.ThirdPartyFee,
|
||||||
|
CryptoToUSDTRate: param.CryptoToUSDTRate,
|
||||||
|
FiatToUSDRate: param.FiatToUSDRate,
|
||||||
|
FeeCryptoToUSDTRate: param.FeeCryptoToUSDTRate,
|
||||||
|
USDTToCryptoTypeRate: param.USDTToCryptoTypeRate,
|
||||||
|
PaymentFiat: param.PaymentFiat,
|
||||||
|
PaymentUnitPrice: param.PaymentUnitPrice,
|
||||||
|
PaymentTemplateID: param.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: param.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: param.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: param.UnpaidTimeoutSecond,
|
||||||
|
ChainType: param.ChainType,
|
||||||
|
TxHash: param.TxHash,
|
||||||
|
FromAddress: param.FromAddress,
|
||||||
|
ToAddress: param.ToAddress,
|
||||||
|
ChainFee: param.ChainFee,
|
||||||
|
ChainFeeCrypto: param.ChainFeeCrypto,
|
||||||
|
Memo: param.Memo,
|
||||||
|
OrderNote: param.OrderNote,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := o.OrderModel.Insert(ctx, order)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// 錯誤代碼 06-021-01
|
||||||
|
e := domain.CommentErrorL(
|
||||||
|
domain.CreateOrderErrorCode,
|
||||||
|
logx.WithContext(ctx),
|
||||||
|
[]logx.LogField{
|
||||||
|
{Key: "req", Value: param},
|
||||||
|
{Key: "func", Value: "OrderModel.Insert"},
|
||||||
|
{Key: "err", Value: err},
|
||||||
|
},
|
||||||
|
"failed to insert order into mongo:").Wrap(err)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) CancelOrder(ctx context.Context, param usecase.CancelOrderQuery) error {
|
||||||
|
_, err := o.OrderModel.UpdateStatus(ctx, model.UpdateStatusReq{
|
||||||
|
BusinessID: param.BusinessID,
|
||||||
|
Status: param.Status.ToInt64(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// 錯誤代碼 06-021-02
|
||||||
|
e := domain.CommentErrorL(
|
||||||
|
domain.CancelOrderErrorCode,
|
||||||
|
logx.WithContext(ctx),
|
||||||
|
[]logx.LogField{
|
||||||
|
{Key: "req", Value: param},
|
||||||
|
{Key: "func", Value: "OrderModel.UpdateStatus"},
|
||||||
|
{Key: "err", Value: err},
|
||||||
|
},
|
||||||
|
"failed to update order status:").Wrap(err)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) DeleteOrder(ctx context.Context, param usecase.DeleteOrderQuery) error {
|
||||||
|
_, err := o.OrderModel.DeleteByBusinessID(ctx, param.BusinessID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) GetOrder(ctx context.Context, param usecase.GetOrderQuery) (*usecase.GetOrderResp, error) {
|
||||||
|
order, err := o.OrderModel.FindOneBusinessID(ctx, param.BusinessID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(mon.ErrNotFound, err) {
|
||||||
|
return nil, domain.NotFoundError(domain.DataNotFoundErrorCode, "failed to get this order id:", param.BusinessID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &usecase.GetOrderResp{
|
||||||
|
UpdateTime: order.UpdateTime,
|
||||||
|
CreateTime: order.CreateTime,
|
||||||
|
BusinessID: order.BusinessID,
|
||||||
|
OrderType: order.OrderType,
|
||||||
|
OrderStatus: order.OrderStatus,
|
||||||
|
Brand: order.Brand,
|
||||||
|
OrderUID: order.OrderUID,
|
||||||
|
ReferenceID: order.ReferenceID,
|
||||||
|
Count: order.Count.String(),
|
||||||
|
OrderFee: order.OrderFee.String(),
|
||||||
|
Amount: order.Amount.String(),
|
||||||
|
ReferenceBrand: order.ReferenceBrand,
|
||||||
|
ReferenceUID: order.ReferenceUID,
|
||||||
|
WalletStatus: Int64Ptr(order.WalletStatus),
|
||||||
|
ThreePartyStatus: order.ThreePartyStatus,
|
||||||
|
DirectionType: Int64Ptr(order.DirectionType),
|
||||||
|
CryptoType: order.CryptoType,
|
||||||
|
ThirdPartyFee: DecimalToStringPtr(order.ThirdPartyFee),
|
||||||
|
CryptoToUsdtRate: DecimalToStringPtr(order.CryptoToUSDTRate),
|
||||||
|
FiatToUsdRate: DecimalToStringPtr(order.FiatToUSDRate),
|
||||||
|
FeeCryptoToUsdtRate: DecimalToStringPtr(order.FeeCryptoToUSDTRate),
|
||||||
|
UsdtToCryptoTypeRate: DecimalToStringPtr(order.USDTToCryptoTypeRate),
|
||||||
|
PaymentFiat: order.PaymentFiat,
|
||||||
|
PaymentUnitPrice: DecimalToStringPtr(order.PaymentUnitPrice),
|
||||||
|
PaymentTemplateID: order.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: order.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: order.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: order.UnpaidTimeoutSecond,
|
||||||
|
ChainType: order.ChainType,
|
||||||
|
TxHash: order.TxHash,
|
||||||
|
FromAddress: order.FromAddress,
|
||||||
|
ToAddress: order.ToAddress,
|
||||||
|
ChainFee: DecimalToStringPtr(order.ChainFee),
|
||||||
|
ChainFeeCrypto: order.ChainFeeCrypto,
|
||||||
|
Memo: order.Memo,
|
||||||
|
OrderNote: order.OrderNote,
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) ListOrder(ctx context.Context, param usecase.GetOrderListReq) (*usecase.ListOrderResp, error) {
|
||||||
|
// 構建查詢條件
|
||||||
|
req := model.GetOrderListReq{
|
||||||
|
PageIndex: param.PageIndex,
|
||||||
|
PageSize: param.PageSize,
|
||||||
|
ReferenceID: param.ReferenceID,
|
||||||
|
ReferenceUID: param.ReferenceUID,
|
||||||
|
BusinessID: param.BusinessID,
|
||||||
|
UID: param.UID,
|
||||||
|
OrderType: param.OrderType.ToInt(),
|
||||||
|
DirectionType: param.DirectionType,
|
||||||
|
OrderStatus: param.OrderStatus,
|
||||||
|
StartCreateTime: param.StartCreateTime,
|
||||||
|
EndCreateTime: param.EndCreateTime,
|
||||||
|
StartUpdateTime: param.StartUpdateTime,
|
||||||
|
EndUpdateTime: param.EndUpdateTime,
|
||||||
|
StartOrderArrivalTime: param.StartOrderArrivalTime,
|
||||||
|
EndOrderArrivalTime: param.EndOrderArrivalTime,
|
||||||
|
StartOrderPaymentTime: param.StartOrderPaymentTime,
|
||||||
|
EndOrderPaymentTime: param.EndOrderPaymentTime,
|
||||||
|
CryptoType: param.CryptoType,
|
||||||
|
TxHash: param.TxHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查詢訂單
|
||||||
|
orders, total, err := o.OrderModel.ListOrder(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &usecase.ListOrderResp{
|
||||||
|
Data: o.convertOrdersToResponses(orders),
|
||||||
|
Page: &usecase.Pager{
|
||||||
|
Total: total,
|
||||||
|
Index: param.PageIndex,
|
||||||
|
Size: param.PageSize,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) ModifyOrderStatus(ctx context.Context, param *usecase.ModifyOrderQuery) error {
|
||||||
|
_, err := o.OrderModel.UpdateStatus(ctx,
|
||||||
|
model.UpdateStatusReq{
|
||||||
|
BusinessID: param.BusinessID,
|
||||||
|
Status: param.Status,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
// 錯誤代碼 06-021-02
|
||||||
|
e := domain.CommentErrorL(
|
||||||
|
domain.ModifyOrderErrorCode,
|
||||||
|
logx.WithContext(ctx),
|
||||||
|
[]logx.LogField{
|
||||||
|
{Key: "req", Value: param},
|
||||||
|
{Key: "func", Value: "OrderModel.UpdateStatus"},
|
||||||
|
{Key: "err", Value: err},
|
||||||
|
},
|
||||||
|
"failed to update order status:").Wrap(err)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderUseCase) OrderStatusTimeout(ctx context.Context) error {
|
||||||
|
now := time.Now().UTC().UnixNano()
|
||||||
|
_, err := o.OrderModel.UpdateTimeoutOrder(ctx, model.UpdateTimeoutReq{
|
||||||
|
CreateTimeBefore: now,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
// 錯誤代碼 06-021-02
|
||||||
|
e := domain.CommentErrorL(
|
||||||
|
domain.TimeoutOrderErrorCode,
|
||||||
|
logx.WithContext(ctx),
|
||||||
|
[]logx.LogField{
|
||||||
|
{Key: "now", Value: now},
|
||||||
|
{Key: "func", Value: "OrderModel.UpdateTimeoutOrder"},
|
||||||
|
{Key: "err", Value: err},
|
||||||
|
},
|
||||||
|
"failed to update timeout order").Wrap(err)
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= 工具類區 =================
|
||||||
|
|
||||||
|
func (o *OrderUseCase) convertOrdersToResponses(orders []model.Order) []*usecase.GetOrderResp {
|
||||||
|
res := make([]*usecase.GetOrderResp, 0, len(orders))
|
||||||
|
for _, order := range orders {
|
||||||
|
resp := &usecase.GetOrderResp{
|
||||||
|
UpdateTime: order.UpdateTime,
|
||||||
|
CreateTime: order.CreateTime,
|
||||||
|
BusinessID: order.BusinessID,
|
||||||
|
OrderType: order.OrderType,
|
||||||
|
OrderStatus: order.OrderStatus,
|
||||||
|
Brand: order.Brand,
|
||||||
|
OrderUID: order.OrderUID,
|
||||||
|
ReferenceID: order.ReferenceID,
|
||||||
|
Count: order.Count.String(),
|
||||||
|
OrderFee: order.OrderFee.String(),
|
||||||
|
Amount: order.Amount.String(),
|
||||||
|
ReferenceBrand: order.ReferenceBrand,
|
||||||
|
ReferenceUID: order.ReferenceUID,
|
||||||
|
WalletStatus: Int64Ptr(order.WalletStatus),
|
||||||
|
ThreePartyStatus: order.ThreePartyStatus,
|
||||||
|
DirectionType: Int64Ptr(order.DirectionType),
|
||||||
|
CryptoType: order.CryptoType,
|
||||||
|
ThirdPartyFee: DecimalToStringPtr(order.ThirdPartyFee),
|
||||||
|
CryptoToUsdtRate: DecimalToStringPtr(order.CryptoToUSDTRate),
|
||||||
|
FiatToUsdRate: DecimalToStringPtr(order.FiatToUSDRate),
|
||||||
|
FeeCryptoToUsdtRate: DecimalToStringPtr(order.FeeCryptoToUSDTRate),
|
||||||
|
UsdtToCryptoTypeRate: DecimalToStringPtr(order.USDTToCryptoTypeRate),
|
||||||
|
PaymentFiat: order.PaymentFiat,
|
||||||
|
PaymentUnitPrice: DecimalToStringPtr(order.PaymentUnitPrice),
|
||||||
|
PaymentTemplateID: order.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: order.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: order.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: order.UnpaidTimeoutSecond,
|
||||||
|
ChainType: order.ChainType,
|
||||||
|
TxHash: order.TxHash,
|
||||||
|
FromAddress: order.FromAddress,
|
||||||
|
ToAddress: order.ToAddress,
|
||||||
|
ChainFee: DecimalToStringPtr(order.ChainFee),
|
||||||
|
ChainFeeCrypto: order.ChainFeeCrypto,
|
||||||
|
Memo: order.Memo,
|
||||||
|
OrderNote: order.OrderNote,
|
||||||
|
}
|
||||||
|
res = append(res, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
|
@ -0,0 +1,500 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
"app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
mockmodel "app-cloudep-trade-service/internal/mock/model"
|
||||||
|
model "app-cloudep-trade-service/internal/model/mongo"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-playground/assert/v2"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOrderUseCase_CancelOrder(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
// 初始化 mock 依賴
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||||
|
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelOrderQuery := usecase.CancelOrderQuery{
|
||||||
|
BusinessID: "business_123",
|
||||||
|
Status: domain.OrderStatusCancelled, // 使用模擬的狀態
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
param usecase.CancelOrderQuery
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful order cancellation",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{
|
||||||
|
BusinessID: cancelOrderQuery.BusinessID,
|
||||||
|
Status: cancelOrderQuery.Status.ToInt64(),
|
||||||
|
}).Return(nil, nil)
|
||||||
|
},
|
||||||
|
param: cancelOrderQuery,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "failed order cancellation",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{
|
||||||
|
BusinessID: cancelOrderQuery.BusinessID,
|
||||||
|
Status: cancelOrderQuery.Status.ToInt64(),
|
||||||
|
}).Return(nil, errors.New("update error"))
|
||||||
|
},
|
||||||
|
param: cancelOrderQuery,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup() // 設置每個測試用例的 mock 行為
|
||||||
|
err := orderUseCase.CancelOrder(context.Background(), tt.param)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("CancelOrder() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderUseCase_CreateOrder(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
// 初始化 mock 依賴
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl)
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now().UTC().UnixNano()
|
||||||
|
|
||||||
|
// 構建測試參數
|
||||||
|
createOrderReq := usecase.CreateOrderReq{
|
||||||
|
BusinessID: "business_123",
|
||||||
|
OrderType: domain.OrderTypeTest,
|
||||||
|
OrderStatus: domain.OrderStatusCreated,
|
||||||
|
Brand: "test_brand",
|
||||||
|
OrderUID: "user_123",
|
||||||
|
ReferenceID: "reference_123",
|
||||||
|
Count: decimal.NewFromInt(2),
|
||||||
|
OrderFee: decimal.NewFromFloat(0.01),
|
||||||
|
Amount: decimal.NewFromFloat(100.0),
|
||||||
|
ReferenceBrand: StringPtr("reference_brand"),
|
||||||
|
ReferenceUID: StringPtr("reference_uid"),
|
||||||
|
WalletStatus: 1,
|
||||||
|
ThreePartyStatus: Int64Ptr(2),
|
||||||
|
DirectionType: 1,
|
||||||
|
CryptoType: StringPtr("BTC"),
|
||||||
|
PaymentFiat: StringPtr("USD"),
|
||||||
|
PaymentTemplateID: StringPtr("template_001"),
|
||||||
|
OrderArrivalTime: Int64Ptr(now),
|
||||||
|
OrderPaymentTime: Int64Ptr(now),
|
||||||
|
UnpaidTimeoutSecond: Int64Ptr(3600),
|
||||||
|
ChainType: StringPtr("mainnet"),
|
||||||
|
TxHash: StringPtr("tx_hash_123"),
|
||||||
|
FromAddress: StringPtr("from_address"),
|
||||||
|
ToAddress: StringPtr("to_address"),
|
||||||
|
ChainFeeCrypto: StringPtr("ETH"),
|
||||||
|
Memo: StringPtr("test memo"),
|
||||||
|
OrderNote: StringPtr("test order note"),
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
param usecase.CreateOrderReq
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful order creation",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(nil)
|
||||||
|
},
|
||||||
|
param: createOrderReq,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "failed order creation",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().Insert(gomock.Any(), gomock.Any()).Return(errors.New("insert error"))
|
||||||
|
},
|
||||||
|
param: createOrderReq,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup() // 設置每個測試用例的 mock 行為
|
||||||
|
err := orderUseCase.CreateOrder(context.Background(), tt.param)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("CreateOrder() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderUseCase_DeleteOrder(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
// 初始化 mock 依賴
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(ctrl)
|
||||||
|
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 構建測試參數
|
||||||
|
deleteOrderQuery := usecase.DeleteOrderQuery{
|
||||||
|
BusinessID: "business_123",
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
param usecase.DeleteOrderQuery
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful order deletion",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().DeleteByBusinessID(gomock.Any(), deleteOrderQuery.BusinessID).Return(nil, nil)
|
||||||
|
},
|
||||||
|
param: deleteOrderQuery,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "failed order deletion",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().DeleteByBusinessID(gomock.Any(), deleteOrderQuery.BusinessID).Return(nil, errors.New("delete error"))
|
||||||
|
},
|
||||||
|
param: deleteOrderQuery,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup() // 設置每個測試用例的 mock 行為
|
||||||
|
err := orderUseCase.DeleteOrder(context.Background(), tt.param)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("DeleteOrder() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderUseCase_GetOrder(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
// 初始化 mock 依賴
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl)
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrderQuery := usecase.GetOrderQuery{
|
||||||
|
BusinessID: "business_123",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 構建測試用例返回的 Order
|
||||||
|
mockOrder := &model.Order{
|
||||||
|
UpdateTime: 123456789,
|
||||||
|
CreateTime: 123456789,
|
||||||
|
BusinessID: "business_123",
|
||||||
|
OrderType: domain.OrderTypeTest,
|
||||||
|
OrderStatus: domain.OrderStatusCreated,
|
||||||
|
Brand: "test_brand",
|
||||||
|
OrderUID: "user_123",
|
||||||
|
ReferenceID: "reference_123",
|
||||||
|
Count: decimal.NewFromInt(2),
|
||||||
|
OrderFee: decimal.NewFromFloat(0.01),
|
||||||
|
Amount: decimal.NewFromFloat(100.0),
|
||||||
|
ReferenceBrand: StringPtr("reference_brand"),
|
||||||
|
ReferenceUID: StringPtr("reference_uid"),
|
||||||
|
WalletStatus: 1,
|
||||||
|
ThreePartyStatus: Int64Ptr(2),
|
||||||
|
DirectionType: 1,
|
||||||
|
CryptoType: StringPtr("BTC"),
|
||||||
|
PaymentFiat: StringPtr("USD"),
|
||||||
|
PaymentTemplateID: StringPtr("template_001"),
|
||||||
|
OrderArrivalTime: Int64Ptr(123456789),
|
||||||
|
OrderPaymentTime: Int64Ptr(123456789),
|
||||||
|
UnpaidTimeoutSecond: Int64Ptr(3600),
|
||||||
|
ChainType: StringPtr("mainnet"),
|
||||||
|
TxHash: StringPtr("tx_hash_123"),
|
||||||
|
FromAddress: StringPtr("from_address"),
|
||||||
|
ToAddress: StringPtr("to_address"),
|
||||||
|
ChainFeeCrypto: StringPtr("ETH"),
|
||||||
|
Memo: StringPtr("test memo"),
|
||||||
|
OrderNote: StringPtr("test order note"),
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
param usecase.GetOrderQuery
|
||||||
|
wantResp *usecase.GetOrderResp
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful order retrieval",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), getOrderQuery.BusinessID).Return(mockOrder, nil)
|
||||||
|
},
|
||||||
|
param: getOrderQuery,
|
||||||
|
wantResp: &usecase.GetOrderResp{ // 构建预期响应
|
||||||
|
UpdateTime: mockOrder.UpdateTime,
|
||||||
|
CreateTime: mockOrder.CreateTime,
|
||||||
|
BusinessID: mockOrder.BusinessID,
|
||||||
|
OrderType: mockOrder.OrderType,
|
||||||
|
OrderStatus: mockOrder.OrderStatus,
|
||||||
|
Brand: mockOrder.Brand,
|
||||||
|
OrderUID: mockOrder.OrderUID,
|
||||||
|
ReferenceID: mockOrder.ReferenceID,
|
||||||
|
Count: mockOrder.Count.String(),
|
||||||
|
OrderFee: mockOrder.OrderFee.String(),
|
||||||
|
Amount: mockOrder.Amount.String(),
|
||||||
|
ReferenceBrand: mockOrder.ReferenceBrand,
|
||||||
|
ReferenceUID: mockOrder.ReferenceUID,
|
||||||
|
WalletStatus: Int64Ptr(mockOrder.WalletStatus),
|
||||||
|
ThreePartyStatus: mockOrder.ThreePartyStatus,
|
||||||
|
DirectionType: Int64Ptr(mockOrder.DirectionType),
|
||||||
|
CryptoType: mockOrder.CryptoType,
|
||||||
|
PaymentFiat: mockOrder.PaymentFiat,
|
||||||
|
PaymentTemplateID: mockOrder.PaymentTemplateID,
|
||||||
|
OrderArrivalTime: mockOrder.OrderArrivalTime,
|
||||||
|
OrderPaymentTime: mockOrder.OrderPaymentTime,
|
||||||
|
UnpaidTimeoutSecond: mockOrder.UnpaidTimeoutSecond,
|
||||||
|
ChainType: mockOrder.ChainType,
|
||||||
|
TxHash: mockOrder.TxHash,
|
||||||
|
FromAddress: mockOrder.FromAddress,
|
||||||
|
ToAddress: mockOrder.ToAddress,
|
||||||
|
ChainFeeCrypto: mockOrder.ChainFeeCrypto,
|
||||||
|
Memo: mockOrder.Memo,
|
||||||
|
OrderNote: mockOrder.OrderNote,
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "order not found",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), getOrderQuery.BusinessID).Return(nil, mon.ErrNotFound)
|
||||||
|
},
|
||||||
|
param: getOrderQuery,
|
||||||
|
wantResp: nil,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "database error",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().FindOneBusinessID(gomock.Any(), getOrderQuery.BusinessID).Return(nil, errors.New("database error"))
|
||||||
|
},
|
||||||
|
param: getOrderQuery,
|
||||||
|
wantResp: nil,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup() // 設置每個測試用例的 mock 行為
|
||||||
|
resp, err := orderUseCase.GetOrder(context.Background(), tt.param)
|
||||||
|
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("GetOrder() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.wantResp, resp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderUseCase_ListOrder(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl)
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
listOrderQuery := usecase.GetOrderListReq{
|
||||||
|
PageIndex: 1,
|
||||||
|
PageSize: 10,
|
||||||
|
BusinessID: "business_123",
|
||||||
|
OrderStatus: []int64{int64(domain.OrderStatusCreated)},
|
||||||
|
}
|
||||||
|
|
||||||
|
mockOrders := []model.Order{
|
||||||
|
{
|
||||||
|
BusinessID: "business_123",
|
||||||
|
OrderUID: "user_123",
|
||||||
|
OrderStatus: domain.OrderStatusCreated,
|
||||||
|
// 其他欄位根據需要填充
|
||||||
|
},
|
||||||
|
}
|
||||||
|
mockTotal := int64(1)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
param usecase.GetOrderListReq
|
||||||
|
wantResp *usecase.ListOrderResp
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful order listing",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().ListOrder(gomock.Any(), gomock.Any()).Return(mockOrders, mockTotal, nil)
|
||||||
|
},
|
||||||
|
param: listOrderQuery,
|
||||||
|
wantResp: &usecase.ListOrderResp{
|
||||||
|
Data: orderUseCase.convertOrdersToResponses(mockOrders),
|
||||||
|
Page: &usecase.Pager{
|
||||||
|
Total: mockTotal,
|
||||||
|
Index: listOrderQuery.PageIndex,
|
||||||
|
Size: listOrderQuery.PageSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "order listing error",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().ListOrder(gomock.Any(), gomock.Any()).Return(nil, int64(0), errors.New("listing error"))
|
||||||
|
},
|
||||||
|
param: listOrderQuery,
|
||||||
|
wantResp: nil,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup()
|
||||||
|
resp, err := orderUseCase.ListOrder(context.Background(), tt.param)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ListOrder() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.wantResp, resp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderUseCase_ModifyOrderStatus(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl)
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyOrderQuery := &usecase.ModifyOrderQuery{
|
||||||
|
BusinessID: "business_123",
|
||||||
|
Status: int64(domain.OrderStatusCancelled),
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
param *usecase.ModifyOrderQuery
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful order status modification",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{
|
||||||
|
BusinessID: modifyOrderQuery.BusinessID,
|
||||||
|
Status: modifyOrderQuery.Status,
|
||||||
|
}).Return(nil, nil)
|
||||||
|
},
|
||||||
|
param: modifyOrderQuery,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "order status modification error",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().UpdateStatus(gomock.Any(), model.UpdateStatusReq{
|
||||||
|
BusinessID: modifyOrderQuery.BusinessID,
|
||||||
|
Status: modifyOrderQuery.Status,
|
||||||
|
}).Return(nil, errors.New("update error"))
|
||||||
|
},
|
||||||
|
param: modifyOrderQuery,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup()
|
||||||
|
err := orderUseCase.ModifyOrderStatus(context.Background(), tt.param)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ModifyOrderStatus() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrderUseCase_OrderStatusTimeout(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
mockOrderModel := mockmodel.NewMockOrderModel(mockCtrl)
|
||||||
|
orderUseCase := &OrderUseCase{
|
||||||
|
OrderModel: mockOrderModel,
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
mockSetup func()
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful timeout update",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().UpdateTimeoutOrder(gomock.Any(), gomock.Any()).Return(nil, nil)
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "timeout update error",
|
||||||
|
mockSetup: func() {
|
||||||
|
mockOrderModel.EXPECT().UpdateTimeoutOrder(gomock.Any(), gomock.Any()).Return(nil, errors.New("timeout error"))
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.mockSetup()
|
||||||
|
err := orderUseCase.OrderStatusTimeout(context.Background())
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("OrderStatusTimeout() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
import "github.com/shopspring/decimal"
|
||||||
|
|
||||||
|
// Int64Ptr 將 int64 類型轉為 *int64,若值為 0 則返回 nil
|
||||||
|
func Int64Ptr(val int64) *int64 {
|
||||||
|
if val == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecimalToStringPtr 將 decimal.Decimal 指標轉換為 *string,若為 nil 則返回 nil
|
||||||
|
func DecimalToStringPtr(val *decimal.Decimal) *string {
|
||||||
|
if val == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
str := val.String()
|
||||||
|
|
||||||
|
return &str
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringPtr 將 *string 或其他欄位直接返回(適合用於已是指標的欄位)
|
||||||
|
func StringPtr(val string) *string {
|
||||||
|
if val == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &val
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-playground/assert/v2"
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 測試 Int64Ptr 函數
|
||||||
|
func TestInt64Ptr(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
val int64
|
||||||
|
want *int64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "non-zero value",
|
||||||
|
val: 123,
|
||||||
|
want: func() *int64 { v := int64(123); return &v }(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "zero value",
|
||||||
|
val: 0,
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := Int64Ptr(tt.val)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 測試 DecimalToStringPtr 函數
|
||||||
|
func TestDecimalToStringPtr(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
val *decimal.Decimal
|
||||||
|
want *string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "non-nil decimal",
|
||||||
|
val: func() *decimal.Decimal { d := decimal.NewFromFloat(123.45); return &d }(),
|
||||||
|
want: func() *string { s := "123.45"; return &s }(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil decimal",
|
||||||
|
val: nil,
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := DecimalToStringPtr(tt.val)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 測試 StringPtr 函數
|
||||||
|
func TestStringPtr(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
val string
|
||||||
|
want *string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "non-empty string",
|
||||||
|
val: "test",
|
||||||
|
want: func() *string { s := "test"; return &s }(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty string",
|
||||||
|
val: "",
|
||||||
|
want: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := StringPtr(tt.val)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
|
||||||
|
"app-cloudep-trade-service/gen_result/pb/trade"
|
||||||
|
"app-cloudep-trade-service/internal/config"
|
||||||
|
couponserviceServer "app-cloudep-trade-service/internal/server/couponservice"
|
||||||
|
inventoryserviceServer "app-cloudep-trade-service/internal/server/inventoryservice"
|
||||||
|
orderserviceServer "app-cloudep-trade-service/internal/server/orderservice"
|
||||||
|
productserviceServer "app-cloudep-trade-service/internal/server/productservice"
|
||||||
|
subscriptionserviceServer "app-cloudep-trade-service/internal/server/subscriptionservice"
|
||||||
|
walletserviceServer "app-cloudep-trade-service/internal/server/walletservice"
|
||||||
|
"app-cloudep-trade-service/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/conf"
|
||||||
|
"github.com/zeromicro/go-zero/core/service"
|
||||||
|
"github.com/zeromicro/go-zero/zrpc"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/reflection"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configFile = flag.String("f", "etc/trade.yaml", "the config file")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var c config.Config
|
||||||
|
conf.MustLoad(*configFile, &c)
|
||||||
|
ctx := svc.NewServiceContext(c)
|
||||||
|
|
||||||
|
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
||||||
|
trade.RegisterOrderServiceServer(grpcServer, orderserviceServer.NewOrderServiceServer(ctx))
|
||||||
|
trade.RegisterWalletServiceServer(grpcServer, walletserviceServer.NewWalletServiceServer(ctx))
|
||||||
|
trade.RegisterInventoryServiceServer(grpcServer, inventoryserviceServer.NewInventoryServiceServer(ctx))
|
||||||
|
trade.RegisterProductServiceServer(grpcServer, productserviceServer.NewProductServiceServer(ctx))
|
||||||
|
trade.RegisterSubscriptionServiceServer(grpcServer, subscriptionserviceServer.NewSubscriptionServiceServer(ctx))
|
||||||
|
trade.RegisterCouponServiceServer(grpcServer, couponserviceServer.NewCouponServiceServer(ctx))
|
||||||
|
|
||||||
|
if c.Mode == service.DevMode || c.Mode == service.TestMode {
|
||||||
|
reflection.Register(grpcServer)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
logx.Infof("Starting rpc server at %s...\n", c.ListenOn)
|
||||||
|
s.Start()
|
||||||
|
}
|
Loading…
Reference in New Issue