package mysqldao import ( "context" "git.lzcwy.cn/zhengchiliu/zt-closet-backend/global" "git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/mysqlmodel" "gorm.io/gorm" "gorm.io/gorm/clause" ) type BenefitRevokeTaskDao struct{ db *gorm.DB } func NewBenefitRevokeTaskDao() *BenefitRevokeTaskDao { return &BenefitRevokeTaskDao{db: global.MysqlEngine} } func (d *BenefitRevokeTaskDao) GetByOrderNo(ctx context.Context, orderNo string) (*mysqlmodel.BenefitRevokeTask, error) { var task mysqlmodel.BenefitRevokeTask err := d.db.WithContext(ctx).Where("order_no = ?", orderNo).First(&task).Error return &task, err } func (d *BenefitRevokeTaskDao) ListPending(ctx context.Context, limit int) ([]mysqlmodel.BenefitRevokeTask, error) { var list []mysqlmodel.BenefitRevokeTask err := d.db.WithContext(ctx).Where("status = ?", 0).Order("id ASC").Limit(limit).Find(&list).Error return list, err } func (d *BenefitRevokeTaskDao) Claim(ctx context.Context, id int64) (bool, error) { r := d.db.WithContext(ctx).Model(&mysqlmodel.BenefitRevokeTask{}).Where("id = ? AND status IN ?", id, []int8{0, 2}).Update("status", 3) return r.RowsAffected > 0, r.Error } func (d *BenefitRevokeTaskDao) Update(ctx context.Context, id int64, updates map[string]any) error { return d.db.WithContext(ctx).Model(&mysqlmodel.BenefitRevokeTask{}).Where("id = ?", id).Updates(updates).Error } func (d *BenefitRevokeTaskDao) RecoverStale(ctx context.Context, before int64) error { return d.db.WithContext(ctx).Model(&mysqlmodel.BenefitRevokeTask{}).Where("status = ? AND updated_at < ?", 3, before).Update("status", 0).Error } // RefundSettleWithRevokeTask 原子写入退款订单终态、取消未执行发放并创建回收任务。 // 前置状态:2=已支付(正常退款)、3=已取消但已付款(竞态兜底)、6=申请退款中(用户已提交退款申请)。 func (d *BenefitRevokeTaskDao) RefundSettleWithRevokeTask(ctx context.Context, orderNo string, refundAmount, refundTime int64) (bool, error) { settled := false err := d.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { var order mysqlmodel.Order if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("order_no = ?", orderNo).First(&order).Error; err != nil { return err } if order.OrderStatus == 5 { return nil } if order.OrderStatus != 2 && order.OrderStatus != 3 && order.OrderStatus != 6 { return nil } if err := tx.Model(&mysqlmodel.Order{}).Where("id = ?", order.ID).Updates(map[string]any{"order_status": 5, "refund_time": refundTime, "refund_amount": refundAmount}).Error; err != nil { return err } if err := tx.Model(&mysqlmodel.BenefitGrantTask{}).Where("order_no = ? AND status IN ?", orderNo, []int8{0, 2}).Update("status", 4).Error; err != nil { return err } // 2 / 6 表示权益已按订单发放过,需创建回收任务;3 从未发放,跳过避免误扣其它来源的会员天数/额度。 if order.OrderStatus == 2 || order.OrderStatus == 6 { if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&mysqlmodel.BenefitRevokeTask{OrderNo: orderNo, UserID: order.UserID, MaxRetry: 10}).Error; err != nil { return err } } settled = true return nil }) return settled, err }