add wallet database
This commit is contained in:
parent
96377d8edb
commit
8687e467c9
11
Makefile
11
Makefile
|
@ -62,3 +62,14 @@ mock-gen: # 建立 mock 資料
|
||||||
.PHONY: migrate-database
|
.PHONY: migrate-database
|
||||||
migrate-database:
|
migrate-database:
|
||||||
migrate -source file://generate/database/mongodb -database 'mongodb://127.0.0.1:27017/digimon_order' up
|
migrate -source file://generate/database/mongodb -database 'mongodb://127.0.0.1:27017/digimon_order' up
|
||||||
|
|
||||||
|
.PHONY: gen-my-sql-model
|
||||||
|
gen-my-sql-model: # 建立 rpc 資料庫
|
||||||
|
goctl model mysql ddl -s ./generate/database/mysql/20230626063528_create_wallet_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i ''
|
||||||
|
goctl model mysql ddl -s ./generate/database/mysql/20230626065705_create_transaction_table.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i ''
|
||||||
|
goctl model mysql ddl -s ./generate/database/mysql/20230913072305_create_wallet_transaction.up.sql --style $(GO_ZERO_STYLE) -d ./internal/model -i ''
|
||||||
|
@echo "Generate mysql model files successfully"
|
||||||
|
|
||||||
|
.PHONY: migrate-database
|
||||||
|
migrate-database:
|
||||||
|
migrate -source file://generate/database/mysql -database 'mysql://root:yytt@tcp(127.0.0.1:3306)/digimon_wallet' up
|
||||||
|
|
|
@ -27,3 +27,15 @@ Mongo:
|
||||||
MaxPoolSize: 30
|
MaxPoolSize: 30
|
||||||
MinPoolSize: 10
|
MinPoolSize: 10
|
||||||
MaxConnIdleTime: 30m
|
MaxConnIdleTime: 30m
|
||||||
|
|
||||||
|
DB:
|
||||||
|
Host: 127.0.0.1
|
||||||
|
Port: 3306
|
||||||
|
User: username
|
||||||
|
Password: password
|
||||||
|
name: permission
|
||||||
|
MaxIdleConns: 10
|
||||||
|
MaxOpenConns: 200
|
||||||
|
ConnMaxLifetime: 10s
|
||||||
|
InterpolateParams: false
|
||||||
|
Database: digimon_wallet
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS `wallet`;
|
|
@ -0,0 +1,13 @@
|
||||||
|
CREATE TABLE `wallet` (
|
||||||
|
`id` BIGINT(20) AUTO_INCREMENT NOT NULL COMMENT '錢包流水號',
|
||||||
|
`uid` VARCHAR(50) NOT NULL COMMENT '用戶ID',
|
||||||
|
`brand` VARCHAR(50) DEFAULT '' NOT NULL COMMENT '品牌名稱',
|
||||||
|
`currency` VARCHAR(20) NOT NULL COMMENT '幣別(或平台點數)',
|
||||||
|
`balance` DECIMAL(30, 18) UNSIGNED DEFAULT 0 NOT NULL COMMENT '錢包餘額',
|
||||||
|
`wallet_type` TINYINT NOT NULL COMMENT '錢包種類: 1=可用, 2=凍結, 3=限制(僅出金)',
|
||||||
|
`created_at` BIGINT NOT NULL COMMENT '創建時間',
|
||||||
|
`updated_at` BIGINT NOT NULL COMMENT '更新時間',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `uq_user_currency_type` (`uid`, `currency`, `wallet_type`),
|
||||||
|
INDEX `idx_user_currency` (`uid`, `currency`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶錢包';
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS `transaction`;
|
|
@ -0,0 +1,20 @@
|
||||||
|
CREATE TABLE `transaction` (
|
||||||
|
`id` BIGINT(20) AUTO_INCREMENT NOT NULL COMMENT '交易流水號',
|
||||||
|
`tx_id` VARCHAR(200) NOT NULL COMMENT '交易 ID',
|
||||||
|
`order_id` VARCHAR(200) NOT NULL COMMENT '訂單 ID',
|
||||||
|
`brand` VARCHAR(50) NOT NULL COMMENT '品牌名稱',
|
||||||
|
`uid` VARCHAR(50) NOT NULL COMMENT '發起 UID',
|
||||||
|
`to_uid` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '接收方UID',
|
||||||
|
`type` TINYINT NOT NULL COMMENT '交易類型: 1=提現, 2=充值',
|
||||||
|
`business_type` TINYINT NOT NULL COMMENT '業務類型',
|
||||||
|
`currency` VARCHAR(20) NOT NULL COMMENT '幣種',
|
||||||
|
`amount` DECIMAL(30, 18) UNSIGNED DEFAULT 0 NOT NULL COMMENT '交易金額',
|
||||||
|
`balance` DECIMAL(30, 18) UNSIGNED DEFAULT 0 NOT NULL COMMENT '交易後餘額',
|
||||||
|
`before_balance` DECIMAL(30, 18) UNSIGNED DEFAULT 0 NOT NULL COMMENT '交易前餘額',
|
||||||
|
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '結算狀態',
|
||||||
|
`create_time` BIGINT NOT NULL COMMENT '創建時間(Unix 時間戳,毫秒)',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `uk_order_id_type` (`order_id`, `type`),
|
||||||
|
INDEX `idx_uid` (`uid`),
|
||||||
|
INDEX `idx_order_id` (`order_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶錢包交異動紀錄';
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE IF EXISTS `wallet_transaction`;
|
|
@ -0,0 +1,19 @@
|
||||||
|
CREATE TABLE `wallet_journal` (
|
||||||
|
`id` BIGINT(20) AUTO_INCREMENT NOT NULL COMMENT '錢包賬本流水號',
|
||||||
|
`transaction_id` BIGINT(20) NOT NULL COMMENT '交易 ID,對應 transaction 表',
|
||||||
|
`order_id` VARCHAR(200) NOT NULL COMMENT '訂單 ID,對應 order 表',
|
||||||
|
`brand` VARCHAR(50) NOT NULL COMMENT '品牌名稱',
|
||||||
|
`uid` VARCHAR(50) NOT NULL COMMENT '用戶 ID',
|
||||||
|
`wallet_type` TINYINT NOT NULL COMMENT '餘額種類: 1=可用, 2=凍結, 3=限制(僅出金)',
|
||||||
|
`currency` VARCHAR(20) NOT NULL COMMENT '幣種或平台點數',
|
||||||
|
`transaction_amount` DECIMAL(30, 18) UNSIGNED DEFAULT 0 NOT NULL COMMENT '交易金額',
|
||||||
|
`post_transaction_balance` DECIMAL(30, 18) UNSIGNED DEFAULT 0 NOT NULL COMMENT '交易後餘額',
|
||||||
|
`business_type` TINYINT NOT NULL COMMENT '業務類型',
|
||||||
|
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '狀態',
|
||||||
|
`due_time` BIGINT NOT NULL DEFAULT 0 COMMENT 'T+N 執行時間',
|
||||||
|
`created_at` BIGINT NOT NULL COMMENT '創建時間(Unix 時間戳,毫秒)',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_user_brand` (`uid`, `brand`),
|
||||||
|
KEY `idx_order_id` (`order_id`),
|
||||||
|
KEY `idx_status` (`status`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶錢包變動';
|
|
@ -0,0 +1 @@
|
||||||
|
DROP DATABASE IF EXISTS `digimon_wallet`;
|
|
@ -0,0 +1 @@
|
||||||
|
CREATE DATABASE IF NOT EXISTS `digimon_wallet`;
|
2
go.mod
2
go.mod
|
@ -16,6 +16,7 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
@ -33,6 +34,7 @@ require (
|
||||||
github.com/go-openapi/swag v0.22.4 // indirect
|
github.com/go-openapi/swag v0.22.4 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
|
|
@ -24,4 +24,16 @@ type Config struct {
|
||||||
// Compressors []string
|
// Compressors []string
|
||||||
// EnableStandardReadWriteSplitMode bool
|
// EnableStandardReadWriteSplitMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DB struct {
|
||||||
|
User string
|
||||||
|
Password string
|
||||||
|
Host string
|
||||||
|
Port int64
|
||||||
|
Database string
|
||||||
|
MaxIdleConns int
|
||||||
|
MaxOpenConns int
|
||||||
|
ConnMaxLifetime time.Duration
|
||||||
|
InterpolateParams bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
package usecase
|
||||||
|
|
||||||
|
type WalletUseCase interface {
|
||||||
|
}
|
|
@ -2,23 +2,8 @@ package orderservicelogic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/shopspring/decimal"
|
"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
|
// getInt64Value 將 *int64 的值返回,如果為 nil 則返回 0
|
||||||
func getInt64Value(val *int64) int64 {
|
func getInt64Value(val *int64) int64 {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ TransactionModel = (*customTransactionModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// TransactionModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customTransactionModel.
|
||||||
|
TransactionModel interface {
|
||||||
|
transactionModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customTransactionModel struct {
|
||||||
|
*defaultTransactionModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewTransactionModel returns a model for the database table.
|
||||||
|
func NewTransactionModel(conn sqlx.SqlConn) TransactionModel {
|
||||||
|
return &customTransactionModel{
|
||||||
|
defaultTransactionModel: newTransactionModel(conn),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
transactionFieldNames = builder.RawFieldNames(&Transaction{})
|
||||||
|
transactionRows = strings.Join(transactionFieldNames, ",")
|
||||||
|
transactionRowsExpectAutoSet = strings.Join(stringx.Remove(transactionFieldNames, "`id`"), ",")
|
||||||
|
transactionRowsWithPlaceHolder = strings.Join(stringx.Remove(transactionFieldNames, "`id`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
transactionModel interface {
|
||||||
|
Insert(ctx context.Context, data *Transaction) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*Transaction, error)
|
||||||
|
FindOneByOrderIdType(ctx context.Context, orderId string, tp int64) (*Transaction, error)
|
||||||
|
Update(ctx context.Context, data *Transaction) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultTransactionModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction struct {
|
||||||
|
Id int64 `db:"id"` // 交易流水號
|
||||||
|
TxId string `db:"tx_id"` // 交易 ID
|
||||||
|
OrderId string `db:"order_id"` // 訂單 ID
|
||||||
|
Brand string `db:"brand"` // 品牌名稱
|
||||||
|
Uid string `db:"uid"` // 發起 UID
|
||||||
|
ToUid string `db:"to_uid"` // 接收方UID
|
||||||
|
Type int64 `db:"type"` // 交易類型: 1=提現, 2=充值
|
||||||
|
BusinessType int64 `db:"business_type"` // 業務類型
|
||||||
|
Currency string `db:"currency"` // 幣種
|
||||||
|
Amount float64 `db:"amount"` // 交易金額
|
||||||
|
Balance float64 `db:"balance"` // 交易後餘額
|
||||||
|
BeforeBalance float64 `db:"before_balance"` // 交易前餘額
|
||||||
|
Status int64 `db:"status"` // 結算狀態
|
||||||
|
CreateTime int64 `db:"create_time"` // 創建時間(Unix 時間戳,毫秒)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTransactionModel(conn sqlx.SqlConn) *defaultTransactionModel {
|
||||||
|
return &defaultTransactionModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`transaction`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) withSession(session sqlx.Session) *defaultTransactionModel {
|
||||||
|
return &defaultTransactionModel{
|
||||||
|
conn: sqlx.NewSqlConnFromSession(session),
|
||||||
|
table: "`transaction`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) FindOne(ctx context.Context, id int64) (*Transaction, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", transactionRows, m.table)
|
||||||
|
var resp Transaction
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) FindOneByOrderIdType(ctx context.Context, orderId string, tp int64) (*Transaction, error) {
|
||||||
|
var resp Transaction
|
||||||
|
query := fmt.Sprintf("select %s from %s where `order_id` = ? and `type` = ? limit 1", transactionRows, m.table)
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, orderId, tp)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) Insert(ctx context.Context, data *Transaction) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, transactionRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.TxId, data.OrderId, data.Brand, data.Uid, data.ToUid, data.Type, data.BusinessType, data.Currency, data.Amount, data.Balance, data.BeforeBalance, data.Status, data.CreateTime)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) Update(ctx context.Context, newData *Transaction) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, transactionRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, newData.TxId, newData.OrderId, newData.Brand, newData.Uid, newData.ToUid, newData.Type, newData.BusinessType, newData.Currency, newData.Amount, newData.Balance, newData.BeforeBalance, newData.Status, newData.CreateTime, newData.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultTransactionModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var ErrNotFound = sqlx.ErrNotFound
|
|
@ -0,0 +1,24 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ WalletJournalModel = (*customWalletJournalModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// WalletJournalModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customWalletJournalModel.
|
||||||
|
WalletJournalModel interface {
|
||||||
|
walletJournalModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customWalletJournalModel struct {
|
||||||
|
*defaultWalletJournalModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWalletJournalModel returns a model for the database table.
|
||||||
|
func NewWalletJournalModel(conn sqlx.SqlConn) WalletJournalModel {
|
||||||
|
return &customWalletJournalModel{
|
||||||
|
defaultWalletJournalModel: newWalletJournalModel(conn),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
walletJournalFieldNames = builder.RawFieldNames(&WalletJournal{})
|
||||||
|
walletJournalRows = strings.Join(walletJournalFieldNames, ",")
|
||||||
|
walletJournalRowsExpectAutoSet = strings.Join(stringx.Remove(walletJournalFieldNames, "`id`"), ",")
|
||||||
|
walletJournalRowsWithPlaceHolder = strings.Join(stringx.Remove(walletJournalFieldNames, "`id`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
walletJournalModel interface {
|
||||||
|
Insert(ctx context.Context, data *WalletJournal) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*WalletJournal, error)
|
||||||
|
Update(ctx context.Context, data *WalletJournal) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultWalletJournalModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
WalletJournal struct {
|
||||||
|
Id int64 `db:"id"` // 錢包賬本流水號
|
||||||
|
TransactionId int64 `db:"transaction_id"` // 交易 ID,對應 transaction 表
|
||||||
|
OrderId string `db:"order_id"` // 訂單 ID,對應 order 表
|
||||||
|
Brand string `db:"brand"` // 品牌名稱
|
||||||
|
Uid string `db:"uid"` // 用戶 ID
|
||||||
|
WalletType int64 `db:"wallet_type"` // 餘額種類: 1=可用, 2=凍結, 3=限制(僅出金)
|
||||||
|
Currency string `db:"currency"` // 幣種或平台點數
|
||||||
|
TransactionAmount float64 `db:"transaction_amount"` // 交易金額
|
||||||
|
PostTransactionBalance float64 `db:"post_transaction_balance"` // 交易後餘額
|
||||||
|
BusinessType int64 `db:"business_type"` // 業務類型
|
||||||
|
Status int64 `db:"status"` // 狀態
|
||||||
|
DueTime int64 `db:"due_time"` // T+N 執行時間
|
||||||
|
CreatedAt int64 `db:"created_at"` // 創建時間(Unix 時間戳,毫秒)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newWalletJournalModel(conn sqlx.SqlConn) *defaultWalletJournalModel {
|
||||||
|
return &defaultWalletJournalModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`wallet_journal`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletJournalModel) withSession(session sqlx.Session) *defaultWalletJournalModel {
|
||||||
|
return &defaultWalletJournalModel{
|
||||||
|
conn: sqlx.NewSqlConnFromSession(session),
|
||||||
|
table: "`wallet_journal`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletJournalModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletJournalModel) FindOne(ctx context.Context, id int64) (*WalletJournal, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", walletJournalRows, m.table)
|
||||||
|
var resp WalletJournal
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletJournalModel) Insert(ctx context.Context, data *WalletJournal) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, walletJournalRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.TransactionId, data.OrderId, data.Brand, data.Uid, data.WalletType, data.Currency, data.TransactionAmount, data.PostTransactionBalance, data.BusinessType, data.Status, data.DueTime, data.CreatedAt)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletJournalModel) Update(ctx context.Context, data *WalletJournal) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, walletJournalRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.TransactionId, data.OrderId, data.Brand, data.Uid, data.WalletType, data.Currency, data.TransactionAmount, data.PostTransactionBalance, data.BusinessType, data.Status, data.DueTime, data.CreatedAt, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletJournalModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ WalletModel = (*customWalletModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// WalletModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customWalletModel.
|
||||||
|
WalletModel interface {
|
||||||
|
walletModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customWalletModel struct {
|
||||||
|
*defaultWalletModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewWalletModel returns a model for the database table.
|
||||||
|
func NewWalletModel(conn sqlx.SqlConn) WalletModel {
|
||||||
|
return &customWalletModel{
|
||||||
|
defaultWalletModel: newWalletModel(conn),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
walletFieldNames = builder.RawFieldNames(&Wallet{})
|
||||||
|
walletRows = strings.Join(walletFieldNames, ",")
|
||||||
|
walletRowsExpectAutoSet = strings.Join(stringx.Remove(walletFieldNames, "`id`"), ",")
|
||||||
|
walletRowsWithPlaceHolder = strings.Join(stringx.Remove(walletFieldNames, "`id`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
walletModel interface {
|
||||||
|
Insert(ctx context.Context, data *Wallet) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int64) (*Wallet, error)
|
||||||
|
FindOneByUidCurrencyWalletType(ctx context.Context, uid string, currency string, walletType int64) (*Wallet, error)
|
||||||
|
Update(ctx context.Context, data *Wallet) error
|
||||||
|
Delete(ctx context.Context, id int64) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultWalletModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
Wallet struct {
|
||||||
|
Id int64 `db:"id"` // 錢包流水號
|
||||||
|
Uid string `db:"uid"` // 用戶ID
|
||||||
|
Brand string `db:"brand"` // 品牌名稱
|
||||||
|
Currency string `db:"currency"` // 幣別(或平台點數)
|
||||||
|
Balance float64 `db:"balance"` // 錢包餘額
|
||||||
|
WalletType int64 `db:"wallet_type"` // 錢包種類: 1=可用, 2=凍結, 3=限制(僅出金)
|
||||||
|
CreatedAt int64 `db:"created_at"` // 創建時間
|
||||||
|
UpdatedAt int64 `db:"updated_at"` // 更新時間
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newWalletModel(conn sqlx.SqlConn) *defaultWalletModel {
|
||||||
|
return &defaultWalletModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`wallet`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) withSession(session sqlx.Session) *defaultWalletModel {
|
||||||
|
return &defaultWalletModel{
|
||||||
|
conn: sqlx.NewSqlConnFromSession(session),
|
||||||
|
table: "`wallet`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) Delete(ctx context.Context, id int64) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) FindOne(ctx context.Context, id int64) (*Wallet, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", walletRows, m.table)
|
||||||
|
var resp Wallet
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) FindOneByUidCurrencyWalletType(ctx context.Context, uid string, currency string, walletType int64) (*Wallet, error) {
|
||||||
|
var resp Wallet
|
||||||
|
query := fmt.Sprintf("select %s from %s where `uid` = ? and `currency` = ? and `wallet_type` = ? limit 1", walletRows, m.table)
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, uid, currency, walletType)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlc.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) Insert(ctx context.Context, data *Wallet) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, walletRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.Brand, data.Currency, data.Balance, data.WalletType, data.CreatedAt, data.UpdatedAt)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) Update(ctx context.Context, newData *Wallet) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, walletRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.Brand, newData.Currency, newData.Balance, newData.WalletType, newData.CreatedAt, newData.UpdatedAt, newData.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultWalletModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package svc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/config"
|
||||||
|
model "app-cloudep-trade-service/internal/model"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mustDSN(c config.Config) string {
|
||||||
|
// 構建 DSN 字符串
|
||||||
|
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true&interpolateParams=%t",
|
||||||
|
c.DB.User,
|
||||||
|
c.DB.Password,
|
||||||
|
c.DB.Host,
|
||||||
|
c.DB.Port,
|
||||||
|
c.DB.Database,
|
||||||
|
c.DB.InterpolateParams,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDatabase(c config.Config) (*sql.DB, error) {
|
||||||
|
// 創建基礎的 *sql.DB 連接
|
||||||
|
db, err := sql.Open("mysql", mustDSN(c))
|
||||||
|
if err != nil {
|
||||||
|
logx.Error(fmt.Errorf("failed to connect to database: %w", err))
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 設置數據庫連接池參數
|
||||||
|
db.SetMaxIdleConns(c.DB.MaxIdleConns)
|
||||||
|
db.SetMaxOpenConns(c.DB.MaxOpenConns)
|
||||||
|
db.SetConnMaxLifetime(c.DB.ConnMaxLifetime)
|
||||||
|
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustWalletModel 連線 wallet 時
|
||||||
|
func MustWalletModel(db *sql.DB) model.WalletModel {
|
||||||
|
// 創建並返回 *sqlx.SqlConn
|
||||||
|
sqlConn := sqlx.NewSqlConnFromDB(db)
|
||||||
|
|
||||||
|
return model.NewWalletModel(sqlConn)
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package svc
|
||||||
import (
|
import (
|
||||||
"app-cloudep-trade-service/internal/config"
|
"app-cloudep-trade-service/internal/config"
|
||||||
duc "app-cloudep-trade-service/internal/domain/usecase"
|
duc "app-cloudep-trade-service/internal/domain/usecase"
|
||||||
|
"app-cloudep-trade-service/internal/model"
|
||||||
"app-cloudep-trade-service/internal/usecase"
|
"app-cloudep-trade-service/internal/usecase"
|
||||||
|
|
||||||
ers "code.30cm.net/digimon/library-go/errs"
|
ers "code.30cm.net/digimon/library-go/errs"
|
||||||
|
@ -15,6 +16,7 @@ type ServiceContext struct {
|
||||||
Validate vi.Validate
|
Validate vi.Validate
|
||||||
|
|
||||||
OrderUseCase duc.OrderUseCase
|
OrderUseCase duc.OrderUseCase
|
||||||
|
WalletModel model.WalletModel
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
|
@ -26,6 +28,11 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
OrderModel: om,
|
OrderModel: om,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mysql, err := newDatabase(c)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to connect to wallet")
|
||||||
|
}
|
||||||
|
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
Validate: vi.MustValidator(
|
Validate: vi.MustValidator(
|
||||||
|
@ -34,5 +41,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
),
|
),
|
||||||
|
|
||||||
OrderUseCase: orderUseCase,
|
OrderUseCase: orderUseCase,
|
||||||
|
WalletModel: MustWalletModel(mysql),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue