Files
hfb_sys/backend/internal/modules/order/queries.go
T

177 lines
5.3 KiB
Go

package order
import (
"context"
"strconv"
"time"
"hfb_sys/backend/internal/model"
"gorm.io/gorm"
)
func (r *Repository) ListForUser(ctx context.Context, userID uint64) ([]OrderDTO, error) {
var rows []orderRow
db := r.db.WithContext(ctx)
err := r.baseQuery(ctx).
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(db)
for _, row := range rows {
dto := row.toDTOForUser(userID)
applyPaymentDeadline(&dto, row.RentalOrder, paymentTimeoutMinutes)
if shouldAttachCheckout(row.Status) {
dto.Checkout = r.latestCheckoutDTOForUser(ctx, row.ID, userID, row.RentalOrder)
}
items = append(items, dto)
}
return items, nil
}
func (r *Repository) ListAdmin(ctx context.Context, page, pageSize int) (*PaginatedResult, error) {
var total int64
db := r.db.WithContext(ctx)
if err := r.adminQuery(ctx).Count(&total).Error; err != nil {
return nil, err
}
offset := (page - 1) * pageSize
var rows []orderRow
err := r.adminQuery(ctx).
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(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(ctx context.Context, orderID uint64) (*OrderDTO, error) {
var row orderRow
db := r.db.WithContext(ctx)
if err := r.adminQuery(ctx).Where("o.id = ?", orderID).First(&row).Error; err != nil {
return nil, err
}
dto := row.toAdminDTO()
applyPaymentDeadline(&dto, row.RentalOrder, pendingPaymentTimeoutMinutes(db))
dto.Checkout = r.latestCheckoutAdminDTO(ctx, orderID)
return &dto, nil
}
func (r *Repository) FindForUser(ctx context.Context, userID uint64, orderID uint64) (*OrderDTO, error) {
var row orderRow
db := r.db.WithContext(ctx)
if err := r.baseQuery(ctx).
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(db))
dto.Checkout = r.latestCheckoutDTOForUser(ctx, 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(ctx context.Context, orderID uint64) *CheckoutDTO {
var checkout model.OrderCheckout
if err := r.db.WithContext(ctx).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(ctx context.Context, orderID uint64, userID uint64, order model.RentalOrder) *CheckoutDTO {
var checkout model.OrderCheckout
if err := r.db.WithContext(ctx).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(ctx context.Context, id uint64) (*model.OrderCheckout, error) {
var checkout model.OrderCheckout
if err := r.db.WithContext(ctx).First(&checkout, id).Error; err != nil {
return nil, err
}
return &checkout, nil
}
func (r *Repository) baseQuery(ctx context.Context) *gorm.DB {
return r.db.WithContext(ctx).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(ctx context.Context) *gorm.DB {
return r.db.WithContext(ctx).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
}