package order import ( "hfb_sys/backend/internal/listingstatus" "hfb_sys/backend/internal/model" "gorm.io/gorm" "gorm.io/gorm/clause" ) type orderAssets struct { Order *model.RentalOrder Listing *model.RentalListing Account *model.GameAccount } func (r *Repository) lockOrderAssets(tx *gorm.DB, orderID uint64) (*orderAssets, error) { var order model.RentalOrder if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil { return nil, err } listing, account, err := r.lockListingAccountForOrder(tx, &order) if err != nil { return nil, err } return &orderAssets{ Order: &order, Listing: listing, Account: account, }, nil } func (r *Repository) lockListingAccountForOrder(tx *gorm.DB, order *model.RentalOrder) (*model.RentalListing, *model.GameAccount, error) { var listing model.RentalListing if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&listing, order.ListingID).Error; err != nil { return nil, nil, err } var account model.GameAccount if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&account, order.AccountID).Error; err != nil { return nil, nil, err } return &listing, &account, nil } func reserveListingForOrder(listing *model.RentalListing) { listing.InTransaction = true } func markAssetsRented(tx *gorm.DB, listing *model.RentalListing, account *model.GameAccount) error { from := listing.Status listing.Status = listingStatusRented account.Status = accountStatusRented return listingstatus.AppendTransition(tx, listing, from, listingstatus.SourceOrder, listingstatus.ActorSystem, 0, "支付成功租出") } func releaseAssetsForRental(tx *gorm.DB, listing *model.RentalListing, account *model.GameAccount) error { from := listing.Status listing.Status = listingStatusPublished listing.InTransaction = false account.Status = accountStatusPublished return listingstatus.AppendTransition(tx, listing, from, listingstatus.SourceOrder, listingstatus.ActorSystem, 0, "订单取消恢复上架") } func terminalOrderStatuses() []string { return []string{orderStatusCompleted, orderStatusCancelled, orderStatusClosed} } func hasActiveSiblingOrder(tx *gorm.DB, order *model.RentalOrder) (bool, error) { if order == nil { return false, nil } var count int64 err := tx.Model(&model.RentalOrder{}). Where("id <> ? AND (listing_id = ? OR account_id = ?) AND status NOT IN ?", order.ID, order.ListingID, order.AccountID, terminalOrderStatuses(), ). Count(&count).Error return count > 0, err } func hasActiveOrderForAssets(tx *gorm.DB, listingID uint64, accountID uint64, excludeOrderID uint64) (bool, error) { var count int64 err := tx.Model(&model.RentalOrder{}). Where("id <> ? AND (listing_id = ? OR account_id = ?) AND status NOT IN ?", excludeOrderID, listingID, accountID, terminalOrderStatuses(), ). Count(&count).Error return count > 0, err } func releaseAssetsForRentalIfIdle(tx *gorm.DB, order *model.RentalOrder, listing *model.RentalListing, account *model.GameAccount) error { active, err := hasActiveSiblingOrder(tx, order) if err != nil { return err } if active { return nil } return releaseAssetsForRental(tx, listing, account) } func archiveAssets(tx *gorm.DB, listing *model.RentalListing, account *model.GameAccount) error { from := listing.Status listing.Status = listingStatusOffline listing.InTransaction = false listing.PublishedAt = nil account.Status = accountStatusOffline return listingstatus.AppendTransition(tx, listing, from, listingstatus.SourceOrder, listingstatus.ActorSystem, 0, "订单归档下架") } func sealAssets(tx *gorm.DB, listing *model.RentalListing, account *model.GameAccount) error { from := listing.Status listing.Status = listingStatusSealed listing.InTransaction = false listing.PublishedAt = nil account.Status = accountStatusSealed return listingstatus.AppendTransition(tx, listing, from, listingstatus.SourceOrder, listingstatus.ActorSystem, 0, "订单封存") } func completeAssets(tx *gorm.DB, listing *model.RentalListing, account *model.GameAccount) error { from := listing.Status listing.Status = listingStatusCompleted listing.InTransaction = false listing.PublishedAt = nil account.Status = accountStatusOffline return listingstatus.AppendTransition(tx, listing, from, listingstatus.SourceOrder, listingstatus.ActorSystem, 0, "订单完成售出") } func markAssetsAbnormal(tx *gorm.DB, listing *model.RentalListing, account *model.GameAccount) error { from := listing.Status listing.Status = listingStatusAbnormal listing.InTransaction = false listing.PublishedAt = nil account.Status = accountStatusAbnormal return listingstatus.AppendTransition(tx, listing, from, listingstatus.SourceOrder, listingstatus.ActorSystem, 0, "标记异常") }