From 43ffc138bf2df75c147b1e021f6b62569944bd36 Mon Sep 17 00:00:00 2001 From: DengBiao <2319963317@qq.com> Date: Tue, 22 Nov 2022 12:04:47 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E7=A7=AF=E5=88=86=E9=87=8A=E6=94=BE=20?= =?UTF-8?q?=E7=9A=84=E5=90=8E=E7=BB=AD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...egral_release_interposition_user_amount.go | 157 ++++++++++++++++++ ...ntegral_release_interposition_user_flow.go | 157 ++++++++++++++++++ ...gral_release_interposition_user_records.go | 157 ++++++++++++++++++ ...egral_release_interposition_user_amount.go | 18 ++ ...ntegral_release_interposition_user_flow.go | 23 +++ enum/fin_user_flow.go | 12 ++ md/app_redis_key.go | 3 +- md/block_star_chain.go | 16 +- md/fin_user_flow.go | 42 +++++ rule/integral_release_settlement.go | 89 +++++++++- svc/svc_deal_user_amount.go | 135 +++++++++++++++ svc/svc_redis_mutex_lock.go | 2 +- svc/svc_redis_mutex_lock_for_amount.go | 24 +++ 13 files changed, 824 insertions(+), 11 deletions(-) create mode 100644 db/db_integral_release_interposition_user_amount.go create mode 100644 db/db_integral_release_interposition_user_flow.go create mode 100644 db/db_integral_release_interposition_user_records.go create mode 100644 db/model/integral_release_interposition_user_amount.go create mode 100644 db/model/integral_release_interposition_user_flow.go create mode 100644 enum/fin_user_flow.go create mode 100644 md/fin_user_flow.go create mode 100644 svc/svc_deal_user_amount.go create mode 100644 svc/svc_redis_mutex_lock_for_amount.go diff --git a/db/db_integral_release_interposition_user_amount.go b/db/db_integral_release_interposition_user_amount.go new file mode 100644 index 0000000..910e72f --- /dev/null +++ b/db/db_integral_release_interposition_user_amount.go @@ -0,0 +1,157 @@ +package db + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" + 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" + "errors" + "fmt" + "reflect" + "xorm.io/xorm" +) + +// BatchSelectIntegralReleaseInterpositionUserAmounts 批量查询数据 TODO::和下面的方法重复了,建议采用下面的 `IntegralReleaseInterpositionUserAmountFindByParams` 方法 +func BatchSelectIntegralReleaseInterpositionUserAmounts(Db *xorm.Engine, params map[string]interface{}) (*[]model.IntegralReleaseInterpositionUserAmount, error) { + var IntegralReleaseInterpositionUserAmountData []model.IntegralReleaseInterpositionUserAmount + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]). + Find(&IntegralReleaseInterpositionUserAmountData); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &IntegralReleaseInterpositionUserAmountData, nil +} + +// IntegralReleaseInterpositionUserAmountInsert 插入单条数据 +func IntegralReleaseInterpositionUserAmountInsert(session *xorm.Session, IntegralReleaseInterpositionUserAmount *model.IntegralReleaseInterpositionUserAmount) (int, error) { + _, err := session.InsertOne(IntegralReleaseInterpositionUserAmount) + if err != nil { + return 0, err + } + return IntegralReleaseInterpositionUserAmount.Id, nil +} + +// BatchAddIntegralReleaseInterpositionUserAmounts 批量新增数据 +func BatchAddIntegralReleaseInterpositionUserAmounts(Db *xorm.Engine, IntegralReleaseInterpositionUserAmountData []*model.IntegralReleaseInterpositionUserAmount) (int64, error) { + affected, err := Db.Insert(IntegralReleaseInterpositionUserAmountData) + if err != nil { + return 0, err + } + return affected, nil +} + +func GetIntegralReleaseInterpositionUserAmountCount(Db *xorm.Engine) int { + var IntegralReleaseInterpositionUserAmount model.IntegralReleaseInterpositionUserAmount + session := Db.Where("") + count, err := session.Count(&IntegralReleaseInterpositionUserAmount) + if err != nil { + return 0 + } + return int(count) +} + +// IntegralReleaseInterpositionUserAmountDelete 删除记录 +func IntegralReleaseInterpositionUserAmountDelete(Db *xorm.Engine, id interface{}) (int64, error) { + if reflect.TypeOf(id).Kind() == reflect.Slice { + return Db.In("id", id).Delete(model.IntegralReleaseInterpositionUserAmount{}) + } else { + return Db.Where("id = ?", id).Delete(model.IntegralReleaseInterpositionUserAmount{}) + } +} + +// IntegralReleaseInterpositionUserAmountUpdate 更新记录 +func IntegralReleaseInterpositionUserAmountUpdate(session *xorm.Session, id interface{}, IntegralReleaseInterpositionUserAmount *model.IntegralReleaseInterpositionUserAmount, forceColums ...string) (int64, error) { + var ( + affected int64 + err error + ) + if forceColums != nil { + affected, err = session.Where("id=?", id).Cols(forceColums...).Update(IntegralReleaseInterpositionUserAmount) + } else { + affected, err = session.Where("id=?", id).Update(IntegralReleaseInterpositionUserAmount) + } + if err != nil { + return 0, err + } + return affected, nil +} + +// IntegralReleaseInterpositionUserAmountGetOneByParams 通过传入的参数查询数据(单条) +func IntegralReleaseInterpositionUserAmountGetOneByParams(session *xorm.Session, coinId int, params map[string]interface{}) (*model.IntegralReleaseInterpositionUserAmount, error) { + var m model.IntegralReleaseInterpositionUserAmount + var query = fmt.Sprintf("%s =?", params["key"]) + has, err := session.Where(query, params["value"]).And("coin_id =?", coinId).Get(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + if has == false { + return nil, errors.New("未查询到相应的 integral_release_interposition_user_amount 记录") + } + return &m, nil +} + +// IntegralReleaseInterpositionUserAmountFindByParams 通过传入的参数查询数据(多条) +func IntegralReleaseInterpositionUserAmountFindByParams(Db *xorm.Engine, params map[string]interface{}) (*[]model.IntegralReleaseInterpositionUserAmount, error) { + var m []model.IntegralReleaseInterpositionUserAmount + if params["value"] == nil { + return nil, errors.New("参数有误") + } + if params["key"] == nil { + //查询全部数据 + err := Db.Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } else { + if reflect.TypeOf(params["value"]).Kind() == reflect.Slice { + //指定In查询 + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]).Find(&m); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &m, nil + } else { + var query = fmt.Sprintf("%s =?", params["key"]) + err := Db.Where(query, params["value"]).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } + + } +} + +func IntegralReleaseInterpositionUserAmountFindByParamsByPage(Db *xorm.Engine, params map[string]interface{}, page, pageSize int) (*[]model.IntegralReleaseInterpositionUserAmount, error) { + var m []model.IntegralReleaseInterpositionUserAmount + if params["value"] == nil { + return nil, errors.New("参数有误") + } + if page == 0 && pageSize == 0 { + page = 1 + pageSize = 10 + } + + if params["key"] == nil { + //查询全部数据 + err := Db.Limit(pageSize, (page-1)*pageSize).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } else { + if reflect.TypeOf(params["value"]).Kind() == reflect.Slice { + //指定In查询 + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]).Limit(pageSize, (page-1)*pageSize).Find(&m); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &m, nil + } else { + var query = fmt.Sprintf("%s =?", params["key"]) + err := Db.Where(query, params["value"]).Limit(pageSize, (page-1)*pageSize).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } + + } +} diff --git a/db/db_integral_release_interposition_user_flow.go b/db/db_integral_release_interposition_user_flow.go new file mode 100644 index 0000000..a0aedcd --- /dev/null +++ b/db/db_integral_release_interposition_user_flow.go @@ -0,0 +1,157 @@ +package db + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" + 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" + "errors" + "fmt" + "reflect" + "xorm.io/xorm" +) + +// BatchSelectIntegralReleaseInterpositionUserFlows 批量查询数据 TODO::和下面的方法重复了,建议采用下面的 `IntegralReleaseInterpositionUserFlowFindByParams` 方法 +func BatchSelectIntegralReleaseInterpositionUserFlows(Db *xorm.Engine, params map[string]interface{}) (*[]model.IntegralReleaseInterpositionUserFlow, error) { + var IntegralReleaseInterpositionUserFlowData []model.IntegralReleaseInterpositionUserFlow + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]). + Find(&IntegralReleaseInterpositionUserFlowData); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &IntegralReleaseInterpositionUserFlowData, nil +} + +// IntegralReleaseInterpositionUserFlowInsert 插入单条数据 +func IntegralReleaseInterpositionUserFlowInsert(session *xorm.Session, IntegralReleaseInterpositionUserFlow *model.IntegralReleaseInterpositionUserFlow) (int, error) { + _, err := session.InsertOne(IntegralReleaseInterpositionUserFlow) + if err != nil { + return 0, err + } + return IntegralReleaseInterpositionUserFlow.Id, nil +} + +// BatchAddIntegralReleaseInterpositionUserFlows 批量新增数据 +func BatchAddIntegralReleaseInterpositionUserFlows(Db *xorm.Engine, IntegralReleaseInterpositionUserFlowData []*model.IntegralReleaseInterpositionUserFlow) (int64, error) { + affected, err := Db.Insert(IntegralReleaseInterpositionUserFlowData) + if err != nil { + return 0, err + } + return affected, nil +} + +func GetIntegralReleaseInterpositionUserFlowCount(Db *xorm.Engine) int { + var IntegralReleaseInterpositionUserFlow model.IntegralReleaseInterpositionUserFlow + session := Db.Where("") + count, err := session.Count(&IntegralReleaseInterpositionUserFlow) + if err != nil { + return 0 + } + return int(count) +} + +// IntegralReleaseInterpositionUserFlowDelete 删除记录 +func IntegralReleaseInterpositionUserFlowDelete(Db *xorm.Engine, id interface{}) (int64, error) { + if reflect.TypeOf(id).Kind() == reflect.Slice { + return Db.In("id", id).Delete(model.IntegralReleaseInterpositionUserFlow{}) + } else { + return Db.Where("id = ?", id).Delete(model.IntegralReleaseInterpositionUserFlow{}) + } +} + +// IntegralReleaseInterpositionUserFlowUpdate 更新记录 +func IntegralReleaseInterpositionUserFlowUpdate(session *xorm.Session, id interface{}, IntegralReleaseInterpositionUserFlow *model.IntegralReleaseInterpositionUserFlow, forceColums ...string) (int64, error) { + var ( + affected int64 + err error + ) + if forceColums != nil { + affected, err = session.Where("id=?", id).Cols(forceColums...).Update(IntegralReleaseInterpositionUserFlow) + } else { + affected, err = session.Where("id=?", id).Update(IntegralReleaseInterpositionUserFlow) + } + if err != nil { + return 0, err + } + return affected, nil +} + +// IntegralReleaseInterpositionUserFlowGetOneByParams 通过传入的参数查询数据(单条) +func IntegralReleaseInterpositionUserFlowGetOneByParams(session *xorm.Session, params map[string]interface{}) (*model.IntegralReleaseInterpositionUserFlow, error) { + var m model.IntegralReleaseInterpositionUserFlow + var query = fmt.Sprintf("%s =?", params["key"]) + has, err := session.Where(query, params["value"]).Get(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + if has == false { + return nil, errors.New("未查询到相应的 block_star_chain 记录") + } + return &m, nil +} + +// IntegralReleaseInterpositionUserFlowFindByParams 通过传入的参数查询数据(多条) +func IntegralReleaseInterpositionUserFlowFindByParams(Db *xorm.Engine, params map[string]interface{}) (*[]model.IntegralReleaseInterpositionUserFlow, error) { + var m []model.IntegralReleaseInterpositionUserFlow + if params["value"] == nil { + return nil, errors.New("参数有误") + } + if params["key"] == nil { + //查询全部数据 + err := Db.Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } else { + if reflect.TypeOf(params["value"]).Kind() == reflect.Slice { + //指定In查询 + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]).Find(&m); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &m, nil + } else { + var query = fmt.Sprintf("%s =?", params["key"]) + err := Db.Where(query, params["value"]).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } + + } +} + +func IntegralReleaseInterpositionUserFlowFindByParamsByPage(Db *xorm.Engine, params map[string]interface{}, page, pageSize int) (*[]model.IntegralReleaseInterpositionUserFlow, error) { + var m []model.IntegralReleaseInterpositionUserFlow + if params["value"] == nil { + return nil, errors.New("参数有误") + } + if page == 0 && pageSize == 0 { + page = 1 + pageSize = 10 + } + + if params["key"] == nil { + //查询全部数据 + err := Db.Limit(pageSize, (page-1)*pageSize).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } else { + if reflect.TypeOf(params["value"]).Kind() == reflect.Slice { + //指定In查询 + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]).Limit(pageSize, (page-1)*pageSize).Find(&m); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &m, nil + } else { + var query = fmt.Sprintf("%s =?", params["key"]) + err := Db.Where(query, params["value"]).Limit(pageSize, (page-1)*pageSize).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } + + } +} diff --git a/db/db_integral_release_interposition_user_records.go b/db/db_integral_release_interposition_user_records.go new file mode 100644 index 0000000..dbeadd4 --- /dev/null +++ b/db/db_integral_release_interposition_user_records.go @@ -0,0 +1,157 @@ +package db + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" + 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" + "errors" + "fmt" + "reflect" + "xorm.io/xorm" +) + +// BatchSelectIntegralReleaseInterpositionUserRecords 批量查询数据 TODO::和下面的方法重复了,建议采用下面的 `IntegralReleaseInterpositionUserRecordsFindByParams` 方法 +func BatchSelectIntegralReleaseInterpositionUserRecords(Db *xorm.Engine, params map[string]interface{}) (*[]model.IntegralReleaseInterpositionUserRecords, error) { + var IntegralReleaseInterpositionUserRecordsData []model.IntegralReleaseInterpositionUserRecords + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]). + Find(&IntegralReleaseInterpositionUserRecordsData); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &IntegralReleaseInterpositionUserRecordsData, nil +} + +// IntegralReleaseInterpositionUserRecordsInsert 插入单条数据 +func IntegralReleaseInterpositionUserRecordsInsert(Db *xorm.Engine, IntegralReleaseInterpositionUserRecords *model.IntegralReleaseInterpositionUserRecords) (int, error) { + _, err := Db.InsertOne(IntegralReleaseInterpositionUserRecords) + if err != nil { + return 0, err + } + return IntegralReleaseInterpositionUserRecords.Id, nil +} + +// BatchAddIntegralReleaseInterpositionUserRecords 批量新增数据 +func BatchAddIntegralReleaseInterpositionUserRecords(Db *xorm.Engine, IntegralReleaseInterpositionUserRecordsData []*model.IntegralReleaseInterpositionUserRecords) (int64, error) { + affected, err := Db.Insert(IntegralReleaseInterpositionUserRecordsData) + if err != nil { + return 0, err + } + return affected, nil +} + +func GetIntegralReleaseInterpositionUserRecordsCount(Db *xorm.Engine) int { + var IntegralReleaseInterpositionUserRecords model.IntegralReleaseInterpositionUserRecords + session := Db.Where("") + count, err := session.Count(&IntegralReleaseInterpositionUserRecords) + if err != nil { + return 0 + } + return int(count) +} + +// IntegralReleaseInterpositionUserRecordsDelete 删除记录 +func IntegralReleaseInterpositionUserRecordsDelete(Db *xorm.Engine, id interface{}) (int64, error) { + if reflect.TypeOf(id).Kind() == reflect.Slice { + return Db.In("id", id).Delete(model.IntegralReleaseInterpositionUserRecords{}) + } else { + return Db.Where("id = ?", id).Delete(model.IntegralReleaseInterpositionUserRecords{}) + } +} + +// IntegralReleaseInterpositionUserRecordsUpdate 更新记录 +func IntegralReleaseInterpositionUserRecordsUpdate(session *xorm.Session, id interface{}, IntegralReleaseInterpositionUserRecords *model.IntegralReleaseInterpositionUserRecords, forceColums ...string) (int64, error) { + var ( + affected int64 + err error + ) + if forceColums != nil { + affected, err = session.Where("id=?", id).Cols(forceColums...).Update(IntegralReleaseInterpositionUserRecords) + } else { + affected, err = session.Where("id=?", id).Update(IntegralReleaseInterpositionUserRecords) + } + if err != nil { + return 0, err + } + return affected, nil +} + +// IntegralReleaseInterpositionUserRecordsGetOneByParams 通过传入的参数查询数据(单条) +func IntegralReleaseInterpositionUserRecordsGetOneByParams(session *xorm.Session, params map[string]interface{}) (*model.IntegralReleaseInterpositionUserRecords, error) { + var m model.IntegralReleaseInterpositionUserRecords + var query = fmt.Sprintf("%s =?", params["key"]) + has, err := session.Where(query, params["value"]).Get(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + if has == false { + return nil, errors.New("未查询到相应的 block_star_chain 记录") + } + return &m, nil +} + +// IntegralReleaseInterpositionUserRecordsFindByParams 通过传入的参数查询数据(多条) +func IntegralReleaseInterpositionUserRecordsFindByParams(Db *xorm.Engine, params map[string]interface{}) (*[]model.IntegralReleaseInterpositionUserRecords, error) { + var m []model.IntegralReleaseInterpositionUserRecords + if params["value"] == nil { + return nil, errors.New("参数有误") + } + if params["key"] == nil { + //查询全部数据 + err := Db.Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } else { + if reflect.TypeOf(params["value"]).Kind() == reflect.Slice { + //指定In查询 + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]).Find(&m); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &m, nil + } else { + var query = fmt.Sprintf("%s =?", params["key"]) + err := Db.Where(query, params["value"]).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } + + } +} + +func IntegralReleaseInterpositionUserRecordsFindByParamsByPage(Db *xorm.Engine, params map[string]interface{}, page, pageSize int) (*[]model.IntegralReleaseInterpositionUserRecords, error) { + var m []model.IntegralReleaseInterpositionUserRecords + if params["value"] == nil { + return nil, errors.New("参数有误") + } + if page == 0 && pageSize == 0 { + page = 1 + pageSize = 10 + } + + if params["key"] == nil { + //查询全部数据 + err := Db.Limit(pageSize, (page-1)*pageSize).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } else { + if reflect.TypeOf(params["value"]).Kind() == reflect.Slice { + //指定In查询 + if err := Db.In(zhios_order_relate_utils.AnyToString(params["key"]), params["value"]).Limit(pageSize, (page-1)*pageSize).Find(&m); err != nil { + return nil, zhios_order_relate_logx.Warn(err) + } + return &m, nil + } else { + var query = fmt.Sprintf("%s =?", params["key"]) + err := Db.Where(query, params["value"]).Limit(pageSize, (page-1)*pageSize).Find(&m) + if err != nil { + return nil, zhios_order_relate_logx.Error(err) + } + return &m, nil + } + + } +} diff --git a/db/model/integral_release_interposition_user_amount.go b/db/model/integral_release_interposition_user_amount.go new file mode 100644 index 0000000..2c8329d --- /dev/null +++ b/db/model/integral_release_interposition_user_amount.go @@ -0,0 +1,18 @@ +package model + +import ( + "time" +) + +type IntegralReleaseInterpositionUserAmount struct { + Id int `json:"id" xorm:"not null pk autoincr comment('主键id') INT(11)"` + Uid int `json:"uid" xorm:"not null default 0 comment('用户uid') INT(11)"` + CoinId int `json:"coin_id" xorm:"not null default 0 comment('虚拟币id(若为0则为 余额)') INT(11)"` + TotalAmount string `json:"total_amount" xorm:"not null default 0.0000 comment('累计金额') DECIMAL(10,4)"` + WaiteAmount string `json:"waite_amount" xorm:"not null default 0.0000 comment('待释放金额') DECIMAL(10,4)"` + AlreadyAmount string `json:"already_amount" xorm:"not null default 0.0000 comment('已释放金额') DECIMAL(10,4)"` + State int `json:"state" xorm:"not null default 1 comment('状态(1:正常 2:冻结(停止释放))') TINYINT(3)"` + Ext string `json:"ext" xorm:"TEXT"` + CreateAt time.Time `json:"create_at" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') TIMESTAMP"` + UpdateAt time.Time `json:"update_at" xorm:"default 'CURRENT_TIMESTAMP' comment('更新时间') TIMESTAMP"` +} diff --git a/db/model/integral_release_interposition_user_flow.go b/db/model/integral_release_interposition_user_flow.go new file mode 100644 index 0000000..cd093fc --- /dev/null +++ b/db/model/integral_release_interposition_user_flow.go @@ -0,0 +1,23 @@ +package model + +import ( + "time" +) + +type IntegralReleaseInterpositionUserFlow struct { + Id int `json:"id" xorm:"not null pk autoincr comment('主键id') INT(11)"` + Uid int `json:"uid" xorm:"not null default 0 comment('用户uid') INT(11)"` + CoinId int `json:"coin_id" xorm:"not null default 0 comment('虚拟币id(若为0则为 余额)') INT(11)"` + OrdId string `json:"ord_id" xorm:"not null default '' comment('订单id') VARCHAR(100)"` + Kind int `json:"kind" xorm:"not null default 1 comment('种类(1:流入 2:流出)') TINYINT(1)"` + Amount string `json:"amount" xorm:"not null default 0.0000 comment('金额') DECIMAL(10,4)"` + BeforeTotalAmount string `json:"before_total_amount" xorm:"not null default 0.0000 comment('累计金额-之前') DECIMAL(10,4)"` + AfterTotalAmount string `json:"after_total_amount" xorm:"not null default 0.0000 comment('累计金额-之后') DECIMAL(10,4)"` + BeforeAlreadyAmount string `json:"before_already_amount" xorm:"not null default 0.0000 comment('已释放金额-之前') DECIMAL(10,4)"` + AfterAlreadyAmount string `json:"after_already_amount" xorm:"not null default 0.0000 comment('已释放金额-之后') DECIMAL(10,4)"` + BeforeWaiteAmount string `json:"before_waite_amount" xorm:"not null default 0.0000 comment('待释放金额-之前') DECIMAL(10,4)"` + AfterWaiteAmount string `json:"after_waite_amount" xorm:"not null default 0.0000 comment('待释放金额-之后') DECIMAL(10,4)"` + Date string `json:"date" xorm:"not null default '0000-00-00' comment('释放日期') VARCHAR(50)"` + CreateAt time.Time `json:"create_at" xorm:"not null default 'CURRENT_TIMESTAMP' comment('创建时间') TIMESTAMP"` + UpdateAt time.Time `json:"update_at" xorm:"default 'CURRENT_TIMESTAMP' comment('更新时间') TIMESTAMP"` +} diff --git a/enum/fin_user_flow.go b/enum/fin_user_flow.go new file mode 100644 index 0000000..02f211b --- /dev/null +++ b/enum/fin_user_flow.go @@ -0,0 +1,12 @@ +package enum + +import "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" + +func FinUserFlowOrderActionString(kind int) string { + switch kind { + case md.IntegralReleaseServiceRevenueOrderTypeForFinUserFlow: + return "integral_release_service_revenue" + default: + return "unknown" + } +} diff --git a/md/app_redis_key.go b/md/app_redis_key.go index d7d5f33..af03a8f 100644 --- a/md/app_redis_key.go +++ b/md/app_redis_key.go @@ -7,7 +7,8 @@ const ( PlanRewardCfgCacheKey = "%s:plan_reward_cfg" UnionSetCacheCfg = "%s:union_set_cfg:%s" // 联盟设置缓存key - UserFinValidUpdateLock = "%s:user_fin_valid_update_lock:%s" // 用户余额更新锁(能拿到锁才能更新余额) + UserFinValidUpdateLock = "%s:user_fin_valid_update_lock:%s" // 用户余额更新锁(能拿到锁才能更新余额) + UserVirtualAmountUpdateLock = "%s:user_virtual_amount_update_lock:%s" // 用户虚拟币更新锁(能拿到锁才能更新余额) WithdrawApplyQueueListKey = "withdraw_apply_queue" // 提现队列 diff --git a/md/block_star_chain.go b/md/block_star_chain.go index 728d5be..4077502 100644 --- a/md/block_star_chain.go +++ b/md/block_star_chain.go @@ -42,10 +42,10 @@ const ( BlockGreenChainTransactionAndDestroyTitleForUserVirtualCoinFlow = "绿色积分-交易(销毁贡献值)" BlockGreenChainAdminDestroyTitleForUserVirtualCoinFlow = "绿色积分-管理员销毁" - IntegralReleaseRedCoinGrantByOrdTitleForUserVirtualCoinFlow = "积分兑换-红积分发放(订单)" - IntegralReleaseRedCoinGrantBySignInTitleForUserVirtualCoinFlow = "积分兑换-红积分发放(签到)" - IntegralReleaseGreenCoinGrantByOrdTitleForUserVirtualCoinFlow = "积分兑换-绿积分发放(订单)" - IntegralReleaseGreenCoinGrantBySignInTitleForUserVirtualCoinFlow = "积分兑换-红积分发放(签到)" + IntegralReleaseRedCoinGrantByOrdTitleForUserVirtualCoinFlow = "积分释放-红积分发放(订单)" + IntegralReleaseRedCoinGrantBySignInTitleForUserVirtualCoinFlow = "积分释放-红积分发放(签到)" + IntegralReleaseGreenCoinGrantByOrdTitleForUserVirtualCoinFlow = "积分释放-绿积分发放(订单)" + IntegralReleaseGreenCoinGrantBySignInTitleForUserVirtualCoinFlow = "积分释放-红积分发放(签到)" ) const ( @@ -80,10 +80,10 @@ const ( BlockGreenChainTransactionAndDestroyTransferTypeForUserVirtualCoinFlow = 133 // 绿色积分-交易(销毁贡献值) BlockGreenChainAdminDestroyTransferTypeForUserVirtualCoinFlow = 134 // 绿色积分-管理员销毁 - IntegralReleaseRedCoinGrantByOrdTransferTypeForUserVirtualCoinFlow = 135 // 积分兑换-红积分发放(订单) - IntegralReleaseRedCoinGrantBySignInTransferTypeForUserVirtualCoinFlow = 136 // 积分兑换-红积分发放(签到) - IntegralReleaseGreenCoinGrantByOrdTransferTypeForUserVirtualCoinFlow = 137 // 积分兑换-绿积分发放(订单) - IntegralReleaseGreenCoinGrantBySignInTransferTypeForUserVirtualCoinFlow = 138 // 积分兑换-绿积分发放(签到) + IntegralReleaseRedCoinGrantByOrdTransferTypeForUserVirtualCoinFlow = 135 // 积分释放-红积分发放(订单) + IntegralReleaseRedCoinGrantBySignInTransferTypeForUserVirtualCoinFlow = 136 // 积分释放-红积分发放(签到) + IntegralReleaseGreenCoinGrantByOrdTransferTypeForUserVirtualCoinFlow = 137 // 积分释放-绿积分发放(订单) + IntegralReleaseGreenCoinGrantBySignInTransferTypeForUserVirtualCoinFlow = 138 // 积分释放-绿积分发放(签到) ) const DealUserCoinRequestIdPrefix = "%s:block_star_chain_deal_user_coin:%d:uid:%d" diff --git a/md/fin_user_flow.go b/md/fin_user_flow.go new file mode 100644 index 0000000..de647f4 --- /dev/null +++ b/md/fin_user_flow.go @@ -0,0 +1,42 @@ +package md + +const ( + FinUserFlowDirectionIncome = 1 //流水 - 收入 + FinUserFlowDirectionExpenditure = 2 //流水 - 支出 +) + +const ( + FinUserFlowRedisDataBase = 0 + FinUserFlowRedisKey = "%s:fin_user_flow:%d:user:%d" +) + +const ( + IntegralReleaseServiceRevenueTitleForFinUserFlow = "积分释放-服务收益" +) + +const ( + IntegralReleaseServiceRevenueOrderTypeForFinUserFlow = 50 // 积分释放-服务收益 +) + +const DealUserAmountRequestIdPrefix = "%s:deal_user_amount:%d" +const UserAmountRedisKey = "%s:user_amount:%d" + +type DealIntegralReleaseInterpositionUserAmountReq struct { + Kind string `json:"kind"` + Mid string `json:"mid"` + OrdId string `json:"ord_id"` + CoinId int `json:"coin_id"` + Uid int `json:"uid"` + Amount float64 `json:"amount"` +} + +type DealUserAmount struct { + Kind string `json:"kind"` + Mid string `json:"mid"` + Title string `json:"title"` + OrderType string `json:"order_type"` + OrdAction int `json:"ord_action"` + OrdId string `json:"ord_id"` + Uid int `json:"uid"` + Amount float64 `json:"amount"` +} diff --git a/rule/integral_release_settlement.go b/rule/integral_release_settlement.go index 3946e0d..48fd1c4 100644 --- a/rule/integral_release_settlement.go +++ b/rule/integral_release_settlement.go @@ -3,6 +3,7 @@ package rule import ( "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/db/model" + "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/enum" "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/svc" zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils" @@ -78,7 +79,7 @@ func DailySettlementIntegralRelease(engine *xorm.Engine, mid string, isTask bool //2、查询所有 `integral_release_user_with_ord` 记录 integralReleaseUserWithOrds, err := db.IntegralReleaseUserWithOrdFindByParams(session, map[string]interface{}{ - "key": "state", + "key": "state", "value": 1, }) for _, ord := range *integralReleaseUserWithOrds { @@ -268,3 +269,89 @@ func DealUserCoinForIntegralRelease(session *xorm.Session, req md.DealUserCoinRe return nil } + +// DealIntegralReleaseInterpositionUserAmount 处理间推用户服务收益 +func DealIntegralReleaseInterpositionUserAmount(session *xorm.Session, req md.DealIntegralReleaseInterpositionUserAmountReq) (err error) { + if req.Amount < 0 { + req.Amount = 0 + } + + //1、计算&&组装数据 + now := time.Now() + userAmount, err := db.IntegralReleaseInterpositionUserAmountGetOneByParams(session, req.CoinId, map[string]interface{}{ + "key": "uid", + "value": req.Uid, + }) + if err != nil { + return err + } + totalAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount.TotalAmount)) + waiteAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount.WaiteAmount)) + alreadyAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount.AlreadyAmount)) + amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4) + + var integralReleaseInterpositionUserFlow = model.IntegralReleaseInterpositionUserFlow{ + Uid: req.Uid, + CoinId: req.CoinId, + OrdId: req.OrdId, + Amount: amountValue.String(), + Date: "", + CreateAt: now, + UpdateAt: now, + } + if req.Kind == "add" { + integralReleaseInterpositionUserFlow.Kind = 1 + integralReleaseInterpositionUserFlow.BeforeTotalAmount = totalAmountValue.String() + integralReleaseInterpositionUserFlow.AfterTotalAmount = totalAmountValue.Add(amountValue).String() + integralReleaseInterpositionUserFlow.BeforeWaiteAmount = waiteAmountValue.String() + integralReleaseInterpositionUserFlow.AfterAlreadyAmount = waiteAmountValue.Add(amountValue).String() + integralReleaseInterpositionUserFlow.BeforeAlreadyAmount = alreadyAmountValue.String() + integralReleaseInterpositionUserFlow.AfterAlreadyAmount = alreadyAmountValue.String() + } else if req.Kind == "sub" { + integralReleaseInterpositionUserFlow.Kind = 1 + integralReleaseInterpositionUserFlow.BeforeTotalAmount = totalAmountValue.String() + integralReleaseInterpositionUserFlow.AfterTotalAmount = totalAmountValue.String() + integralReleaseInterpositionUserFlow.BeforeWaiteAmount = waiteAmountValue.String() + integralReleaseInterpositionUserFlow.AfterAlreadyAmount = waiteAmountValue.Sub(amountValue).String() + integralReleaseInterpositionUserFlow.BeforeAlreadyAmount = alreadyAmountValue.String() + integralReleaseInterpositionUserFlow.AfterAlreadyAmount = alreadyAmountValue.Add(amountValue).String() + integralReleaseInterpositionUserFlow.Date = now.Format("2006-01-02") + //TODO::判断增加用户 余额 or 虚拟币积分 + if req.CoinId == 0 { + orderType := enum.FinUserFlowOrderActionString(md.IntegralReleaseServiceRevenueOrderTypeForFinUserFlow) + var dealUserAmount = md.DealUserAmount{ + Kind: req.Kind, + Mid: req.Mid, + Title: md.IntegralReleaseServiceRevenueTitleForFinUserFlow, + OrderType: orderType, + OrdAction: md.IntegralReleaseServiceRevenueOrderTypeForFinUserFlow, + OrdId: req.OrdId, + Uid: req.Uid, + Amount: req.Amount, + } + err = svc.DealUserAmount(session, dealUserAmount) + if err != nil { + return err + } + } + } else { + err = errors.New("错误的kind类型") + return err + } + + //2、插入 `integral_release_interposition_user_flow` 记录 + _, err = db.IntegralReleaseInterpositionUserFlowInsert(session, &integralReleaseInterpositionUserFlow) + if err != nil { + return err + } + + //3、修改 `integral_release_interposition_user_amount` 的相关 amount 值 + updateAffected, _ := db.IntegralReleaseInterpositionUserAmountUpdate(session, userAmount.Id, userAmount) + if err != nil { + return err + } + if updateAffected == 0 { + return errors.New("更新 integral_release_interposition_user_flow 记录失败") + } + return nil +} diff --git a/svc/svc_deal_user_amount.go b/svc/svc_deal_user_amount.go new file mode 100644 index 0000000..420cdc2 --- /dev/null +++ b/svc/svc_deal_user_amount.go @@ -0,0 +1,135 @@ +package svc + +import ( + "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/db/model" + "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" + 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" + "errors" + "fmt" + "github.com/shopspring/decimal" + "strconv" + "time" + "xorm.io/xorm" +) + +// DealUserAmount 处理给用户余额 +func DealUserAmount(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、计算&&组装数据 + now := time.Now() + userAmount, err := GetUserAmount(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(4) + + var finUserFlow = model.FinUserFlow{ + Uid: req.Uid, + Amount: "", + BeforeAmount: userAmount, + OrdType: req.OrderType, + OrdId: req.OrdId, + OrdTitle: req.Title, + OrdAction: req.OrdAction, + OrdTime: int(now.Unix()), + State: 1, + CreateAt: now, + UpdateAt: now, + } + if req.Kind == "add" { + finUserFlow.Type = 0 + finUserFlow.AfterAmount = userAmountValue.Add(amountValue).RoundFloor(4).String() + } else if req.Kind == "sub" { + finUserFlow.Type = 1 + finUserFlow.AfterAmount = userAmountValue.Sub(amountValue).RoundFloor(4).String() + } else { + err = errors.New("错误的kind类型") + return err + } + 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、插入 `user_virtual_coin_flow` 记录 + affected, err := session.Insert(&finUserFlow) + if affected == 0 || err != nil { + _ = zhios_order_relate_logx.Warn(err) + return err + } + + //4、修改 `user_profile`的fin_valid值 && 及缓存 + err = SetCacheUserAmount(session, req.Mid, finUserFlow.AfterAmount, req.Uid, true) + if err != nil { + return err + } + + return nil +} + +// GetUserAmount 获取用户余额 +func GetUserAmount(session *xorm.Session, masterId string, uid int) (amount string, err error) { + redisKey := fmt.Sprintf(md.UserAmountRedisKey, masterId, uid) + amount, err = cache.GetString(redisKey) + if err != nil { + if err.Error() == "redigo: nil returned" { + userAmount, err := db.UserProfileFindByIDWithSession(session, uid) + if err != nil { + return amount, err + } + if userAmount == nil { + amount = "0" + } else { + amount = userAmount.FinValid + } + //将获取到的余额值缓存至redis + _ = SetCacheUserAmount(session, masterId, amount, uid, false) + return amount, nil + } + return amount, err + } + return amount, nil +} + +// SetCacheUserAmount 设置缓存的用户余额 +func SetCacheUserAmount(session *xorm.Session, masterId, amount string, uid int, isUpdateDb bool) error { + redisKey := fmt.Sprintf(md.UserAmountRedisKey, masterId, uid) + if isUpdateDb { + _, err := session.Where("uid=?", uid).Update(model.UserProfile{ + Uid: uid, + FinValid: amount, + }) + if err != nil { + return err + } + } + //_, err := cache.Set(redisKey, int64(utils.StrToFloat64(amount))) + //TODO::默认缓存1小时 (先调整为 2 min) + _, err := cache.SetEx(redisKey, zhios_order_relate_utils.StrToFloat64(amount), 60*2) + if err != nil { + return err + } + return nil +} diff --git a/svc/svc_redis_mutex_lock.go b/svc/svc_redis_mutex_lock.go index f9e714b..92cf77e 100644 --- a/svc/svc_redis_mutex_lock.go +++ b/svc/svc_redis_mutex_lock.go @@ -69,7 +69,7 @@ func GetDistributedLockRequestId(prefix string) string { // HandleDistributedLock 处理余额更新时获取锁和释放锁 如果加锁成功,使用语句 ` defer cb() ` 释放锁 func HandleDistributedLock(masterId, uid, requestIdPrefix string) (cb func(), err error) { // 获取余额更新锁 - balanceLockKey := fmt.Sprintf(md.UserFinValidUpdateLock, masterId, uid) + balanceLockKey := fmt.Sprintf(md.UserVirtualAmountUpdateLock, masterId, uid) requestId := GetDistributedLockRequestId(requestIdPrefix) balanceLockOk := TryGetDistributedLock(balanceLockKey, requestId, true) if !balanceLockOk { diff --git a/svc/svc_redis_mutex_lock_for_amount.go b/svc/svc_redis_mutex_lock_for_amount.go new file mode 100644 index 0000000..c11e38e --- /dev/null +++ b/svc/svc_redis_mutex_lock_for_amount.go @@ -0,0 +1,24 @@ +package svc + +import ( + "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" + "errors" + "fmt" +) + +// HandleBalanceDistributedLockForAmount 处理余额更新时获取锁和释放锁 如果加锁成功,使用语句 ` defer cb() ` 释放锁 +func HandleBalanceDistributedLockForAmount(masterId, uid, requestIdPrefix string) (cb func(), err error) { + // 获取余额更新锁 + balanceLockKey := fmt.Sprintf(md.UserFinValidUpdateLock, masterId, uid) + requestId := GetDistributedLockRequestId(requestIdPrefix) + balanceLockOk := TryGetDistributedLock(balanceLockKey, requestId, true) + if !balanceLockOk { + return nil, errors.New("系统繁忙,请稍后再试") + } + + cb = func() { + _, _ = ReleaseDistributedLock(balanceLockKey, requestId) + } + + return cb, nil +}