package user import ( "context" "errors" "time" "bindbox-game/internal/repository/mysql/dao" "bindbox-game/internal/repository/mysql/model" "gorm.io/gorm/clause" ) // CancelOrder 取消订单 func (s *service) CancelOrder(ctx context.Context, userID int64, orderID int64, reason string) (*model.Orders, error) { var updatedOrder *model.Orders err := s.writeDB.Transaction(func(tx *dao.Query) error { // 1. 查询订单 order, err := tx.Orders.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}).Where(tx.Orders.ID.Eq(orderID), tx.Orders.UserID.Eq(userID)).First() if err != nil { return err } if order == nil { return errors.New("order not found") } // 2. 校验状态 if order.Status != 1 { return errors.New("order cannot be cancelled") } // 3. 退还积分 if order.PointsAmount > 0 { refundReason := "cancel_order" if reason != "" { refundReason = refundReason + ":" + reason } // Get Rate ratePtsPerCent, _ := s.CentsToPoints(ctx, 1) if ratePtsPerCent <= 0 { ratePtsPerCent = 1 } pointsToRefund := order.PointsAmount * ratePtsPerCent // Update User Points existing, _ := tx.UserPoints.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}).Where(tx.UserPoints.UserID.Eq(userID)).First() if existing == nil { if err := tx.UserPoints.WithContext(ctx).Omit(tx.UserPoints.ValidEnd).Create(&model.UserPoints{UserID: userID, Points: pointsToRefund}); err != nil { return err } } else { if _, err := tx.UserPoints.WithContext(ctx).Where(tx.UserPoints.ID.Eq(existing.ID)).Updates(map[string]any{"points": existing.Points + pointsToRefund}); err != nil { return err } } // Log led := &model.UserPointsLedger{UserID: userID, Action: "refund_points", Points: pointsToRefund, RefTable: "orders", RefID: order.OrderNo, Remark: refundReason} if err := tx.UserPointsLedger.WithContext(ctx).Create(led); err != nil { return err } } // 4. 更新订单状态 updates := map[string]any{ tx.Orders.Status.ColumnName().String(): 3, tx.Orders.CancelledAt.ColumnName().String(): time.Now(), } if _, err := tx.Orders.WithContext(ctx).Where(tx.Orders.ID.Eq(order.ID)).Updates(updates); err != nil { return err } updatedOrder = order updatedOrder.Status = 3 return nil }) if err != nil { return nil, err } return updatedOrder, nil }