From 211b9f012aa6c5aa007e3321c2089b3d51c54f10 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sun, 9 Aug 2026 20:36:19 +0800 Subject: [PATCH] feat(finance): include pickup profit in dashboard --- .../modules/adminfinance/dashboard.go | 66 +++++++++++++++++-- backend/internal/modules/adminfinance/dto.go | 21 ++++-- .../src/features/admin/api/adminFinance.ts | 16 +++++ .../admin/views/AdminFinanceDashboardView.vue | 46 +++++++++++-- 4 files changed, 136 insertions(+), 13 deletions(-) diff --git a/backend/internal/modules/adminfinance/dashboard.go b/backend/internal/modules/adminfinance/dashboard.go index 71089de..fbf4853 100644 --- a/backend/internal/modules/adminfinance/dashboard.go +++ b/backend/internal/modules/adminfinance/dashboard.go @@ -11,11 +11,15 @@ func (r *Repository) Dashboard(ctx context.Context, query DashboardQuery) (*Dash if err != nil { return nil, err } - summary, err := r.summary(ctx, query) + pickup, err := r.pickupSummary(ctx, query) if err != nil { return nil, err } - pickup, err := r.pickupSummary(ctx, query) + summary, err := r.summary(ctx, query, pickup) + if err != nil { + return nil, err + } + mohong, err := r.mohongSummary(ctx, query) if err != nil { return nil, err } @@ -27,6 +31,7 @@ func (r *Repository) Dashboard(ctx context.Context, query DashboardQuery) (*Dash Summary: *summary, DailyItems: dailyItems, PickupSummary: *pickup, + MohongSummary: *mohong, DisbursementSummary: *disbursement, GeneratedAt: timeutil.ShanghaiNow(), }, nil @@ -59,7 +64,31 @@ func (r *Repository) pickupSummary(ctx context.Context, query DashboardQuery) (* }, nil } -func (r *Repository) summary(ctx context.Context, query DashboardQuery) (*FinanceSummaryDTO, error) { +// mohongSummary 撞车商城按支付订单统计交易流水,不计入平台利润。 +func (r *Repository) mohongSummary(ctx context.Context, query DashboardQuery) (*MohongSummaryDTO, error) { + db := r.db.WithContext(ctx) + var row struct { + FlowAmountCent int64 + RefundAmountCent int64 + PaidOrderCount int64 + } + if err := db.Table("payment_orders"). + Select(`COALESCE(SUM(CASE WHEN biz_type = 'mohong_pay' AND status = 'paid' THEN amount_cent ELSE 0 END), 0) AS flow_amount_cent, + COALESCE(SUM(CASE WHEN biz_type = 'mohong_refund' AND status = 'refunded' THEN amount_cent ELSE 0 END), 0) AS refund_amount_cent, + COALESCE(SUM(CASE WHEN biz_type = 'mohong_pay' AND status = 'paid' THEN 1 ELSE 0 END), 0) AS paid_order_count`). + Where("created_at >= ? AND created_at <= ?", query.StartDate, query.EndDate). + Scan(&row).Error; err != nil { + return nil, err + } + return &MohongSummaryDTO{ + FlowAmountCent: row.FlowAmountCent, + RefundAmountCent: row.RefundAmountCent, + NetAmountCent: row.FlowAmountCent - row.RefundAmountCent, + PaidOrderCount: row.PaidOrderCount, + }, nil +} + +func (r *Repository) summary(ctx context.Context, query DashboardQuery, pickup *PickupSummaryDTO) (*FinanceSummaryDTO, error) { db := r.db.WithContext(ctx) var payment paymentSummaryRow if err := db.Table("payment_orders AS po"). @@ -138,12 +167,18 @@ func (r *Repository) summary(ctx context.Context, query DashboardQuery) (*Financ return nil, err } + pickupProfitAmountCent := int64(0) + if pickup != nil { + pickupProfitAmountCent = pickup.ProfitAmountCent + } return &FinanceSummaryDTO{ TotalFlowAmountCent: payment.TotalFlowAmountCent, TotalRefundAmountCent: payment.TotalRefundAmountCent, PendingRefundAmountCent: payment.PendingRefundAmountCent, ChannelNetAmountCent: payment.TotalFlowAmountCent - payment.TotalRefundAmountCent, - PlatformIncomeAmountCent: settlement.PlatformIncomeAmountCent, + PlatformIncomeAmountCent: settlement.PlatformIncomeAmountCent + pickupProfitAmountCent, + NormalOrderProfitAmountCent: settlement.PlatformIncomeAmountCent, + PickupProfitAmountCent: pickupProfitAmountCent, OwnerShouldIncomeAmountCent: settlement.OwnerShouldIncomeAmountCent, OwnerWalletIncomeAmountCent: settlement.OwnerWalletIncomeAmountCent, OwnerEffectiveSettlementAmountCent: settlement.OwnerEffectiveSettlementAmountCent, @@ -222,6 +257,17 @@ func (r *Repository) dailyItems(ctx context.Context, query DashboardQuery) ([]Fi return nil, err } + pickupProfits := make([]dailyPickupProfitRow, 0) + if err := db.Table("admin_pickups"). + Select(`DATE(completed_at) AS date, + COALESCE(SUM(profit_amount_cent), 0) AS profit_amount_cent`). + Where("status = ?", "completed"). + Where("completed_at >= ? AND completed_at <= ?", query.StartDate, query.EndDate). + Group("DATE(completed_at)"). + Scan(&pickupProfits).Error; err != nil { + return nil, err + } + // 每日预计收入:尚未结算订单的下单预估平台手续费,按下单日期归集,口径与 summary 一致。 estimates := make([]dailyEstimatedRow, 0) if err := db.Table("rental_orders"). @@ -275,6 +321,13 @@ func (r *Repository) dailyItems(ctx context.Context, query DashboardQuery) ([]Fi item.OfflineSettlementPendingCount = row.OfflineSettlementPendingCount itemsByDate[date] = item } + for _, row := range pickupProfits { + date := dailyDateKey(row.Date) + item := itemsByDate[date] + item.Date = date + item.PlatformIncomeAmountCent += row.ProfitAmountCent + itemsByDate[date] = item + } for _, row := range estimates { date := dailyDateKey(row.Date) item := itemsByDate[date] @@ -353,6 +406,11 @@ type dailySettlementRow struct { SettledOrderCount int64 } +type dailyPickupProfitRow struct { + Date string + ProfitAmountCent int64 +} + type dailyEstimatedRow struct { Date string EstimatedIncomeAmountCent int64 diff --git a/backend/internal/modules/adminfinance/dto.go b/backend/internal/modules/adminfinance/dto.go index 1fec921..cb296ba 100644 --- a/backend/internal/modules/adminfinance/dto.go +++ b/backend/internal/modules/adminfinance/dto.go @@ -38,6 +38,7 @@ type DashboardDTO struct { Summary FinanceSummaryDTO `json:"summary"` DailyItems []FinanceDailyDTO `json:"daily_items"` PickupSummary PickupSummaryDTO `json:"pickup_summary"` + MohongSummary MohongSummaryDTO `json:"mohong_summary"` DisbursementSummary DisbursementSummaryDTO `json:"disbursement_summary"` GeneratedAt time.Time `json:"generated_at"` } @@ -50,6 +51,14 @@ type PickupSummaryDTO struct { InProgressCount int64 `json:"in_progress_count"` // 当前提号中笔数(不按时间) } +// MohongSummaryDTO 撞车商城的交易流水,单独展示,不计入平台利润。 +type MohongSummaryDTO struct { + FlowAmountCent int64 `json:"flow_amount_cent"` + RefundAmountCent int64 `json:"refund_amount_cent"` + NetAmountCent int64 `json:"net_amount_cent"` + PaidOrderCount int64 `json:"paid_order_count"` +} + // DisbursementSummaryDTO 统计平台实际线下出款及当前待处理金额。 // 已打款按确认打款时间归入查询区间,待处理不受日期范围限制,反映当前资金待办。 type DisbursementSummaryDTO struct { @@ -158,11 +167,15 @@ type ManualDisbursementDTO struct { } type FinanceSummaryDTO struct { - TotalFlowAmountCent int64 `json:"total_flow_amount_cent"` - TotalRefundAmountCent int64 `json:"total_refund_amount_cent"` - PendingRefundAmountCent int64 `json:"pending_refund_amount_cent"` - ChannelNetAmountCent int64 `json:"channel_net_amount_cent"` + TotalFlowAmountCent int64 `json:"total_flow_amount_cent"` + TotalRefundAmountCent int64 `json:"total_refund_amount_cent"` + PendingRefundAmountCent int64 `json:"pending_refund_amount_cent"` + ChannelNetAmountCent int64 `json:"channel_net_amount_cent"` + // PlatformIncomeAmountCent 为正常订单最终结账利润与已完成线下提号利润之和。 + // 保留原 JSON 字段名,避免影响已接入的管理端客户端。 PlatformIncomeAmountCent int64 `json:"platform_income_amount_cent"` + NormalOrderProfitAmountCent int64 `json:"normal_order_profit_amount_cent"` + PickupProfitAmountCent int64 `json:"pickup_profit_amount_cent"` OwnerShouldIncomeAmountCent int64 `json:"owner_should_income_amount_cent"` OwnerWalletIncomeAmountCent int64 `json:"owner_wallet_income_amount_cent"` OwnerEffectiveSettlementAmountCent int64 `json:"owner_effective_settlement_amount_cent"` diff --git a/frontend/src/features/admin/api/adminFinance.ts b/frontend/src/features/admin/api/adminFinance.ts index d801902..bcada81 100644 --- a/frontend/src/features/admin/api/adminFinance.ts +++ b/frontend/src/features/admin/api/adminFinance.ts @@ -11,6 +11,8 @@ export interface FinanceSummary { pending_refund_amount_cent: number channel_net_amount_cent: number platform_income_amount_cent: number + normal_order_profit_amount_cent: number + pickup_profit_amount_cent: number owner_should_income_amount_cent: number owner_wallet_income_amount_cent: number owner_effective_settlement_amount_cent: number @@ -67,6 +69,13 @@ export interface FinancePickupSummary { in_progress_count: number } +export interface FinanceMohongSummary { + flow_amount_cent: number + refund_amount_cent: number + net_amount_cent: number + paid_order_count: number +} + export interface FinanceDisbursementSummary { paid_amount_cent: number paid_count: number @@ -183,6 +192,7 @@ export interface FinanceDashboard { summary: FinanceSummary daily_items: FinanceDailyItem[] pickup_summary: FinancePickupSummary + mohong_summary: FinanceMohongSummary disbursement_summary: FinanceDisbursementSummary generated_at: string } @@ -260,6 +270,12 @@ export async function fetchFinanceDashboard(query: FinanceDateQuery = {}) { completed_count: 0, in_progress_count: 0, }, + mohong_summary: data.data?.mohong_summary ?? { + flow_amount_cent: 0, + refund_amount_cent: 0, + net_amount_cent: 0, + paid_order_count: 0, + }, disbursement_summary: data.data?.disbursement_summary ?? { paid_amount_cent: 0, paid_count: 0, diff --git a/frontend/src/features/admin/views/AdminFinanceDashboardView.vue b/frontend/src/features/admin/views/AdminFinanceDashboardView.vue index 5f00aac..7887f86 100644 --- a/frontend/src/features/admin/views/AdminFinanceDashboardView.vue +++ b/frontend/src/features/admin/views/AdminFinanceDashboardView.vue @@ -66,7 +66,7 @@ function rowOfflinePendingClass(row: FinanceDailyItem) {
成功收款 - 成功退款
- 平台收入 + 平台利润 {{ moneyCent(dashboard.summary.platform_income_amount_cent) }} - {{ dashboard.summary.settled_order_count }} 个已结算订单 + + 普通订单 {{ moneyCent(dashboard.summary.normal_order_profit_amount_cent) }} + 线下提号 + {{ moneyCent(dashboard.summary.pickup_profit_amount_cent) }} +
号主应得 @@ -142,12 +145,37 @@ function rowOfflinePendingClass(row: FinanceDailyItem) { {{ dashboard.summary.financial_exception_count }} 个异常订单
- 预计收入 + 预计利润 {{ moneyCent(dashboard.summary.estimated_income_amount_cent) }} {{ dashboard.summary.pending_settle_order_count }} 个待结算订单
+
+
+

撞车商城

+

商城交易流水单独统计,不计入平台利润。

+
+
+ +
+
+ 商城成交额 + {{ moneyCent(dashboard.mohong_summary.flow_amount_cent) }} + {{ dashboard.mohong_summary.paid_order_count }} 笔成功订单 +
+
+ 商城退款 + {{ moneyCent(dashboard.mohong_summary.refund_amount_cent) }} + 已完成退款 +
+
+ 商城渠道净流入 + {{ moneyCent(dashboard.mohong_summary.net_amount_cent) }} + 成交额 - 已退款 +
+
+

资金出款

@@ -241,7 +269,7 @@ function rowOfflinePendingClass(row: FinanceDailyItem) { - + @@ -322,6 +350,10 @@ function rowOfflinePendingClass(row: FinanceDailyItem) { margin-top: 12px; } +.mohong-grid { + margin-bottom: 20px; +} + .section-heading { display: flex; align-items: flex-end; @@ -362,6 +394,10 @@ function rowOfflinePendingClass(row: FinanceDailyItem) { border-left: 3px solid #6366f1; } +.mohong-card { + border-left: 3px solid #2563eb; +} + .generated-at { margin: 12px 0 0; color: #64748b;