package order import ( "strconv" "time" "hfb_sys/backend/internal/model" "gorm.io/gorm" ) func (r *Repository) ListForUser(userID uint64) ([]OrderDTO, error) { var rows []orderRow err := r.baseQuery(). Where("o.renter_id = ? OR o.owner_id = ?", userID, userID). Order("o.id DESC"). Scan(&rows).Error if err != nil { return nil, err } items := make([]OrderDTO, 0, len(rows)) paymentTimeoutMinutes := pendingPaymentTimeoutMinutes(r.db) for _, row := range rows { dto := row.toDTOForUser(userID) applyPaymentDeadline(&dto, row.RentalOrder, paymentTimeoutMinutes) if shouldAttachCheckout(row.Status) { dto.Checkout = r.latestCheckoutDTOForUser(row.ID, userID, row.RentalOrder) } items = append(items, dto) } return items, nil } func (r *Repository) ListAdmin(page, pageSize int) (*PaginatedResult, error) { var total int64 if err := r.adminQuery().Count(&total).Error; err != nil { return nil, err } offset := (page - 1) * pageSize var rows []orderRow err := r.adminQuery(). Order("o.id DESC"). Limit(pageSize). Offset(offset). Scan(&rows).Error if err != nil { return nil, err } items := make([]OrderDTO, 0, len(rows)) paymentTimeoutMinutes := pendingPaymentTimeoutMinutes(r.db) for _, row := range rows { dto := row.toAdminDTO() applyPaymentDeadline(&dto, row.RentalOrder, paymentTimeoutMinutes) items = append(items, dto) } return &PaginatedResult{ Items: items, Total: total, Page: page, PageSize: pageSize, }, nil } func (r *Repository) FindAdmin(orderID uint64) (*OrderDTO, error) { var row orderRow if err := r.adminQuery().Where("o.id = ?", orderID).First(&row).Error; err != nil { return nil, err } dto := row.toAdminDTO() applyPaymentDeadline(&dto, row.RentalOrder, pendingPaymentTimeoutMinutes(r.db)) dto.Checkout = r.latestCheckoutAdminDTO(orderID) return &dto, nil } func (r *Repository) FindForUser(userID uint64, orderID uint64) (*OrderDTO, error) { var row orderRow if err := r.baseQuery(). Where("o.id = ? AND (o.renter_id = ? OR o.owner_id = ?)", orderID, userID, userID). First(&row).Error; err != nil { return nil, err } dto := row.toDTOForUser(userID) applyPaymentDeadline(&dto, row.RentalOrder, pendingPaymentTimeoutMinutes(r.db)) dto.Checkout = r.latestCheckoutDTOForUser(orderID, userID, row.RentalOrder) return &dto, nil } func pendingPaymentTimeoutMinutes(tx *gorm.DB) int { var row model.SystemConfig err := tx.Where("`key` = ?", "order.pending_payment_timeout_minutes").First(&row).Error if err != nil { return defaultPendingPaymentTimeoutMinutes } value, err := strconv.Atoi(row.Value) if err != nil || value < 0 { return defaultPendingPaymentTimeoutMinutes } return value } func applyPaymentDeadline(dto *OrderDTO, order model.RentalOrder, timeoutMinutes int) { if dto == nil || order.Status != orderStatusPendingPayment || timeoutMinutes <= 0 { return } deadline := order.CreatedAt.Add(time.Duration(timeoutMinutes) * time.Minute) dto.PaymentDeadlineAt = &deadline } func (r *Repository) latestCheckoutAdminDTO(orderID uint64) *CheckoutDTO { var checkout model.OrderCheckout if err := r.db.Where("order_id = ?", orderID).Order("id DESC").First(&checkout).Error; err != nil { return nil } dto := toCheckoutAdminDTO(checkout) return &dto } func shouldAttachCheckout(status string) bool { switch status { case orderStatusPendingCheckoutConfirm, orderStatusPendingCheckoutAccept, orderStatusCheckoutDisputing, orderStatusCompleted: return true default: return false } } func (r *Repository) latestCheckoutDTOForUser(orderID uint64, userID uint64, order model.RentalOrder) *CheckoutDTO { var checkout model.OrderCheckout if err := r.db.Where("order_id = ?", orderID).Order("id DESC").First(&checkout).Error; err != nil { return nil } dto := toCheckoutDTOForUser(checkout, userID, order) return &dto } func (r *Repository) findCheckout(id uint64) (*model.OrderCheckout, error) { var checkout model.OrderCheckout if err := r.db.First(&checkout, id).Error; err != nil { return nil, err } return &checkout, nil } func (r *Repository) baseQuery() *gorm.DB { return r.db.Table("rental_orders AS o"). Select("o.*, l.listing_no, a.title, a.server_region, a.login_platform"). Joins("JOIN rental_listings AS l ON l.id = o.listing_id"). Joins("JOIN game_accounts AS a ON a.id = o.account_id") } func (r *Repository) adminQuery() *gorm.DB { return r.db.Table("rental_orders AS o"). Select("o.*, l.listing_no, a.title, a.server_region, a.login_platform, owner.phone AS owner_phone, renter.phone AS renter_phone"). Joins("JOIN rental_listings AS l ON l.id = o.listing_id"). Joins("JOIN game_accounts AS a ON a.id = o.account_id"). Joins("JOIN users AS owner ON owner.id = o.owner_id"). Joins("JOIN users AS renter ON renter.id = o.renter_id") } type orderRow struct { model.RentalOrder Title string ListingNo string ServerRegion string LoginPlatform string OwnerPhone string RenterPhone string }