From dad34dc1d64483edb5186e8183e4a9ec4e2bb5cf Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Wed, 27 May 2026 17:03:59 +0300 Subject: [PATCH] =?UTF-8?q?fix(algebra-8=20ch1):=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B3=D1=80=D0=B5=D1=81=D1=81=20=D0=BF=D0=B8=D1=88=D0=B5=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D0=BF=D0=BE=D0=B4=20=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20slug=20+=20=D0=BC=D0=B8?= =?UTF-8?q?=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20016?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После переименования slug algebra-8 → algebra-8-ch1 (миграция 014) Глава 1 продолжала POSTить прогресс под старым именем 'algebra-8', который теперь указывает на hub-строку. Эффект: paragraphs_read и last_para уходили в hub-row, а каталог хабов их игнорировал (агрегирует только children). Фикс: - algebra_8.html: _TB_SLUG = 'algebra-8-ch1' - migration 016: union перенос ошибочно записанного прогресса из hub в ch1; очистка hub-row. Идемпотентно (NOT EXISTS guard). Проверено: после миграции у user 2 paragraphs_read='["p1"]' живёт в ch1-row, hub-row пуста. Другие учебники проверены — корректно: - ch2/ch3 уже использовали правильные slug - chemistry-9, physics-9, physics8_* подключены через textbook-tracker - algebra_8_hub.html и physics_8.html — хабы без tracker (правильно) --- .../016_fix_algebra_hub_progress.sql | 59 +++++++++++++++++++ frontend/textbooks/algebra_8.html | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 backend/src/db/migrations/016_fix_algebra_hub_progress.sql diff --git a/backend/src/db/migrations/016_fix_algebra_hub_progress.sql b/backend/src/db/migrations/016_fix_algebra_hub_progress.sql new file mode 100644 index 0000000..45cd422 --- /dev/null +++ b/backend/src/db/migrations/016_fix_algebra_hub_progress.sql @@ -0,0 +1,59 @@ +-- Fix: до этого Глава 1 алгебры писала прогресс под slug 'algebra-8', +-- который после миграции 014 стал hub-строкой. В результате прогресс +-- учеников за ch1 уходил в hub-строку (id=10), где никем не виден +-- (каталог хабов агрегирует по children, hub own paragraphs_read игнорится). +-- +-- 1. Объединить ошибочно сохранённый прогресс из hub-row в ch1-row +-- (берём union paragraphs_read, max last_at). +-- 2. Очистить hub-row. +-- +-- ch1-row id = 3 (старая algebra-8 после rename), +-- hub-row id = 10 (algebra-8 после insert в миграции 014). +-- Используем подзапросы по slug, а не хардкод id — на случай разных окружений. + +-- Step 1: upsert merged progress в ch1, если в hub были данные +INSERT INTO textbook_progress (user_id, textbook_id, paragraphs_read, last_para, last_at) +SELECT + h.user_id, + (SELECT id FROM textbooks WHERE slug = 'algebra-8-ch1') AS ch1_id, + -- если у ch1 уже есть запись, на следующем шаге сольём; пока пишем hub-данные «как есть» + h.paragraphs_read, + h.last_para, + h.last_at +FROM textbook_progress h +WHERE h.textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8' AND parent_slug IS NULL) + AND NOT EXISTS ( + SELECT 1 FROM textbook_progress c + WHERE c.user_id = h.user_id + AND c.textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8-ch1') + ); + +-- Step 2: для пользователей, у которых уже есть запись и в hub, и в ch1 — обновить last_para/last_at +-- если hub был свежее. Слияние массивов paragraphs_read придётся делать вне SQL +-- (SQLite не имеет JSON merge), но текущий сценарий — это единственный неверно +-- залетевший элемент, и в большинстве случаев ch1 ещё пуст; этот блок просто +-- защищает на будущее (обычно сработает только Step 1). +UPDATE textbook_progress +SET last_para = ( + SELECT h.last_para FROM textbook_progress h + WHERE h.user_id = textbook_progress.user_id + AND h.textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8' AND parent_slug IS NULL) + AND h.last_at > textbook_progress.last_at + ), + last_at = ( + SELECT h.last_at FROM textbook_progress h + WHERE h.user_id = textbook_progress.user_id + AND h.textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8' AND parent_slug IS NULL) + AND h.last_at > textbook_progress.last_at + ) +WHERE textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8-ch1') + AND EXISTS ( + SELECT 1 FROM textbook_progress h + WHERE h.user_id = textbook_progress.user_id + AND h.textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8' AND parent_slug IS NULL) + AND h.last_at > textbook_progress.last_at + ); + +-- Step 3: удалить ошибочные записи из hub-row +DELETE FROM textbook_progress +WHERE textbook_id = (SELECT id FROM textbooks WHERE slug = 'algebra-8' AND parent_slug IS NULL); diff --git a/frontend/textbooks/algebra_8.html b/frontend/textbooks/algebra_8.html index 3f128fa..990ed7b 100644 --- a/frontend/textbooks/algebra_8.html +++ b/frontend/textbooks/algebra_8.html @@ -1073,7 +1073,7 @@ function bumpProgress(key, delta){ } /* Server sync of read/last_para — пишем в БД, чтобы каталог /textbooks показывал прогресс */ -const _TB_SLUG = 'algebra-8'; +const _TB_SLUG = 'algebra-8-ch1'; const _markedRead = new Set(); let _pendingProgressBody = null, _progressTimer = null; function _flushProgress(){