diff --git a/app/admin/models/user.go b/app/admin/models/user.go index b7d958f..d77400d 100644 --- a/app/admin/models/user.go +++ b/app/admin/models/user.go @@ -4220,46 +4220,82 @@ func UpdateExpireUserVm() { for _, record := range userVmRecords { // 计算需要扣除的积分 pointsToDeduct := record.Alter - record.UsedVm + if pointsToDeduct <= 0 { + continue + } - if pointsToDeduct > 0 { - // 更新 UserVm 表,防止 vm 变为负值,并更新 updated_at 字段 - sql := ` + // 开启事务 + tx := orm.Eloquent.Begin() + if tx.Error != nil { + log.Printf("Failed to begin transaction for uid %d: %v", record.Uid, tx.Error) + continue + } + + // 查询用户当前总积分 + var currentVm int64 + err = tx.Table("user_vm"). + Where("uid = ?", record.Uid). + Pluck("vm", ¤tVm).Error + if err != nil { + log.Printf("Failed to get current vm for uid %d: %v", record.Uid, err) + tx.Rollback() + continue + } + + // currentVm 是扣减前积分 + beforeVm := currentVm + afterVm := currentVm - int64(pointsToDeduct) + if afterVm < 0 { + afterVm = 0 + } + + // 更新 UserVm 表,防止 vm 变为负值,并更新 updated_at 字段 + sql := ` UPDATE user_vm SET vm = IF(vm - ? >= 0, vm - ?, 0), updated_at = ? WHERE uid = ? ` - err = orm.Eloquent.Exec(sql, pointsToDeduct, pointsToDeduct, time.Now(), record.Uid).Error - if err != nil { - log.Printf("Failed to update user_vm for uid %d: %v", record.Uid, err) - continue - } + err = tx.Exec(sql, pointsToDeduct, pointsToDeduct, time.Now(), record.Uid).Error + if err != nil { + log.Printf("Failed to update user_vm for uid %d: %v", record.Uid, err) + tx.Rollback() + continue + } - // 更新原有的 UserVmRecord,更新 used_vm 的值为 alter - err = orm.Eloquent.Table("user_vm_record").Where("id=?", record.ID). - Updates(map[string]interface{}{ - "used_vm": record.Alter, - "updated_at": time.Now(), - }).Error - if err != nil { - log.Printf("Failed to update user_vm_record (used_vm) for record id %d: %v", record.ID, err) - continue - } + // 更新原有的 UserVmRecord,更新 used_vm 的值为 alter + err = tx.Table("user_vm_record").Where("id=?", record.ID). + Updates(map[string]interface{}{ + "used_vm": record.Alter, + "updated_at": time.Now(), + }).Error + if err != nil { + log.Printf("Failed to update user_vm_record (used_vm) for record id %d: %v", record.ID, err) + tx.Rollback() + continue + } - // 创建新的 UserVmRecord 记录扣除过期积分 - newRecord := UserVmRecord{ - Uid: record.Uid, - BeforeVm: record.AfterVm, - AfterVm: record.AfterVm - uint32(pointsToDeduct), - Alter: -pointsToDeduct, - Event: VmEventExpired, - Describe: "积分过期扣减", - BillSn: record.BillSn, - } + // 创建新的 UserVmRecord 记录扣除过期积分 + newRecord := UserVmRecord{ + Uid: record.Uid, + BeforeVm: uint32(beforeVm), // 扣减前的积分 + AfterVm: uint32(afterVm), // 扣减后的积分 + Alter: -pointsToDeduct, + Event: VmEventExpired, + Describe: "积分过期扣减", + BillSn: record.BillSn, + } - err = orm.Eloquent.Table("user_vm_record").Create(&newRecord).Error - if err != nil { - log.Printf("Failed to create new user_vm_record for uid %d: %v", record.Uid, err) - } + err = tx.Table("user_vm_record").Create(&newRecord).Error + if err != nil { + log.Printf("Failed to create new user_vm_record for uid %d: %v", record.Uid, err) + tx.Rollback() + continue + } + + // 提交事务 + if err = tx.Commit().Error; err != nil { + log.Printf("Failed to commit transaction for uid %d: %v", record.Uid, err) + tx.Rollback() } } } diff --git a/app/admin/models/user_vm.go b/app/admin/models/user_vm.go index 185a9a6..cd8e4a1 100644 --- a/app/admin/models/user_vm.go +++ b/app/admin/models/user_vm.go @@ -57,6 +57,21 @@ type UserVmRecord struct { } func UserVmUpdate(gdb *gorm.DB, billSn string, uid uint32, amount int, event, describe string) error { + // 仅对零售销售事件做幂等检查 + var count int64 + if event == VmEventErpOrderSale { + err := orm.Eloquent.Table("user_vm_record"). + Where("bill_sn = ? AND event = ?", billSn, event). + Count(&count).Error + if err != nil { + return err + } + if count > 0 { + // 已有记录,直接返回 + return nil + } + } + var userVm UserVm err := orm.Eloquent.Table("user_vm"). Where("uid=?", uid).Find(&userVm).Error