Parcourir la source

update

master
dengbiao il y a 4 mois
Parent
révision
ab7eddc295
8 fichiers modifiés avec 382 ajouts et 0 suppressions
  1. +2
    -0
      enum/fin_user_flow.go
  2. +2
    -0
      md/fin_user_flow.go
  3. +20
    -0
      rule/installment_payment/enum/installment_payment_list.go
  4. +164
    -0
      rule/installment_payment/installment_payment.go
  5. +142
    -0
      rule/installment_payment/installment_payment_auto_repaid.go
  6. +14
    -0
      rule/installment_payment/installment_payment_init.go
  7. +18
    -0
      rule/installment_payment/md/installment_payment_list.go
  8. +20
    -0
      rule/installment_payment/md/mq.go

+ 2
- 0
enum/fin_user_flow.go Voir le fichier

@@ -18,6 +18,8 @@ func FinUserFlowOrderActionString(kind int) string {
return "green_coin_double_chain_exchange_for_balance"
case md.StoreSubsidyOrdActionForFinUserFlow:
return "subsidy"
case md.InstallmentPaymentAutoRepaidForFinUserFlow:
return "installment_payment_auto_repaid"
default:
return "unknown"
}


+ 2
- 0
md/fin_user_flow.go Voir le fichier

@@ -19,6 +19,7 @@ const (
GreenEnergyExchangeForBalanceTitleForFinUserFlow = "兑换账户余额"
BalanceExchangeForGreenEnergyTitleForFinUserFlow = "账户余额兑换"
GreenCoinDoubleChainExchangeForBalanceTitleForFinUserFlow = "绿色积分双链兑换账户余额"
InstallmentPaymentAutoRepaidTitleForFinUserFlow = "分期付-自动扣款"
)

const (
@@ -30,6 +31,7 @@ const (
GreenEnergyExchangeForBalanceForFinUserFlow = 112 // 兑换账户余额
BalanceExchangeForGreenEnergyForFinUserFlow = 113 // 账户余额兑换
GreenCoinDoubleChainExchangeForBalanceForFinUserFlow = 114 // 绿色积分双链兑换账户余额
InstallmentPaymentAutoRepaidForFinUserFlow = 116 // 分期付-自动扣款
)

const DealUserAmountRequestIdPrefix = "%s:deal_user_amount:%d"


+ 20
- 0
rule/installment_payment/enum/installment_payment_list.go Voir le fichier

@@ -0,0 +1,20 @@
package enum

// InstallmentPaymentListIsRepaidOff 分期付列表 - 是否已偿还完
type InstallmentPaymentListIsRepaidOff int

const (
InstallmentPaymentListRepaidOff InstallmentPaymentListIsRepaidOff = iota
InstallmentPaymentListRepaidOn
)

func (i InstallmentPaymentListIsRepaidOff) String() string {
switch i {
case InstallmentPaymentListRepaidOff:
return "未偿还完"
case InstallmentPaymentListRepaidOn:
return "已偿还完"
default:
return "未知"
}
}

+ 164
- 0
rule/installment_payment/installment_payment.go Voir le fichier

@@ -0,0 +1,164 @@
package installment_payment

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/enum"
md2 "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md"
enum2 "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/rule/installment_payment/enum"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/rule/installment_payment/md"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/svc"
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils"
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx"
"code.fnuoos.com/go_rely_warehouse/zyos_model.git/src/implement"
"code.fnuoos.com/go_rely_warehouse/zyos_model.git/src/models"
"errors"
"fmt"
"github.com/shopspring/decimal"
"time"
"xorm.io/xorm"
)

// AddInstallmentPaymentList 新增 "分期付-订单" 记录
func AddInstallmentPaymentList(engine *xorm.Engine, masterId string, args md.AddInstallmentPaymentListStruct) (err error) {
now := time.Now()
//1、查找对应方案记录
installmentPaymentSchemeDb := implement.NewInstallmentPaymentSchemeDb(engine)
scheme, err := installmentPaymentSchemeDb.GetInstallmentPaymentSchemeById(args.SchemeId)
if err != nil {
return err
}
if scheme == nil {
return fmt.Errorf("installmentPaymentSchemeDb.InstallmentPaymentSchemeById returned nil")
}

//2、计算相关数据
installmentNumsValue := decimal.NewFromInt32(int32(scheme.InstallmentNums)) //分期数
totalAmount, _ := decimal.NewFromString(args.TotalAmount) //总金额
repaymentAmountPerInstallment := totalAmount.Div(installmentNumsValue).String() //每期还款金额

//3、新增 installment_payment_list 记录
installmentPaymentListDb := implement.NewInstallmentPaymentListDb(engine)
_, err = installmentPaymentListDb.InsertInstallmentPaymentList(&models.InstallmentPaymentList{
Uid: args.Uid,
GoodsId: args.GoodsId,
OrdId: args.OrdId,
TotalAmount: args.TotalAmount,
InstallmentNums: scheme.InstallmentNums,
AlreadyRepaidInstallmentNums: 0,
RepaymentAmountPerInstallment: repaymentAmountPerInstallment,
IsRepaidOff: 0,
CreateAt: now.Format("2006-01-02 15:04:05"),
UpdateAt: now.Format("2006-01-02 15:04:05"),
})
if err != nil {
return err
}
return
}

// InstallmentPaymentManualRepaid 手动还款
func InstallmentPaymentManualRepaid(engine *xorm.Engine, masterId string, args md.InstallmentPaymentManualRepaid) (err error) {
now := time.Now()
session := engine.NewSession()
defer func() {
session.Close()
if err := recover(); err != nil {
_ = zhios_order_relate_logx.Error(err)
}
}()
session.Begin()

//1、查找对应`installment_payment_list`记录
installmentPaymentListDb := implement.NewInstallmentPaymentListDb(engine)
installmentPaymentList, err := installmentPaymentListDb.GetInstallmentPaymentListById(args.RecordId)
if err != nil {
session.Rollback()
return err
}
if installmentPaymentList == nil {
session.Rollback()
return fmt.Errorf("installmentPaymentListDb.InstallmentPaymentListById returned nil")
}

//2、计算相关数据
repaidAmount, _ := decimal.NewFromString(args.RepaidAmount) //还款总金额
repaymentAmountPerInstallmentValue, _ := decimal.NewFromString(installmentPaymentList.RepaymentAmountPerInstallment) //每期还款金额
installmentNumsValue := decimal.NewFromInt32(int32(installmentPaymentList.InstallmentNums)) //分期数
alreadyRepaidInstallmentNumsValue := decimal.NewFromInt32(int32(installmentPaymentList.AlreadyRepaidInstallmentNums)) //已还分期数
residueRepaidInstallmentNumsValue := installmentNumsValue.Sub(alreadyRepaidInstallmentNumsValue) //剩余分期数
residueRepaidTotalAmountValue := residueRepaidInstallmentNumsValue.Mul(repaymentAmountPerInstallmentValue) //剩余待还总金额
if args.RepaidKind == 1 {
//判断还款金额是否正确
if installmentPaymentList.RepaymentAmountPerInstallment != args.RepaidAmount {
session.Rollback()
return errors.New("还款金额与按期还款金额不一致")
}
//按期还款
installmentPaymentList.AlreadyRepaidInstallmentNums++
if installmentPaymentList.AlreadyRepaidInstallmentNums == installmentPaymentList.InstallmentNums {
installmentPaymentList.IsRepaidOff = int(enum2.InstallmentPaymentListRepaidOn) //TODO::已还完
}
} else {
//判断还款金额是否正确
if repaidAmount.GreaterThan(residueRepaidTotalAmountValue) {
session.Rollback()
return errors.New("还款金额大于剩余待还总金额")
}
if repaidAmount.LessThan(residueRepaidTotalAmountValue) {
session.Rollback()
return errors.New("还款金额小于剩余待还总金额")
}
//全额还款
installmentPaymentList.AlreadyRepaidInstallmentNums++
installmentPaymentList.IsRepaidOff = int(enum2.InstallmentPaymentListRepaidOn) //TODO::已还完
}

//3、处理用户余额
orderType := enum.FinUserFlowOrderActionString(md2.InstallmentPaymentAutoRepaidForFinUserFlow)
var dealUserAmount = md2.DealUserAmount{
Kind: "sub",
Mid: masterId,
Title: md2.InstallmentPaymentAutoRepaidTitleForFinUserFlow,
OrderType: orderType,
OrdAction: md2.InstallmentPaymentAutoRepaidForFinUserFlow,
OrdId: zhios_order_relate_utils.Int64ToStr(installmentPaymentList.OrdId),
Uid: args.Uid,
Amount: zhios_order_relate_utils.StrToFloat64(args.RepaidAmount),
}
err = svc.DealUserAmount(session, dealUserAmount)
if err != nil {
session.Rollback()
return err
}

//4、新增 installment_payment_repaid_flow 记录
installmentPaymentRepaidFlowDb := implement.NewInstallmentPaymentRepaidFlowDb(engine)
_, err = installmentPaymentRepaidFlowDb.InsertInstallmentPaymentRepaidFlowBySession(session, &models.InstallmentPaymentRepaidFlow{
RecordId: installmentPaymentList.Id,
Uid: installmentPaymentList.Uid,
Amount: installmentPaymentList.RepaymentAmountPerInstallment,
WhichRepaymentPeriod: installmentPaymentList.AlreadyRepaidInstallmentNums,
CreateAt: now.Format("2006-01-02 15:04:05"),
UpdateAt: now.Format("2006-01-02 15:04:05"),
})
if err != nil {
session.Rollback()
return err
}

//5、修改`installment_payment_list` 记录
updateAffected, err := installmentPaymentListDb.UpdateInstallmentPaymentListBySess(session, installmentPaymentList, "already_repaid_installment_nums", "is_repaid_off")
if err != nil {
session.Rollback()
return err
}
if updateAffected <= 0 {
session.Rollback()
return errors.New("更新 `installment_payment_list` 记录失败")
}
err = session.Commit()
if err != nil {
session.Rollback()
return err
}
return
}

+ 142
- 0
rule/installment_payment/installment_payment_auto_repaid.go Voir le fichier

@@ -0,0 +1,142 @@
package installment_payment

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/enum"
md2 "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md"
enum2 "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/rule/installment_payment/enum"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/rule/installment_payment/md"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/svc"
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/cache"
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx"
"code.fnuoos.com/go_rely_warehouse/zyos_model.git/src/implement"
"code.fnuoos.com/go_rely_warehouse/zyos_model.git/src/models"
"errors"
"fmt"
"time"
"xorm.io/xorm"
)

const LockKey = "installment_payment_auto_repaid_lock_key"

// InstallmentPaymentAutoRepaid 分期付自动还款
func InstallmentPaymentAutoRepaid(engine *xorm.Engine, masterId string, ch *rabbit.Channel) (err error) {
//TODO::增加“悲观锁”防止串行
getString, _ := cache.GetString(LockKey)
if getString != "" {
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", "上一次结算未执行完")
return errors.New("上一次结算未执行完")
}
cache.SetEx(LockKey, "running", 3600*1) //1小时

//1、查找出"可用余额"大于"每期还款金额"的用户数据
var sqlStr = "SELECT ipl.*, up.fin_valid, up.uid FROM `installment_payment_list` ipl " +
"JOIN `user_profile` up ON up.uid = ipl.uid " +
"WHERE ipl.is_repaid_off =0 AND up.fin_valid > ipl.repayment_amount_per_installment;"
nativeStringResultMap, _ := db.QueryNativeString(engine, sqlStr)

//2、整理用户余额数据
var userFinValid = map[string]float64{}
for _, resultMap := range nativeStringResultMap {
userFinValid[resultMap["uid"]] = zhios_order_relate_utils.StrToFloat64(resultMap["fin_valid"])
}

//2、将符合条件的数据推入mq队列
for _, resultMap := range nativeStringResultMap {
if userFinValid[resultMap["uid"]] >= zhios_order_relate_utils.StrToFloat64(resultMap["repayment_amount_per_installment"]) {
//TODO::推入rabbitmq 异步处理
ch.Publish(md.InstallmentPaymentExchange, md.InstallmentPaymentStructForAutoRepaid{
MasterId: masterId,
Id: zhios_order_relate_utils.StrToInt(resultMap["id"]),
Uid: zhios_order_relate_utils.StrToInt(resultMap["uid"]),
GoodsId: zhios_order_relate_utils.StrToInt(resultMap["goods_id"]),
OrdId: zhios_order_relate_utils.StrToInt64(resultMap["ord_id"]),
TotalAmount: resultMap["total_amount"],
InstallmentNums: zhios_order_relate_utils.StrToInt(resultMap["installment_nums"]),
AlreadyRepaidInstallmentNums: zhios_order_relate_utils.StrToInt(resultMap["already_repaid_installment_nums"]),
RepaymentAmountPerInstallment: resultMap["repayment_amount_per_installment"],
IsRepaidOff: zhios_order_relate_utils.StrToInt(resultMap["is_repaid_off"]),
}, md.InstallmentPaymentRoutKeyForAutoRepaid)
userFinValid[resultMap["uid"]] -= zhios_order_relate_utils.StrToFloat64(resultMap["repayment_amount_per_installment"])
}
}

cache.Del(LockKey) //删除悲观锁
return
}

// DealInstallmentPaymentAutoRepaid 处理分期付自动还款
func DealInstallmentPaymentAutoRepaid(engine *xorm.Engine, args md.InstallmentPaymentStructForAutoRepaid, masterId string) (err error) {
now := time.Now()
session := engine.NewSession()
defer func() {
session.Close()
if err := recover(); err != nil {
_ = zhios_order_relate_logx.Error(err)
}
}()
session.Begin()
//1、查询出对应`installment_payment_list` 数据
installmentPaymentListDb := implement.NewInstallmentPaymentListDb(engine)
installmentPaymentList, err := installmentPaymentListDb.GetInstallmentPaymentListById(args.Id)
if err != nil {
session.Rollback()
return err
}
installmentPaymentList.AlreadyRepaidInstallmentNums++
if installmentPaymentList.AlreadyRepaidInstallmentNums == installmentPaymentList.InstallmentNums {
installmentPaymentList.IsRepaidOff = int(enum2.InstallmentPaymentListRepaidOn) //TODO::已还完
}

//2、处理用户余额
orderType := enum.FinUserFlowOrderActionString(md2.InstallmentPaymentAutoRepaidForFinUserFlow)
var dealUserAmount = md2.DealUserAmount{
Kind: "sub",
Mid: masterId,
Title: md2.InstallmentPaymentAutoRepaidTitleForFinUserFlow,
OrderType: orderType,
OrdAction: md2.InstallmentPaymentAutoRepaidForFinUserFlow,
OrdId: zhios_order_relate_utils.Int64ToStr(args.OrdId),
Uid: args.Uid,
Amount: zhios_order_relate_utils.StrToFloat64(installmentPaymentList.RepaymentAmountPerInstallment),
}
err = svc.DealUserAmount(session, dealUserAmount)
if err != nil {
session.Rollback()
return err
}

//3、新增`installment_payment_repaid_flow`数据
installmentPaymentRepaidFlowDb := implement.NewInstallmentPaymentRepaidFlowDb(engine)
_, err = installmentPaymentRepaidFlowDb.InsertInstallmentPaymentRepaidFlowBySession(session, &models.InstallmentPaymentRepaidFlow{
RecordId: installmentPaymentList.Id,
Uid: installmentPaymentList.Uid,
Amount: installmentPaymentList.RepaymentAmountPerInstallment,
WhichRepaymentPeriod: installmentPaymentList.AlreadyRepaidInstallmentNums,
CreateAt: now.Format("2006-01-02 15:04:05"),
UpdateAt: now.Format("2006-01-02 15:04:05"),
})
if err != nil {
session.Rollback()
return err
}

//4、修改`installment_payment_list` 记录
updateAffected, err := installmentPaymentListDb.UpdateInstallmentPaymentListBySess(session, installmentPaymentList, "already_repaid_installment_nums", "is_repaid_off")
if err != nil {
session.Rollback()
return err
}
if updateAffected <= 0 {
session.Rollback()
return errors.New("更新 `installment_payment_list` 记录失败")
}
err = session.Commit()
if err != nil {
session.Rollback()
return err
}
return
}

+ 14
- 0
rule/installment_payment/installment_payment_init.go Voir le fichier

@@ -0,0 +1,14 @@
package installment_payment

import (
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md"
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/cache"
)

func Init(redisAddr string) (err error) {
if redisAddr != "" {
cache.NewRedis(redisAddr)
}
_, err = cache.SelectDb(md.RedisDataBase)
return
}

+ 18
- 0
rule/installment_payment/md/installment_payment_list.go Voir le fichier

@@ -0,0 +1,18 @@
package md

type AddInstallmentPaymentListStruct struct {
MasterId string `json:"master_id"`
Uid int `json:"uid"`
GoodsId int `json:"goods_id"`
OrdId int64 `json:"ord_id"`
TotalAmount string `json:"total_amount"` //总金额
SchemeId int `json:"scheme_id"` //分期方案Id
}

type InstallmentPaymentManualRepaid struct {
MasterId string `json:"master_id"`
Uid int `json:"uid"`
RecordId int `json:"record_id"` //对应 installment_payment_list(分期付-订单列表)id
RepaidAmount string `json:"repaid_amount"` //还款金额
RepaidKind int32 `json:"repaid_kind"` //还款方式(1:按期还款 2:全额还款)
}

+ 20
- 0
rule/installment_payment/md/mq.go Voir le fichier

@@ -0,0 +1,20 @@
package md

const InstallmentPaymentExchange = "installment.payment"

const (
InstallmentPaymentRoutKeyForAutoRepaid = "auto_repaid" // 自动还款
)

type InstallmentPaymentStructForAutoRepaid struct {
MasterId string `json:"master_id"`
Id int `json:"id"`
Uid int `json:"uid"`
GoodsId int `json:"goods_id"`
OrdId int64 `json:"ord_id"`
TotalAmount string `json:"total_amount"`
InstallmentNums int `json:"installment_nums"`
AlreadyRepaidInstallmentNums int `json:"already_repaid_installment_nums"`
RepaymentAmountPerInstallment string `json:"repayment_amount_per_installment"`
IsRepaidOff int `json:"is_repaid_off"`
}

Chargement…
Annuler
Enregistrer