update dashboard analytic
This commit is contained in:
parent
ea980f8cf7
commit
f391b6d853
@ -27,7 +27,7 @@ func (r *AnalyticsRepository) GetLetterSummaryStats(ctx context.Context, startDa
|
|||||||
// Use department_letter_summary for department-specific stats
|
// Use department_letter_summary for department-specific stats
|
||||||
query := db.Table("department_letter_summary").
|
query := db.Table("department_letter_summary").
|
||||||
Where("department_id = ?", *departmentID)
|
Where("department_id = ?", *departmentID)
|
||||||
|
|
||||||
if !startDate.IsZero() {
|
if !startDate.IsZero() {
|
||||||
query = query.Where("summary_date >= ?", startDate)
|
query = query.Where("summary_date >= ?", startDate)
|
||||||
}
|
}
|
||||||
@ -36,13 +36,13 @@ func (r *AnalyticsRepository) GetLetterSummaryStats(ctx context.Context, startDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
TotalIncoming int64 `gorm:"column:total_incoming"`
|
TotalIncoming int64 `gorm:"column:total_incoming"`
|
||||||
TotalOutgoing int64 `gorm:"column:total_outgoing"`
|
TotalOutgoing int64 `gorm:"column:total_outgoing"`
|
||||||
PendingOutgoing int64 `gorm:"column:pending_outgoing"`
|
PendingOutgoing int64 `gorm:"column:pending_outgoing"`
|
||||||
ApprovedOutgoing int64 `gorm:"column:approved_outgoing"`
|
ApprovedOutgoing int64 `gorm:"column:approved_outgoing"`
|
||||||
RejectedOutgoing int64 `gorm:"column:rejected_outgoing"`
|
RejectedOutgoing int64 `gorm:"column:rejected_outgoing"`
|
||||||
AvgResponseHours float64 `gorm:"column:avg_response_hours"`
|
AvgResponseHours float64 `gorm:"column:avg_response_hours"`
|
||||||
CompletionRate float64 `gorm:"column:completion_rate"`
|
CompletionRate float64 `gorm:"column:completion_rate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Select(`
|
query.Select(`
|
||||||
@ -66,7 +66,7 @@ func (r *AnalyticsRepository) GetLetterSummaryStats(ctx context.Context, startDa
|
|||||||
} else if userID == nil && departmentID == nil {
|
} else if userID == nil && departmentID == nil {
|
||||||
// Use letter_summary for overall stats
|
// Use letter_summary for overall stats
|
||||||
query := db.Table("letter_summary")
|
query := db.Table("letter_summary")
|
||||||
|
|
||||||
if !startDate.IsZero() {
|
if !startDate.IsZero() {
|
||||||
query = query.Where("summary_date >= ?", startDate)
|
query = query.Where("summary_date >= ?", startDate)
|
||||||
}
|
}
|
||||||
@ -75,14 +75,14 @@ func (r *AnalyticsRepository) GetLetterSummaryStats(ctx context.Context, startDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
TotalIncoming int64 `gorm:"column:total_incoming"`
|
TotalIncoming int64 `gorm:"column:total_incoming"`
|
||||||
TotalOutgoing int64 `gorm:"column:total_outgoing"`
|
TotalOutgoing int64 `gorm:"column:total_outgoing"`
|
||||||
TotalPending int64 `gorm:"column:total_pending"`
|
TotalPending int64 `gorm:"column:total_pending"`
|
||||||
TotalApproved int64 `gorm:"column:total_approved"`
|
TotalApproved int64 `gorm:"column:total_approved"`
|
||||||
TotalRejected int64 `gorm:"column:total_rejected"`
|
TotalRejected int64 `gorm:"column:total_rejected"`
|
||||||
TotalArchived int64 `gorm:"column:total_archived"`
|
TotalArchived int64 `gorm:"column:total_archived"`
|
||||||
TotalSent int64 `gorm:"column:total_sent"`
|
TotalSent int64 `gorm:"column:total_sent"`
|
||||||
AvgProcessing float64 `gorm:"column:avg_processing"`
|
AvgProcessing float64 `gorm:"column:avg_processing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
query.Select(`
|
query.Select(`
|
||||||
@ -132,39 +132,44 @@ func (r *AnalyticsRepository) GetLetterSummaryStats(ctx context.Context, startDa
|
|||||||
outgoingQuery = outgoingQuery.
|
outgoingQuery = outgoingQuery.
|
||||||
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
||||||
Where("letter_outgoing_recipients.user_id = ?", *userID)
|
Where("letter_outgoing_recipients.user_id = ?", *userID)
|
||||||
|
incomingQuery = incomingQuery.
|
||||||
|
Joins("LEFT JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id").
|
||||||
|
Where("letter_incoming_recipients.recipient_user_id = ?", *userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("[DEBUG] userId analitycs: %v\n", userID)
|
||||||
|
|
||||||
// Count incoming letters
|
// Count incoming letters
|
||||||
var totalIncoming int64
|
var totalIncoming int64
|
||||||
incomingQuery.Count(&totalIncoming)
|
incomingQuery.Distinct("letters_incoming.id").Count(&totalIncoming)
|
||||||
stats["total_incoming"] = totalIncoming
|
stats["total_incoming"] = totalIncoming
|
||||||
|
|
||||||
// Count outgoing letters
|
// Count outgoing letters
|
||||||
var totalOutgoing int64
|
var totalOutgoing int64
|
||||||
outgoingQuery.Count(&totalOutgoing)
|
outgoingQuery.Distinct("letters_outgoing.id").Count(&totalOutgoing)
|
||||||
stats["total_outgoing"] = totalOutgoing
|
stats["total_outgoing"] = totalOutgoing
|
||||||
|
|
||||||
// Count by status - need to clone query for each count
|
// Count by status - need to clone query for each count
|
||||||
var pendingCount, approvedCount, rejectedCount, archivedCount int64
|
var pendingCount, approvedCount, rejectedCount, archivedCount int64
|
||||||
|
|
||||||
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
||||||
Where("letters_outgoing.status = ?", "pending_approval").
|
Where("letters_outgoing.status = ?", "pending_approval").
|
||||||
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
||||||
Where("letter_outgoing_recipients.user_id = ?", *userID).
|
Where("letter_outgoing_recipients.user_id = ?", *userID).
|
||||||
Count(&pendingCount)
|
Count(&pendingCount)
|
||||||
|
|
||||||
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
||||||
Where("letters_outgoing.status = ?", "approved").
|
Where("letters_outgoing.status = ?", "approved").
|
||||||
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
||||||
Where("letter_outgoing_recipients.user_id = ?", *userID).
|
Where("letter_outgoing_recipients.user_id = ?", *userID).
|
||||||
Count(&approvedCount)
|
Count(&approvedCount)
|
||||||
|
|
||||||
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
||||||
Where("letters_outgoing.status = ?", "rejected").
|
Where("letters_outgoing.status = ?", "rejected").
|
||||||
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
||||||
Where("letter_outgoing_recipients.user_id = ?", *userID).
|
Where("letter_outgoing_recipients.user_id = ?", *userID).
|
||||||
Count(&rejectedCount)
|
Count(&rejectedCount)
|
||||||
|
|
||||||
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
db.Table("letters_outgoing").Where("letters_outgoing.deleted_at IS NULL").
|
||||||
Where("letters_outgoing.status = ?", "archived").
|
Where("letters_outgoing.status = ?", "archived").
|
||||||
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
Joins("LEFT JOIN letter_outgoing_recipients ON letter_outgoing_recipients.letter_id = letters_outgoing.id").
|
||||||
@ -386,7 +391,7 @@ func (r *AnalyticsRepository) GetDepartmentStats(ctx context.Context, startDate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fallbackQuery = fmt.Sprintf(fallbackQuery, fallbackDateFilter)
|
fallbackQuery = fmt.Sprintf(fallbackQuery, fallbackDateFilter)
|
||||||
|
|
||||||
if err := db.Raw(fallbackQuery).Scan(&results).Error; err != nil {
|
if err := db.Raw(fallbackQuery).Scan(&results).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -471,9 +476,9 @@ func (r *AnalyticsRepository) GetMonthlyTrend(ctx context.Context, months int) (
|
|||||||
ORDER BY year DESC, month_num DESC
|
ORDER BY year DESC, month_num DESC
|
||||||
LIMIT %d
|
LIMIT %d
|
||||||
`
|
`
|
||||||
|
|
||||||
fallbackQuery = fmt.Sprintf(fallbackQuery, months, months, months)
|
fallbackQuery = fmt.Sprintf(fallbackQuery, months, months, months)
|
||||||
|
|
||||||
if err := db.Raw(fallbackQuery).Scan(&results).Error; err != nil {
|
if err := db.Raw(fallbackQuery).Scan(&results).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -713,6 +718,66 @@ func (r *AnalyticsRepository) GetDailyActivity(ctx context.Context, days int) ([
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *AnalyticsRepository) GetDailyActivityByUserID(ctx context.Context, userID *uuid.UUID, days int) ([]map[string]interface{}, error) {
|
||||||
|
db := DBFromContext(ctx, r.db)
|
||||||
|
var results []map[string]interface{}
|
||||||
|
|
||||||
|
query := `
|
||||||
|
WITH daily_data AS (
|
||||||
|
SELECT
|
||||||
|
DATE(created_at) as date,
|
||||||
|
TO_CHAR(created_at, 'Day') as day_of_week,
|
||||||
|
COUNT(CASE WHEN type = 'incoming' THEN 1 END) as incoming_count,
|
||||||
|
COUNT(CASE WHEN type = 'outgoing' THEN 1 END) as outgoing_count,
|
||||||
|
0 as approved_count,
|
||||||
|
0 as rejected_count
|
||||||
|
FROM (
|
||||||
|
SELECT li.created_at, 'incoming' as type
|
||||||
|
FROM letters_incoming li
|
||||||
|
INNER JOIN letter_incoming_recipients lir ON lir.letter_id = li.id
|
||||||
|
WHERE li.deleted_at IS NULL AND lir.recipient_user_id = ?
|
||||||
|
UNION ALL
|
||||||
|
SELECT lo.created_at, 'outgoing' as type
|
||||||
|
FROM letters_outgoing lo
|
||||||
|
INNER JOIN letter_outgoing_recipients lor ON lor.letter_id = lo.id
|
||||||
|
WHERE lo.deleted_at IS NULL AND lor.user_id = ?
|
||||||
|
) combined
|
||||||
|
WHERE created_at >= CURRENT_DATE - INTERVAL '%d days'
|
||||||
|
GROUP BY DATE(created_at), TO_CHAR(created_at, 'Day')
|
||||||
|
),
|
||||||
|
approval_data AS (
|
||||||
|
SELECT
|
||||||
|
DATE(acted_at) as date,
|
||||||
|
COUNT(CASE WHEN status = 'approved' THEN 1 END) as approved_count,
|
||||||
|
COUNT(CASE WHEN status = 'rejected' THEN 1 END) as rejected_count
|
||||||
|
FROM letter_outgoing_approvals
|
||||||
|
WHERE acted_at IS NOT NULL
|
||||||
|
AND acted_at >= CURRENT_DATE - INTERVAL '%d days'
|
||||||
|
AND approver_id = ?
|
||||||
|
GROUP BY DATE(acted_at)
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
d.date,
|
||||||
|
d.day_of_week,
|
||||||
|
d.incoming_count,
|
||||||
|
d.outgoing_count,
|
||||||
|
COALESCE(a.approved_count, 0) as approved_count,
|
||||||
|
COALESCE(a.rejected_count, 0) as rejected_count
|
||||||
|
FROM daily_data d
|
||||||
|
LEFT JOIN approval_data a ON a.date = d.date
|
||||||
|
ORDER BY d.date DESC
|
||||||
|
LIMIT %d
|
||||||
|
`
|
||||||
|
|
||||||
|
query = fmt.Sprintf(query, days, days, days)
|
||||||
|
|
||||||
|
if err := db.Raw(query, userID, userID, userID).Scan(&results).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetResponseTimeStats gets response time statistics
|
// GetResponseTimeStats gets response time statistics
|
||||||
func (r *AnalyticsRepository) GetResponseTimeStats(ctx context.Context, startDate, endDate time.Time) (map[string]interface{}, error) {
|
func (r *AnalyticsRepository) GetResponseTimeStats(ctx context.Context, startDate, endDate time.Time) (map[string]interface{}, error) {
|
||||||
db := DBFromContext(ctx, r.db)
|
db := DBFromContext(ctx, r.db)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"eslogad-be/internal/appcontext"
|
"eslogad-be/internal/appcontext"
|
||||||
@ -37,7 +38,7 @@ func (s *AnalyticsServiceImpl) GetDashboard(ctx context.Context, req *contract.A
|
|||||||
// Default to last 30 days
|
// Default to last 30 days
|
||||||
startDate = time.Now().AddDate(0, 0, -30)
|
startDate = time.Now().AddDate(0, 0, -30)
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.EndDate != "" {
|
if req.EndDate != "" {
|
||||||
if date, err := time.Parse("2006-01-02", req.EndDate); err == nil {
|
if date, err := time.Parse("2006-01-02", req.EndDate); err == nil {
|
||||||
endDate = date.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
|
endDate = date.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
|
||||||
@ -48,7 +49,7 @@ func (s *AnalyticsServiceImpl) GetDashboard(ctx context.Context, req *contract.A
|
|||||||
|
|
||||||
// Apply user context filters if not admin
|
// Apply user context filters if not admin
|
||||||
var userID *uuid.UUID
|
var userID *uuid.UUID
|
||||||
|
|
||||||
appCtx := appcontext.FromGinContext(ctx)
|
appCtx := appcontext.FromGinContext(ctx)
|
||||||
if appCtx != nil && appCtx.UserRole != "admin" && appCtx.UserRole != "superadmin" {
|
if appCtx != nil && appCtx.UserRole != "admin" && appCtx.UserRole != "superadmin" {
|
||||||
userID = &appCtx.UserID
|
userID = &appCtx.UserID
|
||||||
@ -61,8 +62,9 @@ func (s *AnalyticsServiceImpl) GetDashboard(ctx context.Context, req *contract.A
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
fmt.Printf("[DEBUG] summaryData: %v\n", summaryData)
|
||||||
response.Summary = s.mapSummaryStats(summaryData)
|
response.Summary = s.mapSummaryStats(summaryData)
|
||||||
|
|
||||||
// Calculate growth metrics
|
// Calculate growth metrics
|
||||||
response.Summary.WeekOverWeekGrowth = s.calculateWeekOverWeekGrowth(ctx)
|
response.Summary.WeekOverWeekGrowth = s.calculateWeekOverWeekGrowth(ctx)
|
||||||
response.Summary.MonthOverMonthGrowth = s.calculateMonthOverMonthGrowth(ctx)
|
response.Summary.MonthOverMonthGrowth = s.calculateMonthOverMonthGrowth(ctx)
|
||||||
@ -99,7 +101,7 @@ func (s *AnalyticsServiceImpl) GetDashboard(ctx context.Context, req *contract.A
|
|||||||
response.InstitutionStats = s.mapInstitutionStats(instData)
|
response.InstitutionStats = s.mapInstitutionStats(instData)
|
||||||
|
|
||||||
// Get daily activity (last 7 days)
|
// Get daily activity (last 7 days)
|
||||||
dailyData, err := s.analyticsRepo.GetDailyActivity(ctx, 7)
|
dailyData, err := s.analyticsRepo.GetDailyActivityByUserID(ctx, userID, 7)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -143,17 +145,17 @@ func (s *AnalyticsServiceImpl) calculateWeekOverWeekGrowth(ctx context.Context)
|
|||||||
// Get this week's data
|
// Get this week's data
|
||||||
thisWeekStart := time.Now().AddDate(0, 0, -int(time.Now().Weekday()))
|
thisWeekStart := time.Now().AddDate(0, 0, -int(time.Now().Weekday()))
|
||||||
thisWeekEnd := time.Now()
|
thisWeekEnd := time.Now()
|
||||||
|
|
||||||
// Get last week's data
|
// Get last week's data
|
||||||
lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
|
lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
|
||||||
lastWeekEnd := thisWeekStart.AddDate(0, 0, -1)
|
lastWeekEnd := thisWeekStart.AddDate(0, 0, -1)
|
||||||
|
|
||||||
thisWeekData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, thisWeekStart, thisWeekEnd, nil, nil)
|
thisWeekData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, thisWeekStart, thisWeekEnd, nil, nil)
|
||||||
lastWeekData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, lastWeekStart, lastWeekEnd, nil, nil)
|
lastWeekData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, lastWeekStart, lastWeekEnd, nil, nil)
|
||||||
|
|
||||||
thisWeekTotal := getInt64Value(thisWeekData["total_incoming"]) + getInt64Value(thisWeekData["total_outgoing"])
|
thisWeekTotal := getInt64Value(thisWeekData["total_incoming"]) + getInt64Value(thisWeekData["total_outgoing"])
|
||||||
lastWeekTotal := getInt64Value(lastWeekData["total_incoming"]) + getInt64Value(lastWeekData["total_outgoing"])
|
lastWeekTotal := getInt64Value(lastWeekData["total_incoming"]) + getInt64Value(lastWeekData["total_outgoing"])
|
||||||
|
|
||||||
if lastWeekTotal > 0 {
|
if lastWeekTotal > 0 {
|
||||||
return float64((thisWeekTotal - lastWeekTotal) * 100 / lastWeekTotal)
|
return float64((thisWeekTotal - lastWeekTotal) * 100 / lastWeekTotal)
|
||||||
}
|
}
|
||||||
@ -166,17 +168,17 @@ func (s *AnalyticsServiceImpl) calculateMonthOverMonthGrowth(ctx context.Context
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||||
thisMonthEnd := now
|
thisMonthEnd := now
|
||||||
|
|
||||||
// Get last month's data
|
// Get last month's data
|
||||||
lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
|
lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
|
||||||
lastMonthEnd := thisMonthStart.AddDate(0, 0, -1)
|
lastMonthEnd := thisMonthStart.AddDate(0, 0, -1)
|
||||||
|
|
||||||
thisMonthData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, thisMonthStart, thisMonthEnd, nil, nil)
|
thisMonthData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, thisMonthStart, thisMonthEnd, nil, nil)
|
||||||
lastMonthData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, lastMonthStart, lastMonthEnd, nil, nil)
|
lastMonthData, _ := s.analyticsRepo.GetLetterSummaryStats(ctx, lastMonthStart, lastMonthEnd, nil, nil)
|
||||||
|
|
||||||
thisMonthTotal := getInt64Value(thisMonthData["total_incoming"]) + getInt64Value(thisMonthData["total_outgoing"])
|
thisMonthTotal := getInt64Value(thisMonthData["total_incoming"]) + getInt64Value(thisMonthData["total_outgoing"])
|
||||||
lastMonthTotal := getInt64Value(lastMonthData["total_incoming"]) + getInt64Value(lastMonthData["total_outgoing"])
|
lastMonthTotal := getInt64Value(lastMonthData["total_incoming"]) + getInt64Value(lastMonthData["total_outgoing"])
|
||||||
|
|
||||||
if lastMonthTotal > 0 {
|
if lastMonthTotal > 0 {
|
||||||
return float64((thisMonthTotal - lastMonthTotal) * 100 / lastMonthTotal)
|
return float64((thisMonthTotal - lastMonthTotal) * 100 / lastMonthTotal)
|
||||||
}
|
}
|
||||||
@ -190,7 +192,7 @@ func (s *AnalyticsServiceImpl) getSimpleDepartmentStats(ctx context.Context, sta
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return []contract.SimpleDepartmentStats{}
|
return []contract.SimpleDepartmentStats{}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]contract.SimpleDepartmentStats, 0, len(deptData))
|
result := make([]contract.SimpleDepartmentStats, 0, len(deptData))
|
||||||
for _, item := range deptData {
|
for _, item := range deptData {
|
||||||
deptIDStr := getStringValue(item["department_id"])
|
deptIDStr := getStringValue(item["department_id"])
|
||||||
@ -198,17 +200,17 @@ func (s *AnalyticsServiceImpl) getSimpleDepartmentStats(ctx context.Context, sta
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total letter count (incoming + outgoing)
|
// Calculate total letter count (incoming + outgoing)
|
||||||
letterCount := getInt64Value(item["incoming_count"]) + getInt64Value(item["outgoing_count"])
|
letterCount := getInt64Value(item["incoming_count"]) + getInt64Value(item["outgoing_count"])
|
||||||
|
|
||||||
result = append(result, contract.SimpleDepartmentStats{
|
result = append(result, contract.SimpleDepartmentStats{
|
||||||
DepartmentID: deptID,
|
DepartmentID: deptID,
|
||||||
Department: getStringValue(item["department_name"]),
|
Department: getStringValue(item["department_name"]),
|
||||||
LetterCount: letterCount,
|
LetterCount: letterCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,11 +305,11 @@ func (s *AnalyticsServiceImpl) mapInstitutionStats(data []map[string]interface{}
|
|||||||
OutgoingCount: getInt64Value(item["outgoing_count"]),
|
OutgoingCount: getInt64Value(item["outgoing_count"]),
|
||||||
TotalCount: getInt64Value(item["total_count"]),
|
TotalCount: getInt64Value(item["total_count"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
if lastActivity, ok := item["last_activity"].(time.Time); ok {
|
if lastActivity, ok := item["last_activity"].(time.Time); ok {
|
||||||
stat.LastActivity = lastActivity
|
stat.LastActivity = lastActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
result = append(result, stat)
|
result = append(result, stat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,4 +412,4 @@ func getFloat64Value(v interface{}) float64 {
|
|||||||
default:
|
default:
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user