update analytic
This commit is contained in:
parent
c8ea680e05
commit
490aa19840
@ -3,6 +3,8 @@ package repository
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@ -320,79 +322,143 @@ func (r *AnalyticsRepository) GetDepartmentStats(ctx context.Context, startDate,
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var results []map[string]interface{}
|
||||
|
||||
// First try using summary table for better performance
|
||||
query := `
|
||||
SELECT
|
||||
d.id as department_id,
|
||||
d.name as department_name,
|
||||
d.code as department_code,
|
||||
COALESCE(SUM(dls.incoming_count), 0) as incoming_count,
|
||||
COALESCE(SUM(dls.outgoing_count), 0) as outgoing_count,
|
||||
COALESCE(SUM(dls.pending_outgoing), 0) as pending_count,
|
||||
COALESCE(AVG(dls.avg_response_hours), 0) as avg_response_time,
|
||||
COALESCE(AVG(dls.completion_rate), 0) as completion_rate
|
||||
FROM departments d
|
||||
LEFT JOIN department_letter_summary dls ON dls.department_id = d.id
|
||||
WHERE 1=1
|
||||
%s
|
||||
GROUP BY d.id, d.name, d.code
|
||||
ORDER BY (COALESCE(SUM(dls.incoming_count), 0) + COALESCE(SUM(dls.outgoing_count), 0)) DESC
|
||||
`
|
||||
// Format tanggal untuk logging
|
||||
log.Printf("GetDepartmentStats called with startDate: %v, endDate: %v", startDate, endDate)
|
||||
|
||||
// Try summary table first
|
||||
query := `
|
||||
SELECT
|
||||
d.id as department_id,
|
||||
d.name as department_name,
|
||||
d.code as department_code,
|
||||
COALESCE(SUM(dls.incoming_count), 0) as incoming_count,
|
||||
COALESCE(SUM(dls.outgoing_count), 0) as outgoing_count,
|
||||
COALESCE(SUM(dls.pending_outgoing), 0) as pending_count,
|
||||
COALESCE(AVG(dls.avg_response_hours), 0) as avg_response_time,
|
||||
COALESCE(AVG(dls.completion_rate), 0) as completion_rate
|
||||
FROM departments d
|
||||
LEFT JOIN department_letter_summary dls ON dls.department_id = d.id`
|
||||
|
||||
var conditions []string
|
||||
var args []interface{}
|
||||
|
||||
dateFilter := ""
|
||||
if !startDate.IsZero() {
|
||||
dateFilter += fmt.Sprintf(" AND dls.summary_date >= '%s'", startDate.Format("2006-01-02"))
|
||||
conditions = append(conditions, "dls.summary_date >= ?")
|
||||
args = append(args, startDate.Format("2006-01-02"))
|
||||
}
|
||||
if !endDate.IsZero() {
|
||||
dateFilter += fmt.Sprintf(" AND dls.summary_date <= '%s'", endDate.Format("2006-01-02"))
|
||||
conditions = append(conditions, "dls.summary_date <= ?")
|
||||
args = append(args, endDate.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
query = fmt.Sprintf(query, dateFilter)
|
||||
if len(conditions) > 0 {
|
||||
query += " WHERE " + strings.Join(conditions, " AND ")
|
||||
}
|
||||
|
||||
if err := db.Raw(query).Scan(&results).Error; err != nil {
|
||||
query += `
|
||||
GROUP BY d.id, d.name, d.code
|
||||
ORDER BY (COALESCE(SUM(dls.incoming_count), 0) + COALESCE(SUM(dls.outgoing_count), 0)) DESC`
|
||||
|
||||
log.Printf("Summary query: %s, args: %v", query, args)
|
||||
|
||||
if err := db.Raw(query, args...).Scan(&results).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If no results from summary table, fall back to direct query
|
||||
if len(results) == 0 {
|
||||
fallbackQuery := `
|
||||
SELECT
|
||||
d.id as department_id,
|
||||
d.name as department_name,
|
||||
d.code as department_code,
|
||||
COUNT(DISTINCT lir.letter_id) as incoming_count,
|
||||
COUNT(DISTINCT lor.letter_id) as outgoing_count,
|
||||
COUNT(DISTINCT CASE WHEN lo.status = 'pending_approval' THEN lo.id END) as pending_count,
|
||||
COALESCE(AVG(CASE
|
||||
WHEN lo.status IN ('approved', 'sent', 'archived')
|
||||
THEN EXTRACT(EPOCH FROM (lo.updated_at - lo.created_at))/3600
|
||||
END), 0) as avg_response_time,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT lo.id) > 0
|
||||
THEN ROUND(COUNT(DISTINCT CASE WHEN lo.status IN ('sent', 'archived') THEN lo.id END) * 100.0 / COUNT(DISTINCT lo.id), 2)
|
||||
ELSE 0
|
||||
END as completion_rate
|
||||
FROM departments d
|
||||
LEFT JOIN letter_incoming_recipients lir ON lir.recipient_department_id = d.id
|
||||
LEFT JOIN letter_outgoing_recipients lor ON lor.department_id = d.id
|
||||
LEFT JOIN letters_outgoing lo ON lo.id = lor.letter_id AND lo.deleted_at IS NULL
|
||||
WHERE 1=1
|
||||
%s
|
||||
GROUP BY d.id, d.name, d.code
|
||||
ORDER BY (COUNT(DISTINCT lir.letter_id) + COUNT(DISTINCT lor.letter_id)) DESC
|
||||
`
|
||||
// Check if summary table has data for this period
|
||||
var summaryCount int64
|
||||
checkQuery := "SELECT COUNT(*) FROM department_letter_summary WHERE 1=1"
|
||||
checkArgs := []interface{}{}
|
||||
|
||||
if !startDate.IsZero() {
|
||||
checkQuery += " AND summary_date >= ?"
|
||||
checkArgs = append(checkArgs, startDate.Format("2006-01-02"))
|
||||
}
|
||||
if !endDate.IsZero() {
|
||||
checkQuery += " AND summary_date <= ?"
|
||||
checkArgs = append(checkArgs, endDate.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
db.Raw(checkQuery, checkArgs...).Scan(&summaryCount)
|
||||
log.Printf("Summary count: %d", summaryCount)
|
||||
|
||||
// If no summary data exists for this period, fall back to direct query
|
||||
if summaryCount == 0 {
|
||||
log.Println("Using fallback query (no summary data)")
|
||||
|
||||
// Use CTE for better performance
|
||||
fallbackQuery := `
|
||||
WITH filtered_incoming AS (
|
||||
SELECT
|
||||
li.id,
|
||||
li.created_at,
|
||||
li.updated_at,
|
||||
lir.recipient_department_id
|
||||
FROM letters_incoming li
|
||||
INNER JOIN letter_incoming_recipients lir ON lir.letter_id = li.id
|
||||
WHERE li.deleted_at IS NULL`
|
||||
|
||||
var fallbackArgs []interface{}
|
||||
|
||||
fallbackDateFilter := ""
|
||||
if !startDate.IsZero() {
|
||||
fallbackDateFilter += fmt.Sprintf(" AND (lo.created_at >= '%s' OR lo.created_at IS NULL)", startDate.Format("2006-01-02"))
|
||||
fallbackQuery += " AND li.created_at >= ?"
|
||||
fallbackArgs = append(fallbackArgs, startDate)
|
||||
}
|
||||
if !endDate.IsZero() {
|
||||
fallbackDateFilter += fmt.Sprintf(" AND (lo.created_at <= '%s' OR lo.created_at IS NULL)", endDate.Format("2006-01-02"))
|
||||
fallbackQuery += " AND li.created_at <= ?"
|
||||
fallbackArgs = append(fallbackArgs, endDate)
|
||||
}
|
||||
|
||||
fallbackQuery = fmt.Sprintf(fallbackQuery, fallbackDateFilter)
|
||||
fallbackQuery += `
|
||||
),
|
||||
filtered_outgoing AS (
|
||||
SELECT
|
||||
lo.id,
|
||||
lo.status,
|
||||
lo.created_at,
|
||||
lo.updated_at,
|
||||
lor.department_id
|
||||
FROM letters_outgoing lo
|
||||
INNER JOIN letter_outgoing_recipients lor ON lor.letter_id = lo.id
|
||||
WHERE lo.deleted_at IS NULL`
|
||||
|
||||
if err := db.Raw(fallbackQuery).Scan(&results).Error; err != nil {
|
||||
if !startDate.IsZero() {
|
||||
fallbackQuery += " AND lo.created_at >= ?"
|
||||
fallbackArgs = append(fallbackArgs, startDate)
|
||||
}
|
||||
if !endDate.IsZero() {
|
||||
fallbackQuery += " AND lo.created_at <= ?"
|
||||
fallbackArgs = append(fallbackArgs, endDate)
|
||||
}
|
||||
|
||||
fallbackQuery += `
|
||||
)
|
||||
SELECT
|
||||
d.id as department_id,
|
||||
d.name as department_name,
|
||||
d.code as department_code,
|
||||
COUNT(DISTINCT fi.id) as incoming_count,
|
||||
COUNT(DISTINCT fo.id) as outgoing_count,
|
||||
COUNT(DISTINCT CASE WHEN fo.status = 'pending_approval' THEN fo.id END) as pending_count,
|
||||
COALESCE(AVG(CASE
|
||||
WHEN fo.status IN ('approved', 'sent', 'archived')
|
||||
THEN EXTRACT(EPOCH FROM (fo.updated_at - fo.created_at))/3600
|
||||
END), 0) as avg_response_time,
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT fo.id) > 0
|
||||
THEN ROUND(COUNT(DISTINCT CASE WHEN fo.status IN ('sent', 'archived') THEN fo.id END) * 100.0 / COUNT(DISTINCT fo.id), 2)
|
||||
ELSE 0
|
||||
END as completion_rate
|
||||
FROM departments d
|
||||
LEFT JOIN filtered_incoming fi ON fi.recipient_department_id = d.id
|
||||
LEFT JOIN filtered_outgoing fo ON fo.department_id = d.id
|
||||
GROUP BY d.id, d.name, d.code
|
||||
ORDER BY (COUNT(DISTINCT fi.id) + COUNT(DISTINCT fo.id)) DESC`
|
||||
|
||||
log.Printf("Fallback query: %s", fallbackQuery)
|
||||
log.Printf("Fallback args: %v", fallbackArgs)
|
||||
|
||||
if err := db.Raw(fallbackQuery, fallbackArgs...).Scan(&results).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user