From e42787f7447b5619ae3ac6ad8f46c5f916a844be Mon Sep 17 00:00:00 2001 From: huangjiajun <582604932@qq.com> Date: Sat, 23 Mar 2024 15:48:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/db_user.go | 8 ++ db/model/o2o_fin_user_flow.go | 32 +++++ db/model/o2o_merchant.go | 49 ++++++++ db/model/subsidy_base.go | 3 + db/model/subsidy_with_user_month.go | 1 + md/fin_user_flow.go | 3 + rule/consume_integral_settlement.go | 182 +++++++++++++++++++++++++--- svc/svc_deal_user_amount.go | 115 ++++++++++++++++++ 8 files changed, 379 insertions(+), 14 deletions(-) create mode 100644 db/model/o2o_fin_user_flow.go create mode 100644 db/model/o2o_merchant.go diff --git a/db/db_user.go b/db/db_user.go index f663f54..f35637d 100644 --- a/db/db_user.go +++ b/db/db_user.go @@ -42,6 +42,14 @@ func UserProfileFindByIDWithSession(sess *xorm.Session, id interface{}) (*model. } 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) { var ( affected int64 diff --git a/db/model/o2o_fin_user_flow.go b/db/model/o2o_fin_user_flow.go new file mode 100644 index 0000000..6099f18 --- /dev/null +++ b/db/model/o2o_fin_user_flow.go @@ -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"` +} diff --git a/db/model/o2o_merchant.go b/db/model/o2o_merchant.go new file mode 100644 index 0000000..d9b706f --- /dev/null +++ b/db/model/o2o_merchant.go @@ -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)"` +} diff --git a/db/model/subsidy_base.go b/db/model/subsidy_base.go index 1c297d6..1054671 100644 --- a/db/model/subsidy_base.go +++ b/db/model/subsidy_base.go @@ -18,4 +18,7 @@ type SubsidyBase struct { SettleTime string `json:"settle_time" xorm:"comment('每天 XX:xx') VARCHAR(255)"` 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)"` + 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)"` } diff --git a/db/model/subsidy_with_user_month.go b/db/model/subsidy_with_user_month.go index 78bbd0f..2160e4a 100644 --- a/db/model/subsidy_with_user_month.go +++ b/db/model/subsidy_with_user_month.go @@ -6,4 +6,5 @@ type SubsidyWithUserMonth struct { Date string `json:"date" xorm:"comment('2023-12') VARCHAR(255)"` ConsumeAmount string `json:"consume_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)"` } diff --git a/md/fin_user_flow.go b/md/fin_user_flow.go index 34d7e2f..b8a63e9 100644 --- a/md/fin_user_flow.go +++ b/md/fin_user_flow.go @@ -15,6 +15,7 @@ const ( IntegralReleaseServiceRevenueRefundTitleForFinUserFlow = "订单退款-服务收益扣除" ConsumeSubsidyTitleForFinUserFlow = "消费补贴-收益" ExperienceSubsidyTitleForFinUserFlow = "体验补贴-收益" + StoreSubsidyTitleForFinUserFlow = "门店补贴-收益" GreenEnergyExchangeForBalanceTitleForFinUserFlow = "兑换账户余额" BalanceExchangeForGreenEnergyTitleForFinUserFlow = "账户余额兑换" GreenCoinDoubleChainExchangeForBalanceTitleForFinUserFlow = "绿色积分双链兑换账户余额" @@ -25,6 +26,7 @@ const ( IntegralReleaseServiceRevenueOrderRefundTypeForFinUserFlow = 51 // 积分释放-服务收益退款 ConsumeSubsidyOrdActionForFinUserFlow = 110 // 消费补贴-收益 ExperienceSubsidyOrdActionForFinUserFlow = 111 // 体验补贴-收益 + StoreSubsidyOrdActionForFinUserFlow = 115 // 体验补贴-收益 GreenEnergyExchangeForBalanceForFinUserFlow = 112 // 兑换账户余额 BalanceExchangeForGreenEnergyForFinUserFlow = 113 // 账户余额兑换 GreenCoinDoubleChainExchangeForBalanceForFinUserFlow = 114 // 绿色积分双链兑换账户余额 @@ -32,6 +34,7 @@ const ( const DealUserAmountRequestIdPrefix = "%s:deal_user_amount:%d" const UserAmountRedisKey = "%s:rule_user_amount:%d" +const StoreUserAmountRedisKey = "%s:rule_store_user_amount:%d" type DealIntegralReleaseInterpositionUserAmountReq struct { Kind string `json:"kind"` diff --git a/rule/consume_integral_settlement.go b/rule/consume_integral_settlement.go index 16130ad..2ce14a1 100644 --- a/rule/consume_integral_settlement.go +++ b/rule/consume_integral_settlement.go @@ -83,8 +83,8 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask } 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、统计当前拥有多少份消费补贴 startAt := time.Now().Add(time.Duration(subsidyBase.ConsumptionDay) * -24 * time.Hour).Format("2006-01-02") //起始时间 var subsidyWithUserForConsumeList []model.SubsidyWithUser @@ -94,15 +94,30 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask 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 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 { - consumeValue, err = calcNowEverydayConsumeIntegral(subsidyBase, hasConsumeTotal) - if err != nil { - _ = session.Rollback() - return err - } - for _, v := range subsidyWithUserForConsumeList { consumeTotalMap[v.Uid] = consumeTotalMap[v.Uid].Add(decimal.NewFromFloat(consumeValue)) consumeTotalCountMap[v.Uid]++ @@ -125,12 +140,7 @@ func DailySettlementBlockConsumeIntegral(engine *xorm.Engine, mid string, isTask } } //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 experienceTotalCountMap = make(map[int]int) 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 consumeTotal, _ := consumeValueTotal.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() 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 处理给用户发放消费补贴奖励 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 处理给用户发放消费补贴奖励 流水 func DealUserConsumeAmountFlow(session *xorm.Session, uid int, consumeIntegralValue float64, mid, num string) (err error) { //4、给用户添加余额流水 @@ -405,3 +537,25 @@ func DealUserExperienceAmountFlow(session *xorm.Session, uid int, experienceInte 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 + +} diff --git a/svc/svc_deal_user_amount.go b/svc/svc_deal_user_amount.go index 1358d35..43b8453 100644 --- a/svc/svc_deal_user_amount.go +++ b/svc/svc_deal_user_amount.go @@ -127,6 +127,44 @@ func DealUserAmountNew(session *xorm.Session, req md.DealUserAmount) (err error) 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) { if req.Amount < 0 { req.Amount = 0 @@ -176,6 +214,55 @@ func DealUserAmountFlow(session *xorm.Session, req md.DealUserAmount) (err error } 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 获取用户余额 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 } + +// 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 +}