260 lines
8.5 KiB
Go
260 lines
8.5 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"gorm.io/gorm"
|
|
"psi/database"
|
|
"psi/models"
|
|
"psi/utils"
|
|
"time"
|
|
)
|
|
|
|
type StatistTaskService struct{}
|
|
|
|
// GenerateDailyStat 生成每日统计数据(定时任务调用)
|
|
// GenerateDailyStat 生成每日统计数据(定时任务调用)
|
|
// GenerateDailyStat 生成每日统计数据(定时任务调用)
|
|
func (s *StatistTaskService) GenerateDailyStat(db ...*gorm.DB) error {
|
|
now := time.Now()
|
|
|
|
yesterday := now.AddDate(0, 0, -1)
|
|
statDateStr := yesterday.Format("20060102")
|
|
var statDate int64
|
|
if _, err := fmt.Sscanf(statDateStr, "%d", &statDate); err != nil {
|
|
return fmt.Errorf("日期格式化失败: %v", err)
|
|
}
|
|
|
|
yesterdayStart := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, yesterday.Location()).Unix()
|
|
yesterdayEnd := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 23, 59, 59, 0, yesterday.Location()).Unix()
|
|
|
|
mainDB := database.DB
|
|
if len(db) > 0 && db[0] != nil {
|
|
mainDB = db[0]
|
|
}
|
|
|
|
var aboutIDs []int64
|
|
if err := mainDB.Model(&models.Employee{}).Where("deleted_at = ?", 0).Distinct().Pluck("about_id", &aboutIDs).Error; err != nil {
|
|
return fmt.Errorf("查询租户列表失败: %v", err)
|
|
}
|
|
|
|
if len(aboutIDs) == 0 {
|
|
utils.InfoLog("work", map[string]interface{}{
|
|
"source": "定时任务-生成每日统计",
|
|
"stat_date": statDate,
|
|
"message": "没有找到任何租户",
|
|
})
|
|
return nil
|
|
}
|
|
|
|
for _, aboutID := range aboutIDs {
|
|
if aboutID == 0 {
|
|
continue
|
|
}
|
|
|
|
tenantDB, err := database.GetTenantDB(aboutID)
|
|
if err != nil {
|
|
utils.ErrorLog("work", map[string]interface{}{
|
|
"source": "定时任务-生成每日统计",
|
|
"about_id": aboutID,
|
|
"error": fmt.Sprintf("获取租户数据库失败: %v", err),
|
|
})
|
|
continue
|
|
}
|
|
|
|
tx := tenantDB.Begin()
|
|
func() {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
tx.Rollback()
|
|
}
|
|
}()
|
|
|
|
_, err := s.generateDashboardDailyStat(tx, statDate, yesterdayStart, yesterdayEnd)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
utils.ErrorLog("work", map[string]interface{}{
|
|
"source": "定时任务-生成每日统计",
|
|
"about_id": aboutID,
|
|
"stat_date": statDate,
|
|
"error": fmt.Sprintf("生成全局统计失败: %v", err),
|
|
})
|
|
return
|
|
}
|
|
|
|
if err := s.generateUserDailyStat(tx, aboutID, statDate, yesterdayStart, yesterdayEnd); err != nil {
|
|
tx.Rollback()
|
|
utils.ErrorLog("work", map[string]interface{}{
|
|
"source": "定时任务-生成每日统计",
|
|
"about_id": aboutID,
|
|
"stat_date": statDate,
|
|
"error": fmt.Sprintf("生成用户统计失败: %v", err),
|
|
})
|
|
return
|
|
}
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
utils.ErrorLog("work", map[string]interface{}{
|
|
"source": "定时任务-生成每日统计",
|
|
"about_id": aboutID,
|
|
"stat_date": statDate,
|
|
"error": fmt.Sprintf("提交事务失败: %v", err),
|
|
})
|
|
return
|
|
}
|
|
|
|
utils.InfoLog("work", map[string]interface{}{
|
|
"source": "定时任务-生成每日统计",
|
|
"about_id": aboutID,
|
|
"stat_date": statDate,
|
|
"message": fmt.Sprintf("成功生成%s的统计数据", yesterday.Format("2006-01-02")),
|
|
})
|
|
}()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// generateDashboardDailyStat 生成全局每日统计
|
|
func (s *StatistTaskService) generateDashboardDailyStat(tx *gorm.DB, statDate int64, startDate, endDate int64) (*models.DashboardDailyStat, error) {
|
|
var existingStat models.DashboardDailyStat
|
|
err := tx.Where("stat_date = ? AND is_del = ?", statDate, 0).First(&existingStat).Error
|
|
|
|
if err == nil {
|
|
if err := tx.Model(&models.DashboardDailyStat{}).Where("id = ?", existingStat.ID).Update("is_del", 1).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
var totalReceivingNum, totalOutboundNum int64
|
|
tx.Model(&models.Statist{}).
|
|
Where("stat_date <= ? AND is_del = ?", endDate, 0).
|
|
Select("COALESCE(SUM(receiving_num), 0), COALESCE(SUM(outbound_num), 0)").
|
|
Row().Scan(&totalReceivingNum, &totalOutboundNum)
|
|
|
|
var todayInbound, todayOutbound int64
|
|
tx.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)
|
|
|
|
beforeYesterdayStart := time.Date(time.Unix(startDate, 0).Year(), time.Unix(startDate, 0).Month(), time.Unix(startDate, 0).Day()-1, 0, 0, 0, 0, time.Unix(startDate, 0).Location()).Unix()
|
|
beforeYesterdayEnd := time.Date(time.Unix(startDate, 0).Year(), time.Unix(startDate, 0).Month(), time.Unix(startDate, 0).Day()-1, 23, 59, 59, 0, time.Unix(startDate, 0).Location()).Unix()
|
|
var yesterdayInbound, yesterdayOutbound int64
|
|
tx.Model(&models.Statist{}).
|
|
Where("stat_date >= ? AND stat_date <= ? AND is_del = ?", beforeYesterdayStart, beforeYesterdayEnd, 0).
|
|
Select("COALESCE(SUM(receiving_num), 0), COALESCE(SUM(outbound_num), 0)").
|
|
Row().Scan(&yesterdayInbound, &yesterdayOutbound)
|
|
|
|
var totalSalesCount int64
|
|
tx.Model(&models.SalesOrder{}).
|
|
Where("created_at <= ? AND is_del = ?", endDate, 0).
|
|
Count(&totalSalesCount)
|
|
|
|
var todaySalesCount int64
|
|
tx.Model(&models.SalesOrder{}).
|
|
Where("created_at >= ? AND created_at <= ? AND is_del = ?", startDate, endDate, 0).
|
|
Count(&todaySalesCount)
|
|
|
|
var yesterdaySalesCount int64
|
|
tx.Model(&models.SalesOrder{}).
|
|
Where("created_at >= ? AND created_at <= ? AND is_del = ?", beforeYesterdayStart, beforeYesterdayEnd, 0).
|
|
Count(&yesterdaySalesCount)
|
|
|
|
var productTotal int64
|
|
tx.Model(&models.Product{}).
|
|
Where("is_del = ?", 0).
|
|
Count(&productTotal)
|
|
|
|
var inventoryTotal int64
|
|
tx.Model(&models.Inventory{}).
|
|
Where("is_del = ?", 0).
|
|
Select("COALESCE(SUM(quantity), 0)").
|
|
Row().Scan(&inventoryTotal)
|
|
|
|
now := time.Now().Unix()
|
|
dashboardStat := &models.DashboardDailyStat{
|
|
StatDate: statDate,
|
|
TotalReceivingNum: totalReceivingNum,
|
|
TotalOutboundNum: totalOutboundNum,
|
|
TotalSalesCount: totalSalesCount,
|
|
ProductTotal: productTotal,
|
|
InventoryTotal: inventoryTotal,
|
|
TodayInbound: todayInbound,
|
|
TodayOutbound: todayOutbound,
|
|
YesterdayInbound: yesterdayInbound,
|
|
YesterdayOutbound: yesterdayOutbound,
|
|
TodaySalesCount: todaySalesCount,
|
|
YesterdaySalesCount: yesterdaySalesCount,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
IsDel: 0,
|
|
}
|
|
|
|
if err := tx.Create(dashboardStat).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return dashboardStat, nil
|
|
}
|
|
|
|
// generateUserDailyStat 生成用户每日统计
|
|
func (s *StatistTaskService) generateUserDailyStat(tx *gorm.DB, aboutID int64, statDate int64, startDate, endDate int64) error {
|
|
type UserStatGroup struct {
|
|
UserID int64 `gorm:"column:user_id"`
|
|
UserName string `gorm:"column:user_name"`
|
|
ReceivingNum int64 `gorm:"column:receiving_num"`
|
|
OutboundNum int64 `gorm:"column:outbound_num"`
|
|
SalesCount int64 `gorm:"column:sales_count"`
|
|
}
|
|
|
|
var userStats []UserStatGroup
|
|
tx.Table("employee").
|
|
Select(`
|
|
employee.id as user_id,
|
|
employee.username as user_name,
|
|
COALESCE((SELECT SUM(receiving_num) FROM statist WHERE create_by = employee.id AND stat_date >= ? AND stat_date <= ? AND is_del = ?), 0) as receiving_num,
|
|
COALESCE((SELECT SUM(outbound_num) FROM statist WHERE create_by = employee.id AND stat_date >= ? AND stat_date <= ? AND is_del = ?), 0) as outbound_num,
|
|
COALESCE((SELECT COUNT(*) FROM sales_order WHERE create_by = employee.id AND created_at >= ? AND created_at <= ? AND is_del = ?), 0) as sales_count
|
|
`, startDate, endDate, 0, startDate, endDate, 0, startDate, endDate, 0).
|
|
Where("employee.about_id = ? AND employee.is_del = ?", aboutID, 0).
|
|
Scan(&userStats)
|
|
|
|
if len(userStats) == 0 {
|
|
return nil
|
|
}
|
|
|
|
now := time.Now().Unix()
|
|
for _, userStat := range userStats {
|
|
var existingStat models.UserDailyStat
|
|
err := tx.Where("user_id = ? AND stat_date = ? AND is_del = ?", userStat.UserID, statDate, 0).First(&existingStat).Error
|
|
|
|
if err == nil {
|
|
if err := tx.Model(&models.UserDailyStat{}).Where("id = ?", existingStat.ID).Update("is_del", 1).Error; err != nil {
|
|
continue
|
|
}
|
|
}
|
|
|
|
newStat := &models.UserDailyStat{
|
|
UserID: userStat.UserID,
|
|
UserName: userStat.UserName,
|
|
StatDate: statDate,
|
|
ReceivingNum: userStat.ReceivingNum,
|
|
OutboundNum: userStat.OutboundNum,
|
|
SalesCount: userStat.SalesCount,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
IsDel: 0,
|
|
}
|
|
|
|
if err := tx.Create(newStat).Error; err != nil {
|
|
utils.ErrorLog("work", map[string]interface{}{
|
|
"source": "生成用户统计",
|
|
"user_id": userStat.UserID,
|
|
"error": fmt.Sprintf("创建用户统计记录失败: %v", err),
|
|
})
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|