mh_goadmin_server/app/admin/models/user_vm.go

268 lines
8.1 KiB
Go
Raw Normal View History

2023-09-16 02:56:39 +00:00
package models
import (
"errors"
"fmt"
orm "go-admin/common/global"
"go-admin/logger"
"gorm.io/gorm"
"time"
2023-09-16 02:56:39 +00:00
)
const (
VmEventBuyGoods = "buy_goods" // 购买商品积分抵扣
VmEventBuyGoodsReject = "buy_goods_reject" // 购买商品积分抵扣取消
VmEventOpenMember = "open_member" // 开通会员奖励
VmEventInvite1Member = "invite_1_member" // 邀请会员奖励
VmEventInvite2Member = "invite_2_member" // 邀请会员奖励
VmEventUserShareCard = "user_share_card" // 用户共享卡收益
VmEventAttendance = "attendance" // 连续签到获取积分
VmEventErpOrderSale = "erp_order_sale" // 零售销售获得积分
VmEventErpOrderReject = "erp_order_reject" // 零售退货扣除积分
VmEventExpired = "vm_expired" // 积分过期扣减
VmEventCancelMember = "cancel_member" // 取消租卡会员
VmEventCancelPrivilegeMember = "cancel_privilege_member" // 取消尊享会员
2023-09-16 02:56:39 +00:00
)
// 用户积分
// gen:qs
2023-10-14 08:19:04 +00:00
//
//go:generate goqueryset -in user_vm.go
2023-09-16 02:56:39 +00:00
type UserVm struct {
Model
Uid uint32 `json:"uid" gorm:"column:uid;unique_index"`
Vm uint32 `json:"vm"`
//UserVm uint32 `json:"user_vm"`
}
// 用户积分-变动记录
// gen:qs
type UserVmRecord struct {
Model
Uid uint32 `json:"uid" gorm:"column:uid;unique_index"` // 用户ID
BeforeVm uint32 `json:"before_vm"` // 变动前
AfterVm uint32 `json:"after_vm"` // 变动后
Alter int `json:"alter"` // 数值
Event string `json:"event" gorm:"type:varchar(100)"` // 事件
Describe string `json:"describe" gorm:"type:text"` // 描述
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id
BillSn string `json:"bill_sn"` // 零售订单编号
ExpiryDate time.Time `json:"expiry_date"` // 积分过期时间
UsedVm int `json:"used_vm"` // 已使用积分
ExpiryVm int `json:"expiry_vm" gorm:"-"` // 即将过期的积分
User *UserInfo `json:"user,omitempty" gorm:"-"` // 用户信息
2023-09-16 02:56:39 +00:00
}
func UserVmUpdate(gdb *gorm.DB, billSn string, uid uint32, amount int, event, describe string) error {
2023-09-16 02:56:39 +00:00
var userVm UserVm
err := orm.Eloquent.Table("user_vm").
Where("uid=?", uid).Find(&userVm).Error
if err != nil {
2023-10-14 08:19:04 +00:00
logger.Error("share card retrieve cards err:", logger.Field("err", err))
2023-09-16 02:56:39 +00:00
return err
}
2024-03-27 10:01:38 +00:00
// 变动前的积分
nBeforeVm := userVm.Vm
flag := false
begin := gdb
if gdb == nil {
flag = true
begin = orm.Eloquent.Begin()
}
2024-03-27 10:01:38 +00:00
if userVm.Uid == 0 { // 没有积分记录
2023-09-16 02:56:39 +00:00
if amount < 0 {
begin.Rollback()
logger.Error("amount lt 0")
return errors.New("amount lt 0")
}
userVm = UserVm{
Uid: uid,
Vm: uint32(amount),
}
err = begin.Create(&userVm).Error
if err != nil {
begin.Rollback()
2023-10-14 08:19:04 +00:00
logger.Error("err:", logger.Field("err", err))
2023-09-16 02:56:39 +00:00
return err
}
} else {
// 如果用户积分不够抵扣则扣到0为止
2024-03-27 10:01:38 +00:00
if int(userVm.Vm)+amount <= 0 {
sql := fmt.Sprintf("UPDATE user_vm SET vm = ? WHERE uid=?")
err = begin.Exec(sql, 0, uid).Error
} else {
2024-03-27 10:01:38 +00:00
sql := fmt.Sprintf("UPDATE user_vm SET vm = vm+? WHERE uid=?")
err = begin.Exec(sql, amount, uid).Error
}
2023-09-16 02:56:39 +00:00
if err != nil {
begin.Rollback()
2023-10-14 08:19:04 +00:00
logger.Error("err:", logger.Field("err", err))
2023-09-16 02:56:39 +00:00
return err
}
}
vmRecord := &UserVmRecord{
Uid: uid,
BeforeVm: uint32(nBeforeVm),
AfterVm: 0, // 默认值为 0
Alter: amount,
Event: event,
Describe: describe,
BillSn: billSn,
2023-09-16 02:56:39 +00:00
}
if newValue := int(userVm.Vm) + amount; newValue > 0 {
vmRecord.AfterVm = uint32(newValue)
}
// 如果是正积分,则记录该订单对应积分的有效时间
if amount > 0 {
vmRecord.ExpiryDate = time.Now().AddDate(1, 0, 0)
if event == VmEventBuyGoodsReject { // 使用积分购买商品后取消
err = RefundPoints(gdb, uid, amount)
if err != nil {
begin.Rollback()
logger.Error("err:", logger.Field("err", err))
return err
}
}
} else { // 如果是负积分,则记录积分使用情况;优先扣除最早获得的积分
if event == VmEventBuyGoods || event == VmEventErpOrderReject { // 使用积分购买商品,或者零售退货扣除积分
err = UsePoints(gdb, uid, -amount)
if err != nil {
begin.Rollback()
logger.Error("err:", logger.Field("err", err))
return err
}
}
}
2023-09-16 02:56:39 +00:00
err = begin.Create(vmRecord).Error
if err != nil {
begin.Rollback()
2023-10-14 08:19:04 +00:00
logger.Error("err:", logger.Field("err", err))
2023-09-16 02:56:39 +00:00
return err
}
if flag {
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("err:", logger.Field("err", err))
return err
}
}
2023-09-16 02:56:39 +00:00
return nil
}
// GetUserAvailablePointsRecords 查找用户的所有可用积分记录,按时间排序
func GetUserAvailablePointsRecords(uid uint32) []UserVmRecord {
var userVmRecord []UserVmRecord
err := orm.Eloquent.Table("user_vm_record").Where("uid = ? and event in (?)",
uid, []string{VmEventOpenMember, VmEventInvite1Member, VmEventInvite2Member, VmEventUserShareCard,
VmEventAttendance, VmEventErpOrderSale}).
Order("created_at DESC").
Find(&userVmRecord).Error
if err != nil {
logger.Error("get user_vm_record err:", logger.Field("err", err))
return []UserVmRecord{}
}
return userVmRecord
}
func UsePoints(gdb *gorm.DB, uid uint32, points int) error {
// 1. 查找用户的所有可用积分记录,按时间排序
records := GetUserAvailablePointsRecords(uid)
remaining := points
for _, record := range records {
available := record.Alter - record.UsedVm // 计算该订单剩余可用积分
if available >= remaining {
// 该订单的剩余积分足够
record.UsedVm += remaining
// 更新积分记录
err := gdb.Omit("created_at").Save(record).Error
if err != nil {
logger.Error("update user_vm_record err:", logger.Field("err", err))
return err
}
break
} else {
// 该订单的剩余积分不足,全部使用,继续扣减下一条记录
record.UsedVm = record.Alter
remaining -= available
// 更新积分记录
err := gdb.Omit("created_at").Save(record).Error
if err != nil {
logger.Error("update user_vm_record err:", logger.Field("err", err))
return err
}
}
}
return nil
}
// GetUserUsedPointsRecords 查找用户的已使用积分记录,按使用时间倒序排序
func GetUserUsedPointsRecords(uid uint32) []UserVmRecord {
var userVmRecord []UserVmRecord
err := orm.Eloquent.Table("user_vm_record").Where("uid = ? and event in (?)",
uid, []string{VmEventOpenMember, VmEventInvite1Member, VmEventInvite2Member, VmEventUserShareCard,
VmEventAttendance, VmEventErpOrderSale}).
Where("used_vm != 0").
Order("created_at DESC").
Find(&userVmRecord).Error
if err != nil {
logger.Error("get user_vm_record err:", logger.Field("err", err))
return []UserVmRecord{}
}
return userVmRecord
}
// RefundPoints 查找用户的已使用积分记录,按使用时间倒序排序
func RefundPoints(gdb *gorm.DB, uid uint32, points int) error {
// 1. 查找用户的已使用积分记录,按使用时间倒序排序
usedRecords := GetUserUsedPointsRecords(uid)
remaining := points
for _, record := range usedRecords {
used := record.UsedVm // 获取该订单已使用的积分
if used >= remaining {
// 该订单已使用的积分足够返还
record.UsedVm -= remaining
// 更新积分记录
err := gdb.Omit("created_at").Save(record).Error
if err != nil {
logger.Error("RefundPoints update user_vm_record err:", logger.Field("err", err))
return err
}
break
} else {
// 该订单已使用的积分不足以完全返还,全部返还后继续处理下一条记录
record.UsedVm = 0
remaining -= used
// 更新积分记录
err := gdb.Omit("created_at").Save(record).Error
if err != nil {
logger.Error("RefundPoints update user_vm_record err:", logger.Field("err", err))
return err
}
}
}
return nil
}