package service import ( "time" "affiliate_dash/internal/model" "affiliate_dash/internal/pkg/timeutil" "gorm.io/gorm" ) type DashboardStats struct { Scope string `json:"scope"` CatalogProductCount int64 `json:"catalog_product_count"` ProductCount int64 `json:"product_count"` ActiveProductCount int64 `json:"active_product_count"` MerchantCount int64 `json:"merchant_count"` ActiveMerchantCount int64 `json:"active_merchant_count"` UserCount int64 `json:"user_count"` OrderCount int64 `json:"order_count"` TodayOrderCount int64 `json:"today_order_count"` TotalSales int64 `json:"total_sales"` TodaySales int64 `json:"today_sales"` TotalFees int64 `json:"total_fees"` TodayFees int64 `json:"today_fees"` PaidOrderCount int64 `json:"paid_order_count"` DeliveringOrderCount int64 `json:"delivering_order_count"` DeliveredOrderCount int64 `json:"delivered_order_count"` ShipFailedOrderCount int64 `json:"ship_failed_order_count"` CancelledOrderCount int64 `json:"cancelled_order_count"` WalletAvailableBalance int64 `json:"wallet_available_balance"` WalletFrozenBalance int64 `json:"wallet_frozen_balance"` APIClientCount int64 `json:"api_client_count"` ActiveAPIClientCount int64 `json:"active_api_client_count"` CallbackSubscriptionCount int64 `json:"callback_subscription_count"` PendingCallbackCount int64 `json:"pending_callback_count"` FailedCallbackCount int64 `json:"failed_callback_count"` } type dashboardStatusCount struct { Status string Count int64 } // Dashboard 按角色汇总运营指标:平台管理员看全平台,商户账号看当前商户。 func (s *FulfillmentService) Dashboard(merchantID uint, isPlatformAdmin bool) (*DashboardStats, error) { stats := &DashboardStats{Scope: "merchant"} if isPlatformAdmin { stats.Scope = "platform" } todayStart := timeutil.StartOfDay(time.Now()) productScope := func() *gorm.DB { tx := s.db.Model(&model.MerchantProduct{}) if !isPlatformAdmin { tx = tx.Where("merchant_id = ?", merchantID) } return tx } orderScope := func() *gorm.DB { tx := s.db.Model(&model.FulfillmentOrder{}) if !isPlatformAdmin { tx = tx.Where("merchant_id = ?", merchantID) } return tx } walletScope := func() *gorm.DB { tx := s.db.Model(&model.WalletAccount{}) if !isPlatformAdmin { tx = tx.Where("merchant_id = ?", merchantID) } return tx } apiClientScope := func() *gorm.DB { tx := s.db.Model(&model.APIClient{}) if !isPlatformAdmin { tx = tx.Where("merchant_id = ?", merchantID) } return tx } callbackScope := func() *gorm.DB { tx := s.db.Model(&model.CallbackSubscription{}) if !isPlatformAdmin { tx = tx.Where("merchant_id = ?", merchantID) } return tx } callbackDeliveryScope := func() *gorm.DB { tx := s.db.Model(&model.CallbackDelivery{}) if !isPlatformAdmin { tx = tx.Where("merchant_id = ?", merchantID) } return tx } if err := s.db.Model(&model.Product{}).Count(&stats.CatalogProductCount).Error; err != nil { return nil, err } if err := productScope().Count(&stats.ProductCount).Error; err != nil { return nil, err } if err := productScope().Where("status = ?", model.ProductStatusActive).Count(&stats.ActiveProductCount).Error; err != nil { return nil, err } if isPlatformAdmin { if err := s.db.Model(&model.Merchant{}).Count(&stats.MerchantCount).Error; err != nil { return nil, err } if err := s.db.Model(&model.Merchant{}).Where("status = ?", model.MerchantStatusActive).Count(&stats.ActiveMerchantCount).Error; err != nil { return nil, err } if err := s.db.Model(&model.User{}).Count(&stats.UserCount).Error; err != nil { return nil, err } } else { if err := s.db.Model(&model.Merchant{}).Where("id = ?", merchantID).Count(&stats.MerchantCount).Error; err != nil { return nil, err } if err := s.db.Model(&model.Merchant{}).Where("id = ? AND status = ?", merchantID, model.MerchantStatusActive).Count(&stats.ActiveMerchantCount).Error; err != nil { return nil, err } if err := s.db.Model(&model.User{}). Joins("JOIN merchant_members ON merchant_members.user_id = users.id"). Where("merchant_members.merchant_id = ?", merchantID). Count(&stats.UserCount).Error; err != nil { return nil, err } stats.CatalogProductCount = stats.ProductCount } if err := orderScope().Count(&stats.OrderCount).Error; err != nil { return nil, err } if err := orderScope().Where("created_at >= ?", todayStart).Count(&stats.TodayOrderCount).Error; err != nil { return nil, err } if err := orderScope().Where("order_status <> ?", model.OrderStatusCancelled). Select("COALESCE(SUM(amount),0)").Scan(&stats.TotalSales).Error; err != nil { return nil, err } if err := orderScope().Where("order_status <> ?", model.OrderStatusCancelled). Where("created_at >= ?", todayStart). Select("COALESCE(SUM(amount),0)").Scan(&stats.TodaySales).Error; err != nil { return nil, err } if err := orderScope().Where("order_status <> ?", model.OrderStatusCancelled). Select("COALESCE(SUM(service_fee_amount),0)").Scan(&stats.TotalFees).Error; err != nil { return nil, err } if err := orderScope().Where("order_status <> ?", model.OrderStatusCancelled). Where("created_at >= ?", todayStart). Select("COALESCE(SUM(service_fee_amount),0)").Scan(&stats.TodayFees).Error; err != nil { return nil, err } var orderStatusCounts []dashboardStatusCount if err := orderScope().Select("order_status AS status, COUNT(*) AS count"). Group("order_status").Scan(&orderStatusCounts).Error; err != nil { return nil, err } for _, item := range orderStatusCounts { switch item.Status { case model.OrderStatusPaid: stats.PaidOrderCount = item.Count case model.OrderStatusDelivering: stats.DeliveringOrderCount = item.Count case model.OrderStatusDelivered: stats.DeliveredOrderCount = item.Count case model.OrderStatusShipFailed: stats.ShipFailedOrderCount = item.Count case model.OrderStatusCancelled: stats.CancelledOrderCount = item.Count } } if err := walletScope().Select("COALESCE(SUM(available_balance),0)").Scan(&stats.WalletAvailableBalance).Error; err != nil { return nil, err } if err := walletScope().Select("COALESCE(SUM(frozen_balance),0)").Scan(&stats.WalletFrozenBalance).Error; err != nil { return nil, err } if err := apiClientScope().Count(&stats.APIClientCount).Error; err != nil { return nil, err } if err := apiClientScope().Where("status = ?", model.APIClientStatusActive).Count(&stats.ActiveAPIClientCount).Error; err != nil { return nil, err } if err := callbackScope().Count(&stats.CallbackSubscriptionCount).Error; err != nil { return nil, err } if err := callbackDeliveryScope().Where("status = ?", model.CallbackDeliveryPending).Count(&stats.PendingCallbackCount).Error; err != nil { return nil, err } if err := callbackDeliveryScope().Where("status = ?", model.CallbackDeliveryFailed).Count(&stats.FailedCallbackCount).Error; err != nil { return nil, err } return stats, nil }