拆分 service 与前端大文件,修复 CORS 配置与格式问题
- 后端 internal/service 按职责拆分: fulfillment.go(1397→527)拆出 wallet/timeout/data/order/query/dashboard/shipnotify delivery.go(1124→801)拆出 upstream/link/state/helpers merchant.go(855→251)拆出 member/product/api_client/catalog/helpers - 前端 MerchantCenter.tsx(1327→606)拆出 merchantCenterTabs/merchantCenterUtils - docker-compose backend 透传 CORS_ALLOWED_ORIGINS - CORS 白名单实现(config/router/README/.env.example 配套) - 修复 gofmt 与文件尾部多余空行
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user