go-common/app/service/live/wallet/dao/tx.go
2019-04-22 18:49:16 +08:00

191 lines
8.5 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package dao
import (
"context"
"fmt"
"go-common/app/service/live/wallet/model"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
"time"
)
const (
_selWallet = "SELECT uid,gold,iap_gold,silver,cost_base,gold_recharge_cnt,gold_pay_cnt,silver_pay_cnt,snapshot_time,snapshot_gold,snapshot_iap_gold,snapshot_silver,reserved1,reserved2 FROM user_wallet_%d WHERE uid=? FOR UPDATE"
_recharge = "UPDATE user_wallet_%d set %s = %s + %d,%s=%s+%d where uid = ?"
_rechargeWihoutCnt = "UPDATE user_wallet_%d set %s=%s + %d where uid = ?"
_rechargeWithSnap = "UPDATE user_wallet_%d set %s=%s + %d,%s = %s+ %d, snapshot_time = ? , snapshot_gold = ? , snapshot_iap_gold = ? , snapshot_silver = ? where uid = ?"
_rechargeWithSnapWithoutCnt = "UPDATE user_wallet_%d set %s = %s + %d, snapshot_time = ? , snapshot_gold = ? , snapshot_iap_gold = ? , snapshot_silver = ? where uid = ?"
_exchange = "UPDATE user_wallet_%d set %s = %s - %d , %s = %s + %d, %s = %s + %d, %s = %s + %d where uid = ?"
_exhcangeWithSnap = "UPDATE user_wallet_%d set %s = %s - %d , %s = %s + %d, %s = %s + %d, %s = %s + %d, snapshot_time = ? , snapshot_gold = ? , snapshot_iap_gold = ? , snapshot_silver = ? where uid = ? "
_modifyCnt = "UPDATE user_wallet_%d set gold_pay_cnt = gold_pay_cnt + %d, gold_recharge_cnt = gold_recharge_cnt + %d, silver_pay_cnt = silver_pay_cnt + %d where uid = ?"
)
// 开启事务
func (d *Dao) BeginTx(c context.Context) (conn *sql.Tx, err error) {
return d.db.Begin(c)
}
func (d *Dao) DoTx(c context.Context, doFunc func(conn *sql.Tx) (v interface{}, err error)) (v interface{}, err error) {
conn, err := d.BeginTx(c)
if err != nil {
err = ecode.ServerErr
return
}
v, err = doFunc(conn)
var txErr error
if err != nil {
conn.Rollback()
err = ecode.ServerErr
} else {
txErr = conn.Commit()
if txErr != nil {
err = ecode.ServerErr
v = nil
}
}
return v, err
}
// 为了后续的更新获取数据
func (d *Dao) WalletForUpdate(conn *sql.Tx, uid int64) (wallet *model.DetailWithSnapShot, err error) {
row := conn.QueryRow(fmt.Sprintf(_selWallet, tableIndex(uid)), uid)
wallet = &model.DetailWithSnapShot{}
var snapShotTime time.Time
if err = row.Scan(&wallet.Uid, &wallet.Gold, &wallet.IapGold, &wallet.Silver, &wallet.CostBase, &wallet.GoldRechargeCnt,
&wallet.GoldPayCnt, &wallet.SilverPayCnt, &snapShotTime, &wallet.SnapShotGold, &wallet.SnapShotIapGold,
&wallet.SnapShotSilver, &wallet.Reserved1, &wallet.Reserved2); err == sql.ErrNoRows {
// 查询结果为空时,初始化数据
_, err = d.InitWalletInTx(conn, uid, 0, 0, 0)
wallet.SnapShotTime = snapShotTime.Format("2006-01-02 15:04:05")
return
}
if err != nil {
log.Error("[tx.wallet|Melonseed] row.Scan err: %s", err.Error())
return
}
wallet.SnapShotTime = snapShotTime.Format("2006-01-02 15:04:05")
return
}
// InitExp 初始化用户钱包,用于首次查询
func (d *Dao) InitWalletInTx(conn *sql.Tx, uid int64, gold int64, iap_gold int64, silver int64) (row int64, err error) {
res, err := conn.Exec(fmt.Sprintf(_insWallet, tableIndex(uid)), uid, gold, iap_gold, silver)
if err != nil {
log.Error("[tx.wallet|InitWallet] Exec err: %v", err)
return
}
return res.RowsAffected()
}
func (d *Dao) execSqlInTx(conn *sql.Tx, sql *string, params ...interface{}) (affect int64, err error) {
res, err := conn.Exec(*sql, params...)
if err != nil {
log.Error("[tx.wallet|execSqlInTx] Exec err: %v sql:%s", err, *sql)
return
}
return res.RowsAffected()
}
func (d *Dao) changeCoinInTx(conn *sql.Tx, uid int64, sysCoinTypeNo int32, num int64, originWallet *model.DetailWithSnapShot, cntField string) (affect int64, err error) {
// 判断
coinType := model.GetSysCoinTypeByNo(sysCoinTypeNo)
var s string
absNum := num
if absNum < 0 {
absNum = -absNum
}
if model.TodayNeedSnapShot(originWallet) {
if cntField == "" {
s = getRechargeWithoutCntWithSnapShotSQL(uid, coinType, num)
} else {
s = getRechargeWithSnapShotSQL(uid, coinType, num, cntField, absNum)
}
date := time.Now().Format("2006-01-02 15:04:05")
return d.execSqlInTx(conn, &s, date, originWallet.Gold, originWallet.IapGold, originWallet.Silver, uid)
} else {
if cntField == "" {
s = getRechargeWithoutCntSQL(uid, coinType, num)
} else {
s = getRechargeSQL(uid, coinType, num, cntField, absNum)
}
return d.execSqlInTx(conn, &s, uid)
}
}
// RechargeGold 充值IOS金瓜子 记入充值总值
func (d *Dao) RechargeCoinInTx(conn *sql.Tx, uid int64, sysCoinTypeNo int32, num int64, originWallet *model.DetailWithSnapShot) (affect int64, err error) {
rechargerCntField := model.GetRechargeCnt(sysCoinTypeNo)
return d.changeCoinInTx(conn, uid, sysCoinTypeNo, num, originWallet, rechargerCntField)
}
func (d *Dao) PayCoinInTx(conn *sql.Tx, uid int64, sysCoinTypeNo int32, num int64, originWallet *model.DetailWithSnapShot) (affect int64, err error) {
cntField := model.GetPayCnt(sysCoinTypeNo)
return d.changeCoinInTx(conn, uid, sysCoinTypeNo, -num, originWallet, cntField)
}
func (d *Dao) ModifyCoinInTx(conn *sql.Tx, uid int64, sysCoinTypeNo int32, num int64, originWallet *model.DetailWithSnapShot) (affect int64, err error) {
return d.changeCoinInTx(conn, uid, sysCoinTypeNo, num, originWallet, "")
}
func (d *Dao) ExchangeCoinInTx(conn *sql.Tx, uid int64, srcSysCoinTypeNo int32, srcNum int64, destSysCoinTypeNo int32, destNum int64, originWallet *model.DetailWithSnapShot) (affect int64, err error) {
rechargeCntNum := destNum
var rechargerCntField string
if destSysCoinTypeNo == model.SysCoinTypeSilver { // 如果为银瓜子则不存在充值统计总数字段 使用 消费统计字段代替 适配sql
rechargerCntField = "silver_pay_cnt"
rechargeCntNum = 0
} else {
rechargerCntField = model.GetRechargeCnt(destSysCoinTypeNo)
}
payCntField := model.GetPayCnt(srcSysCoinTypeNo)
srcCoinType := model.GetSysCoinTypeByNo(srcSysCoinTypeNo)
destCoinType := model.GetSysCoinTypeByNo(destSysCoinTypeNo)
var s string
if model.TodayNeedSnapShot(originWallet) {
s = fmt.Sprintf(_exhcangeWithSnap, tableIndex(uid), srcCoinType, srcCoinType, srcNum, destCoinType, destCoinType, destNum, rechargerCntField, rechargerCntField, rechargeCntNum, payCntField, payCntField, srcNum)
date := time.Now().Format("2006-01-02 15:04:05")
return d.execSqlInTx(conn, &s, date, originWallet.Gold, originWallet.IapGold, originWallet.Silver, uid)
} else {
s = fmt.Sprintf(_exchange, tableIndex(uid), srcCoinType, srcCoinType, srcNum, destCoinType, destCoinType, destNum, rechargerCntField, rechargerCntField, rechargeCntNum, payCntField, payCntField, srcNum)
return d.execSqlInTx(conn, &s, uid)
}
}
func getRechargeWithSnapShotSQL(uid int64, coinType string, num int64, cntField string, cntNum int64) string {
return fmt.Sprintf(_rechargeWithSnap, tableIndex(uid), coinType, coinType, num, cntField, cntField, cntNum)
}
func getRechargeWithoutCntWithSnapShotSQL(uid int64, coinType string, num int64) string {
return fmt.Sprintf(_rechargeWithSnapWithoutCnt, tableIndex(uid), coinType, coinType, num)
}
func getRechargeSQL(uid int64, coinType string, num int64, cntField string, cntNum int64) string {
return fmt.Sprintf(_recharge, tableIndex(uid), coinType, coinType, num, cntField, cntField, cntNum)
}
func getRechargeWithoutCntSQL(uid int64, coinType string, num int64) string {
return fmt.Sprintf(_rechargeWihoutCnt, tableIndex(uid), coinType, coinType, num)
}
func (d *Dao) NewCoinStreamRecordInTx(conn *sql.Tx, record *model.CoinStreamRecord) (int64, error) {
s := fmt.Sprintf(_newCoinStremaRecord, getCoinStreamTable(record.TransactionId))
date := model.GetWalletFormatTime(record.OpTime)
return d.execSqlInTx(conn, &s, record.Uid, record.TransactionId, record.ExtendTid, record.CoinType,
record.DeltaCoinNum, record.OrgCoinNum, record.OpResult, record.OpReason, record.OpType, date,
record.BizCode, record.Area, record.Source, record.MetaData, record.BizSource,
record.Platform, record.Reserved1, record.Version)
}
func (d *Dao) NewCoinExchangeRecordInTx(conn *sql.Tx, record *model.CoinExchangeRecord) (int64, error) {
s := fmt.Sprintf(_newCoinExchange, getCoinExchangeTable(record.Uid))
date := model.GetWalletFormatTime(record.ExchangeTime)
return d.execSqlInTx(conn, &s, record.Uid, record.TransactionId, record.SrcType, record.SrcNum, record.DestType, record.DestNum, record.Status, date)
}
func (d *Dao) ModifyCntInTx(conn *sql.Tx, uid int64, goldPay int, goldRecharge int, silverPay int) (int64, error) {
s := fmt.Sprintf(_modifyCnt, tableIndex(uid), goldPay, goldRecharge, silverPay)
return d.execSqlInTx(conn, &s, uid)
}