支持后台转移发布所有权
This commit is contained in:
@@ -6,9 +6,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/modules/notification"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
func (r *Repository) ListPendingReview(ctx context.Context) ([]ListingDTO, error) {
|
||||
@@ -32,6 +35,120 @@ func (r *Repository) AdminMarkAbnormal(ctx context.Context, adminID uint64, list
|
||||
return r.adminUpdateStatus(ctx, adminID, listingID, req, meta, "abnormal", "abnormal", "listing.mark_abnormal", "商品已被标记异常", "你的租号商品已被后台标记异常,请联系客服处理。")
|
||||
}
|
||||
|
||||
func (r *Repository) TransferOwner(ctx context.Context, adminID uint64, listingID uint64, req TransferOwnerRequest, meta AuditMeta) (*ListingDTO, error) {
|
||||
var dto *ListingDTO
|
||||
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
listing, account, err := r.findForReviewUpdate(tx, listingID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if listing.Status == "rented" || listing.InTransaction {
|
||||
return ErrListingLocked
|
||||
}
|
||||
if listing.OwnerID == req.TargetUserID {
|
||||
dto = toDTO(*account, *listing)
|
||||
return nil
|
||||
}
|
||||
|
||||
var target model.User
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("id = ? AND status = ? AND realname_status = ?", req.TargetUserID, "active", "verified").
|
||||
First(&target).Error; err != nil {
|
||||
if IsNotFound(err) {
|
||||
return ErrTargetOwnerInvalid
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
beforeOwnerID := listing.OwnerID
|
||||
listing.OwnerID = target.ID
|
||||
account.OwnerID = target.ID
|
||||
if err := tx.Save(account).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Save(listing).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Model(&model.ListingUpload{}).
|
||||
Where("listing_id = ?", listing.ID).
|
||||
Update("owner_id", target.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := transferListingGroupOwner(tx, listing.ID, beforeOwnerID, target.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
if r.chatCreator != nil {
|
||||
if _, err := r.chatCreator.EnsureListingConversation(tx, *listing, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := appendAuditLog(tx, adminID, "listing.transfer_owner", "listing", listing.ID, meta, map[string]any{
|
||||
"listing_id": listing.ID,
|
||||
"account_id": account.ID,
|
||||
"before_owner_id": beforeOwnerID,
|
||||
"after_owner_id": target.ID,
|
||||
"reason": req.Reason,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
dto = toDTO(*account, *listing)
|
||||
dto.OwnerPhone = target.Phone
|
||||
dto.OwnerNickname = target.Nickname
|
||||
return nil
|
||||
})
|
||||
return dto, err
|
||||
}
|
||||
|
||||
func transferListingGroupOwner(tx *gorm.DB, listingID uint64, beforeOwnerID uint64, afterOwnerID uint64) error {
|
||||
var conversation model.ChatConversation
|
||||
err := tx.Where("listing_id = ? AND type = ?", listingID, "listing_group").First(&conversation).Error
|
||||
if err != nil {
|
||||
if IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tx.Where("conversation_id = ? AND participant_type = ? AND participant_id = ? AND role = ?",
|
||||
conversation.ID, "user", beforeOwnerID, "owner").
|
||||
Delete(&model.ChatParticipant{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
participant := model.ChatParticipant{
|
||||
ConversationID: conversation.ID,
|
||||
ParticipantType: "user",
|
||||
ParticipantID: afterOwnerID,
|
||||
Role: "owner",
|
||||
JoinedAt: time.Now(),
|
||||
}
|
||||
if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&participant).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
message := model.ChatMessage{
|
||||
ConversationID: conversation.ID,
|
||||
SenderType: "system",
|
||||
SenderRole: "system",
|
||||
ContentType: "system",
|
||||
Content: "账号归属已由后台转移给新号主",
|
||||
AttachmentURLS: emptyJSONListForListing(),
|
||||
}
|
||||
if err := tx.Create(&message).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&model.ChatConversation{}).
|
||||
Where("id = ?", conversation.ID).
|
||||
Updates(map[string]interface{}{
|
||||
"last_message_id": message.ID,
|
||||
"last_message_preview": message.Content,
|
||||
"last_message_at": message.CreatedAt,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func emptyJSONListForListing() datatypes.JSON {
|
||||
return datatypes.JSON([]byte("[]"))
|
||||
}
|
||||
|
||||
func (r *Repository) adminUpdateStatus(ctx context.Context, adminID uint64, listingID uint64, req AdminActionRequest, meta AuditMeta, listingStatus string, accountStatus string, action string, title string, content string) (*ListingDTO, error) {
|
||||
var dto *ListingDTO
|
||||
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
Reference in New Issue
Block a user