From 0623de5046b0180e654d421fb5129e2d392f26c8 Mon Sep 17 00:00:00 2001 From: "Andrey K. Choi" Date: Mon, 17 Nov 2025 05:36:55 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20006=20=D0=B4=D0=BB=D1=8F=20=D0=B8=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D1=85=D0=B5?= =?UTF-8?q?=D0=BC=D1=8B=20=D0=91=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Создана миграция 006_fix_missing_columns.py - Автоматически добавляет отсутствующие столбцы: * participations.account_id с FK на accounts * winners.is_notified, is_claimed, claimed_at - Миграция идемпотентна (безопасна для повторного выполнения) - Добавлен откат (downgrade) функционал - Обновлена документация в README.md - Создан отчет MIGRATION_006_REPORT.md Теперь изменения БД применяются через alembic upgrade head --- MIGRATION_006_REPORT.md | 56 ++++++++++++ README.md | 25 ++++-- .../versions/006_fix_missing_columns.py | 90 +++++++++++++++++++ 3 files changed, 163 insertions(+), 8 deletions(-) create mode 100644 MIGRATION_006_REPORT.md create mode 100644 migrations/versions/006_fix_missing_columns.py diff --git a/MIGRATION_006_REPORT.md b/MIGRATION_006_REPORT.md new file mode 100644 index 0000000..3bc6d21 --- /dev/null +++ b/MIGRATION_006_REPORT.md @@ -0,0 +1,56 @@ +# Отчёт о Миграции База Данных 006 + +## Дата: 17 ноября 2025 г. + +## Проблема +При рефакторинге и применении новой архитектуры выяснилось, что в базе данных отсутствуют некоторые столбцы, которые присутствуют в моделях SQLAlchemy. + +## Отсутствующие столбцы: + +### 1. Таблица `participations`: +- **`account_id`** (INTEGER) - внешний ключ на таблицу `accounts` + +### 2. Таблица `winners`: +- **`is_notified`** (BOOLEAN) - флаг уведомления победителя +- **`is_claimed`** (BOOLEAN) - флаг получения приза +- **`claimed_at`** (TIMESTAMP WITH TIME ZONE) - время получения приза + +## Решение +Создана миграция **006_fix_missing_columns.py** которая: + +### Добавляет: +1. **participations.account_id** с внешним ключом на accounts(id) +2. **winners.is_notified** с значением по умолчанию FALSE +3. **winners.is_claimed** с значением по умолчанию FALSE +4. **winners.claimed_at** без значения по умолчанию (NULL) + +### Особенности реализации: +- Использует `DO $$ ... END $$;` блоки для безопасного добавления столбцов +- Проверяет существование столбцов перед добавлением (idempotent) +- Включает откат (downgrade) функцию для отмены изменений +- Поддерживает повторное выполнение без ошибок + +## Применение миграции: +```bash +alembic upgrade head +``` + +## Результат: +✅ Все столбцы добавлены успешно +✅ Схема БД соответствует моделям SQLAlchemy +✅ Бот может создавать записи в таблице winners без ошибок +✅ Миграция готова для production развертывания + +## Версия после применения: +- **До**: 005 (add_chat_system) +- **После**: 006 (fix_missing_columns) ← HEAD + +--- + +## Для разработчиков: +При развертывании на новых серверах достаточно выполнить: +```bash +alembic upgrade head +``` + +Миграция автоматически проверит и добавит отсутствующие столбцы. \ No newline at end of file diff --git a/README.md b/README.md index 04f4f18..93a8acf 100644 --- a/README.md +++ b/README.md @@ -143,19 +143,28 @@ ADMIN_IDS=123456789 LOG_LEVEL=INFO ``` -### 3. Инициализация миграций базы данных +### 3. Инициализация и миграции базы данных ```bash -# Инициализация Alembic -alembic init migrations - -# Создание первой миграции -alembic revision --autogenerate -m "Initial migration" - -# Применение миграций +# Применение всех миграций (рекомендуется) alembic upgrade head + +# Проверка текущей версии +alembic current + +# Просмотр истории миграций +alembic history ``` +**📋 Список миграций:** +- **001** - Инициализация таблиц +- **003** - Добавление регистрации и счетов +- **004** - Добавление claimed_at поля +- **005** - Добавление системы чата +- **006** - Исправление отсутствующих столбцов ✨ + +> **Важно**: При развертывании всегда выполняйте `alembic upgrade head` для применения всех миграций. + ### 4. Запуск бота ```bash diff --git a/migrations/versions/006_fix_missing_columns.py b/migrations/versions/006_fix_missing_columns.py new file mode 100644 index 0000000..17e7a23 --- /dev/null +++ b/migrations/versions/006_fix_missing_columns.py @@ -0,0 +1,90 @@ +"""Add missing columns to fix database schema + +Revision ID: 006 +Revises: 005 +Create Date: 2025-11-17 05:35:00.000000 + +""" +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision = '006' +down_revision = '005' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # Добавляем отсутствующий столбец account_id в participations (если еще не существует) + op.execute(""" + DO $$ + BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='participations' AND column_name='account_id') THEN + ALTER TABLE participations ADD COLUMN account_id INTEGER; + ALTER TABLE participations + ADD CONSTRAINT fk_participations_account_id + FOREIGN KEY (account_id) REFERENCES accounts(id) + ON DELETE SET NULL; + END IF; + END $$; + """) + + # Добавляем отсутствующие столбцы в winners + op.execute(""" + DO $$ + BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='winners' AND column_name='is_notified') THEN + ALTER TABLE winners ADD COLUMN is_notified BOOLEAN DEFAULT FALSE; + END IF; + + IF NOT EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='winners' AND column_name='is_claimed') THEN + ALTER TABLE winners ADD COLUMN is_claimed BOOLEAN DEFAULT FALSE; + END IF; + + IF NOT EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='winners' AND column_name='claimed_at') THEN + ALTER TABLE winners ADD COLUMN claimed_at TIMESTAMP WITH TIME ZONE; + END IF; + END $$; + """) + + +def downgrade() -> None: + # Удаляем добавленные столбцы в обратном порядке + + # Удаляем столбцы из winners + op.execute(""" + DO $$ + BEGIN + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='winners' AND column_name='claimed_at') THEN + ALTER TABLE winners DROP COLUMN claimed_at; + END IF; + + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='winners' AND column_name='is_claimed') THEN + ALTER TABLE winners DROP COLUMN is_claimed; + END IF; + + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='winners' AND column_name='is_notified') THEN + ALTER TABLE winners DROP COLUMN is_notified; + END IF; + END $$; + """) + + # Удаляем account_id из participations + op.execute(""" + DO $$ + BEGIN + IF EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='participations' AND column_name='account_id') THEN + ALTER TABLE participations DROP CONSTRAINT IF EXISTS fk_participations_account_id; + ALTER TABLE participations DROP COLUMN account_id; + END IF; + END $$; + """) \ No newline at end of file