Files
hfb_sys/backend/internal/model/order.go
T
2026-07-29 18:59:07 +08:00

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
}