Order模块:完成分字段重构
核心改造:
1. DTO层全部改为*Cent int64字段(OrderDTO/CheckoutDTO/RefundStatusDTO)
2. 内部结构体orderPricing和checkoutSettlement改为分字段
3. calculateCheckoutSettlement函数改为返回分单位
4. 所有wallet.AppendEntries调用改为AmountCent
5. toAdminDTO/toCheckoutAdminDTO转换函数使用*Cent字段
6. applyOrderPriceView/applyCheckoutPriceView使用分字段
7. buildOrderPricing返回分单位
8. 订单取消/关闭/退款使用分字段计算
技术细节:
- 删除了3处float64金额相加后转分的逻辑
- calculateCheckoutSettlement内部仍用元计算保持兼容性,最后转为分
- 新增effectiveDepositOriginalAmountCent辅助函数
- buildRefundStatusDTO使用TotalAmountCent
- 编译验证通过 ✅
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package adminuser
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDepositFreeQuotaAmountCent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
req DepositFreeQuotaRequest
|
||||
want int64
|
||||
}{
|
||||
{
|
||||
name: "优先使用分字段",
|
||||
req: DepositFreeQuotaRequest{AmountCent: 1234, Amount: 99},
|
||||
want: 1234,
|
||||
},
|
||||
{
|
||||
name: "缺少分字段时回退元字段",
|
||||
req: DepositFreeQuotaRequest{Amount: 12.34},
|
||||
want: 1234,
|
||||
},
|
||||
{
|
||||
name: "负分拒绝",
|
||||
req: DepositFreeQuotaRequest{AmountCent: -1, Amount: 12.34},
|
||||
want: -1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := depositFreeQuotaAmountCent(tt.req); got != tt.want {
|
||||
t.Fatalf("depositFreeQuotaAmountCent() = %d, want %d", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -9,36 +9,36 @@ import (
|
||||
)
|
||||
|
||||
type OrderDTO struct {
|
||||
ID uint64 `json:"id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
ListingID uint64 `json:"listing_id"`
|
||||
ListingNo string `json:"listing_no"`
|
||||
AccountID uint64 `json:"account_id"`
|
||||
OwnerID uint64 `json:"owner_id"`
|
||||
RenterID uint64 `json:"renter_id"`
|
||||
OwnerPhone string `json:"owner_phone,omitempty"`
|
||||
RenterPhone string `json:"renter_phone,omitempty"`
|
||||
Title string `json:"title"`
|
||||
ServerRegion string `json:"server_region"`
|
||||
LoginPlatform string `json:"login_platform"`
|
||||
RentedAt *time.Time `json:"rented_at"`
|
||||
EstimatedDurationHours int `json:"estimated_duration_hours"`
|
||||
PriceRole string `json:"price_role,omitempty"`
|
||||
DisplayAmount float64 `json:"display_amount"`
|
||||
RentAmount *float64 `json:"rent_amount,omitempty"`
|
||||
OwnerRentAmount *float64 `json:"owner_rent_amount,omitempty"`
|
||||
DepositAmount float64 `json:"deposit_amount"`
|
||||
DepositOriginalAmount float64 `json:"deposit_original_amount"`
|
||||
DepositWaivedAmount float64 `json:"deposit_waived_amount"`
|
||||
PlatformFee *float64 `json:"platform_fee,omitempty"`
|
||||
AccountSnapshot datatypes.JSON `json:"account_snapshot"`
|
||||
Status string `json:"status"`
|
||||
HandoffStatus string `json:"handoff_status"`
|
||||
SettlementStatus string `json:"settlement_status"`
|
||||
Checkout *CheckoutDTO `json:"checkout,omitempty"`
|
||||
PaymentDeadlineAt *time.Time `json:"payment_deadline_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID uint64 `json:"id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
ListingID uint64 `json:"listing_id"`
|
||||
ListingNo string `json:"listing_no"`
|
||||
AccountID uint64 `json:"account_id"`
|
||||
OwnerID uint64 `json:"owner_id"`
|
||||
RenterID uint64 `json:"renter_id"`
|
||||
OwnerPhone string `json:"owner_phone,omitempty"`
|
||||
RenterPhone string `json:"renter_phone,omitempty"`
|
||||
Title string `json:"title"`
|
||||
ServerRegion string `json:"server_region"`
|
||||
LoginPlatform string `json:"login_platform"`
|
||||
RentedAt *time.Time `json:"rented_at"`
|
||||
EstimatedDurationHours int `json:"estimated_duration_hours"`
|
||||
PriceRole string `json:"price_role,omitempty"`
|
||||
DisplayAmountCent int64 `json:"display_amount_cent"`
|
||||
RentAmountCent *int64 `json:"rent_amount_cent,omitempty"`
|
||||
OwnerRentAmountCent *int64 `json:"owner_rent_amount_cent,omitempty"`
|
||||
DepositAmountCent int64 `json:"deposit_amount_cent"`
|
||||
DepositOriginalAmountCent int64 `json:"deposit_original_amount_cent"`
|
||||
DepositWaivedAmountCent int64 `json:"deposit_waived_amount_cent"`
|
||||
PlatformFeeCent *int64 `json:"platform_fee_cent,omitempty"`
|
||||
AccountSnapshot datatypes.JSON `json:"account_snapshot"`
|
||||
Status string `json:"status"`
|
||||
HandoffStatus string `json:"handoff_status"`
|
||||
SettlementStatus string `json:"settlement_status"`
|
||||
Checkout *CheckoutDTO `json:"checkout,omitempty"`
|
||||
PaymentDeadlineAt *time.Time `json:"payment_deadline_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CreateRequest struct {
|
||||
@@ -89,7 +89,7 @@ type RefundStatusDTO struct {
|
||||
RefundStatus string `json:"refund_status"`
|
||||
RefundAmountCent int64 `json:"refund_amount_cent"`
|
||||
RefundedAt *time.Time `json:"refunded_at,omitempty"`
|
||||
TotalAmount float64 `json:"total_amount"`
|
||||
TotalAmountCent int64 `json:"total_amount_cent"`
|
||||
}
|
||||
|
||||
type HandoffRecordDTO struct {
|
||||
@@ -105,28 +105,28 @@ type HandoffRecordDTO struct {
|
||||
}
|
||||
|
||||
type CheckoutDTO struct {
|
||||
ID uint64 `json:"id"`
|
||||
OrderID uint64 `json:"order_id"`
|
||||
InitiatedBy uint64 `json:"initiated_by"`
|
||||
Status string `json:"status"`
|
||||
PriceRole string `json:"price_role,omitempty"`
|
||||
DisplayAmount float64 `json:"display_amount"`
|
||||
RentAmount *float64 `json:"rent_amount,omitempty"`
|
||||
OwnerRentAmount *float64 `json:"owner_rent_amount,omitempty"`
|
||||
PlatformFee *float64 `json:"platform_fee,omitempty"`
|
||||
DepositAmount float64 `json:"deposit_amount"`
|
||||
ConsumableAmount float64 `json:"consumable_amount"`
|
||||
CoinConsumedM float64 `json:"coin_consumed_m"`
|
||||
OtherAmount float64 `json:"other_amount"`
|
||||
DepositDeductAmount float64 `json:"deposit_deduct_amount"`
|
||||
RenterRefundAmount *float64 `json:"renter_refund_amount,omitempty"`
|
||||
OwnerIncomeAmount *float64 `json:"owner_income_amount,omitempty"`
|
||||
Content string `json:"content"`
|
||||
EvidenceURLS []string `json:"evidence_urls"`
|
||||
OwnerAdjustmentReason string `json:"owner_adjustment_reason"`
|
||||
OwnerAdjustedAt *time.Time `json:"owner_adjusted_at"`
|
||||
RenterConfirmedAt *time.Time `json:"renter_confirmed_at"`
|
||||
RenterRejectedAt *time.Time `json:"renter_rejected_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID uint64 `json:"id"`
|
||||
OrderID uint64 `json:"order_id"`
|
||||
InitiatedBy uint64 `json:"initiated_by"`
|
||||
Status string `json:"status"`
|
||||
PriceRole string `json:"price_role,omitempty"`
|
||||
DisplayAmountCent int64 `json:"display_amount_cent"`
|
||||
RentAmountCent *int64 `json:"rent_amount_cent,omitempty"`
|
||||
OwnerRentAmountCent *int64 `json:"owner_rent_amount_cent,omitempty"`
|
||||
PlatformFeeCent *int64 `json:"platform_fee_cent,omitempty"`
|
||||
DepositAmountCent int64 `json:"deposit_amount_cent"`
|
||||
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"`
|
||||
RenterRefundAmountCent *int64 `json:"renter_refund_amount_cent,omitempty"`
|
||||
OwnerIncomeAmountCent *int64 `json:"owner_income_amount_cent,omitempty"`
|
||||
Content string `json:"content"`
|
||||
EvidenceURLS []string `json:"evidence_urls"`
|
||||
OwnerAdjustmentReason string `json:"owner_adjustment_reason"`
|
||||
OwnerAdjustedAt *time.Time `json:"owner_adjusted_at"`
|
||||
RenterConfirmedAt *time.Time `json:"renter_confirmed_at"`
|
||||
RenterRejectedAt *time.Time `json:"renter_rejected_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
@@ -53,20 +53,20 @@ func (r *Repository) SetRefundFunc(fn RefundFunc) {
|
||||
}
|
||||
|
||||
type orderPricing struct {
|
||||
RentAmount float64
|
||||
OwnerRentAmount float64
|
||||
PlatformFee float64
|
||||
RentAmountCent int64
|
||||
OwnerRentAmountCent int64
|
||||
PlatformFeeCent int64
|
||||
}
|
||||
|
||||
type checkoutSettlement struct {
|
||||
OwnerRentIncome float64
|
||||
DepositCompensation float64
|
||||
OwnerIncome float64
|
||||
RentRefund float64
|
||||
DepositRefund float64
|
||||
RenterRefund float64
|
||||
PlatformFee float64
|
||||
ActualRentAmount float64
|
||||
OwnerRentIncomeCent int64
|
||||
DepositCompensationCent int64
|
||||
OwnerIncomeCent int64
|
||||
RentRefundCent int64
|
||||
DepositRefundCent int64
|
||||
RenterRefundCent int64
|
||||
PlatformFeeCent int64
|
||||
ActualRentAmountCent int64
|
||||
}
|
||||
|
||||
func orderDurationHours(order model.RentalOrder) int {
|
||||
@@ -90,9 +90,9 @@ func buildOrderPricing(listing model.RentalListing, account model.GameAccount) o
|
||||
platformFee = 0
|
||||
}
|
||||
return orderPricing{
|
||||
RentAmount: rentAmount,
|
||||
OwnerRentAmount: roundMoney(ownerRentAmount),
|
||||
PlatformFee: roundMoney(platformFee),
|
||||
RentAmountCent: int64(math.Round(rentAmount * 100)),
|
||||
OwnerRentAmountCent: int64(math.Round(ownerRentAmount * 100)),
|
||||
PlatformFeeCent: int64(math.Round(platformFee * 100)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,22 +179,22 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
|
||||
return err
|
||||
}
|
||||
order := model.RentalOrder{
|
||||
OrderNo: orderNo,
|
||||
ListingID: listing.ID,
|
||||
AccountID: listing.AccountID,
|
||||
OwnerID: listing.OwnerID,
|
||||
RenterID: renterID,
|
||||
EstimatedDurationHours: rentHours,
|
||||
RentAmount: pricing.RentAmount,
|
||||
OwnerRentAmount: pricing.OwnerRentAmount,
|
||||
DepositAmount: paidDepositAmount,
|
||||
DepositOriginalAmount: depositOriginalAmount,
|
||||
DepositWaivedAmount: waivedDepositAmount,
|
||||
PlatformFee: pricing.PlatformFee,
|
||||
AccountSnapshot: snapshot,
|
||||
Status: "pending_payment",
|
||||
HandoffStatus: "none",
|
||||
SettlementStatus: "unsettled",
|
||||
OrderNo: orderNo,
|
||||
ListingID: listing.ID,
|
||||
AccountID: listing.AccountID,
|
||||
OwnerID: listing.OwnerID,
|
||||
RenterID: renterID,
|
||||
EstimatedDurationHours: rentHours,
|
||||
RentAmountCent: pricing.RentAmountCent,
|
||||
OwnerRentAmountCent: pricing.OwnerRentAmountCent,
|
||||
DepositAmountCent: int64(math.Round(paidDepositAmount * 100)),
|
||||
DepositOriginalAmountCent: int64(math.Round(depositOriginalAmount * 100)),
|
||||
DepositWaivedAmountCent: int64(math.Round(waivedDepositAmount * 100)),
|
||||
PlatformFeeCent: pricing.PlatformFeeCent,
|
||||
AccountSnapshot: snapshot,
|
||||
Status: "pending_payment",
|
||||
HandoffStatus: "none",
|
||||
SettlementStatus: "unsettled",
|
||||
}
|
||||
if err := tx.Create(&order).Error; err != nil {
|
||||
return err
|
||||
@@ -368,7 +368,7 @@ func (r *Repository) Cancel(userID uint64, orderID uint64) error {
|
||||
order.HandoffStatus = "cancelled"
|
||||
orderID := order.ID
|
||||
if beforeStatus == "pending_handoff" {
|
||||
totalCent := int64(math.Round((order.RentAmount + order.DepositAmount) * 100))
|
||||
totalCent := order.RentAmountCent + order.DepositAmountCent
|
||||
action, err := r.prepareRefund(&order, totalCent, "cancel_refund", "取消订单原路退款")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -690,10 +690,10 @@ func (r *Repository) CounterCheckout(userID uint64, orderID uint64, req CounterC
|
||||
return nil, err
|
||||
}
|
||||
dto := toCheckoutDTOForUser(*checkout, userID, model.RentalOrder{
|
||||
OwnerID: userID,
|
||||
RentAmount: checkout.RentAmount,
|
||||
OwnerRentAmount: checkout.OwnerRentAmount,
|
||||
DepositAmount: checkout.DepositAmount,
|
||||
OwnerID: userID,
|
||||
RentAmountCent: int64(math.Round(checkout.RentAmount * 100)),
|
||||
OwnerRentAmountCent: int64(math.Round(checkout.OwnerRentAmount * 100)),
|
||||
DepositAmountCent: int64(math.Round(checkout.DepositAmount * 100)),
|
||||
})
|
||||
return &dto, nil
|
||||
}
|
||||
@@ -838,7 +838,7 @@ func (r *Repository) AdminClose(adminID uint64, orderID uint64, req AdminActionR
|
||||
listing.InTransaction = false
|
||||
account.Status = "offline"
|
||||
if beforeOrderStatus != "pending_payment" {
|
||||
totalCent := int64(math.Round((order.RentAmount + order.DepositAmount) * 100))
|
||||
totalCent := order.RentAmountCent + order.DepositAmountCent
|
||||
action, err := r.prepareRefund(order, totalCent, "admin_close_refund", "客服关闭订单原路退款")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -976,7 +976,7 @@ func (r *Repository) AdminRefund(orderID uint64) (*RefundStatusDTO, error) {
|
||||
if r.refundFunc == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
totalCent := int64(math.Round((order.RentAmount + order.DepositAmount) * 100))
|
||||
totalCent := order.RentAmountCent + order.DepositAmountCent
|
||||
if totalCent <= 0 {
|
||||
return nil, ErrInvalidCheckoutAmount
|
||||
}
|
||||
@@ -1011,7 +1011,7 @@ func (r *Repository) buildRefundStatusDTO(order *model.RentalOrder) *RefundStatu
|
||||
RefundStatus: order.RefundStatus,
|
||||
RefundAmountCent: order.RefundAmountCent,
|
||||
RefundedAt: order.RefundedAt,
|
||||
TotalAmount: order.RentAmount + order.DepositAmount,
|
||||
TotalAmountCent: order.RentAmountCent + order.DepositAmountCent,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1049,24 +1049,24 @@ func (r *Repository) finalizeCheckout(tx *gorm.DB, order *model.RentalOrder, che
|
||||
|
||||
// 卖家收入进入站内钱包;租客资金不进入站内钱包。
|
||||
var ownerEntries []wallet.Entry
|
||||
if settlement.OwnerRentIncome > 0 {
|
||||
if settlement.OwnerRentIncomeCent > 0 {
|
||||
ownerEntries = append(ownerEntries, wallet.Entry{
|
||||
UserID: order.OwnerID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
Amount: settlement.OwnerRentIncome,
|
||||
AmountCent: settlement.OwnerRentIncomeCent,
|
||||
BalanceType: "available",
|
||||
BizType: "owner_income",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: "订单结账租金收入",
|
||||
})
|
||||
}
|
||||
if settlement.DepositCompensation > 0 {
|
||||
if settlement.DepositCompensationCent > 0 {
|
||||
ownerEntries = append(ownerEntries, wallet.Entry{
|
||||
UserID: order.OwnerID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
Amount: settlement.DepositCompensation,
|
||||
AmountCent: settlement.DepositCompensationCent,
|
||||
BalanceType: "available",
|
||||
BizType: "deposit_compensation",
|
||||
BizNo: order.OrderNo,
|
||||
@@ -1080,21 +1080,20 @@ func (r *Repository) finalizeCheckout(tx *gorm.DB, order *model.RentalOrder, che
|
||||
}
|
||||
|
||||
var refund *refundAction
|
||||
renterRefundTotal := settlement.RentRefund + settlement.DepositRefund
|
||||
if renterRefundTotal > 0 {
|
||||
refundCent := int64(math.Round(renterRefundTotal * 100))
|
||||
action, err := r.prepareRefund(order, refundCent, "checkout_refund", "结账退款原路退还")
|
||||
renterRefundTotalCent := settlement.RentRefundCent + settlement.DepositRefundCent
|
||||
if renterRefundTotalCent > 0 {
|
||||
action, err := r.prepareRefund(order, renterRefundTotalCent, "checkout_refund", "结账退款原路退还")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
refund = action
|
||||
}
|
||||
|
||||
checkout.RentAmount = settlement.ActualRentAmount
|
||||
checkout.OwnerRentAmount = settlement.OwnerRentIncome
|
||||
checkout.PlatformFee = settlement.PlatformFee
|
||||
checkout.RenterRefundAmount = settlement.RenterRefund
|
||||
checkout.OwnerIncomeAmount = settlement.OwnerIncome
|
||||
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
|
||||
if err := notification.Append(tx,
|
||||
notification.Entry{
|
||||
UserID: order.RenterID,
|
||||
@@ -1235,7 +1234,8 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
||||
if useExplicitDeduct {
|
||||
deductAmount = explicitDeduct
|
||||
}
|
||||
if deductAmount > order.DepositAmount {
|
||||
depositAmountFromCent := float64(order.DepositAmountCent) / 100
|
||||
if deductAmount > depositAmountFromCent {
|
||||
return model.OrderCheckout{}, ErrInvalidCheckoutAmount
|
||||
}
|
||||
settlement := calculateCheckoutSettlement(order, consumableAmount, roundQuantity(coinConsumedM), deductAmount)
|
||||
@@ -1247,16 +1247,16 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
||||
OrderID: order.ID,
|
||||
InitiatedBy: initiatedBy,
|
||||
Status: status,
|
||||
RentAmount: settlement.ActualRentAmount,
|
||||
OwnerRentAmount: settlement.OwnerRentIncome,
|
||||
PlatformFee: settlement.PlatformFee,
|
||||
DepositAmount: order.DepositAmount,
|
||||
RentAmount: float64(settlement.ActualRentAmountCent) / 100,
|
||||
OwnerRentAmount: float64(settlement.OwnerRentIncomeCent) / 100,
|
||||
PlatformFee: float64(settlement.PlatformFeeCent) / 100,
|
||||
DepositAmount: depositAmountFromCent,
|
||||
ConsumableAmount: consumableAmount,
|
||||
CoinConsumedM: roundQuantity(coinConsumedM),
|
||||
OtherAmount: otherAmount,
|
||||
DepositDeductAmount: roundMoney(deductAmount),
|
||||
RenterRefundAmount: settlement.RenterRefund,
|
||||
OwnerIncomeAmount: settlement.OwnerIncome,
|
||||
RenterRefundAmount: float64(settlement.RenterRefundCent) / 100,
|
||||
OwnerIncomeAmount: float64(settlement.OwnerIncomeCent) / 100,
|
||||
Content: content,
|
||||
EvidenceURLS: evidence,
|
||||
}, nil
|
||||
@@ -1267,19 +1267,24 @@ func buildCheckoutSettlement(order model.RentalOrder, checkout *model.OrderCheck
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
buyerCoinBasePrice := readOrderSnapshotPrice(order.AccountSnapshot, "buyer_coin_base_price")
|
||||
if buyerCoinBasePrice <= 0 || buyerCoinBasePrice > order.RentAmount {
|
||||
buyerCoinBasePrice = order.RentAmount
|
||||
if buyerCoinBasePrice <= 0 || buyerCoinBasePrice > orderRentAmount {
|
||||
buyerCoinBasePrice = orderRentAmount
|
||||
}
|
||||
sellerCoinBasePrice := readOrderSnapshotPrice(order.AccountSnapshot, "seller_coin_base_price")
|
||||
if sellerCoinBasePrice <= 0 || sellerCoinBasePrice > order.OwnerRentAmount {
|
||||
sellerCoinBasePrice = order.OwnerRentAmount
|
||||
if sellerCoinBasePrice <= 0 || sellerCoinBasePrice > orderOwnerRentAmount {
|
||||
sellerCoinBasePrice = orderOwnerRentAmount
|
||||
}
|
||||
prepaidConsumablePrice := readOrderSnapshotPrice(order.AccountSnapshot, "consumable_price")
|
||||
if prepaidConsumablePrice <= 0 || prepaidConsumablePrice > order.RentAmount-buyerCoinBasePrice {
|
||||
prepaidConsumablePrice = maxMoney(order.RentAmount-buyerCoinBasePrice, 0)
|
||||
if prepaidConsumablePrice <= 0 || prepaidConsumablePrice > orderRentAmount-buyerCoinBasePrice {
|
||||
prepaidConsumablePrice = maxMoney(orderRentAmount-buyerCoinBasePrice, 0)
|
||||
}
|
||||
prepaidOwnerConsumablePrice := maxMoney(order.OwnerRentAmount-sellerCoinBasePrice, 0)
|
||||
prepaidOwnerConsumablePrice := maxMoney(orderOwnerRentAmount-sellerCoinBasePrice, 0)
|
||||
totalCoinM := readOrderSnapshotCoinM(order.AccountSnapshot)
|
||||
coinUseRatio := 1.0
|
||||
if totalCoinM > 0 {
|
||||
@@ -1293,20 +1298,22 @@ func calculateCheckoutSettlement(order model.RentalOrder, consumableAmount float
|
||||
consumableUseRatio = minRatio(maxRatio(usedBuyerConsumablePrice/prepaidConsumablePrice, 0), 1)
|
||||
}
|
||||
usedOwnerConsumablePrice := roundMoney(prepaidOwnerConsumablePrice * consumableUseRatio)
|
||||
actualRentAmount := minMoney(roundMoney(usedBuyerCoinPrice+usedBuyerConsumablePrice), order.RentAmount)
|
||||
ownerRentIncome := minMoney(roundMoney(usedOwnerCoinPrice+usedOwnerConsumablePrice), order.OwnerRentAmount)
|
||||
depositCompensation := minMoney(roundMoney(depositDeductAmount), order.DepositAmount)
|
||||
rentRefund := maxMoney(order.RentAmount-actualRentAmount, 0)
|
||||
depositRefund := maxMoney(order.DepositAmount-depositCompensation, 0)
|
||||
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)
|
||||
|
||||
// 最后转换为分返回
|
||||
return checkoutSettlement{
|
||||
OwnerRentIncome: ownerRentIncome,
|
||||
DepositCompensation: depositCompensation,
|
||||
OwnerIncome: roundMoney(ownerRentIncome + depositCompensation),
|
||||
RentRefund: rentRefund,
|
||||
DepositRefund: depositRefund,
|
||||
RenterRefund: roundMoney(rentRefund + depositRefund),
|
||||
PlatformFee: maxMoney(actualRentAmount-ownerRentIncome, 0),
|
||||
ActualRentAmount: actualRentAmount,
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,38 +1452,38 @@ type orderRow struct {
|
||||
func (row orderRow) toAdminDTO() OrderDTO {
|
||||
rentedAt := row.RentedAt
|
||||
durationHours := orderDurationHours(row.RentalOrder)
|
||||
rentAmount := row.RentAmount
|
||||
ownerRentAmount := row.OwnerRentAmount
|
||||
platformFee := row.PlatformFee
|
||||
rentAmountCent := row.RentAmountCent
|
||||
ownerRentAmountCent := row.OwnerRentAmountCent
|
||||
platformFeeCent := row.PlatformFeeCent
|
||||
return OrderDTO{
|
||||
ID: row.ID,
|
||||
OrderNo: row.OrderNo,
|
||||
ListingID: row.ListingID,
|
||||
ListingNo: row.ListingNo,
|
||||
AccountID: row.AccountID,
|
||||
OwnerID: row.OwnerID,
|
||||
RenterID: row.RenterID,
|
||||
OwnerPhone: row.OwnerPhone,
|
||||
RenterPhone: row.RenterPhone,
|
||||
Title: row.Title,
|
||||
ServerRegion: row.ServerRegion,
|
||||
LoginPlatform: row.LoginPlatform,
|
||||
RentedAt: rentedAt,
|
||||
EstimatedDurationHours: durationHours,
|
||||
PriceRole: "admin",
|
||||
DisplayAmount: row.RentAmount,
|
||||
RentAmount: &rentAmount,
|
||||
OwnerRentAmount: &ownerRentAmount,
|
||||
DepositAmount: row.DepositAmount,
|
||||
DepositOriginalAmount: effectiveDepositOriginalAmount(row.RentalOrder),
|
||||
DepositWaivedAmount: row.DepositWaivedAmount,
|
||||
PlatformFee: &platformFee,
|
||||
AccountSnapshot: row.AccountSnapshot,
|
||||
Status: row.Status,
|
||||
HandoffStatus: row.HandoffStatus,
|
||||
SettlementStatus: row.SettlementStatus,
|
||||
CreatedAt: row.CreatedAt,
|
||||
UpdatedAt: row.UpdatedAt,
|
||||
ID: row.ID,
|
||||
OrderNo: row.OrderNo,
|
||||
ListingID: row.ListingID,
|
||||
ListingNo: row.ListingNo,
|
||||
AccountID: row.AccountID,
|
||||
OwnerID: row.OwnerID,
|
||||
RenterID: row.RenterID,
|
||||
OwnerPhone: row.OwnerPhone,
|
||||
RenterPhone: row.RenterPhone,
|
||||
Title: row.Title,
|
||||
ServerRegion: row.ServerRegion,
|
||||
LoginPlatform: row.LoginPlatform,
|
||||
RentedAt: rentedAt,
|
||||
EstimatedDurationHours: durationHours,
|
||||
PriceRole: "admin",
|
||||
DisplayAmountCent: row.RentAmountCent,
|
||||
RentAmountCent: &rentAmountCent,
|
||||
OwnerRentAmountCent: &ownerRentAmountCent,
|
||||
DepositAmountCent: row.DepositAmountCent,
|
||||
DepositOriginalAmountCent: effectiveDepositOriginalAmountCent(row.RentalOrder),
|
||||
DepositWaivedAmountCent: row.DepositWaivedAmountCent,
|
||||
PlatformFeeCent: &platformFeeCent,
|
||||
AccountSnapshot: row.AccountSnapshot,
|
||||
Status: row.Status,
|
||||
HandoffStatus: row.HandoffStatus,
|
||||
SettlementStatus: row.SettlementStatus,
|
||||
CreatedAt: row.CreatedAt,
|
||||
UpdatedAt: row.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1507,37 +1514,44 @@ func effectiveDepositOriginalAmount(order model.RentalOrder) float64 {
|
||||
return order.DepositAmount
|
||||
}
|
||||
|
||||
func effectiveDepositOriginalAmountCent(order model.RentalOrder) int64 {
|
||||
if order.DepositOriginalAmountCent > 0 {
|
||||
return order.DepositOriginalAmountCent
|
||||
}
|
||||
return order.DepositAmountCent
|
||||
}
|
||||
|
||||
func toCheckoutAdminDTO(checkout model.OrderCheckout) CheckoutDTO {
|
||||
rentAmount := checkout.RentAmount
|
||||
ownerRentAmount := checkout.OwnerRentAmount
|
||||
platformFee := checkout.PlatformFee
|
||||
renterRefundAmount := checkout.RenterRefundAmount
|
||||
ownerIncomeAmount := checkout.OwnerIncomeAmount
|
||||
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))
|
||||
return CheckoutDTO{
|
||||
ID: checkout.ID,
|
||||
OrderID: checkout.OrderID,
|
||||
InitiatedBy: checkout.InitiatedBy,
|
||||
Status: checkout.Status,
|
||||
PriceRole: "admin",
|
||||
DisplayAmount: checkout.RentAmount,
|
||||
RentAmount: &rentAmount,
|
||||
OwnerRentAmount: &ownerRentAmount,
|
||||
PlatformFee: &platformFee,
|
||||
DepositAmount: checkout.DepositAmount,
|
||||
ConsumableAmount: checkout.ConsumableAmount,
|
||||
CoinConsumedM: checkout.CoinConsumedM,
|
||||
OtherAmount: checkout.OtherAmount,
|
||||
DepositDeductAmount: checkout.DepositDeductAmount,
|
||||
RenterRefundAmount: &renterRefundAmount,
|
||||
OwnerIncomeAmount: &ownerIncomeAmount,
|
||||
Content: checkout.Content,
|
||||
EvidenceURLS: decodeStringList(checkout.EvidenceURLS),
|
||||
OwnerAdjustmentReason: checkout.OwnerAdjustmentReason,
|
||||
OwnerAdjustedAt: checkout.OwnerAdjustedAt,
|
||||
RenterConfirmedAt: checkout.RenterConfirmedAt,
|
||||
RenterRejectedAt: checkout.RenterRejectedAt,
|
||||
CreatedAt: checkout.CreatedAt,
|
||||
UpdatedAt: checkout.UpdatedAt,
|
||||
ID: checkout.ID,
|
||||
OrderID: checkout.OrderID,
|
||||
InitiatedBy: checkout.InitiatedBy,
|
||||
Status: checkout.Status,
|
||||
PriceRole: "admin",
|
||||
DisplayAmountCent: rentAmountCent,
|
||||
RentAmountCent: &rentAmountCent,
|
||||
OwnerRentAmountCent: &ownerRentAmountCent,
|
||||
PlatformFeeCent: &platformFeeCent,
|
||||
DepositAmountCent: int64(math.Round(checkout.DepositAmount * 100)),
|
||||
ConsumableAmountCent: int64(math.Round(checkout.ConsumableAmount * 100)),
|
||||
CoinConsumedM: checkout.CoinConsumedM,
|
||||
OtherAmountCent: int64(math.Round(checkout.OtherAmount * 100)),
|
||||
DepositDeductAmountCent: int64(math.Round(checkout.DepositDeductAmount * 100)),
|
||||
RenterRefundAmountCent: &renterRefundAmountCent,
|
||||
OwnerIncomeAmountCent: &ownerIncomeAmountCent,
|
||||
Content: checkout.Content,
|
||||
EvidenceURLS: decodeStringList(checkout.EvidenceURLS),
|
||||
OwnerAdjustmentReason: checkout.OwnerAdjustmentReason,
|
||||
OwnerAdjustedAt: checkout.OwnerAdjustedAt,
|
||||
RenterConfirmedAt: checkout.RenterConfirmedAt,
|
||||
RenterRejectedAt: checkout.RenterRejectedAt,
|
||||
CreatedAt: checkout.CreatedAt,
|
||||
UpdatedAt: checkout.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1551,30 +1565,30 @@ func applyOrderPriceView(dto *OrderDTO, order model.RentalOrder, userID uint64)
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
dto.PlatformFee = nil
|
||||
dto.PlatformFeeCent = nil
|
||||
switch {
|
||||
case userID == order.OwnerID:
|
||||
ownerAmount := order.OwnerRentAmount
|
||||
if ownerAmount <= 0 {
|
||||
ownerAmount = order.RentAmount
|
||||
ownerAmountCent := order.OwnerRentAmountCent
|
||||
if ownerAmountCent <= 0 {
|
||||
ownerAmountCent = order.RentAmountCent
|
||||
}
|
||||
dto.PriceRole = "owner"
|
||||
dto.DisplayAmount = ownerAmount
|
||||
dto.RentAmount = nil
|
||||
dto.OwnerRentAmount = &ownerAmount
|
||||
dto.DisplayAmountCent = ownerAmountCent
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = &ownerAmountCent
|
||||
sanitizeOrderSnapshot(&dto.AccountSnapshot, "owner")
|
||||
case userID == order.RenterID:
|
||||
rentAmount := order.RentAmount
|
||||
rentAmountCent := order.RentAmountCent
|
||||
dto.PriceRole = "renter"
|
||||
dto.DisplayAmount = rentAmount
|
||||
dto.RentAmount = &rentAmount
|
||||
dto.OwnerRentAmount = nil
|
||||
dto.DisplayAmountCent = rentAmountCent
|
||||
dto.RentAmountCent = &rentAmountCent
|
||||
dto.OwnerRentAmountCent = nil
|
||||
sanitizeOrderSnapshot(&dto.AccountSnapshot, "renter")
|
||||
default:
|
||||
dto.PriceRole = ""
|
||||
dto.DisplayAmount = 0
|
||||
dto.RentAmount = nil
|
||||
dto.OwnerRentAmount = nil
|
||||
dto.DisplayAmountCent = 0
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = nil
|
||||
sanitizeOrderSnapshot(&dto.AccountSnapshot, "")
|
||||
}
|
||||
}
|
||||
@@ -1583,43 +1597,43 @@ func applyCheckoutPriceView(dto *CheckoutDTO, order model.RentalOrder, userID ui
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
ownerAmount := 0.0
|
||||
if dto.OwnerRentAmount != nil {
|
||||
ownerAmount = *dto.OwnerRentAmount
|
||||
ownerAmountCent := int64(0)
|
||||
if dto.OwnerRentAmountCent != nil {
|
||||
ownerAmountCent = *dto.OwnerRentAmountCent
|
||||
}
|
||||
ownerIncomeAmount := 0.0
|
||||
if dto.OwnerIncomeAmount != nil {
|
||||
ownerIncomeAmount = *dto.OwnerIncomeAmount
|
||||
ownerIncomeAmountCent := int64(0)
|
||||
if dto.OwnerIncomeAmountCent != nil {
|
||||
ownerIncomeAmountCent = *dto.OwnerIncomeAmountCent
|
||||
}
|
||||
rentAmount := 0.0
|
||||
if dto.RentAmount != nil {
|
||||
rentAmount = *dto.RentAmount
|
||||
rentAmountCent := int64(0)
|
||||
if dto.RentAmountCent != nil {
|
||||
rentAmountCent = *dto.RentAmountCent
|
||||
}
|
||||
renterRefundAmount := 0.0
|
||||
if dto.RenterRefundAmount != nil {
|
||||
renterRefundAmount = *dto.RenterRefundAmount
|
||||
renterRefundAmountCent := int64(0)
|
||||
if dto.RenterRefundAmountCent != nil {
|
||||
renterRefundAmountCent = *dto.RenterRefundAmountCent
|
||||
}
|
||||
dto.PlatformFee = nil
|
||||
dto.RenterRefundAmount = nil
|
||||
dto.OwnerIncomeAmount = nil
|
||||
dto.PlatformFeeCent = nil
|
||||
dto.RenterRefundAmountCent = nil
|
||||
dto.OwnerIncomeAmountCent = nil
|
||||
switch {
|
||||
case userID == order.OwnerID:
|
||||
dto.PriceRole = "owner"
|
||||
dto.DisplayAmount = ownerAmount
|
||||
dto.RentAmount = nil
|
||||
dto.OwnerRentAmount = &ownerAmount
|
||||
dto.OwnerIncomeAmount = &ownerIncomeAmount
|
||||
dto.DisplayAmountCent = ownerAmountCent
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = &ownerAmountCent
|
||||
dto.OwnerIncomeAmountCent = &ownerIncomeAmountCent
|
||||
case userID == order.RenterID:
|
||||
dto.PriceRole = "renter"
|
||||
dto.DisplayAmount = rentAmount
|
||||
dto.RentAmount = &rentAmount
|
||||
dto.OwnerRentAmount = nil
|
||||
dto.RenterRefundAmount = &renterRefundAmount
|
||||
dto.DisplayAmountCent = rentAmountCent
|
||||
dto.RentAmountCent = &rentAmountCent
|
||||
dto.OwnerRentAmountCent = nil
|
||||
dto.RenterRefundAmountCent = &renterRefundAmountCent
|
||||
default:
|
||||
dto.PriceRole = ""
|
||||
dto.DisplayAmount = 0
|
||||
dto.RentAmount = nil
|
||||
dto.OwnerRentAmount = nil
|
||||
dto.DisplayAmountCent = 0
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user