package order import ( "context" "hfb_sys/backend/internal/model" "hfb_sys/backend/internal/modules/notification" "gorm.io/gorm" "gorm.io/gorm/clause" ) func (r *Repository) SubmitHandoff(ctx context.Context, userID uint64, orderID uint64, req SubmitHandoffRequest) (*HandoffRecordDTO, error) { var recordID uint64 err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { var order model.RentalOrder if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil { return err } if order.OwnerID != userID { return ErrPermissionDenied } // 号主交接超时(owner_timeout)后仍允许补提交,避免临时延误导致订单卡死。 if order.Status != orderStatusPendingHandoff || (order.HandoffStatus != handoffStatusPendingOwner && order.HandoffStatus != handoffStatusOwnerTimeout) { return ErrOrderCannotHandoff } lateSubmit := order.HandoffStatus == handoffStatusOwnerTimeout record := model.HandoffRecord{ OrderID: order.ID, FromUserID: order.OwnerID, ToUserID: order.RenterID, Type: "owner_handoff", Content: req.Content, } if err := tx.Create(&record).Error; err != nil { return err } order.HandoffStatus = handoffStatusPendingRenterConfirm orderID := order.ID renterContent := "请查看交接记录,确认账号可正常登录后点击确认收号。" if lateSubmit { renterContent = "号主已补交交接说明,请查看交接记录,确认账号可正常登录后点击确认收号。" } if err := notification.Append(tx, notification.Entry{ UserID: order.RenterID, Type: "handoff", Title: "号主已提交交接说明", Content: renterContent, BizType: "order", BizID: &orderID, }); err != nil { return err } if err := tx.Save(&order).Error; err != nil { return err } recordID = record.ID return nil }) if err != nil { return nil, err } return r.findHandoffRecord(ctx, recordID) } func (r *Repository) HandoffRecords(ctx context.Context, userID uint64, orderID uint64) ([]HandoffRecordDTO, error) { var order model.RentalOrder db := r.db.WithContext(ctx) if err := db.Where("id = ? AND (renter_id = ? OR owner_id = ?)", orderID, userID, userID).First(&order).Error; err != nil { return nil, err } var records []model.HandoffRecord if err := db.Where("order_id = ?", orderID).Order("id ASC").Find(&records).Error; err != nil { return nil, err } items := make([]HandoffRecordDTO, 0, len(records)) for _, record := range records { items = append(items, toHandoffDTO(record)) } return items, nil } func (r *Repository) SubmitReturn(ctx context.Context, userID uint64, orderID uint64, req SubmitReturnRequest) (*HandoffRecordDTO, error) { return r.SubmitCheckout(ctx, userID, orderID, SubmitCheckoutRequest{Content: req.Content}) } func (r *Repository) HandoffRecordsAdmin(ctx context.Context, orderID uint64) ([]HandoffRecordDTO, error) { var order model.RentalOrder db := r.db.WithContext(ctx) if err := db.First(&order, orderID).Error; err != nil { return nil, err } var records []model.HandoffRecord if err := db.Where("order_id = ?", orderID).Order("id ASC").Find(&records).Error; err != nil { return nil, err } items := make([]HandoffRecordDTO, 0, len(records)) for _, record := range records { items = append(items, toHandoffDTO(record)) } return items, nil } func (r *Repository) findHandoffRecord(ctx context.Context, id uint64) (*HandoffRecordDTO, error) { var record model.HandoffRecord if err := r.db.WithContext(ctx).First(&record, id).Error; err != nil { return nil, err } dto := toHandoffDTO(record) return &dto, nil } func toHandoffDTO(record model.HandoffRecord) HandoffRecordDTO { return HandoffRecordDTO{ ID: record.ID, OrderID: record.OrderID, FromUserID: record.FromUserID, ToUserID: record.ToUserID, Type: record.Type, Content: record.Content, ConfirmedByRenterAt: record.ConfirmedByRenterAt, ConfirmedByOwnerAt: record.ConfirmedByOwnerAt, CreatedAt: record.CreatedAt, } }