feat(orders): 号主可从自己的列表隐藏已结束订单
只写入隐藏时间,订单和款项仍保留给租客与后台。详情按钮固定对齐,删除跟在后面。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
// ownerMayHideOrder 判断号主能否把订单从自己的列表里隐藏。
|
||||
// 进行中的订单、未结清的款项、暂扣押金、处理中争议和未释放的分销结算都不能藏。
|
||||
func ownerMayHideOrder(order model.RentalOrder, hasOpenDispute bool, distributionSettlement string) bool {
|
||||
if order.OwnerHiddenAt != nil {
|
||||
return false
|
||||
}
|
||||
switch order.Status {
|
||||
case orderStatusCompleted, orderStatusClosed:
|
||||
if order.SettlementStatus != settlementStatusSettled &&
|
||||
order.SettlementStatus != settlementStatusClosed &&
|
||||
order.SettlementStatus != settlementStatusArbitrated {
|
||||
return false
|
||||
}
|
||||
if order.OfflineSettlementStatus == offlineSettlementStatusPending {
|
||||
return false
|
||||
}
|
||||
case orderStatusCancelled:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
switch order.RefundStatus {
|
||||
case "", "none", refundStatusRefunded:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
if order.DepositHoldStatus == model.DepositHoldStatusHeld {
|
||||
return false
|
||||
}
|
||||
if hasOpenDispute {
|
||||
return false
|
||||
}
|
||||
if distributionSettlement != "" && distributionSettlement != "settled" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type ownerHideSignal struct {
|
||||
disputed map[uint64]struct{}
|
||||
dist map[uint64]string
|
||||
}
|
||||
|
||||
func loadOwnerHideSignals(db *gorm.DB, orderIDs []uint64) (ownerHideSignal, error) {
|
||||
signal := ownerHideSignal{
|
||||
disputed: map[uint64]struct{}{},
|
||||
dist: map[uint64]string{},
|
||||
}
|
||||
if len(orderIDs) == 0 {
|
||||
return signal, nil
|
||||
}
|
||||
var disputeIDs []uint64
|
||||
if err := db.Model(&model.Dispute{}).
|
||||
Where("order_id IN ? AND status IN ?", orderIDs, []string{"open", "processing"}).
|
||||
Distinct().
|
||||
Pluck("order_id", &disputeIDs).Error; err != nil {
|
||||
return signal, err
|
||||
}
|
||||
for _, id := range disputeIDs {
|
||||
signal.disputed[id] = struct{}{}
|
||||
}
|
||||
var rows []struct {
|
||||
OrderID uint64 `gorm:"column:order_id"`
|
||||
SettlementStatus string `gorm:"column:settlement_status"`
|
||||
}
|
||||
if err := db.Model(&model.DistributionOrderFinancial{}).
|
||||
Select("order_id, settlement_status").
|
||||
Where("order_id IN ?", orderIDs).
|
||||
Scan(&rows).Error; err != nil {
|
||||
return signal, err
|
||||
}
|
||||
for _, row := range rows {
|
||||
signal.dist[row.OrderID] = row.SettlementStatus
|
||||
}
|
||||
return signal, nil
|
||||
}
|
||||
|
||||
func (r *Repository) HideForOwner(ctx context.Context, userID uint64, orderID uint64) 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 order.OwnerID != userID {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
if order.OwnerHiddenAt != nil {
|
||||
return nil
|
||||
}
|
||||
signals, err := loadOwnerHideSignals(tx, []uint64{order.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, disputed := signals.disputed[order.ID]
|
||||
if !ownerMayHideOrder(order, disputed, signals.dist[order.ID]) {
|
||||
return ErrOrderCannotHide
|
||||
}
|
||||
now := time.Now()
|
||||
return tx.Model(&model.RentalOrder{}).Where("id = ?", order.ID).Update("owner_hidden_at", now).Error
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user