2、修改商品资料前端入参分页错误时,接口报错的缺陷; 3、修复串码商品(手动添加)零售退货订单审核失败的缺陷; 4、优惠券增加商品编号字段; 5、取消会员时扣减积分,尊享会员优惠券更新为过期状态;
268 lines
8.1 KiB
Go
268 lines
8.1 KiB
Go
package models
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
orm "go-admin/common/global"
|
||
"go-admin/logger"
|
||
"gorm.io/gorm"
|
||
"time"
|
||
)
|
||
|
||
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" // 取消尊享会员
|
||
)
|
||
|
||
// 用户积分
|
||
// gen:qs
|
||
//
|
||
//go:generate goqueryset -in user_vm.go
|
||
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:"-"` // 用户信息
|
||
}
|
||
|
||
func UserVmUpdate(gdb *gorm.DB, billSn string, uid uint32, amount int, event, describe string) error {
|
||
var userVm UserVm
|
||
err := orm.Eloquent.Table("user_vm").
|
||
Where("uid=?", uid).Find(&userVm).Error
|
||
if err != nil {
|
||
logger.Error("share card retrieve cards err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
// 变动前的积分
|
||
nBeforeVm := userVm.Vm
|
||
|
||
flag := false
|
||
begin := gdb
|
||
if gdb == nil {
|
||
flag = true
|
||
begin = orm.Eloquent.Begin()
|
||
}
|
||
|
||
if userVm.Uid == 0 { // 没有积分记录
|
||
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()
|
||
logger.Error("err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else {
|
||
// 如果用户积分不够抵扣,则扣到0为止
|
||
if int(userVm.Vm)+amount <= 0 {
|
||
sql := fmt.Sprintf("UPDATE user_vm SET vm = ? WHERE uid=?")
|
||
err = begin.Exec(sql, 0, uid).Error
|
||
} else {
|
||
sql := fmt.Sprintf("UPDATE user_vm SET vm = vm+? WHERE uid=?")
|
||
err = begin.Exec(sql, amount, uid).Error
|
||
}
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
}
|
||
|
||
vmRecord := &UserVmRecord{
|
||
Uid: uid,
|
||
BeforeVm: uint32(nBeforeVm),
|
||
AfterVm: 0, // 默认值为 0
|
||
Alter: amount,
|
||
Event: event,
|
||
Describe: describe,
|
||
BillSn: billSn,
|
||
}
|
||
|
||
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
|
||
}
|
||
}
|
||
}
|
||
|
||
err = begin.Create(vmRecord).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
if flag {
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
}
|
||
|
||
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
|
||
}
|