service/app/mix/dao/mysql.go

576 lines
18 KiB
Go

package dao
import (
"errors"
"fmt"
"service/app/mix/conf"
"service/bizcommon/util"
"service/dbstruct"
"service/library/logger"
"service/library/mysqldb"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/jmoiron/sqlx"
goproto "google.golang.org/protobuf/proto"
)
type Mysql struct {
dbVas *sqlx.DB
}
func (m *Mysql) getDBVas() *sqlx.DB {
return m.dbVas
}
func (m *Mysql) VasBegin(ctx *gin.Context) (tx *sqlx.Tx, err error) {
tx, err = m.dbVas.BeginTxx(ctx, nil)
if err != nil {
logger.Error("beginx fail, err: %v", err)
return
}
if tx == nil {
err = errors.New("get tx fail")
logger.Error("nil tx, err: %v", err)
return
}
return
}
func (m *Mysql) DealTxCR(tx *sqlx.Tx, errIn error) (errOut error) {
if errIn != nil {
// 事务回滚
logger.Error("deal tx err, %v", errIn)
errOut = tx.Rollback()
if errOut != nil {
logger.Error("tx rollback fail, err: %v", errOut)
return
}
} else {
// 提交事务
errOut = tx.Commit()
if errOut != nil {
logger.Error("tx commit fail, err: %v", errOut)
return
}
}
return
}
// mysql
const (
DatabaseVas = "vas"
TableOrder = "vas_order" // 订单表
TableWallet = "vas_wallet" // 钱包
TableCoinOrder = "vas_coin_order" // 金币订单
TableConsumeHistoryCost = "vas_ch_cost" // 消费明细
TableConsumeHistoryCharge = "vas_ch_charge" // 充值明细
TableConsumeHistoryIncome = "vas_ch_income" // 收入明细
TableConsumeHistoryWithdraw = "vas_ch_withdraw" // 提现明细
TableVasUserUnlock = "vas_user_unlock" // 用增解锁
)
func (m *Mysql) ChTableName(ch *dbstruct.ConsumeHistory) (string, error) {
switch ch.GetType() {
case dbstruct.CHTypeCost:
return TableConsumeHistoryCost, nil
case dbstruct.CHTypeCharge:
return TableConsumeHistoryCharge, nil
case dbstruct.CHTypeIncome:
return TableConsumeHistoryIncome, nil
case dbstruct.CHTypeWithdraw:
return TableConsumeHistoryWithdraw, nil
default:
return "", errors.New(fmt.Sprintf("invalid ch type: %v", *ch.Type))
}
}
func NewMysql(cfg *conf.ConfigSt) (mysql *Mysql, err error) {
mysql = new(Mysql)
mysql.dbVas, err = mysqldb.NewMysqlDB(cfg.MixMysql, DatabaseVas)
if err != nil {
logger.Error("NewMysqlDB fail, cfg: %v, db: %v, err: %v", util.ToJson(cfg.MixMongo), DatabaseVas, err)
return
}
mysql.dbVas.SetMaxOpenConns(20)
mysql.dbVas.SetMaxIdleConns(10)
err = mysql.dbVas.Ping()
if err != nil {
logger.Error("MysqlDB ping fail, cfg: %v, db: %v, err: %v", util.ToJson(cfg.MixMongo), DatabaseVas, err)
return
}
return
}
// 创建订单
func (m *Mysql) CreateOrder(ctx *gin.Context, tx *sqlx.Tx, order *dbstruct.Order) error {
var err error
sqlStr := "insert into " + TableOrder +
" (id, mid, uid, product_id, pay_type, pay_amount, " +
" out_order_id, receipt_data, coins, order_status, order_from, " +
" ct, ut, ext, b_did, b_ver, b_osver, b_dt, b_ch, b_model, b_nt, ip) " +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
order.GetID(), order.GetMid(), order.GetUid(), order.GetProductId(), order.GetPayType(), order.GetPayAmount(),
order.GetOutOrderID(), order.GetReceiptData(), order.GetCoins(), order.GetOrderStatus(), order.GetOrderFrom(),
order.GetCt(), order.GetUt(), order.GetExt(), order.GetDid(), order.GetVersion(), order.GetOsVersion(), order.GetDevType(), order.GetChannel(), order.GetModel(), order.GetNetType(), order.GetIp(),
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
order.GetID(), order.GetMid(), order.GetUid(), order.GetProductId(), order.GetPayType(), order.GetPayAmount(),
order.GetOutOrderID(), order.GetReceiptData(), order.GetCoins(), order.GetOrderStatus(), order.GetOrderFrom(),
order.GetCt(), order.GetUt(), order.GetExt(), order.GetDid(), order.GetVersion(), order.GetOsVersion(), order.GetDevType(), order.GetChannel(), order.GetModel(), order.GetNetType(), order.GetIp(),
)
}
if err != nil {
logger.Error("CreateOrder fail, order: %v, err: %v", order.ToString(), err)
return err
}
return err
}
// 获取订单
func (m *Mysql) GetOrderById(ctx *gin.Context, tx *sqlx.Tx, id string) (order *dbstruct.Order, err error) {
var tmpOrder dbstruct.Order
if tx != nil {
err = tx.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ?", TableOrder), id)
} else {
db := m.getDBVas()
err = db.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ?", TableOrder), id)
}
if err != nil {
return
}
order = &tmpOrder
return
}
// 获取订单
func (m *Mysql) GetOrderByOutOrderId(ctx *gin.Context, tx *sqlx.Tx, outOrderId string) (order *dbstruct.Order, err error) {
var tmpOrder dbstruct.Order
if tx != nil {
err = tx.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where out_order_id = ?", TableOrder), outOrderId)
} else {
db := m.getDBVas()
err = db.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where out_order_id = ?", TableOrder), outOrderId)
}
if err != nil {
return
}
order = &tmpOrder
return
}
// 获取订单for update
func (m *Mysql) GetOrderByIdForUpdate(ctx *gin.Context, tx *sqlx.Tx, id string) (order *dbstruct.Order, err error) {
var tmpOrder dbstruct.Order
err = tx.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ? for update", TableOrder), id)
if err != nil {
return
}
order = &tmpOrder
return
}
// 更新订单状态
func (m *Mysql) UpdateOrderStatus(ctx *gin.Context, tx *sqlx.Tx, orderId string, preStatus, aftStatus int32) error {
var err error
sqlStr := "update " + TableOrder + " set order_status=? where id=? and order_status=?"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr, aftStatus, orderId, preStatus)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr, aftStatus, orderId, preStatus)
}
if err != nil {
logger.Error("UpdateOrderStatus fail, orderId: %v, preStatus: %v, aftStatus: %v, err: %v", orderId, preStatus, aftStatus, err)
return err
}
return err
}
// 获取钱包 for update
func (m *Mysql) GetWalletForUpdate(ctx *gin.Context, tx *sqlx.Tx, mid int64) (wallet *dbstruct.Wallet, err error) {
var tmpWallet dbstruct.Wallet
err = tx.GetContext(ctx, &tmpWallet, fmt.Sprintf("select * from %s where id = ? for update", TableWallet), mid)
if err != nil {
return
}
wallet = &tmpWallet
return
}
// 新建钱包
func (m *Mysql) CreateWallet(ctx *gin.Context, tx *sqlx.Tx, mid int64) error {
var err error
sqlStr := "insert into " + TableWallet +
" (id, coins, diamonds, withdraw_diamonds) " +
" values (?, ?, ?, ?)"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr, mid, 0, 0, 0)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr, mid, 0, 0, 0)
}
if err != nil {
logger.Error("CreateWallet fail, mid: %v, err: %v", mid, err)
return err
}
return nil
}
// 获取钱包
func (m *Mysql) GetWalletByMid(ctx *gin.Context, mid int64) (wallet *dbstruct.Wallet, err error) {
var (
db = m.getDBVas()
tmpWallet dbstruct.Wallet
)
err = db.GetContext(ctx, &tmpWallet, fmt.Sprintf("select * from %s where id = ?", TableWallet), mid)
if err != nil {
return
}
wallet = &tmpWallet
return
}
// 增加金币
func (m *Mysql) IncCoins(ctx *gin.Context, tx *sqlx.Tx, mid, coins int64) error {
var err error
sqlStr := "update " + TableWallet + " set coins = coins + ? where id = ?"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
coins, mid,
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
coins, mid,
)
}
if err != nil {
logger.Error("IncCoins fail, mid: %v, coins: %v, err: %v", mid, coins, err)
return err
}
return err
}
// 扣金币
func (m *Mysql) DecCoins(ctx *gin.Context, tx *sqlx.Tx, mid, coins int64) error {
var err error
sqlStr := "update " + TableWallet + " set coins = coins - ? where id = ?"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
coins, mid,
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
coins, mid,
)
}
if err != nil {
logger.Error("IncCoins fail, mid: %v, coins: %v, err: %v", mid, coins, err)
return err
}
return err
}
// 增加钻石
func (m *Mysql) IncDiamonds(ctx *gin.Context, tx *sqlx.Tx, mid, dias int64) error {
var err error
sqlStr := "update " + TableWallet + " set diamonds = diamonds + ? where id = ?"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
dias, mid,
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
dias, mid,
)
}
if err != nil {
logger.Error("IncCoins fail, mid: %v, dias: %v, err: %v", mid, dias, err)
return err
}
return err
}
// 创建金币订单
func (m *Mysql) CreateCoinOrder(ctx *gin.Context, tx *sqlx.Tx, order *dbstruct.CoinOrder) error {
var err error
sqlStr := "insert into " + TableCoinOrder +
" (id, mid, uid, product_id, " +
" coins, order_status, order_from, " +
" ct, ut, ext, b_did, b_ver, b_osver, " +
" b_dt, b_ch, b_model, b_nt, ip) " +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
order.GetID(), order.GetMid(), order.GetUid(), order.GetProductId(),
order.GetCoins(), order.GetOrderStatus(), order.GetOrderFrom(),
order.GetCt(), order.GetUt(), order.GetExt(), order.GetDid(), order.GetVersion(), order.GetOsVersion(),
order.GetDevType(), order.GetChannel(), order.GetModel(), order.GetNetType(), order.GetIp(),
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
order.GetID(), order.GetMid(), order.GetUid(), order.GetProductId(),
order.GetCoins(), order.GetOrderStatus(), order.GetOrderFrom(),
order.GetCt(), order.GetUt(), order.GetExt(), order.GetDid(), order.GetVersion(), order.GetOsVersion(),
order.GetDevType(), order.GetChannel(), order.GetModel(), order.GetNetType(), order.GetIp(),
)
}
if err != nil {
logger.Error("CreateCoinOrder fail, order: %v, err: %v", order.ToString(), err)
return err
}
return err
}
// 获取金币订单
func (m *Mysql) GetCoinOrderById(ctx *gin.Context, tx *sqlx.Tx, id string) (order *dbstruct.CoinOrder, err error) {
var tmpOrder dbstruct.CoinOrder
if tx != nil {
err = tx.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ?", TableCoinOrder), id)
} else {
db := m.getDBVas()
err = db.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ?", TableCoinOrder), id)
}
if err != nil {
return
}
order = &tmpOrder
return
}
// 获取金币订单 for update
func (m *Mysql) GetCoinOrderByIdForUpdate(ctx *gin.Context, tx *sqlx.Tx, id string) (order *dbstruct.CoinOrder, err error) {
var tmpOrder dbstruct.CoinOrder
err = tx.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ? for update", TableCoinOrder), id)
if err != nil {
return
}
order = &tmpOrder
return
}
// 金币订单填写联系方式
func (m *Mysql) FillCoinOderContact(ctx *gin.Context, tx *sqlx.Tx, id, qq, wechat, phone, addr, note string) error {
var err error
sqlStr := "update " + TableCoinOrder + " set qq=?, wechat=?, phone=?, addr=?, note=?, order_status=? where id=?"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
qq, wechat, phone, addr, note, dbstruct.VasCoinOrderStatusWaitDeal, id,
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
qq, wechat, phone, addr, note, dbstruct.VasCoinOrderStatusWaitDeal, id,
)
}
if err != nil {
return err
}
return nil
}
// todo 获取待结算的订单
func (m *Mysql) Get(ctx *gin.Context, tx *sqlx.Tx, id string) (order *dbstruct.CoinOrder, err error) {
var tmpOrder dbstruct.CoinOrder
err = tx.GetContext(ctx, &tmpOrder, fmt.Sprintf("select * from %s where id = ? for update", TableCoinOrder), id)
if err != nil {
return
}
order = &tmpOrder
return
}
// 待添加微信的订单
func (m *Mysql) GetWaitWechatAddCoinOrders(ctx *gin.Context, tx *sqlx.Tx, mid int64, statusList []int32, offset, limit int) (list []*dbstruct.CoinOrder, err error) {
list = make([]*dbstruct.CoinOrder, 0)
sqlStr := fmt.Sprintf("select * from %s where uid=? and product_id=? and order_status in (%s) limit ? offset ?", TableCoinOrder, util.Convert2SqlArr(statusList))
if tx != nil {
err = tx.SelectContext(ctx, &list, sqlStr, mid, dbstruct.ProductIdContactWechat, limit, offset)
} else {
db := m.getDBVas()
err = db.SelectContext(ctx, &list, sqlStr, mid, dbstruct.ProductIdContactWechat, limit, offset)
}
if err != nil {
return
}
return
}
// 确定推荐微信
func (m *Mysql) ConfirmAddWechat(ctx *gin.Context, tx *sqlx.Tx, coinOrderId string) (err error) {
sqlStr := "update " + TableCoinOrder + " set order_status=? where id=? and order_status=?"
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr, dbstruct.VasCoinOrderStatusDeal, coinOrderId, dbstruct.VasCoinOrderStatusWaitDeal)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr, dbstruct.VasCoinOrderStatusDeal, coinOrderId, dbstruct.VasCoinOrderStatusWaitDeal)
}
if err != nil {
return
}
return
}
// 创建消费历史
func (m *Mysql) CreateConsumeHistory(ctx *gin.Context, tx *sqlx.Tx, ch *dbstruct.ConsumeHistory) error {
var (
timeNow = time.Now().Unix()
tableName, err = m.ChTableName(ch)
)
if err != nil {
return err
}
sqlStr := "insert into " + tableName +
" (mid, uid, did, `type`, stype, type_id, " +
" `order_id`, `change`, `before`, `after`, `count`, ct) " +
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
ch.Mid, ch.Uid, ch.Did, ch.Type, ch.SType, ch.TypeId,
ch.OrderId, ch.Change, ch.Before, ch.After, ch.Count, timeNow,
//ch.GetMid(), ch.GetUid(), ch.GetDid(), ch.GetType(), ch.GetSType(), ch.GetTypeId(),
//ch.GetOrderId(), ch.GetChange(), ch.GetBefore(), ch.GetAfter(), ch.GetCount(), timeNow,
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
ch.Mid, ch.Uid, ch.Did, ch.Type, ch.SType, ch.TypeId,
ch.OrderId, ch.Change, ch.Before, ch.After, ch.Count, timeNow,
)
}
if err != nil {
logger.Error("CreateConsumeHistory fail, ch: %v, err: %v", util.ToJson(ch), err)
return err
}
return err
}
// 创建解锁记录
func (m *Mysql) CreateUserVasUnlock(ctx *gin.Context, tx *sqlx.Tx, uu *dbstruct.UserVasUnlock) error {
var (
err error
timeNow = time.Now().Unix()
)
sqlStr := "insert into " + TableVasUserUnlock +
" (mid, uid, product_id, ct, lock_type, status, means, order_id) " +
" values (?, ?, ?, ?, ?, ?, ?, ?) "
if tx != nil {
_, err = tx.ExecContext(ctx, sqlStr,
uu.Mid, uu.Uid, uu.ProductId, timeNow, uu.LockType, uu.Status, uu.Means, uu.OrderId,
)
} else {
db := m.getDBVas()
_, err = db.ExecContext(ctx, sqlStr,
uu.Mid, uu.Uid, uu.ProductId, timeNow, uu.LockType, uu.Status, uu.Means, uu.OrderId,
)
}
if err != nil {
logger.Error("CreateCoinOrder fail, uu: %v, err: %v", util.ToJson(uu), err)
return err
}
return err
}
// 获取解锁记录
func (m *Mysql) GetUserVasUnlock(ctx *gin.Context, tx *sqlx.Tx, mid, uid int64, productId string) (uu *dbstruct.UserVasUnlock, err error) {
var uuTmp dbstruct.UserVasUnlock
sqlStr := fmt.Sprintf("select * from %s where mid=? and uid=? and product_id=?", TableVasUserUnlock)
fmt.Println(sqlStr)
if tx != nil {
err = tx.GetContext(ctx, &uuTmp, sqlStr, mid, uid, productId)
} else {
db := m.getDBVas()
err = db.GetContext(ctx, &uuTmp, sqlStr, mid, uid, productId)
}
if err != nil {
return
}
uu = &uuTmp
return
}
// 获取解锁记录
func (m *Mysql) GetUnlockWechatList(ctx *gin.Context, tx *sqlx.Tx, mid int64, offset, limit int) (list []*dbstruct.UserVasUnlock, err error) {
list = make([]*dbstruct.UserVasUnlock, 0)
sqlStr := fmt.Sprintf("select * from %s where mid=? limit ? offset ? ", TableVasUserUnlock)
if tx != nil {
err = tx.SelectContext(ctx, &list, sqlStr, mid, limit, offset)
} else {
db := m.getDBVas()
err = db.SelectContext(ctx, &list, sqlStr, mid, limit, offset)
}
if err != nil {
return
}
return
}
// 获取消费历史
func (m *Mysql) GetUCHList(ctx *gin.Context, tx *sqlx.Tx, mid int64, typ int32, offset, limit int) (list []*dbstruct.ConsumeHistory, err error) {
list = make([]*dbstruct.ConsumeHistory, 0)
tableName, err := m.ChTableName(&dbstruct.ConsumeHistory{Type: goproto.Int32(typ)})
sqlStr := fmt.Sprintf("select * from %s where mid=? limit ? offset ?", tableName)
if tx != nil {
err = tx.SelectContext(ctx, &list, sqlStr, mid, limit, offset)
} else {
db := m.getDBVas()
err = db.SelectContext(ctx, &list, sqlStr, mid, limit, offset)
}
if err != nil {
return
}
return
}
// 获取订单
func (m *Mysql) GetOrderCountGroupByStatus(ctx *gin.Context, tx *sqlx.Tx, orderStatuses []int32, ctStart *int64, ctEnd *int64) (list []*dbstruct.VasOrderStatusCount, err error) {
var sql strings.Builder
var args []interface{}
sql.WriteString(fmt.Sprintf("select order_status, count(1) as count from %s where 1 = 1", TableOrder))
if ctStart != nil {
sql.WriteString(" and ct >= ?")
args = append(args, util.DerefInt64(ctStart))
}
if ctEnd != nil {
sql.WriteString(" and ct <= ?")
args = append(args, util.DerefInt64(ctEnd))
}
if len(orderStatuses) > 0 {
inClause := strings.Builder{}
inClause.WriteString("?")
args = append(args, orderStatuses[0])
for i := 1; i < len(orderStatuses); i++ {
inClause.WriteString(",?")
args = append(args, orderStatuses[i])
}
sql.WriteString(fmt.Sprintf(" and order_status in (%s)", inClause.String()))
}
sql.WriteString(" group by order_status")
list = make([]*dbstruct.VasOrderStatusCount, 0)
if tx != nil {
err = tx.SelectContext(ctx, &list, sql.String(), args...)
} else {
db := m.getDBVas()
err = db.SelectContext(ctx, &list, sql.String(), args...)
}
if err != nil {
return
}
return
}