update dashboard analytic

This commit is contained in:
efrilm 2025-10-20 18:47:29 +07:00
parent ea980f8cf7
commit f391b6d853
2 changed files with 112 additions and 45 deletions

View File

@ -132,16 +132,21 @@ 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
@ -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)

View File

@ -2,6 +2,7 @@ package service
import ( import (
"context" "context"
"fmt"
"time" "time"
"eslogad-be/internal/appcontext" "eslogad-be/internal/appcontext"
@ -61,6 +62,7 @@ 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
@ -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
} }