package shanghu
import (
orm "duoduo/database"
"errors"
"fmt"
"github.com/shopspring/decimal"
"time"
)
type ClientPayTrans struct {
ID int64 `gorm:"column:id;type:bigint(20);primary_key" json:"id"` // 主键
RequestID string `gorm:"column:request_id;type:varchar(255)" json:"request_id"` // 请求id,幂等性
OutTradeNo string `gorm:"column:out_trade_no;type:varchar(255)" json:"out_trade_no"` // 交易id
MerchantCardID int64 `gorm:"column:merchant_card_id;type:bigint(20)" json:"merchant_card_id"` // 商户卡id
ClientOpenID string `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"` // 客户端openid
Status int `gorm:"column:status;type:int(11)" json:"status"` // 1-未支付 2-支付成功 3-取消支付 4-退款
Amount decimal.Decimal `gorm:"column:amount;type:decimal(10,2)" json:"amount"` // 交易金额
ThirdTradeNo string `gorm:"column:third_trade_no;type:varchar(255)" json:"third_trade_no"` // 微信交易id
PayTime time.Time `gorm:"column:pay_time;type:datetime(3);default:null" json:"pay_time"` // 支付时间
InvitationCode string `gorm:"column:invitation_code;type:varchar(25)" json:"invitation_code"` // 邀请码
AccountStatus int `gorm:"column:account_status;type:int(11)" json:"account_status"` // 分账状态 99-分账成功 2-分账失败 1-未分账
AccountErrLog string `gorm:"column:account_err_log;type:varchar(255)" json:"account_err_log"` // 分账err日志
CreateBy int64 `gorm:"column:create_by;type:bigint(20)" json:"create_by"` // 创建者
UpdateBy int64 `gorm:"column:update_by;type:bigint(20)" json:"update_by"` // 更新者
CreatedAt time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"` // 创建时间
UpdatedAt time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"` // 最后更新时间
DeletedAt time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
}
func (m *ClientPayTrans) TableName() string {
return "client_pay_trans"
}
func (m *ClientPayTrans) GetRequestNum() int {
var count int
tableCount := orm.ShMysql.Table(m.TableName()).Where("request_id = ? ", m.RequestID)
tableCount.Count(&count)
return count
}
func (m *ClientPayTrans) GetNumByCardID() int {
var count int
tableCount := orm.ShMysql.Table(m.TableName()).Where("merchant_card_id = ? and status =2 ", m.MerchantCardID)
tableCount.Count(&count)
return count
}
func (m *ClientPayTrans) GetPayTransByOpenid() (ClientPayTrans, error) {
var doc ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("merchant_card_id = ? and client_open_id = ? and status = 2 ", m.MerchantCardID, m.ClientOpenID)
if err := table.Select("*").First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
func (m *ClientPayTrans) GetPayTransByOpenId() (ClientPayTrans, error) {
var doc ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("client_open_id = ? and status = 2 ", m.ClientOpenID)
if err := table.Select("*").First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
func (m *ClientPayTrans) GetPaySuccessTransByInvitationCode(pageSize int, pageIndex int) ([]ClientPayTrans, int, error) {
var doc []ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("invitation_code = ? and status = 2 and account_status = 99", m.InvitationCode)
var count int
if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
return nil, 0, err
}
table.Count(&count)
return doc, count, nil
}
func (m *ClientPayTrans) GetPayTransById() (ClientPayTrans, error) {
var doc ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("id = ? ", m.ID)
if err := table.Select("*").First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
func (m *ClientPayTrans) GetPayTransByTradeNo() (ClientPayTrans, error) {
var doc ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("out_trade_no = ? ", m.OutTradeNo)
if err := table.Select("*").First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
func (u *ClientPayTrans) Create() (ClientPayTrans, error) {
var doc ClientPayTrans
var err error
doc = *u
err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
if err != nil {
return doc, err
}
return doc, nil
}
func (m *ClientPayTrans) UpdatePayTransByTradeNo() error {
if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("out_trade_no = ? ", m.OutTradeNo).Updates(
map[string]interface{}{
"third_trade_no": m.ThirdTradeNo,
"pay_time": m.PayTime,
"status": m.Status,
"account_status": m.AccountStatus,
"updated_at": time.Now()}).Error; err != nil {
return err
}
return nil
}
func (m *ClientPayTrans) GetTransByAccount() (ClientPayTrans, error) {
var doc ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("account_status = ? ", m.AccountStatus)
if err := table.Select("*").First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
func (m *ClientPayTrans) GetPayTransByStatus() (ClientPayTrans, error) {
var doc ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("status = ? and account_status = ?", m.Status, m.AccountStatus)
if err := table.Select("*").First(&doc).Error; err != nil {
return doc, err
}
return doc, nil
}
func (m *ClientPayTrans) UpdateById(data map[string]interface{}) error {
err := orm.ShMysql.Table(m.TableName()).Where("id = ?", m.ID).Updates(data).Error
if err != nil {
return err
}
return nil
}
func (m *ClientPayTrans) GetPayTransSuccessByOpenID(pageSize int, pageIndex int) ([]ClientPayTrans, int, error) {
var doc []ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
//if m.ActivityStartTime != 0
table = table.Where("client_open_id = ? and status = 2", m.ClientOpenID)
var count int
if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
return nil, 0, err
}
table.Count(&count)
return doc, count, nil
}
func (m *ClientPayTrans) GetPayTransSuccessByMerchantID(pageSize int, pageIndex int, merchantId []int64) ([]ClientPayTrans, int, error) {
var doc []ClientPayTrans
table := orm.ShMysql.Table(m.TableName())
table = table.Where("merchant_card_id in (?) and status = 2", merchantId)
var count int
if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
return nil, 0, err
}
table.Count(&count)
return doc, count, nil
}
func (m *ClientPayTrans) SettleAdd(merchantAmount, clientAmount decimal.Decimal, merchantOpenId, clientOpenId string, payTransId int64) error {
// 使用事务 添加
var err error
var clientAccount MerchantClientAccount
var merchantAccount MerchantAccount
var amountPreMerchant decimal.Decimal
var amountPreClient decimal.Decimal
tx := orm.ShMysql.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
//查看是否有账号,没有创建
err = tx.Table("merchant_account").Select("*").Where("merchant_open_id = ?", merchantOpenId).Find(&merchantAccount).Error
if err != nil && err.Error() != "record not found" {
return err
}
if merchantAccount.ID == 0 {
merchantAccount.MerchantOpenID = merchantOpenId
merchantAccount.Version = 1
merchantAccount.UpdatedAt = time.Now()
merchantAccount.CreatedAt = time.Now()
err = tx.Table("merchant_account").Create(&merchantAccount).Error
if err != nil {
return err
}
}
amountPreMerchant = merchantAccount.Amount
if clientOpenId != "" { //原始码不抽佣金
err = tx.Table("merchant_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error
if err != nil && err.Error() != "record not found" {
return err
}
if clientAccount.ID == 0 {
clientAccount.ClientOpenID = clientOpenId
clientAccount.Version = 1
clientAccount.UpdatedAt = time.Now()
clientAccount.CreatedAt = time.Now()
err = tx.Table("merchant_client_account").Create(&clientAccount).Error
if err != nil {
return err
}
}
amountPreClient = clientAccount.Amount
clientAmountAdd := clientAccount.Amount.Add(clientAmount)
result := tx.Table("merchant_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates(
map[string]interface{}{
"amount": clientAmountAdd,
"version": clientAccount.Version + 1,
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
var clientAccountLog MerchantClientAccountLog
clientAccountLog.ClientOpenID = clientOpenId
clientAccountLog.UpdatedAt = time.Now()
clientAccountLog.AmountPre = amountPreClient
clientAccountLog.AmountAfter = clientAmountAdd
clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount
clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount
clientAccountLog.Amount = clientAmount
clientAccountLog.PayTransId = payTransId
err = tx.Table("merchant_client_account_log").Create(&clientAccountLog).Error
if err != nil {
return err
}
}
//做金额加减操作并且入日志库
merchantAmountAdd := merchantAccount.Amount.Add(merchantAmount)
result := tx.Table("merchant_account").Model(&merchantAccount).Where("merchant_open_id = ? and version = ?", merchantOpenId, merchantAccount.Version).Updates(
map[string]interface{}{
"amount": merchantAmountAdd,
"version": merchantAccount.Version + 1,
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
var merchantAccountLog MerchantAccountLog
fmt.Println("amountPreMerchant = ", amountPreMerchant)
fmt.Println("merchantAccount.Amount = ", merchantAccount.Amount)
merchantAccountLog.MerchantOpenID = merchantOpenId
merchantAccountLog.UpdatedAt = time.Now()
merchantAccountLog.AmountPre = amountPreMerchant
merchantAccountLog.AmountAfter = merchantAmountAdd
merchantAccountLog.ReviewAmountAfter = merchantAccount.ReviewAmount
merchantAccountLog.ReviewAmountPre = merchantAccount.ReviewAmount
merchantAccountLog.Amount = merchantAmount
merchantAccountLog.PayTransId = payTransId
err = tx.Table("merchant_account_log").Create(&merchantAccountLog).Error
if err != nil {
return err
}
return nil
}
func (m *ClientPayTrans) SettleAddCashOutFee(amount decimal.Decimal, clientOpenId string, cashOutId int64) error {
// 使用事务 添加
var err error
var clientAccount MerchantClientAccount
var amountPreClient decimal.Decimal
tx := orm.ShMysql.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
err = tx.Table("merchant_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error
if err != nil && err.Error() != "record not found" {
return err
}
if clientAccount.ID == 0 {
clientAccount.ClientOpenID = clientOpenId
clientAccount.Version = 1
clientAccount.UpdatedAt = time.Now()
clientAccount.CreatedAt = time.Now()
err = tx.Table("merchant_client_account").Create(&clientAccount).Error
if err != nil {
return err
}
}
amountPreClient = clientAccount.Amount
clientAmountAdd := clientAccount.Amount.Add(amount)
result := tx.Table("merchant_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates(
map[string]interface{}{
"amount": clientAmountAdd,
"version": clientAccount.Version + 1,
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
var clientAccountLog MerchantClientAccountLog
clientAccountLog.ClientOpenID = clientOpenId
clientAccountLog.UpdatedAt = time.Now()
clientAccountLog.AmountPre = amountPreClient
clientAccountLog.AmountAfter = clientAmountAdd
clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount
clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount
clientAccountLog.Amount = amount
clientAccountLog.PayTransId = cashOutId
clientAccountLog.TransType = 3 //服务费
err = tx.Table("merchant_client_account_log").Create(&clientAccountLog).Error
if err != nil {
return err
}
return nil
}
func (m *ClientPayTrans) SettleSubClient(clientAmount decimal.Decimal, clientOpenId string, cashOutId int64) error {
// 使用事务 添加
var err error
var clientAccount MerchantClientAccount
var cashOut CashOut
var amountPreClient decimal.Decimal
tx := orm.ShMysql.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
err = tx.Table("merchant_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error
if err != nil {
return err
}
amountPreClient = clientAccount.Amount
if clientAccount.Amount.Cmp(clientAmount) < 0 {
err = errors.New("账户金额不够")
return err
}
clientAmountSub := clientAccount.Amount.Sub(clientAmount)
result := tx.Table("merchant_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates(
map[string]interface{}{
"amount": clientAmountSub,
"version": clientAccount.Version + 1,
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
var clientAccountLog MerchantClientAccountLog
clientAccountLog.ClientOpenID = clientOpenId
clientAccountLog.UpdatedAt = time.Now()
clientAccountLog.AmountPre = amountPreClient
clientAccountLog.AmountAfter = clientAmountSub
clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount
clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount
clientAccountLog.Amount = clientAmount
clientAccountLog.PayTransId = cashOutId
clientAccountLog.TransType = 2
err = tx.Table("merchant_client_account_log").Create(&clientAccountLog).Error
if err != nil {
return err
}
result = tx.Table("cash_out").Model(&cashOut).Where("id = ? ", cashOutId).Updates(
map[string]interface{}{
"status": 99, //体现成功
"account_status": 99, //分账成功
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
return nil
}
func (m *ClientPayTrans) SettleSubMerchant(merchantAmount decimal.Decimal, merchantOpenId string, cashOutId int64) error {
// 使用事务 添加
var err error
var merchantAccount MerchantAccount
var cashOut CashOut
var amountPreMerchant decimal.Decimal
tx := orm.ShMysql.Begin()
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
err = tx.Table("merchant_account").Select("*").Where("merchant_open_id = ?", merchantOpenId).Find(&merchantAccount).Error
if err != nil {
return err
}
amountPreMerchant = merchantAccount.Amount
if merchantAccount.Amount.Cmp(merchantAmount) < 0 {
err = errors.New("账户金额不够")
return err
}
merchantAmountSub := merchantAccount.Amount.Sub(merchantAmount)
result := tx.Table("merchant_account").Model(&merchantAccount).Where("merchant_open_id = ? and version = ?", merchantOpenId, merchantAccount.Version).Updates(
map[string]interface{}{
"amount": merchantAmountSub,
"version": merchantAccount.Version + 1,
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
var merchantAccountLog MerchantAccountLog
merchantAccountLog.MerchantOpenID = merchantOpenId
merchantAccountLog.UpdatedAt = time.Now()
merchantAccountLog.AmountPre = amountPreMerchant
merchantAccountLog.AmountAfter = merchantAmountSub
merchantAccountLog.ReviewAmountAfter = merchantAccount.ReviewAmount
merchantAccountLog.ReviewAmountPre = merchantAccount.ReviewAmount
merchantAccountLog.Amount = merchantAmount
merchantAccountLog.PayTransId = cashOutId
merchantAccountLog.TransType = 2
err = tx.Table("merchant_account_log").Create(&merchantAccountLog).Error
if err != nil {
return err
}
result = tx.Table("cash_out").Model(&cashOut).Where("id = ? ", cashOutId).Updates(
map[string]interface{}{
"status": 99, //体现成功
"account_status": 99, //分账成功
"updated_at": time.Now()})
if result.Error != nil {
err = result.Error
return err
}
if result.RowsAffected <= 0 {
err = errors.New("rows is zero")
return err
}
return nil
}