新增客服「封存订单」动作,用于号主失联、无法联系的场景:单事务内 完成关闭订单、全量原路退款、永久封存关联商品、解散发布群、双方通知 与审计日志。 - 新增 listing 终态 sealed(封存),区别于可恢复的 offline - listingLockedForOwnerMutation 锁定 sealed,号主无法再编辑/提审/上架 - 解散群聊按 listing_id 查发布群(listing_group)置 archived, 阻断所有成员发言并留系统消息 - 新增 order.AdminSeal 及 /admin/orders/:id/seal 路由 - 前端:卖家页 PC/移动端 sealed 视为终态禁用操作,客服后台新增 「封存订单」按钮与二次确认 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
86 lines
2.4 KiB
Go
86 lines
2.4 KiB
Go
package order
|
|
|
|
import (
|
|
"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(listing *model.RentalListing, account *model.GameAccount) {
|
|
listing.Status = listingStatusRented
|
|
account.Status = accountStatusRented
|
|
}
|
|
|
|
func releaseAssetsForRental(listing *model.RentalListing, account *model.GameAccount) {
|
|
listing.Status = listingStatusPublished
|
|
listing.InTransaction = false
|
|
account.Status = accountStatusPublished
|
|
}
|
|
|
|
func archiveAssets(listing *model.RentalListing, account *model.GameAccount) {
|
|
listing.Status = listingStatusOffline
|
|
listing.InTransaction = false
|
|
listing.PublishedAt = nil
|
|
account.Status = accountStatusOffline
|
|
}
|
|
|
|
func sealAssets(listing *model.RentalListing, account *model.GameAccount) {
|
|
listing.Status = listingStatusSealed
|
|
listing.InTransaction = false
|
|
listing.PublishedAt = nil
|
|
account.Status = accountStatusSealed
|
|
}
|
|
|
|
func completeAssets(listing *model.RentalListing, account *model.GameAccount) {
|
|
listing.Status = listingStatusCompleted
|
|
listing.InTransaction = false
|
|
listing.PublishedAt = nil
|
|
account.Status = accountStatusOffline
|
|
}
|
|
|
|
func markAssetsAbnormal(listing *model.RentalListing, account *model.GameAccount) {
|
|
listing.Status = listingStatusAbnormal
|
|
listing.InTransaction = false
|
|
listing.PublishedAt = nil
|
|
account.Status = accountStatusAbnormal
|
|
}
|