修复结账金额和后台类型
This commit is contained in:
@@ -40,6 +40,17 @@ type orderPricing struct {
|
||||
PlatformFee float64
|
||||
}
|
||||
|
||||
type checkoutSettlement struct {
|
||||
OwnerRentIncome float64
|
||||
DepositCompensation float64
|
||||
OwnerIncome float64
|
||||
RentRefund float64
|
||||
DepositRefund float64
|
||||
RenterRefund float64
|
||||
PlatformFee float64
|
||||
ActualRentAmount float64
|
||||
}
|
||||
|
||||
func orderDurationHours(order model.RentalOrder) int {
|
||||
if order.EstimatedDurationHours > 0 {
|
||||
return order.EstimatedDurationHours
|
||||
@@ -68,14 +79,21 @@ func buildOrderPricing(listing model.RentalListing, account model.GameAccount) o
|
||||
}
|
||||
|
||||
func readSnapshotPrice(raw datatypes.JSON, key string) float64 {
|
||||
return readOrderSnapshotPrice(raw, key)
|
||||
}
|
||||
|
||||
func readOrderSnapshotPrice(raw datatypes.JSON, key string) float64 {
|
||||
if len(raw) == 0 {
|
||||
return 0
|
||||
}
|
||||
var summary map[string]any
|
||||
if err := json.Unmarshal(raw, &summary); err != nil {
|
||||
var snapshot map[string]any
|
||||
if err := json.Unmarshal(raw, &snapshot); err != nil {
|
||||
return 0
|
||||
}
|
||||
breakdown, ok := summary["price_breakdown"].(map[string]any)
|
||||
if assetSummary, ok := snapshot["asset_summary"].(map[string]any); ok {
|
||||
snapshot = assetSummary
|
||||
}
|
||||
breakdown, ok := snapshot["price_breakdown"].(map[string]any)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
@@ -927,7 +945,8 @@ func (r *Repository) finalizeCheckout(tx *gorm.DB, order *model.RentalOrder, che
|
||||
listing.InTransaction = false
|
||||
account.Status = "published"
|
||||
orderID := order.ID
|
||||
if err := wallet.AppendEntries(tx,
|
||||
settlement := buildCheckoutSettlement(*order, checkout)
|
||||
entries := []wallet.Entry{
|
||||
wallet.Entry{
|
||||
UserID: order.RenterID,
|
||||
OrderID: &orderID,
|
||||
@@ -938,29 +957,63 @@ func (r *Repository) finalizeCheckout(tx *gorm.DB, order *model.RentalOrder, che
|
||||
BizNo: order.OrderNo,
|
||||
Remark: "订单结账释放冻结金额",
|
||||
},
|
||||
wallet.Entry{
|
||||
}
|
||||
if settlement.OwnerRentIncome > 0 {
|
||||
entries = append(entries, wallet.Entry{
|
||||
UserID: order.OwnerID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
Amount: checkout.OwnerIncomeAmount,
|
||||
Amount: settlement.OwnerRentIncome,
|
||||
BalanceType: "available",
|
||||
BizType: "owner_income",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: "订单结账收入",
|
||||
},
|
||||
wallet.Entry{
|
||||
Remark: "订单结账租金收入",
|
||||
})
|
||||
}
|
||||
if settlement.DepositCompensation > 0 {
|
||||
entries = append(entries, wallet.Entry{
|
||||
UserID: order.OwnerID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
Amount: settlement.DepositCompensation,
|
||||
BalanceType: "available",
|
||||
BizType: "deposit_compensation",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: "订单结账押金赔付",
|
||||
})
|
||||
}
|
||||
if settlement.RentRefund > 0 {
|
||||
entries = append(entries, wallet.Entry{
|
||||
UserID: order.RenterID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
Amount: checkout.RenterRefundAmount,
|
||||
Amount: settlement.RentRefund,
|
||||
BalanceType: "available",
|
||||
BizType: "rent_refund",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: "订单结账退回未使用租金",
|
||||
})
|
||||
}
|
||||
if settlement.DepositRefund > 0 {
|
||||
entries = append(entries, wallet.Entry{
|
||||
UserID: order.RenterID,
|
||||
OrderID: &orderID,
|
||||
Direction: "in",
|
||||
Amount: settlement.DepositRefund,
|
||||
BalanceType: "available",
|
||||
BizType: "deposit_release",
|
||||
BizNo: order.OrderNo,
|
||||
Remark: "订单结账退回押金",
|
||||
},
|
||||
); err != nil {
|
||||
})
|
||||
}
|
||||
if err := wallet.AppendEntries(tx, entries...); err != nil {
|
||||
return err
|
||||
}
|
||||
checkout.RentAmount = settlement.ActualRentAmount
|
||||
checkout.OwnerRentAmount = settlement.OwnerRentIncome
|
||||
checkout.PlatformFee = settlement.PlatformFee
|
||||
checkout.RenterRefundAmount = settlement.RenterRefund
|
||||
checkout.OwnerIncomeAmount = settlement.OwnerIncome
|
||||
if err := notification.Append(tx,
|
||||
notification.Entry{
|
||||
UserID: order.RenterID,
|
||||
@@ -1049,7 +1102,7 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
||||
if deductAmount > order.DepositAmount {
|
||||
return model.OrderCheckout{}, ErrInvalidCheckoutAmount
|
||||
}
|
||||
renterRefund := order.DepositAmount - deductAmount
|
||||
settlement := calculateCheckoutSettlement(order, consumableAmount, roundQuantity(coinConsumedM), deductAmount)
|
||||
evidence, err := marshalStringList(evidenceURLS)
|
||||
if err != nil {
|
||||
return model.OrderCheckout{}, err
|
||||
@@ -1058,21 +1111,80 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
|
||||
OrderID: order.ID,
|
||||
InitiatedBy: initiatedBy,
|
||||
Status: status,
|
||||
RentAmount: order.RentAmount,
|
||||
OwnerRentAmount: order.OwnerRentAmount,
|
||||
PlatformFee: order.PlatformFee,
|
||||
RentAmount: settlement.ActualRentAmount,
|
||||
OwnerRentAmount: settlement.OwnerRentIncome,
|
||||
PlatformFee: settlement.PlatformFee,
|
||||
DepositAmount: order.DepositAmount,
|
||||
ConsumableAmount: consumableAmount,
|
||||
CoinConsumedM: roundQuantity(coinConsumedM),
|
||||
OtherAmount: otherAmount,
|
||||
DepositDeductAmount: roundMoney(deductAmount),
|
||||
RenterRefundAmount: roundMoney(renterRefund),
|
||||
OwnerIncomeAmount: roundMoney(order.OwnerRentAmount + deductAmount),
|
||||
RenterRefundAmount: settlement.RenterRefund,
|
||||
OwnerIncomeAmount: settlement.OwnerIncome,
|
||||
Content: content,
|
||||
EvidenceURLS: evidence,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func buildCheckoutSettlement(order model.RentalOrder, checkout *model.OrderCheckout) checkoutSettlement {
|
||||
return calculateCheckoutSettlement(order, checkout.ConsumableAmount, checkout.CoinConsumedM, checkout.DepositDeductAmount)
|
||||
}
|
||||
|
||||
func calculateCheckoutSettlement(order model.RentalOrder, consumableAmount float64, coinConsumedM float64, depositDeductAmount float64) checkoutSettlement {
|
||||
buyerCoinBasePrice := readOrderSnapshotPrice(order.AccountSnapshot, "buyer_coin_base_price")
|
||||
if buyerCoinBasePrice <= 0 || buyerCoinBasePrice > order.RentAmount {
|
||||
buyerCoinBasePrice = order.RentAmount
|
||||
}
|
||||
sellerCoinBasePrice := readOrderSnapshotPrice(order.AccountSnapshot, "seller_coin_base_price")
|
||||
if sellerCoinBasePrice <= 0 || sellerCoinBasePrice > order.OwnerRentAmount {
|
||||
sellerCoinBasePrice = order.OwnerRentAmount
|
||||
}
|
||||
prepaidConsumablePrice := readOrderSnapshotPrice(order.AccountSnapshot, "consumable_price")
|
||||
if prepaidConsumablePrice <= 0 || prepaidConsumablePrice > order.RentAmount-buyerCoinBasePrice {
|
||||
prepaidConsumablePrice = maxMoney(order.RentAmount-buyerCoinBasePrice, 0)
|
||||
}
|
||||
prepaidOwnerConsumablePrice := maxMoney(order.OwnerRentAmount-sellerCoinBasePrice, 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)
|
||||
consumableUseRatio := 1.0
|
||||
if prepaidConsumablePrice > 0 {
|
||||
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)
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
func readOrderSnapshotCoinM(raw datatypes.JSON) float64 {
|
||||
if len(raw) == 0 {
|
||||
return 0
|
||||
}
|
||||
var snapshot map[string]any
|
||||
if err := json.Unmarshal(raw, &snapshot); err != nil {
|
||||
return 0
|
||||
}
|
||||
return roundQuantity(readJSONNumber(snapshot["haf_coin_amount"]) / 1000000)
|
||||
}
|
||||
|
||||
func marshalStringList(items []string) (datatypes.JSON, error) {
|
||||
if items == nil {
|
||||
items = []string{}
|
||||
@@ -1100,6 +1212,34 @@ func roundQuantity(value float64) float64 {
|
||||
return math.Round(value*100) / 100
|
||||
}
|
||||
|
||||
func minMoney(a float64, b float64) float64 {
|
||||
if a < b {
|
||||
return roundMoney(a)
|
||||
}
|
||||
return roundMoney(b)
|
||||
}
|
||||
|
||||
func maxMoney(a float64, b float64) float64 {
|
||||
if a > b {
|
||||
return roundMoney(a)
|
||||
}
|
||||
return roundMoney(b)
|
||||
}
|
||||
|
||||
func minRatio(a float64, b float64) float64 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func maxRatio(a float64, b float64) float64 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func hasOpenCheckout(tx *gorm.DB, orderID uint64) (bool, error) {
|
||||
var count int64
|
||||
err := tx.Model(&model.OrderCheckout{}).
|
||||
@@ -1288,27 +1428,33 @@ func applyCheckoutPriceView(dto *CheckoutDTO, order model.RentalOrder, userID ui
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
ownerAmount := 0.0
|
||||
if dto.OwnerRentAmount != nil {
|
||||
ownerAmount = *dto.OwnerRentAmount
|
||||
}
|
||||
ownerIncomeAmount := 0.0
|
||||
if dto.OwnerIncomeAmount != nil {
|
||||
ownerIncomeAmount = *dto.OwnerIncomeAmount
|
||||
}
|
||||
rentAmount := 0.0
|
||||
if dto.RentAmount != nil {
|
||||
rentAmount = *dto.RentAmount
|
||||
}
|
||||
renterRefundAmount := 0.0
|
||||
if dto.RenterRefundAmount != nil {
|
||||
renterRefundAmount = *dto.RenterRefundAmount
|
||||
}
|
||||
dto.PlatformFee = nil
|
||||
dto.RenterRefundAmount = nil
|
||||
dto.OwnerIncomeAmount = nil
|
||||
switch {
|
||||
case userID == order.OwnerID:
|
||||
ownerAmount := order.OwnerRentAmount
|
||||
if ownerAmount <= 0 {
|
||||
ownerAmount = order.RentAmount
|
||||
}
|
||||
ownerIncomeAmount := dto.DepositDeductAmount + ownerAmount
|
||||
dto.PriceRole = "owner"
|
||||
dto.DisplayAmount = ownerAmount
|
||||
dto.RentAmount = nil
|
||||
dto.OwnerRentAmount = &ownerAmount
|
||||
dto.OwnerIncomeAmount = &ownerIncomeAmount
|
||||
case userID == order.RenterID:
|
||||
rentAmount := order.RentAmount
|
||||
renterRefundAmount := order.DepositAmount - dto.DepositDeductAmount
|
||||
if renterRefundAmount < 0 {
|
||||
renterRefundAmount = 0
|
||||
}
|
||||
dto.PriceRole = "renter"
|
||||
dto.DisplayAmount = rentAmount
|
||||
dto.RentAmount = &rentAmount
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
func TestCalculateCheckoutSettlementRefundsUnusedRent(t *testing.T) {
|
||||
order := model.RentalOrder{
|
||||
RentAmount: 383,
|
||||
OwnerRentAmount: 353,
|
||||
DepositAmount: 150,
|
||||
AccountSnapshot: datatypes.JSON([]byte(`{
|
||||
"haf_coin_amount": 100000000,
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"buyer_coin_base_price": 263,
|
||||
"seller_coin_base_price": 233,
|
||||
"consumable_price": 120
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
}
|
||||
|
||||
settlement := calculateCheckoutSettlement(order, 7, 90, 0)
|
||||
|
||||
if settlement.ActualRentAmount != 244 {
|
||||
t.Fatalf("ActualRentAmount = %.2f, want 244.00", settlement.ActualRentAmount)
|
||||
}
|
||||
if settlement.OwnerRentIncome != 217 {
|
||||
t.Fatalf("OwnerRentIncome = %.2f, want 217.00", settlement.OwnerRentIncome)
|
||||
}
|
||||
if settlement.PlatformFee != 27 {
|
||||
t.Fatalf("PlatformFee = %.2f, want 27.00", settlement.PlatformFee)
|
||||
}
|
||||
if settlement.RentRefund != 139 {
|
||||
t.Fatalf("RentRefund = %.2f, want 139.00", settlement.RentRefund)
|
||||
}
|
||||
if settlement.DepositRefund != 150 {
|
||||
t.Fatalf("DepositRefund = %.2f, want 150.00", settlement.DepositRefund)
|
||||
}
|
||||
if settlement.RenterRefund != 289 {
|
||||
t.Fatalf("RenterRefund = %.2f, want 289.00", settlement.RenterRefund)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately(t *testing.T) {
|
||||
order := model.RentalOrder{
|
||||
RentAmount: 383,
|
||||
OwnerRentAmount: 353,
|
||||
DepositAmount: 150,
|
||||
AccountSnapshot: datatypes.JSON([]byte(`{
|
||||
"haf_coin_amount": 100000000,
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"buyer_coin_base_price": 263,
|
||||
"seller_coin_base_price": 233,
|
||||
"consumable_price": 120
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
}
|
||||
|
||||
settlement := calculateCheckoutSettlement(order, 0, 50, 0)
|
||||
|
||||
if settlement.ActualRentAmount != 132 {
|
||||
t.Fatalf("租客侧实际租金 = %.2f, want 132.00", settlement.ActualRentAmount)
|
||||
}
|
||||
if settlement.OwnerRentIncome != 117 {
|
||||
t.Fatalf("卖家侧租金收入 = %.2f, want 117.00", settlement.OwnerRentIncome)
|
||||
}
|
||||
if settlement.PlatformFee != 15 {
|
||||
t.Fatalf("平台差价 = %.2f, want 15.00", settlement.PlatformFee)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
|
||||
order := model.RentalOrder{
|
||||
RentAmount: 383,
|
||||
OwnerRentAmount: 353,
|
||||
DepositAmount: 150,
|
||||
AccountSnapshot: datatypes.JSON([]byte(`{
|
||||
"haf_coin_amount": 100000000,
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"buyer_coin_base_price": 263,
|
||||
"seller_coin_base_price": 233,
|
||||
"consumable_price": 120
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
}
|
||||
|
||||
settlement := calculateCheckoutSettlement(order, 120, 100, 30)
|
||||
|
||||
if settlement.ActualRentAmount != 383 {
|
||||
t.Fatalf("ActualRentAmount = %.2f, want 383.00", settlement.ActualRentAmount)
|
||||
}
|
||||
if settlement.OwnerRentIncome != 353 {
|
||||
t.Fatalf("OwnerRentIncome = %.2f, want 353.00", settlement.OwnerRentIncome)
|
||||
}
|
||||
if settlement.DepositCompensation != 30 {
|
||||
t.Fatalf("DepositCompensation = %.2f, want 30.00", settlement.DepositCompensation)
|
||||
}
|
||||
if settlement.OwnerIncome != 383 {
|
||||
t.Fatalf("OwnerIncome = %.2f, want 383.00", settlement.OwnerIncome)
|
||||
}
|
||||
if settlement.RenterRefund != 120 {
|
||||
t.Fatalf("RenterRefund = %.2f, want 120.00", settlement.RenterRefund)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { ref, type Ref } from 'vue'
|
||||
interface AdminQueryOptions<T> {
|
||||
fetchFn: () => Promise<T>
|
||||
immediate?: boolean
|
||||
initialData?: T
|
||||
}
|
||||
|
||||
interface AdminQueryResult<T> {
|
||||
@@ -15,7 +16,7 @@ interface AdminQueryResult<T> {
|
||||
export function useAdminQuery<T>(options: AdminQueryOptions<T>): AdminQueryResult<T> {
|
||||
const loading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const data = ref<T>() as Ref<T>
|
||||
const data = ref<T>(options.initialData as T) as Ref<T>
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
|
||||
@@ -550,7 +550,7 @@ function linesToList(value: string) {
|
||||
<div class="checkout-resource-panel panel-action">
|
||||
<div class="checkout-resource-head">
|
||||
<strong>额外消耗品</strong>
|
||||
<span>金额合计:¥{{ money(resourceChargeAmount) }}</span>
|
||||
<span>已用金额:¥{{ money(resourceChargeAmount) }}</span>
|
||||
</div>
|
||||
<el-empty v-if="checkoutResources.length === 0" description="订单快照中暂无额外消耗品" />
|
||||
<div v-for="item in checkoutResources" v-else :key="item.key" class="checkout-resource-row">
|
||||
@@ -573,7 +573,7 @@ function linesToList(value: string) {
|
||||
<el-input-number v-model="checkoutForm.coin_consumed_m" class="full-control" :min="0" :max="snapshotHafCoinM" :precision="2" controls-position="right" />
|
||||
<span class="field-hint">订单快照 {{ quantity(snapshotHafCoinM) }}M,预计剩余 {{ quantity(remainingHafCoinM) }}M</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="其他扣款(元)">
|
||||
<el-form-item label="其他押金扣款(元)">
|
||||
<el-input-number v-model="checkoutForm.other_amount" class="full-control" :min="0" :precision="0" controls-position="right" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -589,10 +589,10 @@ function linesToList(value: string) {
|
||||
|
||||
<div v-if="order && order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="order-panel">
|
||||
<h2>结账明细</h2>
|
||||
<p>{{ orderAmountLabel }}:¥{{ money(order.checkout.display_amount) }},押金:¥{{ money(order.checkout.deposit_amount) }}</p>
|
||||
<p>额外消耗品金额:¥{{ money(order.checkout.consumable_amount) }},押金扣除:¥{{ money(order.checkout.deposit_deduct_amount) }}</p>
|
||||
<p v-if="isRenter">退还租客:¥{{ money(order.checkout.renter_refund_amount) }}</p>
|
||||
<p v-if="isOwner">号主收入:¥{{ money(order.checkout.owner_income_amount) }}</p>
|
||||
<p>实际结算租金:¥{{ money(order.checkout.display_amount) }},预收押金:¥{{ money(order.checkout.deposit_amount) }}</p>
|
||||
<p>额外消耗品已用:¥{{ money(order.checkout.consumable_amount) }},押金赔付扣除:¥{{ money(order.checkout.deposit_deduct_amount) }}</p>
|
||||
<p v-if="isRenter">退还租客(未使用租金 + 剩余押金):¥{{ money(order.checkout.renter_refund_amount) }}</p>
|
||||
<p v-if="isOwner">号主最终收入(租金 + 押金赔付):¥{{ money(order.checkout.owner_income_amount) }}</p>
|
||||
<p v-if="order.checkout.content">说明:{{ order.checkout.content }}</p>
|
||||
<p v-if="order.checkout.owner_adjustment_reason">修正原因:{{ order.checkout.owner_adjustment_reason }}</p>
|
||||
</div>
|
||||
@@ -604,13 +604,13 @@ function linesToList(value: string) {
|
||||
|
||||
<h2 class="panel-action">修改结账</h2>
|
||||
<el-form class="form-grid" label-position="top">
|
||||
<el-form-item label="额外消耗品金额(已含租金)">
|
||||
<el-form-item label="额外消耗品已用金额">
|
||||
<el-input-number v-model="counterForm.consumable_amount" class="full-control" :min="0" :precision="0" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="消耗哈夫币(M)">
|
||||
<el-input-number v-model="counterForm.coin_consumed_m" class="full-control" :min="0" :precision="2" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="其他扣款(元)">
|
||||
<el-form-item label="其他押金扣款(元)">
|
||||
<el-input-number v-model="counterForm.other_amount" class="full-control" :min="0" :precision="0" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="押金扣除(元)">
|
||||
|
||||
@@ -17,8 +17,9 @@ const filters = reactive<AdminListingQuery>({
|
||||
limit: 200,
|
||||
})
|
||||
|
||||
const { loading, data: listings, load: loadListings } = useAdminTable<Listing>({
|
||||
const { loading, data: listings, load: loadListings } = useAdminTable<Listing[]>({
|
||||
fetchFn: () => fetchAdminListings(filters),
|
||||
initialData: [],
|
||||
})
|
||||
|
||||
const publishedCount = computed(() => listings.value.filter((item) => item.status === 'published').length)
|
||||
|
||||
@@ -8,8 +8,9 @@ import { formatDateTime } from '@/utils/time'
|
||||
|
||||
const status = ref('')
|
||||
|
||||
const { loading, data: orders, load: loadOrders } = useAdminTable<Order>({
|
||||
const { loading, data: orders, load: loadOrders } = useAdminTable<Order[]>({
|
||||
fetchFn: fetchAdminOrders,
|
||||
initialData: [],
|
||||
})
|
||||
|
||||
const filteredOrders = computed(() => {
|
||||
|
||||
@@ -792,12 +792,12 @@ function getStatusTagType(status: string) {
|
||||
<section v-if="order.checkout && ['pending_checkout_confirm', 'pending_checkout_accept'].includes(order.status)" class="card-section">
|
||||
<h3 class="section-title">结账结算账单</h3>
|
||||
<van-cell-group inset :border="false">
|
||||
<van-cell :title="orderAmountLabel" :value="`¥${money(order.checkout.display_amount)}`" />
|
||||
<van-cell title="实际结算租金" :value="`¥${money(order.checkout.display_amount)}`" />
|
||||
<van-cell title="押金总额" :value="`¥${money(order.checkout.deposit_amount)}`" />
|
||||
<van-cell title="额外消耗品金额" :value="`¥${money(order.checkout.consumable_amount)}`" />
|
||||
<van-cell title="押金扣除" :value="`¥${money(order.checkout.deposit_deduct_amount)}`" value-class="red-text" />
|
||||
<van-cell v-if="isRenter" title="退还租客押金" :value="`¥${money(order.checkout.renter_refund_amount)}`" value-class="green-text" />
|
||||
<van-cell v-if="isOwner" title="号主最终收益" :value="`¥${money(order.checkout.owner_income_amount)}`" value-class="green-text" />
|
||||
<van-cell title="额外消耗品已用" :value="`¥${money(order.checkout.consumable_amount)}`" />
|
||||
<van-cell title="押金赔付扣除" :value="`¥${money(order.checkout.deposit_deduct_amount)}`" value-class="red-text" />
|
||||
<van-cell v-if="isRenter" title="退还租客" :value="`¥${money(order.checkout.renter_refund_amount)}`" value-class="green-text" />
|
||||
<van-cell v-if="isOwner" title="号主最终收入" :value="`¥${money(order.checkout.owner_income_amount)}`" value-class="green-text" />
|
||||
<van-cell v-if="order.checkout.content" title="结账备注" :label="order.checkout.content" />
|
||||
<van-cell v-if="order.checkout.owner_adjustment_reason" title="号主修正原因" :label="order.checkout.owner_adjustment_reason" />
|
||||
</van-cell-group>
|
||||
@@ -911,9 +911,9 @@ function getStatusTagType(status: string) {
|
||||
<button class="popup-close" @click="showCounterPopup = false">✕</button>
|
||||
</header>
|
||||
<div class="popup-body">
|
||||
<p class="form-hint-info">在此调整扣减租客押金或各项损耗的金额,提案将交由租客二次确认。</p>
|
||||
<p class="form-hint-info">在此调整实际使用的租金项目和押金赔付金额,提案将交由租客二次确认。</p>
|
||||
<van-cell-group :border="false">
|
||||
<van-field label="消耗损耗款">
|
||||
<van-field label="额外消耗品已用">
|
||||
<template #input>
|
||||
<input v-model.number="counterForm.consumable_amount" type="number" class="custom-inline-input" />
|
||||
</template>
|
||||
@@ -923,12 +923,12 @@ function getStatusTagType(status: string) {
|
||||
<input v-model.number="counterForm.coin_consumed_m" type="number" class="custom-inline-input" />
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field label="其他损失扣款">
|
||||
<van-field label="其他押金扣款">
|
||||
<template #input>
|
||||
<input v-model.number="counterForm.other_amount" type="number" class="custom-inline-input" />
|
||||
</template>
|
||||
</van-field>
|
||||
<van-field label="扣除押金总额" required>
|
||||
<van-field label="押金赔付扣除" required>
|
||||
<template #input>
|
||||
<input v-model.number="counterForm.deposit_deduct_amount" type="number" class="custom-inline-input" />
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user