feat(finance): include pickup profit in dashboard
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"`
|
||||
|
||||
Reference in New Issue
Block a user