fix(distribution): 修复分销结账退款分成计算逻辑与利润统计,优化分销订单表格列宽与展示体验
This commit is contained in:
@@ -240,7 +240,7 @@ func SnapshotPaidOrderTx(tx *gorm.DB, orderID uint64, grossPaidCent int64) error
|
||||
return tx.Create(&parties).Error
|
||||
}
|
||||
|
||||
// ApplyRefundTx 按累计成功退款金额重算手续费、分成基数和各方分成,不覆盖订单创建时的规则版本。
|
||||
// ApplyRefundTx 按累计成功退款或结账结算重算手续费、分成基数和各方分成,不覆盖订单创建时的规则版本。
|
||||
func ApplyRefundTx(tx *gorm.DB, orderID uint64, refundAmountCent int64) error {
|
||||
if !distributionTablesPresent(tx) {
|
||||
return nil
|
||||
@@ -255,33 +255,96 @@ func ApplyRefundTx(tx *gorm.DB, orderID uint64, refundAmountCent int64) error {
|
||||
if refundAmountCent < 0 {
|
||||
return ErrInvalidAmount
|
||||
}
|
||||
if refundAmountCent > financial.GrossPaidAmountCent {
|
||||
refundAmountCent = financial.GrossPaidAmountCent
|
||||
}
|
||||
|
||||
var rule model.DistributionRuleVersion
|
||||
if err := tx.First(&rule, financial.RuleVersionID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var order model.RentalOrder
|
||||
ownerRent := int64(0)
|
||||
if err := tx.Select("owner_rent_amount_cent").First(&order, orderID).Error; err == nil {
|
||||
ownerRent = order.OwnerRentAmountCent
|
||||
if err := tx.First(&order, orderID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 判定实际租金退款和号主应得租金:
|
||||
// 1. 如果存在已达成一致的结账单(accepted 或 settled),以结账单中的实际消费租金与号主实际所得为准
|
||||
var checkout model.OrderCheckout
|
||||
hasAcceptedCheckout := false
|
||||
if err := tx.Where("order_id = ? AND status IN ('accepted', 'settled')", orderID).
|
||||
Order("id DESC").First(&checkout).Error; err == nil {
|
||||
hasAcceptedCheckout = true
|
||||
}
|
||||
|
||||
rentRefundCent := refundAmountCent
|
||||
ownerRent := order.OwnerRentAmountCent
|
||||
if ownerRent < 0 {
|
||||
ownerRent = 0
|
||||
}
|
||||
|
||||
if hasAcceptedCheckout {
|
||||
// 结账单中,实际有效租金为 checkout.RentAmountCent
|
||||
// 真实的租金退款为 订单初始租金 - 实际有效租金
|
||||
actualRentRefund := order.RentAmountCent - checkout.RentAmountCent
|
||||
if actualRentRefund < 0 {
|
||||
actualRentRefund = 0
|
||||
}
|
||||
rentRefundCent = actualRentRefund
|
||||
// 号主实际租金所得以结账单的实际租金收入为准
|
||||
ownerRent = checkout.OwnerRentAmountCent
|
||||
if ownerRent < 0 {
|
||||
ownerRent = 0
|
||||
}
|
||||
} else {
|
||||
// 无结账单场景(例如交接超时、提前取消退款、维权全额退款):
|
||||
// refundAmountCent 是租客收到的总退款(含押金与租金),押金不计入分销毛收入
|
||||
// 先抵扣押金退款,剩余部分才属于租金退款
|
||||
depositRefund := order.DepositAmountCent
|
||||
if refundAmountCent < depositRefund {
|
||||
depositRefund = refundAmountCent
|
||||
}
|
||||
actualRentRefund := refundAmountCent - depositRefund
|
||||
if actualRentRefund < 0 {
|
||||
actualRentRefund = 0
|
||||
}
|
||||
rentRefundCent = actualRentRefund
|
||||
// 如果租金全额退款,号主应得租金为 0
|
||||
if rentRefundCent >= financial.GrossPaidAmountCent {
|
||||
ownerRent = 0
|
||||
}
|
||||
}
|
||||
result, err := calculateForRule(rule, SettlementInput{GrossPaidAmountCent: financial.GrossPaidAmountCent, RefundAmountCent: refundAmountCent, OwnerRentAmountCent: ownerRent, MarkupAmountCent: financial.MarkupAmountCent})
|
||||
|
||||
if rentRefundCent > financial.GrossPaidAmountCent {
|
||||
rentRefundCent = financial.GrossPaidAmountCent
|
||||
}
|
||||
|
||||
result, err := calculateForRule(rule, SettlementInput{
|
||||
GrossPaidAmountCent: financial.GrossPaidAmountCent,
|
||||
RefundAmountCent: rentRefundCent,
|
||||
OwnerRentAmountCent: ownerRent,
|
||||
MarkupAmountCent: financial.MarkupAmountCent,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
splits := SplitSettlement(ruleFromVersion(rule), result.SplitBaseAmountCent, financial.MarkupAmountCent)
|
||||
if err := tx.Model(&financial).Updates(map[string]any{"refund_amount_cent": refundAmountCent, "net_paid_amount_cent": result.NetPaidAmountCent, "payment_fee_cent": result.PaymentFeeCent, "service_fee_cent": result.ServiceFeeCent, "split_base_amount_cent": result.SplitBaseAmountCent, "rounding_adjustment_cent": SplitRoundingCent(result.SplitBaseAmountCent, result.ServiceFeeCent, financial.MarkupAmountCent, splits), "settlement_status": "pending"}).Error; err != nil {
|
||||
if err := tx.Model(&financial).Updates(map[string]any{
|
||||
"refund_amount_cent": rentRefundCent,
|
||||
"net_paid_amount_cent": result.NetPaidAmountCent,
|
||||
"payment_fee_cent": result.PaymentFeeCent,
|
||||
"service_fee_cent": result.ServiceFeeCent,
|
||||
"split_base_amount_cent": result.SplitBaseAmountCent,
|
||||
"rounding_adjustment_cent": SplitRoundingCent(result.SplitBaseAmountCent, result.ServiceFeeCent, financial.MarkupAmountCent, splits),
|
||||
"settlement_status": "pending",
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for _, split := range splits {
|
||||
if err := tx.Model(&model.DistributionOrderParty{}).
|
||||
Where("order_id = ? AND party_role = ?", orderID, split.PartyRole).
|
||||
Updates(map[string]any{"income_amount_cent": split.AmountCent, "profit_amount_cent": split.AmountCent}).Error; err != nil {
|
||||
Updates(map[string]any{
|
||||
"income_amount_cent": split.AmountCent,
|
||||
"profit_amount_cent": split.AmountCent,
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user