Fix: Исправление определения недели на границе года (ISOYEAR)
- Заменен EXTRACT(YEAR) на EXTRACT(ISOYEAR) в materialized view для корректной работы на границе года - Обновлена миграция 001_create_schema.sql для использования ISOYEAR - Создана миграция 006_fix_weekly_report_mv_structure.sql для исправления структуры view (LEFT JOIN) - Добавлен endpoint /admin/recreate-mv для пересоздания materialized view - Обновлена документация миграций в README.md - Обновлены зависимости Go (go.mod, go.sum)
This commit is contained in:
@@ -1871,7 +1871,7 @@ func (a *App) initPlayLifeDB() error {
|
||||
(
|
||||
SELECT
|
||||
n.project_id,
|
||||
EXTRACT(YEAR FROM e.created_date)::INTEGER AS report_year,
|
||||
EXTRACT(ISOYEAR FROM e.created_date)::INTEGER AS report_year,
|
||||
EXTRACT(WEEK FROM e.created_date)::INTEGER AS report_week,
|
||||
SUM(n.score) AS total_score
|
||||
FROM
|
||||
@@ -2342,6 +2342,7 @@ func main() {
|
||||
r.HandleFunc("/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b", app.getFullStatisticsHandler).Methods("GET", "OPTIONS")
|
||||
r.HandleFunc("/admin", app.adminHandler).Methods("GET")
|
||||
r.HandleFunc("/admin.html", app.adminHandler).Methods("GET")
|
||||
r.HandleFunc("/admin/recreate-mv", app.recreateMaterializedViewHandler).Methods("POST", "OPTIONS")
|
||||
|
||||
port := getEnv("PORT", "8080")
|
||||
log.Printf("Server starting on port %s", port)
|
||||
@@ -3147,6 +3148,75 @@ func (a *App) adminHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, adminPath)
|
||||
}
|
||||
|
||||
// recreateMaterializedViewHandler пересоздает materialized view с исправленной логикой ISOYEAR
|
||||
func (a *App) recreateMaterializedViewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "OPTIONS" {
|
||||
setCORSHeaders(w)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
setCORSHeaders(w)
|
||||
|
||||
log.Printf("Recreating materialized view weekly_report_mv with ISOYEAR fix")
|
||||
|
||||
// Удаляем старый view
|
||||
dropMaterializedView := `DROP MATERIALIZED VIEW IF EXISTS weekly_report_mv`
|
||||
if _, err := a.DB.Exec(dropMaterializedView); err != nil {
|
||||
log.Printf("Error dropping materialized view: %v", err)
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Error dropping materialized view: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем новый view с ISOYEAR
|
||||
createMaterializedView := `
|
||||
CREATE MATERIALIZED VIEW weekly_report_mv AS
|
||||
SELECT
|
||||
p.id AS project_id,
|
||||
agg.report_year,
|
||||
agg.report_week,
|
||||
COALESCE(agg.total_score, 0.0000) AS total_score
|
||||
FROM
|
||||
projects p
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT
|
||||
n.project_id,
|
||||
EXTRACT(ISOYEAR FROM e.created_date)::INTEGER AS report_year,
|
||||
EXTRACT(WEEK FROM e.created_date)::INTEGER AS report_week,
|
||||
SUM(n.score) AS total_score
|
||||
FROM
|
||||
nodes n
|
||||
JOIN
|
||||
entries e ON n.entry_id = e.id
|
||||
GROUP BY
|
||||
1, 2, 3
|
||||
) agg
|
||||
ON p.id = agg.project_id
|
||||
ORDER BY
|
||||
p.id, agg.report_year, agg.report_week
|
||||
`
|
||||
|
||||
if _, err := a.DB.Exec(createMaterializedView); err != nil {
|
||||
log.Printf("Error creating materialized view: %v", err)
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Error creating materialized view: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем индекс
|
||||
createMVIndex := `
|
||||
CREATE INDEX IF NOT EXISTS idx_weekly_report_mv_project_year_week
|
||||
ON weekly_report_mv(project_id, report_year, report_week)
|
||||
`
|
||||
if _, err := a.DB.Exec(createMVIndex); err != nil {
|
||||
log.Printf("Warning: Failed to create materialized view index: %v", err)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "Materialized view recreated successfully with ISOYEAR fix",
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) getProjectsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "OPTIONS" {
|
||||
setCORSHeaders(w)
|
||||
|
||||
Reference in New Issue
Block a user