daShangDao_psiServer/service/statist.go

431 lines
17 KiB
Go

package service
import (
"fmt"
"gorm.io/gorm"
"psi/database"
"psi/models"
systemReq "psi/models/request"
systemRes "psi/models/response"
"psi/utils"
"time"
)
type StatistService struct{}
// DashboardStatist 获取仪表盘统计数据
/*func (s *StatistService) DashboardStatist(req systemReq.DashboardStatistRequest, db ...*gorm.DB) (*systemRes.DashboardStatistResponse, error) {
databaseConn := database.OptionalDB(db...)
now := time.Now()
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()).Unix()
if req.StartDate == 0 {
req.StartDate = startOfDay
}
if req.EndDate == 0 {
req.EndDate = endOfDay
}
statDateStr := now.Format("20060102")
var statDate int64
if _, err := fmt.Sscanf(statDateStr, "%d", &statDate); err != nil {
return s.getDashboardStatRealtime(databaseConn, req.StartDate, req.EndDate)
}
var dashboardStat models.DashboardDailyStat
err := databaseConn.Where("stat_date = ? AND is_del = ?", statDate, 0).First(&dashboardStat).Error
if err != nil {
return s.getDashboardStatRealtime(databaseConn, req.StartDate, req.EndDate)
}
var userStats []systemRes.UserStatItem
var userDailyStats []models.UserDailyStat
if err := databaseConn.Where("stat_date = ? AND is_del = ?", statDate, 0).Find(&userDailyStats).Error; err == nil {
for _, userStat := range userDailyStats {
userStats = append(userStats, systemRes.UserStatItem{
UserID: userStat.UserID,
UserName: userStat.UserName,
ReceivingCount: userStat.ReceivingNum,
OutboundCount: userStat.OutboundNum,
})
}
}
return &systemRes.DashboardStatistResponse{
TotalReceivingCount: dashboardStat.TotalReceivingNum,
TotalOutboundCount: dashboardStat.TotalOutboundNum,
TotalSaleCount: dashboardStat.TodaySalesCount,
UserStats: userStats,
ProductTotal: dashboardStat.ProductTotal,
InventoryTotal: dashboardStat.InventoryTotal,
TodayInbound: dashboardStat.TodayInbound,
TodayOutbound: dashboardStat.TodayOutbound,
YesterdayInbound: dashboardStat.YesterdayInbound,
YesterdayOutbound: dashboardStat.YesterdayOutbound,
}, nil
}*/
// DashboardStatist 获取仪表盘统计数据
/*func (s *StatistService) DashboardStatist(req systemReq.DashboardStatistRequest, db ...*gorm.DB) (*systemRes.DashboardStatistResponse, error) {
databaseConn := database.OptionalDB(db...)
// 计算今日的时间范围(如果未指定)
now := time.Now()
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()).Unix()
if req.StartDate == 0 {
req.StartDate = startOfDay
}
if req.EndDate == 0 {
req.EndDate = endOfDay
}
// 查询今日销售订单总数
var totalSaleCount int64
saleOrderQuery := databaseConn.Model(&models.SalesOrder{}).
Where("created_at >= ? AND created_at <= ? AND is_del = ?", req.StartDate, req.EndDate, 0)
saleOrderQuery.Count(&totalSaleCount)
// 从 statist 表查询总入库和出库次数
var totalReceivingCount, totalOutboundCount int64
statistQuery := databaseConn.Model(&models.Statist{}).
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", req.StartDate, req.EndDate, 0)
var statistList []models.Statist
if err := statistQuery.Find(&statistList).Error; err != nil {
return nil, utils.NewError("查询统计数据失败")
}
if len(statistList) == 0 {
return &systemRes.DashboardStatistResponse{
TotalReceivingCount: 0,
TotalOutboundCount: 0,
TotalSaleCount: totalSaleCount,
UserStats: []systemRes.UserStatItem{},
}, nil
}
for _, stat := range statistList {
totalReceivingCount += stat.ReceivingNum
totalOutboundCount += stat.OutboundNum
}
// 查询个人统计数据
var userStats []systemRes.UserStatItem
// 按用户分组统计
type UserStatGroup struct {
CreateBy int64 `gorm:"column:create_by"`
TotalReceiving int64 `gorm:"column:total_receiving"`
TotalOutbound int64 `gorm:"column:total_outbound"`
}
var userStatGroups []UserStatGroup
databaseConn.Model(&models.Statist{}).
Select("create_by, SUM(receiving_num) as total_receiving, SUM(outbound_num) as total_outbound").
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", req.StartDate, req.EndDate, 0).
Group("create_by").
Scan(&userStatGroups)
// 获取用户信息并构建返回数据
for _, group := range userStatGroups {
var employee models.Employee
if err := database.DB.Where("id = ?", group.CreateBy).First(&employee).Error; err == nil {
userStats = append(userStats, systemRes.UserStatItem{
UserID: employee.ID,
UserName: employee.Username,
ReceivingCount: group.TotalReceiving,
OutboundCount: group.TotalOutbound,
})
}
}
return &systemRes.DashboardStatistResponse{
TotalReceivingCount: totalReceivingCount,
TotalOutboundCount: totalOutboundCount,
TotalSaleCount: totalSaleCount,
UserStats: userStats,
}, nil
}*/
// DashboardStatist 获取仪表盘统计数据
func (s *StatistService) DashboardStatist(req systemReq.DashboardStatistRequest, db ...*gorm.DB) (*systemRes.DashboardStatistResponse, error) {
databaseConn := database.OptionalDB(db...)
now := time.Now()
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()).Unix()
if req.StartDate == 0 {
req.StartDate = startOfDay
}
if req.EndDate == 0 {
req.EndDate = endOfDay
}
statDateStr := now.Format("20060102")
var statDate int64
if _, err := fmt.Sscanf(statDateStr, "%d", &statDate); err != nil {
return s.getDashboardStatRealtime(databaseConn, req.StartDate, req.EndDate)
}
var dashboardStat models.DashboardDailyStat
err := databaseConn.Where("stat_date = ? AND is_del = ?", statDate, 0).First(&dashboardStat).Error
if err != nil {
return s.getDashboardStatRealtime(databaseConn, req.StartDate, req.EndDate)
}
var userStats []systemRes.UserStatItem
var userDailyStats []models.UserDailyStat
if err := databaseConn.Where("stat_date = ? AND is_del = ?", statDate, 0).Find(&userDailyStats).Error; err == nil {
for _, userStat := range userDailyStats {
userStats = append(userStats, systemRes.UserStatItem{
UserID: userStat.UserID,
UserName: userStat.UserName,
ReceivingCount: userStat.ReceivingNum,
OutboundCount: userStat.OutboundNum,
})
}
}
return &systemRes.DashboardStatistResponse{
TotalReceivingCount: dashboardStat.TotalReceivingNum,
TotalOutboundCount: dashboardStat.TotalOutboundNum,
TotalSaleCount: dashboardStat.TodaySalesCount,
UserStats: userStats,
ProductTotal: dashboardStat.ProductTotal,
InventoryTotal: dashboardStat.InventoryTotal,
TodayInbound: dashboardStat.TodayInbound,
TodayOutbound: dashboardStat.TodayOutbound,
YesterdayInbound: dashboardStat.YesterdayInbound,
YesterdayOutbound: dashboardStat.YesterdayOutbound,
}, nil
}
// getDashboardStatRealtime 实时查询仪表盘统计数据(降级方案)
func (s *StatistService) getDashboardStatRealtime(databaseConn *gorm.DB, startDate, endDate int64) (*systemRes.DashboardStatistResponse, error) {
var totalSaleCount int64
saleOrderQuery := databaseConn.Model(&models.SalesOrder{}).
Where("created_at >= ? AND created_at <= ? AND is_del = ?", startDate, endDate, 0)
saleOrderQuery.Count(&totalSaleCount)
var totalReceivingCount, totalOutboundCount int64
statistQuery := databaseConn.Model(&models.Statist{}).
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", startDate, endDate, 0)
var statistList []models.Statist
if err := statistQuery.Find(&statistList).Error; err != nil {
return nil, utils.NewError("查询统计数据失败")
}
if len(statistList) == 0 {
return &systemRes.DashboardStatistResponse{
TotalReceivingCount: 0,
TotalOutboundCount: 0,
TotalSaleCount: totalSaleCount,
UserStats: []systemRes.UserStatItem{},
}, nil
}
for _, stat := range statistList {
totalReceivingCount += stat.ReceivingNum
totalOutboundCount += stat.OutboundNum
}
var userStats []systemRes.UserStatItem
type UserStatGroup struct {
CreateBy int64 `gorm:"column:create_by"`
TotalReceiving int64 `gorm:"column:total_receiving"`
TotalOutbound int64 `gorm:"column:total_outbound"`
}
var userStatGroups []UserStatGroup
databaseConn.Model(&models.Statist{}).
Select("create_by, SUM(receiving_num) as total_receiving, SUM(outbound_num) as total_outbound").
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", startDate, endDate, 0).
Group("create_by").
Scan(&userStatGroups)
for _, group := range userStatGroups {
var employee models.Employee
if err := database.DB.Where("id = ?", group.CreateBy).First(&employee).Error; err == nil {
userStats = append(userStats, systemRes.UserStatItem{
UserID: employee.ID,
UserName: employee.Username,
ReceivingCount: group.TotalReceiving,
OutboundCount: group.TotalOutbound,
})
}
}
var productTotal int64
databaseConn.Model(&models.Product{}).Where("is_del = ?", 0).Count(&productTotal)
var inventoryTotal int64
databaseConn.Model(&models.Inventory{}).Where("is_del = ?", 0).Select("COALESCE(SUM(quantity), 0)").Row().Scan(&inventoryTotal)
now := time.Now()
yesterdayStart := time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, now.Location()).Unix()
yesterdayEnd := time.Date(now.Year(), now.Month(), now.Day()-1, 23, 59, 59, 0, now.Location()).Unix()
var todayInbound, todayOutbound, yesterdayInbound, yesterdayOutbound int64
databaseConn.Model(&models.Statist{}).
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", startDate, endDate, 0).
Select("COALESCE(SUM(receiving_num), 0), COALESCE(SUM(outbound_num), 0)").
Row().Scan(&todayInbound, &todayOutbound)
databaseConn.Model(&models.Statist{}).
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", yesterdayStart, yesterdayEnd, 0).
Select("COALESCE(SUM(receiving_num), 0), COALESCE(SUM(outbound_num), 0)").
Row().Scan(&yesterdayInbound, &yesterdayOutbound)
return &systemRes.DashboardStatistResponse{
TotalReceivingCount: totalReceivingCount,
TotalOutboundCount: totalOutboundCount,
TotalSaleCount: totalSaleCount,
UserStats: userStats,
ProductTotal: productTotal,
InventoryTotal: inventoryTotal,
TodayInbound: todayInbound,
TodayOutbound: todayOutbound,
YesterdayInbound: yesterdayInbound,
YesterdayOutbound: yesterdayOutbound,
}, nil
}
// GetWarehouseStatist 获取仓库统计数据
func (s *StatistService) GetWarehouseStatist(req systemReq.WarehouseStatistRequest, db ...*gorm.DB) (*systemRes.WarehouseStatistResponse, error) {
databaseConn := database.OptionalDB(db...)
now := time.Now()
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()).Unix()
yesterdayStart := time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, now.Location()).Unix()
yesterdayEnd := time.Date(now.Year(), now.Month(), now.Day()-1, 23, 59, 59, 0, now.Location()).Unix()
if req.StartDate == 0 {
req.StartDate = startOfDay
}
if req.EndDate == 0 {
req.EndDate = endOfDay
}
type WarehouseStat struct {
ProductTotal int64 `gorm:"column:product_total"`
InventoryTotal int64 `gorm:"column:inventory_total"`
}
var warehouseStat WarehouseStat
databaseConn.Table("(?) as p", databaseConn.Model(&models.Product{}).Where("is_del = ?", 0).Select("COUNT(*) as product_total")).
Select(`
p.product_total,
COALESCE((SELECT SUM(quantity) FROM inventory WHERE is_del = ?), 0) as inventory_total
`, 0).
Scan(&warehouseStat)
type DailyStat struct {
TodayInbound int64 `gorm:"column:today_inbound"`
TodayOutbound int64 `gorm:"column:today_outbound"`
YesterdayInbound int64 `gorm:"column:yesterday_inbound"`
YesterdayOutbound int64 `gorm:"column:yesterday_outbound"`
}
var dailyStat DailyStat
databaseConn.Model(&models.Statist{}).
Select(`
COALESCE(SUM(CASE WHEN stat_date >= ? AND stat_date <= ? THEN receiving_num ELSE 0 END), 0) as today_inbound,
COALESCE(SUM(CASE WHEN stat_date >= ? AND stat_date <= ? THEN outbound_num ELSE 0 END), 0) as today_outbound,
COALESCE(SUM(CASE WHEN stat_date >= ? AND stat_date <= ? THEN receiving_num ELSE 0 END), 0) as yesterday_inbound,
COALESCE(SUM(CASE WHEN stat_date >= ? AND stat_date <= ? THEN outbound_num ELSE 0 END), 0) as yesterday_outbound
`, req.StartDate, req.EndDate, req.StartDate, req.EndDate, yesterdayStart, yesterdayEnd, yesterdayStart, yesterdayEnd).
Where("is_del = ?", 0).
Scan(&dailyStat)
return &systemRes.WarehouseStatistResponse{
ProductTotal: warehouseStat.ProductTotal,
InventoryTotal: warehouseStat.InventoryTotal,
TodayInbound: dailyStat.TodayInbound,
TodayOutbound: dailyStat.TodayOutbound,
YesterdayInbound: dailyStat.YesterdayInbound,
YesterdayOutbound: dailyStat.YesterdayOutbound,
}, nil
}
// GetOrderStatist 获取订单统计数据
func (s *StatistService) GetOrderStatist(req systemReq.OrderStatistRequest, db ...*gorm.DB) (*systemRes.OrderStatistResponse, error) {
databaseConn := database.OptionalDB(db...)
now := time.Now()
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()).Unix()
yesterdayStart := time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, now.Location()).Unix()
yesterdayEnd := time.Date(now.Year(), now.Month(), now.Day()-1, 23, 59, 59, 0, now.Location()).Unix()
if req.StartDate == 0 {
req.StartDate = startOfDay
}
if req.EndDate == 0 {
req.EndDate = endOfDay
}
const (
StatusDraft = 1
StatusConfirmed = 2
StatusShipped = 5
StatusCancelled = 6
)
type OrderDailyStat struct {
TodayQuantity int64 `gorm:"column:today_quantity"`
TodayAmount int64 `gorm:"column:today_amount"`
TodayShipped int64 `gorm:"column:today_shipped"`
TodayUnshipped int64 `gorm:"column:today_unshipped"`
TodayPending int64 `gorm:"column:today_pending"`
YesterdayQuantity int64 `gorm:"column:yesterday_quantity"`
YesterdayAmount int64 `gorm:"column:yesterday_amount"`
YesterdayShipped int64 `gorm:"column:yesterday_shipped"`
YesterdayUnshipped int64 `gorm:"column:yesterday_unshipped"`
YesterdayPending int64 `gorm:"column:yesterday_pending"`
}
var orderStat OrderDailyStat
databaseConn.Model(&models.SalesOrder{}).
Select(`
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN 1 ELSE 0 END), 0) as today_quantity,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN total_amount ELSE 0 END), 0) as today_amount,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? AND status = ? THEN 1 ELSE 0 END), 0) as today_shipped,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? AND status NOT IN (?, ?) THEN 1 ELSE 0 END), 0) as today_unshipped,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? AND status IN (?, ?) THEN 1 ELSE 0 END), 0) as today_pending,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN 1 ELSE 0 END), 0) as yesterday_quantity,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? THEN total_amount ELSE 0 END), 0) as yesterday_amount,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? AND status = ? THEN 1 ELSE 0 END), 0) as yesterday_shipped,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? AND status NOT IN (?, ?) THEN 1 ELSE 0 END), 0) as yesterday_unshipped,
COALESCE(SUM(CASE WHEN created_at >= ? AND created_at <= ? AND status IN (?, ?) THEN 1 ELSE 0 END), 0) as yesterday_pending
`, req.StartDate, req.EndDate, req.StartDate, req.EndDate, req.StartDate, req.EndDate, StatusShipped, req.StartDate, req.EndDate, StatusShipped, StatusCancelled, req.StartDate, req.EndDate, StatusDraft, StatusConfirmed,
yesterdayStart, yesterdayEnd, yesterdayStart, yesterdayEnd, yesterdayStart, yesterdayEnd, StatusShipped, yesterdayStart, yesterdayEnd, StatusShipped, StatusCancelled, yesterdayStart, yesterdayEnd, StatusDraft, StatusConfirmed).
Where("is_del = ?", 0).
Scan(&orderStat)
return &systemRes.OrderStatistResponse{
Today: systemRes.OrderStatItem{
Quantity: orderStat.TodayQuantity,
Amount: orderStat.TodayAmount,
Shipped: orderStat.TodayShipped,
Unshipped: orderStat.TodayUnshipped,
Pending: orderStat.TodayPending,
},
Yesterday: systemRes.OrderStatItem{
Quantity: orderStat.YesterdayQuantity,
Amount: orderStat.YesterdayAmount,
Shipped: orderStat.YesterdayShipped,
Unshipped: orderStat.YesterdayUnshipped,
Pending: orderStat.YesterdayPending,
},
}, nil
}