5.0.6: Удаление max_score, норма по max_goal_score
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m20s

This commit is contained in:
poignatov
2026-02-09 15:28:44 +03:00
parent 1f5f3299f8
commit 1fe3819be6
6 changed files with 108 additions and 15 deletions

View File

@@ -0,0 +1,51 @@
-- Migration: Restore max_score column and MV using max_score for normalized_total_score
ALTER TABLE weekly_goals ADD COLUMN max_score NUMERIC(10,4);
UPDATE weekly_goals SET max_score = max_goal_score WHERE max_score IS NULL;
DROP MATERIALIZED VIEW IF EXISTS weekly_report_mv;
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,
CASE
WHEN wg.max_score IS NULL THEN COALESCE(agg.total_score, 0.0000)
ELSE LEAST(COALESCE(agg.total_score, 0.0000), wg.max_score)
END AS normalized_total_score
FROM
projects p
LEFT JOIN
(
SELECT
n.project_id,
EXTRACT(ISOYEAR FROM n.created_date)::INTEGER AS report_year,
EXTRACT(WEEK FROM n.created_date)::INTEGER AS report_week,
SUM(n.score) AS total_score
FROM
nodes n
WHERE
(EXTRACT(ISOYEAR FROM n.created_date)::INTEGER < EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER)
OR (EXTRACT(ISOYEAR FROM n.created_date)::INTEGER = EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER
AND EXTRACT(WEEK FROM n.created_date)::INTEGER < EXTRACT(WEEK FROM CURRENT_DATE)::INTEGER)
GROUP BY
1, 2, 3
) agg
ON p.id = agg.project_id
LEFT JOIN
weekly_goals wg
ON wg.project_id = p.id
AND wg.goal_year = agg.report_year
AND wg.goal_week = agg.report_week
WHERE
p.deleted = FALSE
ORDER BY
p.id, agg.report_year, agg.report_week
WITH DATA;
CREATE INDEX idx_weekly_report_mv_project_year_week
ON weekly_report_mv(project_id, report_year, report_week);
COMMENT ON MATERIALIZED VIEW weekly_report_mv IS 'Materialized view aggregating weekly scores by project using ISOYEAR for correct week calculations at year boundaries. Includes all projects via LEFT JOIN. Adds normalized_total_score using weekly_goals.max_score snapshot. Contains only historical data (excludes current week). Uses nodes.created_date (denormalized) instead of entries.created_date.';

View File

@@ -0,0 +1,51 @@
-- Migration: Remove max_score from weekly_goals, use max_goal_score for normalized_total_score
-- normalized_total_score is now computed from max_goal_score (current goal) instead of max_score (snapshot).
DROP MATERIALIZED VIEW IF EXISTS weekly_report_mv;
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,
CASE
WHEN wg.max_goal_score IS NULL THEN COALESCE(agg.total_score, 0.0000)
ELSE LEAST(COALESCE(agg.total_score, 0.0000), wg.max_goal_score)
END AS normalized_total_score
FROM
projects p
LEFT JOIN
(
SELECT
n.project_id,
EXTRACT(ISOYEAR FROM n.created_date)::INTEGER AS report_year,
EXTRACT(WEEK FROM n.created_date)::INTEGER AS report_week,
SUM(n.score) AS total_score
FROM
nodes n
WHERE
(EXTRACT(ISOYEAR FROM n.created_date)::INTEGER < EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER)
OR (EXTRACT(ISOYEAR FROM n.created_date)::INTEGER = EXTRACT(ISOYEAR FROM CURRENT_DATE)::INTEGER
AND EXTRACT(WEEK FROM n.created_date)::INTEGER < EXTRACT(WEEK FROM CURRENT_DATE)::INTEGER)
GROUP BY
1, 2, 3
) agg
ON p.id = agg.project_id
LEFT JOIN
weekly_goals wg
ON wg.project_id = p.id
AND wg.goal_year = agg.report_year
AND wg.goal_week = agg.report_week
WHERE
p.deleted = FALSE
ORDER BY
p.id, agg.report_year, agg.report_week
WITH DATA;
CREATE INDEX idx_weekly_report_mv_project_year_week
ON weekly_report_mv(project_id, report_year, report_week);
COMMENT ON MATERIALIZED VIEW weekly_report_mv IS 'Materialized view aggregating weekly scores by project using ISOYEAR for correct week calculations at year boundaries. Includes all projects via LEFT JOIN. Adds normalized_total_score using weekly_goals.max_goal_score. Contains only historical data (excludes current week). Uses nodes.created_date (denormalized) instead of entries.created_date.';
ALTER TABLE weekly_goals DROP COLUMN max_score;

View File

@@ -45,7 +45,6 @@ docker-compose exec db psql -U playeng -d playeng -f /migrations/001_create_sche
- `goal_week` (INTEGER NOT NULL)
- `min_goal_score` (NUMERIC(10,4) NOT NULL, DEFAULT 0)
- `max_goal_score` (NUMERIC(10,4))
- `max_score` (NUMERIC(10,4), NULL) — snapshot max на неделю (заполняется только для новых недель)
- `priority` (SMALLINT)
- UNIQUE CONSTRAINT: `(project_id, goal_year, goal_week)`
@@ -56,7 +55,7 @@ docker-compose exec db psql -U playeng -d playeng -f /migrations/001_create_sche
- `report_year` (INTEGER)
- `report_week` (INTEGER)
- `total_score` (NUMERIC)
- `normalized_total_score` (NUMERIC)
- `normalized_total_score` (NUMERIC) — ограничение total_score по `max_goal_score` (миграция 000020 удалила колонку `max_score`, normalized считается по `max_goal_score`)
## Миграции