143 lines
4.7 KiB
Go
143 lines
4.7 KiB
Go
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, "标记异常")
|
|
}
|