@@ -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 | ||||
@@ -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"` | |||||
} |
@@ -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)"` | |||||
} |
@@ -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)"` | |||||
} | } |
@@ -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)"` | |||||
} | } |
@@ -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"` | ||||
@@ -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 | |||||
} |
@@ -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 | |||||
} |