优化仲裁
This commit is contained in:
@@ -53,7 +53,7 @@ func (r *Repository) Arbitrate(ctx context.Context, adminID uint64, id uint64, r
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settlement, err := buildArbitrationSettlement(order, req, frozenBalance)
|
||||
settlement, actualSettlement, linkedCheckout, depositDeductAmountCent, err := buildArbitrationDecision(tx, row, order, req, frozenBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -114,23 +114,16 @@ func (r *Repository) Arbitrate(ctx context.Context, adminID uint64, id uint64, r
|
||||
return err
|
||||
}
|
||||
if order.Status == "completed" {
|
||||
coinConsumedM, linkedCheckout, err := arbitrationCoinConsumedM(tx, row, req)
|
||||
if err != nil {
|
||||
return err
|
||||
if actualSettlement == nil {
|
||||
return ErrInvalidDispute
|
||||
}
|
||||
pureCoin := ordermodule.CalculateActualPureCoinAmounts(order, coinConsumedM)
|
||||
order.ActualCoinConsumedM = pureCoin.ConsumedM
|
||||
order.ActualPureCoinAmountCent = pureCoin.AmountCent
|
||||
order.ActualPureCoinDiscountCent = pureCoin.DiscountCent
|
||||
applyArbitrationActualSettlement(&order, linkedCheckout, *actualSettlement, depositDeductAmountCent)
|
||||
if linkedCheckout != nil {
|
||||
linkedCheckout.PureCoinAmountCent = pureCoin.AmountCent
|
||||
linkedCheckout.PureCoinDiscountCent = pureCoin.DiscountCent
|
||||
linkedCheckout.PureCoinPayableCent = pureCoin.PayableCent
|
||||
if err := tx.Save(linkedCheckout).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := rentergrowth.AwardOrderCompleted(tx, &order, pureCoin.AmountCent, rentergrowth.SourceOrderCompleted); err != nil {
|
||||
if err := rentergrowth.AwardOrderCompleted(tx, &order, actualSettlement.PureCoinAmountCent, rentergrowth.SourceOrderCompleted); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -166,6 +159,7 @@ func (r *Repository) Arbitrate(ctx context.Context, adminID uint64, id uint64, r
|
||||
"deposit_deduct_amount_cent": settlement.DepositDeductAmountCent,
|
||||
"actual_coin_consumed_m": order.ActualCoinConsumedM,
|
||||
"actual_pure_coin_cent": order.ActualPureCoinAmountCent,
|
||||
"actual_extra_item_cent": order.ActualExtraItemAmountCent,
|
||||
"before_order_status": beforeOrderStatus,
|
||||
"after_order_status": order.Status,
|
||||
"before_handoff_status": beforeHandoffStatus,
|
||||
@@ -220,22 +214,131 @@ func (r *Repository) Arbitrate(ctx context.Context, adminID uint64, id uint64, r
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
func arbitrationCoinConsumedM(tx *gorm.DB, row model.Dispute, req ArbitrateRequest) (float64, *model.OrderCheckout, error) {
|
||||
var checkout *model.OrderCheckout
|
||||
if row.CheckoutID != nil && *row.CheckoutID > 0 {
|
||||
var saved model.OrderCheckout
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&saved, *row.CheckoutID).Error; err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
checkout = &saved
|
||||
func buildArbitrationDecision(tx *gorm.DB, row model.Dispute, order model.RentalOrder, req ArbitrateRequest, renterFrozenBalanceCent int64) (arbitrationSettlement, *ordermodule.ActualCheckoutSettlement, *model.OrderCheckout, int64, error) {
|
||||
if arbitrationUsesActualCheckout(req.Result) {
|
||||
return buildActualCheckoutArbitrationSettlement(tx, row, order, req, renterFrozenBalanceCent)
|
||||
}
|
||||
settlement, err := buildArbitrationSettlement(order, req, renterFrozenBalanceCent)
|
||||
return settlement, nil, nil, 0, err
|
||||
}
|
||||
|
||||
func arbitrationUsesActualCheckout(result string) bool {
|
||||
switch result {
|
||||
case "release_deposit", "deduct_deposit", "compensate_owner":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func buildActualCheckoutArbitrationSettlement(tx *gorm.DB, row model.Dispute, order model.RentalOrder, req ArbitrateRequest, renterFrozenBalanceCent int64) (arbitrationSettlement, *ordermodule.ActualCheckoutSettlement, *model.OrderCheckout, int64, error) {
|
||||
settlement := newArbitrationSettlement(order, renterFrozenBalanceCent)
|
||||
linkedCheckout, err := lockArbitrationCheckout(tx, row)
|
||||
if err != nil {
|
||||
return settlement, nil, nil, 0, err
|
||||
}
|
||||
coinConsumedM, err := arbitrationCoinConsumedM(linkedCheckout, req)
|
||||
if err != nil {
|
||||
return settlement, nil, linkedCheckout, 0, err
|
||||
}
|
||||
consumableAmountCent, err := arbitrationConsumableAmountCent(order, linkedCheckout, req)
|
||||
if err != nil {
|
||||
return settlement, nil, linkedCheckout, 0, err
|
||||
}
|
||||
depositDeductAmountCent, err := arbitrationDepositDeductAmountCent(order, req)
|
||||
if err != nil {
|
||||
return settlement, nil, linkedCheckout, 0, err
|
||||
}
|
||||
actualSettlement := ordermodule.CalculateActualCheckoutSettlement(order, consumableAmountCent, coinConsumedM, depositDeductAmountCent)
|
||||
if actualSettlement.ShortfallCent > 0 {
|
||||
return settlement, nil, linkedCheckout, 0, ErrInvalidDispute
|
||||
}
|
||||
if actualSettlement.OwnerIncomeCent > 0 {
|
||||
settlement.addOwnerIncome(order, actualSettlement.OwnerIncomeCent, "仲裁按实际消耗结算给号主")
|
||||
}
|
||||
if actualSettlement.RenterRefundCent > 0 {
|
||||
settlement.RenterRefundAmountCent = actualSettlement.RenterRefundCent
|
||||
settlement.RenterDepositRefundCent = actualSettlement.DepositRefundCent
|
||||
}
|
||||
settlement.DepositDeductAmountCent = depositDeductAmountCent + actualSettlement.OvershootAmountCent
|
||||
settlement.ActualExtraItemAmountCent = actualSettlement.ExtraItemAmountCent
|
||||
return settlement, &actualSettlement, linkedCheckout, depositDeductAmountCent, nil
|
||||
}
|
||||
|
||||
func lockArbitrationCheckout(tx *gorm.DB, row model.Dispute) (*model.OrderCheckout, error) {
|
||||
if row.CheckoutID == nil || *row.CheckoutID == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var checkout model.OrderCheckout
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&checkout, *row.CheckoutID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &checkout, nil
|
||||
}
|
||||
|
||||
func arbitrationCoinConsumedM(checkout *model.OrderCheckout, req ArbitrateRequest) (float64, error) {
|
||||
if req.ActualCoinConsumedM != nil {
|
||||
return *req.ActualCoinConsumedM, checkout, nil
|
||||
return *req.ActualCoinConsumedM, nil
|
||||
}
|
||||
if checkout != nil {
|
||||
return checkout.CoinConsumedM, checkout, nil
|
||||
return checkout.CoinConsumedM, nil
|
||||
}
|
||||
return 0, nil, ErrInvalidDispute
|
||||
return 0, ErrInvalidDispute
|
||||
}
|
||||
|
||||
func arbitrationConsumableAmountCent(order model.RentalOrder, checkout *model.OrderCheckout, req ArbitrateRequest) (int64, error) {
|
||||
if req.ActualConsumableAmountCent != nil {
|
||||
return *req.ActualConsumableAmountCent, nil
|
||||
}
|
||||
if checkout != nil {
|
||||
return checkout.ConsumableAmountCent, nil
|
||||
}
|
||||
if order.ExtraItemOriginalAmountCent <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, ErrInvalidDispute
|
||||
}
|
||||
|
||||
func arbitrationDepositDeductAmountCent(order model.RentalOrder, req ArbitrateRequest) (int64, error) {
|
||||
switch req.Result {
|
||||
case "release_deposit":
|
||||
return 0, nil
|
||||
case "deduct_deposit", "compensate_owner":
|
||||
deductAmountCent := req.AmountCent
|
||||
if deductAmountCent <= 0 {
|
||||
deductAmountCent = order.DepositAmountCent
|
||||
}
|
||||
if deductAmountCent > order.DepositAmountCent {
|
||||
return 0, ErrInvalidDispute
|
||||
}
|
||||
return deductAmountCent, nil
|
||||
default:
|
||||
return 0, ErrInvalidDispute
|
||||
}
|
||||
}
|
||||
|
||||
func applyArbitrationActualSettlement(order *model.RentalOrder, checkout *model.OrderCheckout, settlement ordermodule.ActualCheckoutSettlement, depositDeductAmountCent int64) {
|
||||
order.ActualCoinConsumedM = settlement.CoinConsumedM
|
||||
order.ActualPureCoinAmountCent = settlement.PureCoinAmountCent
|
||||
order.ActualPureCoinDiscountCent = settlement.PureCoinDiscountCent
|
||||
order.ActualExtraItemAmountCent = settlement.ExtraItemAmountCent
|
||||
if checkout == nil {
|
||||
return
|
||||
}
|
||||
checkout.RentAmountCent = settlement.ActualRentAmountCent
|
||||
checkout.OwnerRentAmountCent = settlement.OwnerRentIncomeCent
|
||||
checkout.PlatformFeeCent = settlement.PlatformFeeCent
|
||||
checkout.PureCoinAmountCent = settlement.PureCoinAmountCent
|
||||
checkout.PureCoinDiscountCent = settlement.PureCoinDiscountCent
|
||||
checkout.PureCoinPayableCent = settlement.PureCoinPayableCent
|
||||
checkout.ConsumableAmountCent = settlement.ExtraItemAmountCent
|
||||
checkout.CoinConsumedM = settlement.CoinConsumedM
|
||||
checkout.DepositDeductAmountCent = depositDeductAmountCent
|
||||
checkout.OtherAmountCent = depositDeductAmountCent
|
||||
checkout.RenterRefundAmountCent = settlement.RenterRefundCent
|
||||
checkout.OwnerIncomeAmountCent = settlement.OwnerIncomeCent
|
||||
checkout.ShortfallCent = settlement.ShortfallCent
|
||||
checkout.OvershootAmountCent = settlement.OvershootAmountCent
|
||||
}
|
||||
|
||||
func isPlatformManagedOrder(order model.RentalOrder) bool {
|
||||
@@ -275,24 +378,18 @@ func applyPlatformManagedSettlement(order *model.RentalOrder, settlement *arbitr
|
||||
}
|
||||
|
||||
type arbitrationSettlement struct {
|
||||
Entries []wallet.Entry
|
||||
RenterRefundAmountCent int64
|
||||
RenterDepositRefundCent int64
|
||||
OwnerIncomeAmountCent int64
|
||||
DepositDeductAmountCent int64
|
||||
Entries []wallet.Entry
|
||||
RenterRefundAmountCent int64
|
||||
RenterDepositRefundCent int64
|
||||
OwnerIncomeAmountCent int64
|
||||
DepositDeductAmountCent int64
|
||||
ActualExtraItemAmountCent int64
|
||||
}
|
||||
|
||||
func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, renterFrozenBalanceCent int64) (arbitrationSettlement, error) {
|
||||
rentAmountCent := order.RentAmountCent
|
||||
depositAmountCent := order.DepositAmountCent
|
||||
ownerRentAmountCent := order.OwnerRentAmountCent
|
||||
if ownerRentAmountCent <= 0 || ownerRentAmountCent > rentAmountCent {
|
||||
ownerRentAmountCent = rentAmountCent
|
||||
}
|
||||
totalCent := rentAmountCent + depositAmountCent
|
||||
func newArbitrationSettlement(order model.RentalOrder, renterFrozenBalanceCent int64) arbitrationSettlement {
|
||||
settlement := arbitrationSettlement{}
|
||||
orderID := order.ID
|
||||
releaseFrozenAmountCent := money.MinCent(totalCent, renterFrozenBalanceCent)
|
||||
releaseFrozenAmountCent := money.MinCent(order.RentAmountCent+order.DepositAmountCent, renterFrozenBalanceCent)
|
||||
if releaseFrozenAmountCent > 0 {
|
||||
settlement.Entries = append(settlement.Entries, wallet.Entry{
|
||||
UserID: order.RenterID,
|
||||
@@ -305,6 +402,36 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, r
|
||||
Remark: "仲裁释放冻结金额",
|
||||
})
|
||||
}
|
||||
return settlement
|
||||
}
|
||||
|
||||
func (settlement *arbitrationSettlement) addOwnerIncome(order model.RentalOrder, amountCent int64, remark string) {
|
||||
if settlement == nil || amountCent <= 0 {
|
||||
return
|
||||
}
|
||||
orderID := order.ID
|
||||
settlement.OwnerIncomeAmountCent += amountCent
|
||||
settlement.Entries = append(settlement.Entries, wallet.Entry{
|
||||
UserID: order.OwnerID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
AmountCent: amountCent,
|
||||
BalanceType: "available",
|
||||
BizType: "arbitration_owner_income",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: remark,
|
||||
})
|
||||
}
|
||||
|
||||
func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, renterFrozenBalanceCent int64) (arbitrationSettlement, error) {
|
||||
rentAmountCent := order.RentAmountCent
|
||||
depositAmountCent := order.DepositAmountCent
|
||||
ownerRentAmountCent := order.OwnerRentAmountCent
|
||||
if ownerRentAmountCent <= 0 || ownerRentAmountCent > rentAmountCent {
|
||||
ownerRentAmountCent = rentAmountCent
|
||||
}
|
||||
totalCent := rentAmountCent + depositAmountCent
|
||||
settlement := newArbitrationSettlement(order, renterFrozenBalanceCent)
|
||||
|
||||
addRenterRefund := func(amountCent int64, remark string) {
|
||||
if amountCent <= 0 {
|
||||
@@ -316,17 +443,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, r
|
||||
if amountCent <= 0 {
|
||||
return
|
||||
}
|
||||
settlement.OwnerIncomeAmountCent += amountCent
|
||||
settlement.Entries = append(settlement.Entries, wallet.Entry{
|
||||
UserID: order.OwnerID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
AmountCent: amountCent,
|
||||
BalanceType: "available",
|
||||
BizType: "arbitration_owner_income",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: remark,
|
||||
})
|
||||
settlement.addOwnerIncome(order, amountCent, remark)
|
||||
}
|
||||
|
||||
switch req.Result {
|
||||
@@ -503,6 +620,9 @@ func buildArbitrationHandoffContent(req ArbitrateRequest, settlement arbitration
|
||||
if settlement.DepositDeductAmountCent > 0 {
|
||||
content += "\n押金赔付扣除:" + money.FormatWithSymbol(settlement.DepositDeductAmountCent)
|
||||
}
|
||||
if settlement.ActualExtraItemAmountCent > 0 {
|
||||
content += "\n额外物品消耗:" + money.FormatWithSymbol(settlement.ActualExtraItemAmountCent)
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user