统一金额分制重构
This commit is contained in:
@@ -54,20 +54,20 @@ type SubmitReturnRequest struct {
|
||||
}
|
||||
|
||||
type SubmitCheckoutRequest struct {
|
||||
Content string `json:"content" binding:"required"`
|
||||
ConsumableAmount float64 `json:"consumable_amount"`
|
||||
CoinConsumedM float64 `json:"coin_consumed_m"`
|
||||
OtherAmount float64 `json:"other_amount"`
|
||||
EvidenceURLS []string `json:"evidence_urls"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
ConsumableAmountCent int64 `json:"consumable_amount_cent"`
|
||||
CoinConsumedM float64 `json:"coin_consumed_m"`
|
||||
OtherAmountCent int64 `json:"other_amount_cent"`
|
||||
EvidenceURLS []string `json:"evidence_urls"`
|
||||
}
|
||||
|
||||
type CounterCheckoutRequest struct {
|
||||
ConsumableAmount float64 `json:"consumable_amount"`
|
||||
CoinConsumedM float64 `json:"coin_consumed_m"`
|
||||
OtherAmount float64 `json:"other_amount"`
|
||||
DepositDeductAmount float64 `json:"deposit_deduct_amount"`
|
||||
Reason string `json:"reason" binding:"required"`
|
||||
EvidenceURLS []string `json:"evidence_urls"`
|
||||
ConsumableAmountCent int64 `json:"consumable_amount_cent"`
|
||||
CoinConsumedM float64 `json:"coin_consumed_m"`
|
||||
OtherAmountCent int64 `json:"other_amount_cent"`
|
||||
DepositDeductAmountCent int64 `json:"deposit_deduct_amount_cent"`
|
||||
Reason string `json:"reason" binding:"required"`
|
||||
EvidenceURLS []string `json:"evidence_urls"`
|
||||
}
|
||||
|
||||
type AdminActionRequest struct {
|
||||
|
||||
@@ -77,22 +77,22 @@ func orderDurationHours(order model.RentalOrder) int {
|
||||
}
|
||||
|
||||
func buildOrderPricing(listing model.RentalListing, account model.GameAccount) orderPricing {
|
||||
rentAmount := roundMoney(listing.Price)
|
||||
ownerRentAmount := readSnapshotPrice(account.AssetSummary, "seller_total_price")
|
||||
if ownerRentAmount <= 0 || ownerRentAmount > rentAmount {
|
||||
ownerRentAmount = rentAmount
|
||||
rentAmountCent := listing.PriceCent
|
||||
ownerRentAmountCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "seller_total_price") * 100))
|
||||
if ownerRentAmountCent <= 0 || ownerRentAmountCent > rentAmountCent {
|
||||
ownerRentAmountCent = rentAmountCent
|
||||
}
|
||||
platformFee := readSnapshotPrice(account.AssetSummary, "platform_markup_amount")
|
||||
if platformFee <= 0 || roundMoney(ownerRentAmount+platformFee) != rentAmount {
|
||||
platformFee = roundMoney(rentAmount - ownerRentAmount)
|
||||
platformFeeCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "platform_markup_amount") * 100))
|
||||
if platformFeeCent <= 0 || ownerRentAmountCent+platformFeeCent != rentAmountCent {
|
||||
platformFeeCent = rentAmountCent - ownerRentAmountCent
|
||||
}
|
||||
if platformFee < 0 {
|
||||
platformFee = 0
|
||||
if platformFeeCent < 0 {
|
||||
platformFeeCent = 0
|
||||
}
|
||||
return orderPricing{
|
||||
RentAmountCent: int64(math.Round(rentAmount * 100)),
|
||||
OwnerRentAmountCent: int64(math.Round(ownerRentAmount * 100)),
|
||||
PlatformFeeCent: int64(math.Round(platformFee * 100)),
|
||||
RentAmountCent: rentAmountCent,
|
||||
OwnerRentAmountCent: ownerRentAmountCent,
|
||||
PlatformFeeCent: platformFeeCent,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,8 +173,8 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
|
||||
}
|
||||
rentHours := internalOrderHours
|
||||
pricing := buildOrderPricing(listing, account)
|
||||
depositOriginalAmount := roundMoney(listing.DepositAmount)
|
||||
paidDepositAmount, waivedDepositAmount, err := r.depositAmountsForOrder(tx, renterID, depositOriginalAmount)
|
||||
depositOriginalAmountCent := listing.DepositAmountCent
|
||||
paidDepositAmountCent, waivedDepositAmountCent, err := r.depositAmountsForOrder(tx, renterID, depositOriginalAmountCent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -185,17 +185,11 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
|
||||
OwnerID: listing.OwnerID,
|
||||
RenterID: renterID,
|
||||
EstimatedDurationHours: rentHours,
|
||||
RentAmount: float64(pricing.RentAmountCent) / 100,
|
||||
RentAmountCent: pricing.RentAmountCent,
|
||||
OwnerRentAmount: float64(pricing.OwnerRentAmountCent) / 100,
|
||||
OwnerRentAmountCent: pricing.OwnerRentAmountCent,
|
||||
DepositAmount: paidDepositAmount,
|
||||
DepositAmountCent: int64(math.Round(paidDepositAmount * 100)),
|
||||
DepositOriginalAmount: depositOriginalAmount,
|
||||
DepositOriginalAmountCent: int64(math.Round(depositOriginalAmount * 100)),
|
||||
DepositWaivedAmount: waivedDepositAmount,
|
||||
DepositWaivedAmountCent: int64(math.Round(waivedDepositAmount * 100)),
|
||||
PlatformFee: float64(pricing.PlatformFeeCent) / 100,
|
||||
DepositAmountCent: paidDepositAmountCent,
|
||||
DepositOriginalAmountCent: depositOriginalAmountCent,
|
||||
DepositWaivedAmountCent: waivedDepositAmountCent,
|
||||
PlatformFeeCent: pricing.PlatformFeeCent,
|
||||
AccountSnapshot: snapshot,
|
||||
Status: "pending_payment",
|
||||
@@ -231,9 +225,8 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
|
||||
return r.FindForUser(renterID, createdID)
|
||||
}
|
||||
|
||||
func (r *Repository) depositAmountsForOrder(tx *gorm.DB, renterID uint64, originalDeposit float64) (float64, float64, error) {
|
||||
originalDeposit = roundMoney(originalDeposit)
|
||||
if originalDeposit <= 0 {
|
||||
func (r *Repository) depositAmountsForOrder(tx *gorm.DB, renterID uint64, originalDepositCent int64) (int64, int64, error) {
|
||||
if originalDepositCent <= 0 {
|
||||
return 0, 0, nil
|
||||
}
|
||||
var user model.User
|
||||
@@ -244,28 +237,27 @@ func (r *Repository) depositAmountsForOrder(tx *gorm.DB, renterID uint64, origin
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
paidDeposit, waivedDeposit := calculateDepositWaiver(originalDeposit, user.DepositFreeQuota, used)
|
||||
paidDeposit, waivedDeposit := calculateDepositWaiver(originalDepositCent, user.DepositFreeQuotaCent, used)
|
||||
return paidDeposit, waivedDeposit, nil
|
||||
}
|
||||
|
||||
func activeDepositFreeUsed(tx *gorm.DB, renterID uint64) (float64, error) {
|
||||
var used float64
|
||||
func activeDepositFreeUsed(tx *gorm.DB, renterID uint64) (int64, error) {
|
||||
var used int64
|
||||
err := tx.Model(&model.RentalOrder{}).
|
||||
Where("renter_id = ? AND status NOT IN ?",
|
||||
renterID,
|
||||
[]string{"completed", "cancelled", "closed"},
|
||||
).
|
||||
Select("COALESCE(SUM(deposit_waived_amount), 0)").
|
||||
Select("COALESCE(SUM(deposit_waived_amount_cent), 0)").
|
||||
Scan(&used).Error
|
||||
return roundMoney(used), err
|
||||
return used, err
|
||||
}
|
||||
|
||||
func calculateDepositWaiver(originalDeposit float64, quota float64, used float64) (float64, float64) {
|
||||
originalDeposit = roundMoney(originalDeposit)
|
||||
remaining := maxMoney(roundMoney(quota)-roundMoney(used), 0)
|
||||
waived := minMoney(originalDeposit, remaining)
|
||||
paid := maxMoney(originalDeposit-waived, 0)
|
||||
return roundMoney(paid), roundMoney(waived)
|
||||
func calculateDepositWaiver(originalDepositCent int64, quotaCent int64, usedCent int64) (int64, int64) {
|
||||
remaining := maxCent(quotaCent-usedCent, 0)
|
||||
waived := minCent(originalDepositCent, remaining)
|
||||
paid := maxCent(originalDepositCent-waived, 0)
|
||||
return paid, waived
|
||||
}
|
||||
|
||||
// Pay 保留旧接口兼容,但真实付款必须走 payment 模块的渠道支付入口。
|
||||
@@ -554,7 +546,7 @@ func (r *Repository) SubmitCheckout(userID uint64, orderID uint64, req SubmitChe
|
||||
if err := tx.Create(&record).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
checkout, err := buildCheckout(order, order.RenterID, "submitted", req.Content, req.EvidenceURLS, req.ConsumableAmount, req.CoinConsumedM, req.OtherAmount, 0, false)
|
||||
checkout, err := buildCheckout(order, order.RenterID, "submitted", req.Content, req.EvidenceURLS, req.ConsumableAmountCent, req.CoinConsumedM, req.OtherAmountCent, 0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -650,18 +642,22 @@ func (r *Repository) CounterCheckout(userID uint64, orderID uint64, req CounterC
|
||||
First(&checkout).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
next, err := buildCheckout(order, checkout.InitiatedBy, "countered", checkout.Content, req.EvidenceURLS, req.ConsumableAmount, req.CoinConsumedM, req.OtherAmount, req.DepositDeductAmount, true)
|
||||
next, err := buildCheckout(order, checkout.InitiatedBy, "countered", checkout.Content, req.EvidenceURLS, req.ConsumableAmountCent, req.CoinConsumedM, req.OtherAmountCent, req.DepositDeductAmountCent, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
checkout.Status = "countered"
|
||||
checkout.ConsumableAmount = next.ConsumableAmount
|
||||
checkout.RentAmountCent = next.RentAmountCent
|
||||
checkout.OwnerRentAmountCent = next.OwnerRentAmountCent
|
||||
checkout.PlatformFeeCent = next.PlatformFeeCent
|
||||
checkout.DepositAmountCent = next.DepositAmountCent
|
||||
checkout.ConsumableAmountCent = next.ConsumableAmountCent
|
||||
checkout.CoinConsumedM = next.CoinConsumedM
|
||||
checkout.OtherAmount = next.OtherAmount
|
||||
checkout.DepositDeductAmount = next.DepositDeductAmount
|
||||
checkout.RenterRefundAmount = next.RenterRefundAmount
|
||||
checkout.OwnerIncomeAmount = next.OwnerIncomeAmount
|
||||
checkout.OtherAmountCent = next.OtherAmountCent
|
||||
checkout.DepositDeductAmountCent = next.DepositDeductAmountCent
|
||||
checkout.RenterRefundAmountCent = next.RenterRefundAmountCent
|
||||
checkout.OwnerIncomeAmountCent = next.OwnerIncomeAmountCent
|
||||
checkout.OwnerAdjustmentReason = req.Reason
|
||||
checkout.OwnerAdjustedAt = &now
|
||||
checkout.EvidenceURLS = next.EvidenceURLS
|
||||
@@ -697,9 +693,9 @@ func (r *Repository) CounterCheckout(userID uint64, orderID uint64, req CounterC
|
||||
}
|
||||
dto := toCheckoutDTOForUser(*checkout, userID, model.RentalOrder{
|
||||
OwnerID: userID,
|
||||
RentAmountCent: int64(math.Round(checkout.RentAmount * 100)),
|
||||
OwnerRentAmountCent: int64(math.Round(checkout.OwnerRentAmount * 100)),
|
||||
DepositAmountCent: int64(math.Round(checkout.DepositAmount * 100)),
|
||||
RentAmountCent: checkout.RentAmountCent,
|
||||
OwnerRentAmountCent: checkout.OwnerRentAmountCent,
|
||||
DepositAmountCent: checkout.DepositAmountCent,
|
||||
})
|
||||
return &dto, nil
|
||||
}
|
||||
@@ -1095,11 +1091,11 @@ func (r *Repository) finalizeCheckout(tx *gorm.DB, order *model.RentalOrder, che
|
||||
refund = action
|
||||
}
|
||||
|
||||
checkout.RentAmount = float64(settlement.ActualRentAmountCent) / 100
|
||||
checkout.OwnerRentAmount = float64(settlement.OwnerRentIncomeCent) / 100
|
||||
checkout.PlatformFee = float64(settlement.PlatformFeeCent) / 100
|
||||
checkout.RenterRefundAmount = float64(settlement.RenterRefundCent) / 100
|
||||
checkout.OwnerIncomeAmount = float64(settlement.OwnerIncomeCent) / 100
|
||||
checkout.RentAmountCent = settlement.ActualRentAmountCent
|
||||
checkout.OwnerRentAmountCent = settlement.OwnerRentIncomeCent
|
||||
checkout.PlatformFeeCent = settlement.PlatformFeeCent
|
||||
checkout.RenterRefundAmountCent = settlement.RenterRefundCent
|
||||
checkout.OwnerIncomeAmountCent = settlement.OwnerIncomeCent
|
||||
if err := notification.Append(tx,
|
||||
notification.Entry{
|
||||
UserID: order.RenterID,
|
||||
@@ -1229,22 +1225,18 @@ func applyPaymentDeadline(dto *OrderDTO, order model.RentalOrder, timeoutMinutes
|
||||
dto.PaymentDeadlineAt = &deadline
|
||||
}
|
||||
|
||||
func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, content string, evidenceURLS []string, consumableAmount float64, coinConsumedM float64, otherAmount float64, explicitDeduct float64, useExplicitDeduct bool) (model.OrderCheckout, error) {
|
||||
if consumableAmount < 0 || coinConsumedM < 0 || otherAmount < 0 || explicitDeduct < 0 {
|
||||
func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, content string, evidenceURLS []string, consumableAmountCent int64, coinConsumedM float64, otherAmountCent int64, explicitDeductCent int64, useExplicitDeduct bool) (model.OrderCheckout, error) {
|
||||
if consumableAmountCent < 0 || coinConsumedM < 0 || otherAmountCent < 0 || explicitDeductCent < 0 {
|
||||
return model.OrderCheckout{}, ErrInvalidCheckoutAmount
|
||||
}
|
||||
consumableAmount = roundMoney(consumableAmount)
|
||||
otherAmount = roundMoney(otherAmount)
|
||||
explicitDeduct = roundMoney(explicitDeduct)
|
||||
deductAmount := otherAmount
|
||||
deductAmountCent := otherAmountCent
|
||||
if useExplicitDeduct {
|
||||
deductAmount = explicitDeduct
|
||||
deductAmountCent = explicitDeductCent
|
||||
}
|
||||
depositAmountFromCent := float64(order.DepositAmountCent) / 100
|
||||
if deductAmount > depositAmountFromCent {
|
||||
if deductAmountCent > order.DepositAmountCent {
|
||||
return model.OrderCheckout{}, ErrInvalidCheckoutAmount
|
||||
}
|
||||
settlement := calculateCheckoutSettlement(order, consumableAmount, roundQuantity(coinConsumedM), deductAmount)
|
||||
settlement := calculateCheckoutSettlement(order, consumableAmountCent, roundQuantity(coinConsumedM), deductAmountCent)
|
||||
evidence, err := marshalStringList(evidenceURLS)
|
||||
if err != nil {
|
||||
return model.OrderCheckout{}, err
|
||||
@@ -1253,24 +1245,15 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
||||
OrderID: order.ID,
|
||||
InitiatedBy: initiatedBy,
|
||||
Status: status,
|
||||
RentAmount: float64(settlement.ActualRentAmountCent) / 100,
|
||||
RentAmountCent: settlement.ActualRentAmountCent,
|
||||
OwnerRentAmount: float64(settlement.OwnerRentIncomeCent) / 100,
|
||||
OwnerRentAmountCent: settlement.OwnerRentIncomeCent,
|
||||
PlatformFee: float64(settlement.PlatformFeeCent) / 100,
|
||||
PlatformFeeCent: settlement.PlatformFeeCent,
|
||||
DepositAmount: depositAmountFromCent,
|
||||
DepositAmountCent: order.DepositAmountCent,
|
||||
ConsumableAmount: consumableAmount,
|
||||
ConsumableAmountCent: int64(math.Round(consumableAmount * 100)),
|
||||
ConsumableAmountCent: consumableAmountCent,
|
||||
CoinConsumedM: roundQuantity(coinConsumedM),
|
||||
OtherAmount: otherAmount,
|
||||
OtherAmountCent: int64(math.Round(otherAmount * 100)),
|
||||
DepositDeductAmount: roundMoney(deductAmount),
|
||||
OtherAmountCent: otherAmountCent,
|
||||
DepositDeductAmountCent: settlement.DepositCompensationCent,
|
||||
RenterRefundAmount: float64(settlement.RenterRefundCent) / 100,
|
||||
RenterRefundAmountCent: settlement.RenterRefundCent,
|
||||
OwnerIncomeAmount: float64(settlement.OwnerIncomeCent) / 100,
|
||||
OwnerIncomeAmountCent: settlement.OwnerIncomeCent,
|
||||
Content: content,
|
||||
EvidenceURLS: evidence,
|
||||
@@ -1278,57 +1261,55 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
||||
}
|
||||
|
||||
func buildCheckoutSettlement(order model.RentalOrder, checkout *model.OrderCheckout) checkoutSettlement {
|
||||
return calculateCheckoutSettlement(order, checkout.ConsumableAmount, checkout.CoinConsumedM, checkout.DepositDeductAmount)
|
||||
return calculateCheckoutSettlement(order, checkout.ConsumableAmountCent, checkout.CoinConsumedM, checkout.DepositDeductAmountCent)
|
||||
}
|
||||
|
||||
func calculateCheckoutSettlement(order model.RentalOrder, consumableAmount float64, coinConsumedM float64, depositDeductAmount float64) checkoutSettlement {
|
||||
// 从分字段读取,转为元进行计算(保持现有逻辑兼容性)
|
||||
orderRentAmount := float64(order.RentAmountCent) / 100
|
||||
orderOwnerRentAmount := float64(order.OwnerRentAmountCent) / 100
|
||||
orderDepositAmount := float64(order.DepositAmountCent) / 100
|
||||
func calculateCheckoutSettlement(order model.RentalOrder, consumableAmountCent int64, coinConsumedM float64, depositDeductAmountCent int64) checkoutSettlement {
|
||||
orderRentAmountCent := order.RentAmountCent
|
||||
orderOwnerRentAmountCent := order.OwnerRentAmountCent
|
||||
orderDepositAmountCent := order.DepositAmountCent
|
||||
|
||||
buyerCoinBasePrice := readOrderSnapshotPrice(order.AccountSnapshot, "buyer_coin_base_price")
|
||||
if buyerCoinBasePrice <= 0 || buyerCoinBasePrice > orderRentAmount {
|
||||
buyerCoinBasePrice = orderRentAmount
|
||||
buyerCoinBasePriceCent := int64(math.Round(readOrderSnapshotPrice(order.AccountSnapshot, "buyer_coin_base_price") * 100))
|
||||
if buyerCoinBasePriceCent <= 0 || buyerCoinBasePriceCent > orderRentAmountCent {
|
||||
buyerCoinBasePriceCent = orderRentAmountCent
|
||||
}
|
||||
sellerCoinBasePrice := readOrderSnapshotPrice(order.AccountSnapshot, "seller_coin_base_price")
|
||||
if sellerCoinBasePrice <= 0 || sellerCoinBasePrice > orderOwnerRentAmount {
|
||||
sellerCoinBasePrice = orderOwnerRentAmount
|
||||
sellerCoinBasePriceCent := int64(math.Round(readOrderSnapshotPrice(order.AccountSnapshot, "seller_coin_base_price") * 100))
|
||||
if sellerCoinBasePriceCent <= 0 || sellerCoinBasePriceCent > orderOwnerRentAmountCent {
|
||||
sellerCoinBasePriceCent = orderOwnerRentAmountCent
|
||||
}
|
||||
prepaidConsumablePrice := readOrderSnapshotPrice(order.AccountSnapshot, "consumable_price")
|
||||
if prepaidConsumablePrice <= 0 || prepaidConsumablePrice > orderRentAmount-buyerCoinBasePrice {
|
||||
prepaidConsumablePrice = maxMoney(orderRentAmount-buyerCoinBasePrice, 0)
|
||||
prepaidConsumablePriceCent := int64(math.Round(readOrderSnapshotPrice(order.AccountSnapshot, "consumable_price") * 100))
|
||||
if prepaidConsumablePriceCent <= 0 || prepaidConsumablePriceCent > orderRentAmountCent-buyerCoinBasePriceCent {
|
||||
prepaidConsumablePriceCent = maxCent(orderRentAmountCent-buyerCoinBasePriceCent, 0)
|
||||
}
|
||||
prepaidOwnerConsumablePrice := maxMoney(orderOwnerRentAmount-sellerCoinBasePrice, 0)
|
||||
prepaidOwnerConsumablePriceCent := maxCent(orderOwnerRentAmountCent-sellerCoinBasePriceCent, 0)
|
||||
totalCoinM := readOrderSnapshotCoinM(order.AccountSnapshot)
|
||||
coinUseRatio := 1.0
|
||||
if totalCoinM > 0 {
|
||||
coinUseRatio = minRatio(maxRatio(roundQuantity(coinConsumedM)/totalCoinM, 0), 1)
|
||||
}
|
||||
usedBuyerCoinPrice := roundMoney(buyerCoinBasePrice * coinUseRatio)
|
||||
usedOwnerCoinPrice := roundMoney(sellerCoinBasePrice * coinUseRatio)
|
||||
usedBuyerConsumablePrice := minMoney(roundMoney(consumableAmount), prepaidConsumablePrice)
|
||||
usedBuyerCoinPriceCent := int64(math.Round(float64(buyerCoinBasePriceCent) * coinUseRatio))
|
||||
usedOwnerCoinPriceCent := int64(math.Round(float64(sellerCoinBasePriceCent) * coinUseRatio))
|
||||
usedBuyerConsumablePriceCent := minCent(consumableAmountCent, prepaidConsumablePriceCent)
|
||||
consumableUseRatio := 1.0
|
||||
if prepaidConsumablePrice > 0 {
|
||||
consumableUseRatio = minRatio(maxRatio(usedBuyerConsumablePrice/prepaidConsumablePrice, 0), 1)
|
||||
if prepaidConsumablePriceCent > 0 {
|
||||
consumableUseRatio = minRatio(maxRatio(float64(usedBuyerConsumablePriceCent)/float64(prepaidConsumablePriceCent), 0), 1)
|
||||
}
|
||||
usedOwnerConsumablePrice := roundMoney(prepaidOwnerConsumablePrice * consumableUseRatio)
|
||||
actualRentAmount := minMoney(roundMoney(usedBuyerCoinPrice+usedBuyerConsumablePrice), orderRentAmount)
|
||||
ownerRentIncome := minMoney(roundMoney(usedOwnerCoinPrice+usedOwnerConsumablePrice), orderOwnerRentAmount)
|
||||
depositCompensation := minMoney(roundMoney(depositDeductAmount), orderDepositAmount)
|
||||
rentRefund := maxMoney(orderRentAmount-actualRentAmount, 0)
|
||||
depositRefund := maxMoney(orderDepositAmount-depositCompensation, 0)
|
||||
usedOwnerConsumablePriceCent := int64(math.Round(float64(prepaidOwnerConsumablePriceCent) * consumableUseRatio))
|
||||
actualRentAmountCent := minCent(usedBuyerCoinPriceCent+usedBuyerConsumablePriceCent, orderRentAmountCent)
|
||||
ownerRentIncomeCent := minCent(usedOwnerCoinPriceCent+usedOwnerConsumablePriceCent, orderOwnerRentAmountCent)
|
||||
depositCompensationCent := minCent(depositDeductAmountCent, orderDepositAmountCent)
|
||||
rentRefundCent := maxCent(orderRentAmountCent-actualRentAmountCent, 0)
|
||||
depositRefundCent := maxCent(orderDepositAmountCent-depositCompensationCent, 0)
|
||||
|
||||
// 最后转换为分返回
|
||||
return checkoutSettlement{
|
||||
OwnerRentIncomeCent: int64(math.Round(ownerRentIncome * 100)),
|
||||
DepositCompensationCent: int64(math.Round(depositCompensation * 100)),
|
||||
OwnerIncomeCent: int64(math.Round((ownerRentIncome + depositCompensation) * 100)),
|
||||
RentRefundCent: int64(math.Round(rentRefund * 100)),
|
||||
DepositRefundCent: int64(math.Round(depositRefund * 100)),
|
||||
RenterRefundCent: int64(math.Round((rentRefund + depositRefund) * 100)),
|
||||
PlatformFeeCent: int64(math.Round(maxMoney(actualRentAmount-ownerRentIncome, 0) * 100)),
|
||||
ActualRentAmountCent: int64(math.Round(actualRentAmount * 100)),
|
||||
OwnerRentIncomeCent: ownerRentIncomeCent,
|
||||
DepositCompensationCent: depositCompensationCent,
|
||||
OwnerIncomeCent: ownerRentIncomeCent + depositCompensationCent,
|
||||
RentRefundCent: rentRefundCent,
|
||||
DepositRefundCent: depositRefundCent,
|
||||
RenterRefundCent: rentRefundCent + depositRefundCent,
|
||||
PlatformFeeCent: maxCent(actualRentAmountCent-ownerRentIncomeCent, 0),
|
||||
ActualRentAmountCent: actualRentAmountCent,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1381,6 +1362,20 @@ func maxMoney(a float64, b float64) float64 {
|
||||
return money.Max(a, b)
|
||||
}
|
||||
|
||||
func minCent(a int64, b int64) int64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func maxCent(a int64, b int64) int64 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func minRatio(a float64, b float64) float64 {
|
||||
if a < b {
|
||||
return a
|
||||
@@ -1522,13 +1517,6 @@ func toHandoffDTO(record model.HandoffRecord) HandoffRecordDTO {
|
||||
}
|
||||
}
|
||||
|
||||
func effectiveDepositOriginalAmount(order model.RentalOrder) float64 {
|
||||
if order.DepositOriginalAmount > 0 {
|
||||
return order.DepositOriginalAmount
|
||||
}
|
||||
return order.DepositAmount
|
||||
}
|
||||
|
||||
func effectiveDepositOriginalAmountCent(order model.RentalOrder) int64 {
|
||||
if order.DepositOriginalAmountCent > 0 {
|
||||
return order.DepositOriginalAmountCent
|
||||
@@ -1537,11 +1525,11 @@ func effectiveDepositOriginalAmountCent(order model.RentalOrder) int64 {
|
||||
}
|
||||
|
||||
func toCheckoutAdminDTO(checkout model.OrderCheckout) CheckoutDTO {
|
||||
rentAmountCent := int64(math.Round(checkout.RentAmount * 100))
|
||||
ownerRentAmountCent := int64(math.Round(checkout.OwnerRentAmount * 100))
|
||||
platformFeeCent := int64(math.Round(checkout.PlatformFee * 100))
|
||||
renterRefundAmountCent := int64(math.Round(checkout.RenterRefundAmount * 100))
|
||||
ownerIncomeAmountCent := int64(math.Round(checkout.OwnerIncomeAmount * 100))
|
||||
rentAmountCent := checkout.RentAmountCent
|
||||
ownerRentAmountCent := checkout.OwnerRentAmountCent
|
||||
platformFeeCent := checkout.PlatformFeeCent
|
||||
renterRefundAmountCent := checkout.RenterRefundAmountCent
|
||||
ownerIncomeAmountCent := checkout.OwnerIncomeAmountCent
|
||||
return CheckoutDTO{
|
||||
ID: checkout.ID,
|
||||
OrderID: checkout.OrderID,
|
||||
@@ -1552,11 +1540,11 @@ func toCheckoutAdminDTO(checkout model.OrderCheckout) CheckoutDTO {
|
||||
RentAmountCent: &rentAmountCent,
|
||||
OwnerRentAmountCent: &ownerRentAmountCent,
|
||||
PlatformFeeCent: &platformFeeCent,
|
||||
DepositAmountCent: int64(math.Round(checkout.DepositAmount * 100)),
|
||||
ConsumableAmountCent: int64(math.Round(checkout.ConsumableAmount * 100)),
|
||||
DepositAmountCent: checkout.DepositAmountCent,
|
||||
ConsumableAmountCent: checkout.ConsumableAmountCent,
|
||||
CoinConsumedM: checkout.CoinConsumedM,
|
||||
OtherAmountCent: int64(math.Round(checkout.OtherAmount * 100)),
|
||||
DepositDeductAmountCent: int64(math.Round(checkout.DepositDeductAmount * 100)),
|
||||
OtherAmountCent: checkout.OtherAmountCent,
|
||||
DepositDeductAmountCent: checkout.DepositDeductAmountCent,
|
||||
RenterRefundAmountCent: &renterRefundAmountCent,
|
||||
OwnerIncomeAmountCent: &ownerIncomeAmountCent,
|
||||
Content: checkout.Content,
|
||||
|
||||
@@ -27,7 +27,7 @@ func TestCalculateCheckoutSettlementRefundsUnusedRent(t *testing.T) {
|
||||
}`)),
|
||||
}
|
||||
|
||||
settlement := calculateCheckoutSettlement(order, 7, 90, 0)
|
||||
settlement := calculateCheckoutSettlement(order, 700, 90, 0)
|
||||
|
||||
// 角精度:243.7 = roundMoney(236.7 + 7)
|
||||
if settlement.ActualRentAmountCent != 24370 {
|
||||
@@ -104,7 +104,7 @@ func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
|
||||
}`)),
|
||||
}
|
||||
|
||||
settlement := calculateCheckoutSettlement(order, 120, 100, 30)
|
||||
settlement := calculateCheckoutSettlement(order, 12000, 100, 3000)
|
||||
|
||||
if settlement.ActualRentAmountCent != 38300 {
|
||||
t.Fatalf("ActualRentAmountCent = %d, want 38300", settlement.ActualRentAmountCent)
|
||||
@@ -126,17 +126,17 @@ func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
|
||||
func TestCalculateDepositWaiverUsesSharedRemainingQuota(t *testing.T) {
|
||||
paid, waived := calculateDepositWaiver(500, 300, 0)
|
||||
if paid != 200 || waived != 300 {
|
||||
t.Fatalf("paid = %.1f, waived = %.1f, want 200.0, 300.0", paid, waived)
|
||||
t.Fatalf("paid = %d, waived = %d, want 200, 300", paid, waived)
|
||||
}
|
||||
|
||||
paid, waived = calculateDepositWaiver(500, 300, 200)
|
||||
if paid != 400 || waived != 100 {
|
||||
t.Fatalf("paid = %.1f, waived = %.1f, want 400.0, 100.0", paid, waived)
|
||||
t.Fatalf("paid = %d, waived = %d, want 400, 100", paid, waived)
|
||||
}
|
||||
|
||||
paid, waived = calculateDepositWaiver(500, 300, 300)
|
||||
if paid != 500 || waived != 0 {
|
||||
t.Fatalf("paid = %.1f, waived = %.1f, want 500.0, 0.0", paid, waived)
|
||||
t.Fatalf("paid = %d, waived = %d, want 500, 0", paid, waived)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user