Browse Source

更新

master
huangjiajun 7 months ago
parent
commit
e42787f744
8 changed files with 379 additions and 14 deletions
  1. +8
    -0
      db/db_user.go
  2. +32
    -0
      db/model/o2o_fin_user_flow.go
  3. +49
    -0
      db/model/o2o_merchant.go
  4. +3
    -0
      db/model/subsidy_base.go
  5. +1
    -0
      db/model/subsidy_with_user_month.go
  6. +3
    -0
      md/fin_user_flow.go
  7. +168
    -14
      rule/consume_integral_settlement.go
  8. +115
    -0
      svc/svc_deal_user_amount.go

+ 8
- 0
db/db_user.go View File

@@ -42,6 +42,14 @@ func UserProfileFindByIDWithSession(sess *xorm.Session, id interface{}) (*model.
} }
return &m, nil return &m, nil
} }
func O2oMerchantFindByIDWithSession(sess *xorm.Session, id interface{}) (*model.O2oMerchant, error) {
var m model.O2oMerchant
if has, err := sess.Where("id = ?", id).
Get(&m); err != nil || has == false {
return nil, zhios_order_relate_logx.Warn(err)
}
return &m, nil
}
func UserProfileUpdateWithSession(session *xorm.Session, uid interface{}, userProfile *model.UserProfile, forceCols ...string) (int64, error) { func UserProfileUpdateWithSession(session *xorm.Session, uid interface{}, userProfile *model.UserProfile, forceCols ...string) (int64, error) {
var ( var (
affected int64 affected int64


+ 32
- 0
db/model/o2o_fin_user_flow.go View File

@@ -0,0 +1,32 @@
package model

import (
"time"
)

type O2oFinUserFlow struct {
Id int64 `json:"id" xorm:"pk autoincr comment('流水编号') BIGINT(20)"`
Uid int `json:"uid" xorm:"not null default 0 comment('用户id') INT(11)"`
MerchantId int `json:"merchant_id" xorm:"default 0 comment('商家id') INT(11)"`
StoreId int `json:"store_id" xorm:"default 0 comment('店铺id') INT(11)"`
Type int `json:"type" xorm:"not null default 0 comment('0收入,1支出') TINYINT(1)"`
Amount string `json:"amount" xorm:"not null default 0.0000 comment('变动金额') DECIMAL(11,4)"`
BeforeAmount string `json:"before_amount" xorm:"not null default 0.0000 comment('变动前金额') DECIMAL(11,4)"`
AfterAmount string `json:"after_amount" xorm:"not null default 0.0000 comment('变动后金额') DECIMAL(11,4)"`
SysFee string `json:"sys_fee" xorm:"not null default 0.0000 comment('手续费') DECIMAL(11,4)"`
PaymentType int `json:"payment_type" xorm:"not null default 1 comment('1支付宝,2微信.3手动转账') TINYINT(1)"`
OrdType string `json:"ord_type" xorm:"not null default '' comment('订单类型 o2o_goods(小店), o2o_hotel(酒店) withdraw(提现)') VARCHAR(255)"`
OrdId string `json:"ord_id" xorm:"not null default '' comment('对应订单编号') VARCHAR(50)"`
OrdTitle string `json:"ord_title" xorm:"not null default '' comment('订单标题') VARCHAR(50)"`
OrdAction int `json:"ord_action" xorm:"not null default 0 comment('10自购,11推广,12团队,13免单,20提现,21消费,22退款,23拼团返佣,24区域代理,25重置虚拟币 26充值') TINYINT(2)"`
OrdTime int `json:"ord_time" xorm:"not null default 0 comment('下单时间or提现时间') INT(11)"`
OrdDetail string `json:"ord_detail" xorm:"not null default '' comment('记录商品ID或提现账号') VARCHAR(50)"`
ExpectedTime string `json:"expected_time" xorm:"not null default '0' comment('预期到账时间,字符串用于直接显示,结算后清除内容') VARCHAR(30)"`
Date string `json:"date" xorm:"not null default 1 comment('1未到账,2已到账') VARCHAR(50)"`
State int `json:"state" xorm:"not null default 1 comment('1未到账,2已到账') TINYINT(1)"`
Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(2000)"`
OtherId int64 `json:"other_id" xorm:"not null default 0 comment('其他关联订单,具体根据订单类型判断') index BIGINT(20)"`
AliOrdId string `json:"ali_ord_id" xorm:"default '' comment('支付宝订单号') VARCHAR(128)"`
CreateAt time.Time `json:"create_at" xorm:"created not null default 'CURRENT_TIMESTAMP' comment('创建时间') TIMESTAMP"`
UpdateAt time.Time `json:"update_at" xorm:"updated not null default 'CURRENT_TIMESTAMP' comment('更新时间') TIMESTAMP"`
}

+ 49
- 0
db/model/o2o_merchant.go View File

@@ -0,0 +1,49 @@
package model

import (
"time"
)

type O2oMerchant struct {
Id int `json:"id" xorm:"not null pk autoincr INT(11)"`
Pid int `json:"pid" xorm:"comment('主账号id') INT(11)"`
AvatarUrl string `json:"avatar_url" xorm:"comment('用户头像') VARCHAR(255)"`
Type string `json:"type" xorm:"not null comment('商家类型,可多个') VARCHAR(255)"`
Phone string `json:"phone" xorm:"not null comment('商家手机号') VARCHAR(255)"`
Email string `json:"email" xorm:"not null comment('商家邮箱') VARCHAR(255)"`
Wechat string `json:"wechat" xorm:"comment('微信号') VARCHAR(255)"`
AccountAlipay string `json:"account_alipay" xorm:"comment('支付宝账户') VARCHAR(50)"`
AccountAlipayRealName string `json:"account_alipay_real_name" xorm:"comment('支付宝持有人姓名') VARCHAR(255)"`
Password string `json:"password" xorm:"not null comment('密码') VARCHAR(255)"`
Name string `json:"name" xorm:"not null comment('名称') VARCHAR(255)"`
FunctionalAuthority string `json:"functional_authority" xorm:"not null comment('功能权限角色id') VARCHAR(255)"`
State int `json:"state" xorm:"default 1 comment('商家状态') TINYINT(1)"`
Token string `json:"token" xorm:"comment('token') VARCHAR(520)"`
Amount float64 `json:"amount" xorm:"comment('商家余额') DOUBLE(10,2)"`
FrozenAmount float64 `json:"frozen_amount" xorm:"comment('商家冻结余额') DOUBLE(16,4)"`
AuthWay int `json:"auth_way" xorm:"default 1 comment('1:统一授权模式,2:普通授权') TINYINT(1)"`
CreateTime time.Time `json:"create_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') DATETIME"`
UpdateTime time.Time `json:"update_time" xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') DATETIME"`
DeletedTime time.Time `json:"deleted_time" xorm:"comment('删除时间') DATETIME"`
Gender int `json:"gender" xorm:"default 0 comment('0女,1:男,其他为未知性别') TINYINT(1)"`
Birthday *time.Time `json:"birthday" xorm:"comment('生日') DATE"`
NotificationSetting string `json:"notification_setting" xorm:"comment('通知设置 json格式') TEXT"`
Info string `json:"info" xorm:"comment('补充信息') LONGTEXT"`
BelongStore string `json:"belong_store" xorm:"comment('归属店铺(只有员工才有)') VARCHAR(255)"`
RealName string `json:"real_name" xorm:"comment('真实姓名') VARCHAR(255)"`
IdNumber string `json:"Id_number" xorm:"comment('身份证号') VARCHAR(255)"`
InviteCode string `json:"invite_code" xorm:"comment('邀请码(唯一)') VARCHAR(255)"`
IsvTicket string `json:"isv_ticket" xorm:"comment('支付宝isv_ticket(唯一)') VARCHAR(255)"`
PushHandId int `json:"push_hand_id" xorm:"comment('推手id(推送分享出去后注册的商家绑定)') INT(11)"`
Uid string `json:"uid" xorm:"comment('智莺生活用户id') VARCHAR(50)"`
FreezeAmount float64 `json:"freeze_amount" xorm:"comment('商家冻结余额(B2C中用户支付后,商家的钱先流去冻结余额,完成订单才会流去余额)') DOUBLE(10,2)"`
B2cAmount float64 `json:"b2c_amount" xorm:"comment('b2c商家余额') DOUBLE(16,4)"`
B2cBindAlipay string `json:"b2c_bind_alipay" xorm:"comment('b2c绑定的支付宝账户') VARCHAR(50)"`
B2cBindAlipayName string `json:"b2c_bind_alipay_name" xorm:"comment('b2c绑定的支付宝账户姓名') VARCHAR(255)"`
AccountWx string `json:"account_wx" xorm:"comment('微信账号(o2o用)') VARCHAR(255)"`
AccountWxRealName string `json:"account_wx_real_name" xorm:"comment('微信账号持有人姓名(o2o用)') VARCHAR(255)"`
AccountWxOpenId string `json:"account_wx_open_id" xorm:"comment('微信账号持有人的OpenId(o2o用)') VARCHAR(255)"`
B2cBindWx string `json:"b2c_bind_wx" xorm:"comment('b2c绑定的微信账户') VARCHAR(255)"`
B2cBindWxName string `json:"b2c_bind_wx_name" xorm:"comment('b2c绑定的微信账户姓名') VARCHAR(255)"`
Zone string `json:"zone" xorm:" default '86' comment('区号') VARCHAR(10)"`
}

+ 3
- 0
db/model/subsidy_base.go View File

@@ -18,4 +18,7 @@ type SubsidyBase struct {
SettleTime string `json:"settle_time" xorm:"comment('每天 XX:xx') VARCHAR(255)"` SettleTime string `json:"settle_time" xorm:"comment('每天 XX:xx') VARCHAR(255)"`
HolidaySettleOpen int `json:"holiday_settle_open" xorm:"default 0 comment('节假日是否结算') INT(1)"` HolidaySettleOpen int `json:"holiday_settle_open" xorm:"default 0 comment('节假日是否结算') INT(1)"`
SettlementDate string `json:"settlement_date" xorm:"not null default '0000-00' comment('结算日期(0000-00)') CHAR(50)"` SettlementDate string `json:"settlement_date" xorm:"not null default '0000-00' comment('结算日期(0000-00)') CHAR(50)"`
StoreOpen int `json:"store_open" xorm:"default 0 comment('节假日是否结算') INT(1)"`
StoreIntegral string `json:"store_integral" xorm:"default 0.00 comment('消费补贴') DECIMAL(20,2)"`
StoreMoney string `json:"store_money" xorm:"default 0.00 comment('消费补贴') DECIMAL(20,2)"`
} }

+ 1
- 0
db/model/subsidy_with_user_month.go View File

@@ -6,4 +6,5 @@ type SubsidyWithUserMonth struct {
Date string `json:"date" xorm:"comment('2023-12') VARCHAR(255)"` Date string `json:"date" xorm:"comment('2023-12') VARCHAR(255)"`
ConsumeAmount string `json:"consume_amount" xorm:"default 0.00 DECIMAL(20,2)"` ConsumeAmount string `json:"consume_amount" xorm:"default 0.00 DECIMAL(20,2)"`
ExperienceAmount string `json:"experience_amount" xorm:"default 0.00 DECIMAL(20,2)"` ExperienceAmount string `json:"experience_amount" xorm:"default 0.00 DECIMAL(20,2)"`
StoreAmount string `json:"store_amount" xorm:"default 0.00 DECIMAL(20,2)"`
} }

+ 3
- 0
md/fin_user_flow.go View File

@@ -15,6 +15,7 @@ const (
IntegralReleaseServiceRevenueRefundTitleForFinUserFlow = "订单退款-服务收益扣除" IntegralReleaseServiceRevenueRefundTitleForFinUserFlow = "订单退款-服务收益扣除"
ConsumeSubsidyTitleForFinUserFlow = "消费补贴-收益" ConsumeSubsidyTitleForFinUserFlow = "消费补贴-收益"
ExperienceSubsidyTitleForFinUserFlow = "体验补贴-收益" ExperienceSubsidyTitleForFinUserFlow = "体验补贴-收益"
StoreSubsidyTitleForFinUserFlow = "门店补贴-收益"
GreenEnergyExchangeForBalanceTitleForFinUserFlow = "兑换账户余额" GreenEnergyExchangeForBalanceTitleForFinUserFlow = "兑换账户余额"
BalanceExchangeForGreenEnergyTitleForFinUserFlow = "账户余额兑换" BalanceExchangeForGreenEnergyTitleForFinUserFlow = "账户余额兑换"
GreenCoinDoubleChainExchangeForBalanceTitleForFinUserFlow = "绿色积分双链兑换账户余额" GreenCoinDoubleChainExchangeForBalanceTitleForFinUserFlow = "绿色积分双链兑换账户余额"
@@ -25,6 +26,7 @@ const (
IntegralReleaseServiceRevenueOrderRefundTypeForFinUserFlow = 51 // 积分释放-服务收益退款 IntegralReleaseServiceRevenueOrderRefundTypeForFinUserFlow = 51 // 积分释放-服务收益退款
ConsumeSubsidyOrdActionForFinUserFlow = 110 // 消费补贴-收益 ConsumeSubsidyOrdActionForFinUserFlow = 110 // 消费补贴-收益
ExperienceSubsidyOrdActionForFinUserFlow = 111 // 体验补贴-收益 ExperienceSubsidyOrdActionForFinUserFlow = 111 // 体验补贴-收益
StoreSubsidyOrdActionForFinUserFlow = 115 // 体验补贴-收益
GreenEnergyExchangeForBalanceForFinUserFlow = 112 // 兑换账户余额 GreenEnergyExchangeForBalanceForFinUserFlow = 112 // 兑换账户余额
BalanceExchangeForGreenEnergyForFinUserFlow = 113 // 账户余额兑换 BalanceExchangeForGreenEnergyForFinUserFlow = 113 // 账户余额兑换
GreenCoinDoubleChainExchangeForBalanceForFinUserFlow = 114 // 绿色积分双链兑换账户余额 GreenCoinDoubleChainExchangeForBalanceForFinUserFlow = 114 // 绿色积分双链兑换账户余额
@@ -32,6 +34,7 @@ const (


const DealUserAmountRequestIdPrefix = "%s:deal_user_amount:%d" const DealUserAmountRequestIdPrefix = "%s:deal_user_amount:%d"
const UserAmountRedisKey = "%s:rule_user_amount:%d" const UserAmountRedisKey = "%s:rule_user_amount:%d"
const StoreUserAmountRedisKey = "%s:rule_store_user_amount:%d"


type DealIntegralReleaseInterpositionUserAmountReq struct { type DealIntegralReleaseInterpositionUserAmountReq struct {
Kind string `json:"kind"` Kind string `json:"kind"`


+ 168
- 14
rule/consume_integral_settlement.go View File

@@ -83,8 +83,8 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask
} }
cache.SetEx(key, PessimismLockValueForConsumeIntegral, 3600*8) //8小时 cache.SetEx(key, PessimismLockValueForConsumeIntegral, 3600*8) //8小时


var consumeValueTotal, experienceValueTotal = decimal.NewFromInt(0), decimal.NewFromInt(0)
var consumeValue, experienceValue float64
var consumeValueTotal, experienceValueTotal, storeValueTotal = decimal.NewFromInt(0), decimal.NewFromInt(0), decimal.NewFromInt(0)
var consumeValue, experienceValue, storeValue float64
//1、统计当前拥有多少份消费补贴 //1、统计当前拥有多少份消费补贴
startAt := time.Now().Add(time.Duration(subsidyBase.ConsumptionDay) * -24 * time.Hour).Format("2006-01-02") //起始时间 startAt := time.Now().Add(time.Duration(subsidyBase.ConsumptionDay) * -24 * time.Hour).Format("2006-01-02") //起始时间
var subsidyWithUserForConsumeList []model.SubsidyWithUser var subsidyWithUserForConsumeList []model.SubsidyWithUser
@@ -94,15 +94,30 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask


return return
} }
var subsidyWithUserForExperienceList []model.SubsidyWithUser
hasExperienceTotal, err := session.Where("date <= ?", startAt).And("kind = ? and is_can_subsidy=?", 2, 1).FindAndCount(&subsidyWithUserForExperienceList)
if err != nil {
_ = session.Rollback()
return
}
var subsidyWithUserForStoreList []model.SubsidyWithUser
hasStoreTotal, err := session.Where("date <= ?", startAt).And("kind = ? and is_can_subsidy=?", 3, 1).FindAndCount(&subsidyWithUserForStoreList)
if err != nil {
_ = session.Rollback()
return
}
var consumeTotalMap = make(map[int]decimal.Decimal) var consumeTotalMap = make(map[int]decimal.Decimal)
var consumeTotalCountMap = make(map[int]int) var consumeTotalCountMap = make(map[int]int)
total := hasConsumeTotal + hasExperienceTotal
if subsidyBase.StoreOpen == 1 {
total += hasStoreTotal
}
consumeValue, err = calcNowEverydayConsumeIntegral(subsidyBase, total)
if err != nil {
_ = session.Rollback()
return err
}
if hasConsumeTotal > 0 { if hasConsumeTotal > 0 {
consumeValue, err = calcNowEverydayConsumeIntegral(subsidyBase, hasConsumeTotal)
if err != nil {
_ = session.Rollback()
return err
}

for _, v := range subsidyWithUserForConsumeList { for _, v := range subsidyWithUserForConsumeList {
consumeTotalMap[v.Uid] = consumeTotalMap[v.Uid].Add(decimal.NewFromFloat(consumeValue)) consumeTotalMap[v.Uid] = consumeTotalMap[v.Uid].Add(decimal.NewFromFloat(consumeValue))
consumeTotalCountMap[v.Uid]++ consumeTotalCountMap[v.Uid]++
@@ -125,12 +140,7 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask
} }
} }
//2、统计当前拥有多少份体验补贴 //2、统计当前拥有多少份体验补贴
var subsidyWithUserForExperienceList []model.SubsidyWithUser
hasExperienceTotal, err := session.Where("date <= ?", startAt).And("kind = ? and is_can_subsidy=?", 2, 1).FindAndCount(&subsidyWithUserForExperienceList)
if err != nil {
_ = session.Rollback()
return
}

var experienceTotalMap = make(map[int]decimal.Decimal) var experienceTotalMap = make(map[int]decimal.Decimal)
var experienceTotalCountMap = make(map[int]int) var experienceTotalCountMap = make(map[int]int)
if hasExperienceTotal > 0 && consumeValue > 0 { if hasExperienceTotal > 0 && consumeValue > 0 {
@@ -160,6 +170,41 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask
} }
} }
} }

//2、统计当前拥有多少份门店补贴
if subsidyBase.StoreOpen == 1 {

var storeTotalMap = make(map[int]decimal.Decimal)
var storeTotalCountMap = make(map[int]int)
if hasStoreTotal > 0 && consumeValue > 0 {
experienceValue, err = calcNowEverydayStoreIntegral(consumeValue, zhios_order_relate_utils.StrToFloat64(subsidyBase.StoreIntegral)/zhios_order_relate_utils.StrToFloat64(subsidyBase.ConsumptionIntegral))
if err != nil {
_ = session.Rollback()
return err
}
for _, v := range subsidyWithUserForStoreList {
storeTotalCountMap[v.Uid]++
storeTotalMap[v.Uid] = storeTotalMap[v.Uid].Add(decimal.NewFromFloat(storeValue))
storeValueTotal = storeValueTotal.Add(decimal.NewFromFloat(storeValue))
err1 := DealUserStoreIntegral(session, &v, storeValue, mid)
if err1 != nil {
_ = session.Rollback()
return err1
}
}
}
//加余额流水
if len(storeTotalMap) > 0 {
for k, v := range storeTotalMap {
err1 := DealUserStoreAmountFlow(session, k, zhios_order_relate_utils.StrToFloat64(v.String()), mid, zhios_order_relate_utils.IntToStr(experienceTotalCountMap[k]))
if err1 != nil {
_ = session.Rollback()
return err1
}
}
}
}

//3、修改 subsidy_base 中 consumption_money、experience_money //3、修改 subsidy_base 中 consumption_money、experience_money
consumeTotal, _ := consumeValueTotal.Float64() consumeTotal, _ := consumeValueTotal.Float64()
experienceTotal, _ := experienceValueTotal.Float64() experienceTotal, _ := experienceValueTotal.Float64()
@@ -215,6 +260,19 @@ func calcNowEverydayExperienceIntegral(consumeValue float64) (value float64, err
//value, _ = experienceMoney.Mul(floatSubsidyBili).Div(consumeTotal).Add(baseSubsidyMoney).RoundFloor(2).Float64() //value, _ = experienceMoney.Mul(floatSubsidyBili).Div(consumeTotal).Add(baseSubsidyMoney).RoundFloor(2).Float64()
return return
} }
func calcNowEverydayStoreIntegral(consumeValue, bili float64) (value float64, err error) {
value, _ = decimal.NewFromFloat(consumeValue * bili).RoundFloor(2).Float64()
////2、通过公式计算 "((资金池的金额 * 浮动比例) / 体验补贴总数) + 基础补贴"
//experienceMoney, _ := decimal.NewFromString(subsidyBase.ExperienceTotalMoney)
//baseSubsidyMoney, _ := decimal.NewFromString(subsidyBase.BaseSubsidyMoney)
//if subsidyBase.FloatSubsidyOpen == 0 { //没有浮动补贴情况
// subsidyBase.FloatSubsidyBili = 0
//}
//floatSubsidyBili := decimal.NewFromFloat(float64(subsidyBase.FloatSubsidyBili) / 10000)
//consumeTotal := decimal.NewFromInt(hasExperienceTotal)
//value, _ = experienceMoney.Mul(floatSubsidyBili).Div(consumeTotal).Add(baseSubsidyMoney).RoundFloor(2).Float64()
return
}


// DealUserConsumeIntegral 处理给用户发放消费补贴奖励 // DealUserConsumeIntegral 处理给用户发放消费补贴奖励
func DealUserConsumeIntegral(session *xorm.Session, subsidyWithUser *model.SubsidyWithUser, consumeIntegralValue float64, mid string) (err error) { func DealUserConsumeIntegral(session *xorm.Session, subsidyWithUser *model.SubsidyWithUser, consumeIntegralValue float64, mid string) (err error) {
@@ -363,6 +421,80 @@ func DealUserExperienceIntegral(session *xorm.Session, subsidyWithUser *model.Su


} }


// DealUserExperienceIntegral 处理给用户发放体验补贴奖励
func DealUserStoreIntegral(session *xorm.Session, subsidyWithUser *model.SubsidyWithUser, experienceIntegralValue float64, mid string) (err error) {
now := time.Now()
//1、扣除 subsidy_with_user 的 balance_amount、state
if subsidyWithUser.Amount == subsidyWithUser.BalanceAmount {
subsidyWithUser.State = 2 //补贴中
}
balanceAmount, _ := decimal.NewFromString(subsidyWithUser.BalanceAmount)
afterAmount, _ := balanceAmount.Sub(decimal.NewFromFloat(experienceIntegralValue)).Float64()
if afterAmount <= 0 {
afterAmount = 0
experienceIntegralValue = zhios_order_relate_utils.StrToFloat64(subsidyWithUser.BalanceAmount)
subsidyWithUser.State = 3 //补贴完
}
subsidyWithUser.BalanceAmount = zhios_order_relate_utils.Float64ToStr(afterAmount)
updateAffected, err := db.SubsidyWithUserUpdate(session, subsidyWithUser.Id, subsidyWithUser, "balance_amount", "state")
if err != nil {
return err
}
if updateAffected <= 0 {
return errors.New("修改 subsidy_with_user 记录失败")
}

//2、新增 subsidy_with_user_flow 记录
var subsidyWitUserFlow = &model.SubsidyWithUserFlow{
RecordsId: subsidyWithUser.Id,
Uid: subsidyWithUser.Uid,
Kind: subsidyWithUser.Kind,
Amount: zhios_order_relate_utils.Float64ToStr(experienceIntegralValue),
BalanceAmount: zhios_order_relate_utils.Float64ToStr(afterAmount),
CreateAt: now.Format("2006-01-02 15:04:05"),
Date: now.Format("2006-01-02"),
Month: zhios_order_relate_utils.StrToInt(now.Format("200601")),
UpdateAt: now.Format("2006-01-02 15:04:05"),
}
insertAffected, err := db.SubsidyWithUserFlowInsert(session, subsidyWitUserFlow)
if err != nil {
return err
}
if insertAffected <= 0 {
return errors.New("新增 subsidy_with_user_flow 记录失败")
}
//3、加入每月统计
if experienceIntegralValue > 0 {
var subsidyWitUserMonth = &model.SubsidyWithUserMonth{
Uid: subsidyWithUser.Uid,
StoreAmount: zhios_order_relate_utils.Float64ToStr(experienceIntegralValue),
Date: now.Format("2006-01"),
}
_, err1 := db.SubsidyWithMonthInsert(session, subsidyWitUserMonth)
if err1 != nil {
return err
}
}
//4、给用户添加余额
orderType := enum.FinUserFlowOrderActionString(md.StoreSubsidyOrdActionForFinUserFlow)
var dealUserAmount = md.DealUserAmount{
Kind: "add",
Mid: mid,
Title: md.StoreSubsidyTitleForFinUserFlow,
OrderType: orderType,
OrdAction: md.StoreSubsidyOrdActionForFinUserFlow,
OrdId: strconv.Itoa(subsidyWithUser.Id),
Uid: subsidyWithUser.Uid,
Amount: experienceIntegralValue,
}
err = svc.DealStoreUserAmountNew(session, dealUserAmount)
if err != nil {
return
}
return nil

}

// DealUserConsumeIntegral 处理给用户发放消费补贴奖励 流水 // DealUserConsumeIntegral 处理给用户发放消费补贴奖励 流水
func DealUserConsumeAmountFlow(session *xorm.Session, uid int, consumeIntegralValue float64, mid, num string) (err error) { func DealUserConsumeAmountFlow(session *xorm.Session, uid int, consumeIntegralValue float64, mid, num string) (err error) {
//4、给用户添加余额流水 //4、给用户添加余额流水
@@ -405,3 +537,25 @@ func DealUserExperienceAmountFlow(session *xorm.Session, uid int, experienceInte
return nil return nil


} }

// DealUserExperienceIntegral 处理给用户发放体验补贴奖励
func DealUserStoreAmountFlow(session *xorm.Session, uid int, experienceIntegralValue float64, mid, num string) (err error) {
//4、给用户添加余额
orderType := enum.FinUserFlowOrderActionString(md.StoreSubsidyOrdActionForFinUserFlow)
var dealUserAmount = md.DealUserAmount{
Kind: "add",
Mid: mid,
Title: md.StoreSubsidyTitleForFinUserFlow,
OrderType: orderType,
OrdAction: md.StoreSubsidyOrdActionForFinUserFlow,
Uid: uid,
Amount: experienceIntegralValue,
Num: num,
}
err = svc.DealUserStoreAmountFlow(session, dealUserAmount)
if err != nil {
return
}
return nil

}

+ 115
- 0
svc/svc_deal_user_amount.go View File

@@ -127,6 +127,44 @@ func DealUserAmountNew(session *xorm.Session, req md.DealUserAmount) (err error)


return nil return nil
} }
func DealStoreUserAmountNew(session *xorm.Session, req md.DealUserAmount) (err error) {
if req.Amount < 0 {
req.Amount = 0
}
//1、分布式锁阻拦
requestIdPrefix := fmt.Sprintf(md.DealUserAmountRequestIdPrefix, req.Mid, req.Uid)
cb, err := HandleBalanceDistributedLockForAmount(req.Mid, strconv.Itoa(req.Uid), requestIdPrefix)
if err != nil {
return err
}
if cb != nil {
defer cb() // 释放锁
}

//2、计算&&组装数据
userAmount, err := GetStoreUserAmount(session, req.Mid, req.Uid)
if err != nil {
return err
}
userAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount))
amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(8)
AfterAmount := ""
if req.Kind == "add" {
AfterAmount = userAmountValue.Add(amountValue).RoundFloor(8).String()
} else if req.Kind == "sub" {
AfterAmount = userAmountValue.Sub(amountValue).RoundFloor(8).String()
} else {
err = errors.New("错误的kind类型")
return err
}
//4、修改 `user_profile`的fin_valid值 && 及缓存
err = SetCacheStoreUserAmount(session, req.Mid, AfterAmount, req.Uid, true)
if err != nil {
return err
}

return nil
}
func DealUserAmountFlow(session *xorm.Session, req md.DealUserAmount) (err error) { func DealUserAmountFlow(session *xorm.Session, req md.DealUserAmount) (err error) {
if req.Amount < 0 { if req.Amount < 0 {
req.Amount = 0 req.Amount = 0
@@ -176,6 +214,55 @@ func DealUserAmountFlow(session *xorm.Session, req md.DealUserAmount) (err error
} }
return nil return nil
} }
func DealUserStoreAmountFlow(session *xorm.Session, req md.DealUserAmount) (err error) {
if req.Amount < 0 {
req.Amount = 0
}
//2、计算&&组装数据
now := time.Now()
userAmount, err := GetStoreUserAmount(session, req.Mid, req.Uid)
if err != nil {
return err
}
userAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount))
amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(8)

var finUserFlow = model.O2oFinUserFlow{
Uid: req.Uid,
Amount: amountValue.String(),
AfterAmount: userAmount,
OrdType: req.OrderType,
OrdId: req.OrdId,
OrdTitle: req.Title,
OrdAction: req.OrdAction,
OrdTime: int(now.Unix()),
State: 1,
CreateAt: now,
UpdateAt: now,
Memo: req.Num,
Date: now.Format("2006-01-02"),
}
finUserFlow.Type = 0
finUserFlow.BeforeAmount = userAmountValue.Sub(amountValue).RoundFloor(8).String()
if zhios_order_relate_utils.StrToFloat64(finUserFlow.AfterAmount) < 0 {
zhios_order_relate_utils.FilePutContents("user_amount_not", zhios_order_relate_utils.SerializeStr(map[string]interface{}{
"uid": finUserFlow.Uid,
"amount": finUserFlow.Amount,
"before_amount": finUserFlow.BeforeAmount,
"title": finUserFlow.OrdTitle,
"mid": req.Mid,
}))
return errors.New("用户余额不足")
}

//3、插入 `fin_user_flow` 记录
affected, err := session.Insert(&finUserFlow)
if affected == 0 || err != nil {
_ = zhios_order_relate_logx.Warn(err)
return err
}
return nil
}


// GetUserAmount 获取用户余额 // GetUserAmount 获取用户余额
func GetUserAmount(session *xorm.Session, masterId string, uid int) (amount string, err error) { func GetUserAmount(session *xorm.Session, masterId string, uid int) (amount string, err error) {
@@ -221,3 +308,31 @@ func SetCacheUserAmount(session *xorm.Session, masterId, amount string, uid int,
} }
return nil return nil
} }

// GetUserAmount 获取用户余额
func GetStoreUserAmount(session *xorm.Session, masterId string, uid int) (amount string, err error) {
userAmount, err := db.O2oMerchantFindByIDWithSession(session, uid)
if err != nil {
return amount, err
}
if userAmount == nil {
amount = "0"
} else {
amount = zhios_order_relate_utils.Float64ToStrByPrec(userAmount.Amount, 8)
}

return amount, nil
}

// SetCacheUserAmount 设置缓存的用户余额
func SetCacheStoreUserAmount(session *xorm.Session, masterId, amount string, uid int, isUpdateDb bool) error {

_, err := session.Where("id=?", uid).Update(model.O2oMerchant{
Id: uid,
Amount: zhios_order_relate_utils.StrToFloat64(amount),
})
if err != nil {
return err
}
return nil
}

Loading…
Cancel
Save