115 lines
7.1 KiB
Go
115 lines
7.1 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gorm.io/datatypes"
|
|
)
|
|
|
|
type RentalOrder struct {
|
|
ID uint64 `gorm:"primaryKey" json:"id"`
|
|
OrderNo string `gorm:"size:64;not null;uniqueIndex" json:"order_no"`
|
|
ListingID uint64 `gorm:"not null;index" json:"listing_id"`
|
|
AccountID uint64 `gorm:"not null;index" json:"account_id"`
|
|
OwnerID uint64 `gorm:"not null;index" json:"owner_id"`
|
|
RenterID uint64 `gorm:"not null;index" json:"renter_id"`
|
|
RentedAt *time.Time `json:"rented_at"`
|
|
HandoffStartedAt *time.Time `json:"handoff_started_at"`
|
|
EstimatedDurationHours int `gorm:"not null;default:24" json:"estimated_duration_hours"`
|
|
RentAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
OwnerRentAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
DepositAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
DepositOriginalAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
DepositWaivedAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
DepositFreeLevelQuotaCent int64 `gorm:"not null;default:0" json:"deposit_free_level_quota_cent"`
|
|
DepositFreeManualQuotaCent int64 `gorm:"not null;default:0" json:"deposit_free_manual_quota_cent"`
|
|
DepositFreeUsedBeforeCent int64 `gorm:"not null;default:0" json:"deposit_free_used_before_cent"`
|
|
PlatformFeeCent int64 `gorm:"not null;default:0" json:"-"`
|
|
RentOriginalAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
RentDiscountAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
PureCoinOriginalAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
ExtraItemOriginalAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
ActualCoinConsumedM float64 `gorm:"type:decimal(12,2);not null;default:0" json:"actual_coin_consumed_m"`
|
|
ActualPureCoinAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
ActualPureCoinDiscountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
ActualExtraItemAmountCent int64 `gorm:"not null;default:0" json:"-"`
|
|
RenterGrowthLevel string `gorm:"size:32;not null;default:'normal'" json:"renter_growth_level"`
|
|
RenterGrowthLevelName string `gorm:"size:32;not null;default:'普通'" json:"renter_growth_level_name"`
|
|
RenterDiscountBps int `gorm:"not null;default:10000" json:"renter_discount_bps"`
|
|
GrowthPointsBasisCent int64 `gorm:"not null;default:0" json:"growth_points_basis_cent"`
|
|
GrowthPointsPerYuan int64 `gorm:"not null;default:0" json:"growth_points_per_yuan"`
|
|
GrowthPointsAwarded int64 `gorm:"not null;default:0" json:"growth_points_awarded"`
|
|
GrowthPointsAwardedAt *time.Time `json:"growth_points_awarded_at"`
|
|
AccountSnapshot datatypes.JSON `json:"account_snapshot"`
|
|
Status string `gorm:"size:32;not null;default:'pending_payment'" json:"status"`
|
|
HandoffStatus string `gorm:"size:32;not null;default:'none'" json:"handoff_status"`
|
|
HandoffMode string `gorm:"size:16;not null;default:'owner';index" json:"handoff_mode"`
|
|
SettlementMode string `gorm:"size:32;not null;default:'owner_wallet'" json:"settlement_mode"`
|
|
ManagedAdminID *uint64 `gorm:"index" json:"managed_admin_id"`
|
|
SettlementStatus string `gorm:"size:32;not null;default:'unsettled'" json:"settlement_status"`
|
|
OfflineSettlementStatus string `gorm:"size:16;not null;default:'none';index" json:"offline_settlement_status"`
|
|
OfflineSettlementAmountCent int64 `gorm:"not null;default:0" json:"offline_settlement_amount_cent"`
|
|
OfflineSettlementRemark string `gorm:"size:255;not null;default:''" json:"offline_settlement_remark"`
|
|
OfflineSettledBy *uint64 `json:"offline_settled_by"`
|
|
OfflineSettledAt *time.Time `json:"offline_settled_at"`
|
|
RefundStatus string `gorm:"size:32;not null;default:'none';index" json:"refund_status"`
|
|
RefundAmountCent int64 `gorm:"not null;default:0" json:"refund_amount_cent"`
|
|
RefundedAt *time.Time `json:"refunded_at"`
|
|
DepositHoldStatus string `gorm:"size:16;not null;default:'none';index" json:"deposit_hold_status"`
|
|
DepositHoldAmountCent int64 `gorm:"not null;default:0" json:"deposit_hold_amount_cent"`
|
|
DepositHoldReason string `gorm:"size:255;not null;default:''" json:"deposit_hold_reason"`
|
|
DepositHeldBy *uint64 `json:"deposit_held_by"`
|
|
DepositHeldAt *time.Time `json:"deposit_held_at"`
|
|
DepositHoldReleasedAt *time.Time `json:"deposit_hold_released_at"`
|
|
OwnerSettledAt *time.Time `json:"owner_settled_at"`
|
|
SettledAt *time.Time `json:"settled_at"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (RentalOrder) TableName() string {
|
|
return "rental_orders"
|
|
}
|
|
|
|
// 押金暂扣状态:客服可对进行中订单的押金退款进行暂扣,订单照常结算,
|
|
// 但本应原路退给租客的押金部分挂起不退,后续由客服手动归还。
|
|
const (
|
|
DepositHoldStatusNone = "none" // 未暂扣
|
|
DepositHoldStatusHeld = "held" // 已暂扣(押金退款被拦截/挂起)
|
|
DepositHoldStatusReleased = "released" // 已归还
|
|
)
|
|
|
|
// IsDepositHeld 判断订单当前是否处于押金暂扣状态。
|
|
func (o *RentalOrder) IsDepositHeld() bool {
|
|
return o.DepositHoldStatus == DepositHoldStatusHeld
|
|
}
|
|
|
|
// ApplyDepositHold 在任一结算退款路径中拦截押金退款。
|
|
// totalRefundCent 是本次本应原路退还给租客的总金额(含租金退款和押金退款),
|
|
// depositPortionCent 是其中属于押金退款的部分。
|
|
// 若订单已暂扣,则把押金部分(不超过本次退款总额)从退款中扣除,
|
|
// 并把尚未记录过的部分累加到暂扣金额(累计不超过实付押金),返回扣除后实际发起原路退款的金额;
|
|
// 未暂扣时原样返回 totalRefundCent。
|
|
// 注意:本函数只做“少退、挂起”,绝不多退,因此在任何路径下都不会造成租客损失或平台多付。
|
|
func (o *RentalOrder) ApplyDepositHold(totalRefundCent, depositPortionCent int64) int64 {
|
|
if !o.IsDepositHeld() {
|
|
return totalRefundCent
|
|
}
|
|
withheld := depositPortionCent
|
|
if withheld > totalRefundCent {
|
|
withheld = totalRefundCent
|
|
}
|
|
if withheld <= 0 {
|
|
return totalRefundCent
|
|
}
|
|
remainingDepositHoldCent := o.DepositAmountCent - o.DepositHoldAmountCent
|
|
if remainingDepositHoldCent > 0 {
|
|
newHold := withheld
|
|
if newHold > remainingDepositHoldCent {
|
|
newHold = remainingDepositHoldCent
|
|
}
|
|
o.DepositHoldAmountCent += newHold
|
|
}
|
|
return totalRefundCent - withheld
|
|
}
|