新增客服一键交接功能
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/modules/notification"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
func canAdminForceHandoff(order model.RentalOrder) bool {
|
||||
if isPlatformHandoffOrder(order) || isPlatformSettlementOrder(order) {
|
||||
return false
|
||||
}
|
||||
if order.Status == orderStatusPendingHandoff {
|
||||
return order.HandoffStatus == handoffStatusPendingOwner ||
|
||||
order.HandoffStatus == handoffStatusOwnerTimeout ||
|
||||
order.HandoffStatus == handoffStatusPendingRenterConfirm
|
||||
}
|
||||
return order.Status == orderStatusAbnormal && order.HandoffStatus == handoffStatusRenterConfirmTimeout
|
||||
}
|
||||
|
||||
func forceHandoffNeedsContent(order model.RentalOrder) bool {
|
||||
return order.HandoffStatus == handoffStatusPendingOwner || order.HandoffStatus == handoffStatusOwnerTimeout
|
||||
}
|
||||
|
||||
// AdminForceHandoff 由客服确认普通号主订单已完成线下交接,并立即开始租期。
|
||||
func (r *Repository) AdminForceHandoff(ctx context.Context, adminID uint64, orderID uint64, req ForceHandoffRequest, meta AuditMeta) error {
|
||||
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var order model.RentalOrder
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&order, orderID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if !canAdminForceHandoff(order) || strings.TrimSpace(req.Reason) == "" {
|
||||
return ErrOrderCannotForceHandoff
|
||||
}
|
||||
if order.RefundStatus == refundStatusPending || order.RefundStatus == refundStatusPendingReview {
|
||||
return ErrOrderCannotForceHandoff
|
||||
}
|
||||
|
||||
var activeDisputeCount int64
|
||||
if err := tx.Model(&model.Dispute{}).
|
||||
Where("order_id = ? AND status IN ?", order.ID, []string{"open", "processing"}).
|
||||
Count(&activeDisputeCount).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if activeDisputeCount > 0 {
|
||||
return ErrOrderCannotForceHandoff
|
||||
}
|
||||
|
||||
needsContent := forceHandoffNeedsContent(order)
|
||||
content := strings.TrimSpace(req.Content)
|
||||
if needsContent && content == "" {
|
||||
return ErrOrderCannotForceHandoff
|
||||
}
|
||||
if !needsContent {
|
||||
var handoffCount int64
|
||||
if err := tx.Model(&model.HandoffRecord{}).
|
||||
Where("order_id = ? AND type = ?", order.ID, "owner_handoff").
|
||||
Count(&handoffCount).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if handoffCount == 0 {
|
||||
return ErrOrderCannotForceHandoff
|
||||
}
|
||||
content = "客服已确认双方完成交接,订单已进入使用中。"
|
||||
}
|
||||
|
||||
beforeOrderStatus := order.Status
|
||||
beforeHandoffStatus := order.HandoffStatus
|
||||
now := time.Now()
|
||||
record := model.HandoffRecord{
|
||||
OrderID: order.ID,
|
||||
FromUserID: adminID,
|
||||
ToUserID: order.RenterID,
|
||||
Type: "admin_force_handoff",
|
||||
Content: content,
|
||||
}
|
||||
if err := tx.Create(&record).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
order.Status = orderStatusRenting
|
||||
order.HandoffStatus = handoffStatusReceived
|
||||
order.EstimatedDurationHours = estimateOrderDurationHours(order.AccountSnapshot)
|
||||
order.RentedAt = &now
|
||||
orderID := order.ID
|
||||
if err := notification.Append(tx,
|
||||
notification.Entry{
|
||||
UserID: order.RenterID,
|
||||
Type: "order_admin",
|
||||
Title: "客服已确认交接",
|
||||
Content: "客服已确认双方完成交接,订单已进入使用中,租期已开始计算。",
|
||||
BizType: "order",
|
||||
BizID: &orderID,
|
||||
},
|
||||
notification.Entry{
|
||||
UserID: order.OwnerID,
|
||||
Type: "order_admin",
|
||||
Title: "客服已确认交接",
|
||||
Content: "客服已确认双方完成交接,订单已进入使用中,租期已开始计算。",
|
||||
BizType: "order",
|
||||
BizID: &orderID,
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := appendAuditLog(tx, adminID, "order.force_handoff", "order", order.ID, meta, map[string]any{
|
||||
"order_id": order.ID,
|
||||
"order_no": order.OrderNo,
|
||||
"reason": strings.TrimSpace(req.Reason),
|
||||
"content_length": len(content),
|
||||
"before_order_status": beforeOrderStatus,
|
||||
"after_order_status": order.Status,
|
||||
"before_handoff_status": beforeHandoffStatus,
|
||||
"after_handoff_status": order.HandoffStatus,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Save(&order).Error
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user