162 lines
3.9 KiB
Go
162 lines
3.9 KiB
Go
package repository
|
|
|
|
import (
|
|
"app-cloudep-trade-service/internal/domain"
|
|
"app-cloudep-trade-service/internal/domain/repository"
|
|
"app-cloudep-trade-service/internal/domain/wallet"
|
|
"app-cloudep-trade-service/internal/model"
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/zeromicro/go-zero/core/stores/sqlc"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
|
)
|
|
|
|
type WalletRepositoryParam struct {
|
|
WalletModel model.WalletModel
|
|
TxConn sqlx.SqlConn
|
|
}
|
|
|
|
type WalletRepository struct {
|
|
WalletRepositoryParam
|
|
}
|
|
|
|
func (repo *WalletRepository) Transaction(ctx context.Context, fn func(tx sqlx.Session) error) error {
|
|
// 取得原生的 *sql.DB
|
|
db, err := repo.TxConn.RawDB()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 定義事務選項
|
|
txOptions := &sql.TxOptions{
|
|
Isolation: sql.LevelReadCommitted,
|
|
ReadOnly: false,
|
|
}
|
|
|
|
// 開啟事務
|
|
tx, err := db.BeginTx(ctx, txOptions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 使用 sqlx.Session 包裹事務
|
|
session := sqlx.NewSessionFromTx(tx)
|
|
|
|
// 執行傳入的操作
|
|
if err := fn(session); err != nil {
|
|
// 若有錯誤則回滾
|
|
err := tx.Rollback()
|
|
if err != nil {
|
|
// 錯誤代碼 06-021-22
|
|
e := domain.CommentErrorL(
|
|
domain.WalletTxErrorCode,
|
|
logx.WithContext(ctx),
|
|
[]logx.LogField{
|
|
{Key: "func", Value: "WalletModel.Transaction.Rollback"},
|
|
{Key: "err", Value: err},
|
|
},
|
|
"failed to find balance into mongo:").Wrap(err)
|
|
|
|
return e
|
|
}
|
|
|
|
// 裡面那一層會紀錄
|
|
return err
|
|
}
|
|
|
|
// 提交事務
|
|
return tx.Commit()
|
|
}
|
|
|
|
// GetUserWalletOperator 取得本地操作使用者錢包的操作運算元
|
|
func (repo *WalletRepository) GetUserWalletOperator(uid, currency string, opts ...repository.Option) repository.UserWalletOperator {
|
|
db := repo.TxConn
|
|
|
|
// 看是否有最新的DB 連線要傳入,做 tx
|
|
for _, fn := range opts {
|
|
db = fn()
|
|
}
|
|
|
|
return NewUserWalletOperator(uid, currency, repo.WalletModel, db)
|
|
}
|
|
|
|
// Create 創建錢包,如果有相同的就跳過不建立
|
|
func (repo *WalletRepository) Create(ctx context.Context, uid, currency, brand string) ([]*model.Wallet, error) {
|
|
wallets := make([]*model.Wallet, 0, len(wallet.AllBalanceTypes))
|
|
// 建立個人所有種類的錢包
|
|
now := time.Now().UTC().UnixNano()
|
|
for _, item := range wallet.AllBalanceTypes {
|
|
balance := decimal.Zero
|
|
wallets = append(wallets, &model.Wallet{
|
|
Brand: brand,
|
|
Currency: currency,
|
|
Uid: uid,
|
|
Balance: balance,
|
|
WalletType: item,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
})
|
|
}
|
|
|
|
_, err := repo.WalletModel.InsertMany(ctx, wallets)
|
|
if err != nil {
|
|
// 錯誤代碼 06-021-20
|
|
e := domain.CommentErrorL(
|
|
domain.CreateWalletErrorCode,
|
|
logx.WithContext(ctx),
|
|
[]logx.LogField{
|
|
{Key: "param", Value: fmt.Sprintf("uid: %s, currency:%s, brand:%s", uid, currency, brand)},
|
|
{Key: "func", Value: "WalletModel.InsertMany"},
|
|
{Key: "err", Value: err},
|
|
},
|
|
"failed to insert wallet into mysql:").Wrap(err)
|
|
|
|
return nil, e
|
|
}
|
|
|
|
return wallets, nil
|
|
}
|
|
|
|
func (repo *WalletRepository) Balances(ctx context.Context, req repository.BalanceReq) ([]model.Wallet, error) {
|
|
data, err := repo.WalletModel.Balances(ctx, model.BalanceReq{
|
|
UID: req.UID,
|
|
Currency: req.Currency,
|
|
Kind: req.BalanceType,
|
|
}, false, repo.TxConn)
|
|
|
|
if err != nil {
|
|
if errors.Is(sqlc.ErrNotFound, err) {
|
|
// 錯誤代碼 06-031-23
|
|
return nil, domain.NotFoundError(domain.WalletBalanceNotFound, "balance not found")
|
|
}
|
|
|
|
// 錯誤代碼 06-021-20
|
|
e := domain.CommentErrorL(
|
|
domain.CreateWalletErrorCode,
|
|
logx.WithContext(ctx),
|
|
[]logx.LogField{
|
|
{Key: "param", Value: req},
|
|
{Key: "func", Value: "WalletModel.Balances"},
|
|
{Key: "err", Value: err},
|
|
},
|
|
"failed to get balance")
|
|
|
|
return nil, e
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func NewWalletRepository(param WalletRepositoryParam) repository.WalletRepository {
|
|
return &WalletRepository{
|
|
WalletRepositoryParam: param,
|
|
}
|
|
}
|