Files
colibre/src/migrations.py
T
Colin Maudry c4aa90b0d1 feat: améliorations UX roadmap votes #94
- Votes cappés à VOTES_PER_WEEK (pas d'accumulation) pour valoriser
  les connexions régulières
- Solde de votes affiché dans la liste (input inéditable) à la place
  du bandeau Alert, avec date de prochain rechargement
- Compteur de votes par feature affiché comme input inéditable en
  fin de ligne (avant le bouton "+")
- Animation FLIP JS (roadmap_flip.js) : seules les lignes qui changent
  de position sont animées après un vote
- Renommage votes_credited_until → votes_last_credited_at (migration 0005)
- Constantes du module utilisées dans les assertions de tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 16:39:13 +02:00

64 lines
2.1 KiB
Python

"""
Migrations de schéma SQLite.
Ajouter une migration : append un tuple (id, sql) à _MIGRATIONS.
L'id doit être unique et croissant (convention : NNNN_description).
apply_pending() est idempotent ; elle peut être appelée à chaque démarrage.
"""
import sqlite3
from datetime import datetime, timezone
from src.auth.db import get_conn
_MIGRATIONS: list[tuple[str, str]] = [
(
"0001_add_prix_ht_to_subscriptions",
"ALTER TABLE subscriptions ADD COLUMN prix_ht REAL",
),
(
"0002_add_siret_to_users",
"ALTER TABLE users ADD COLUMN siret TEXT",
),
(
"0003_add_votes_balance_to_subscriptions",
"ALTER TABLE subscriptions ADD COLUMN votes_balance INTEGER NOT NULL DEFAULT 0",
),
(
"0004_add_votes_last_credited_at_to_subscriptions",
"ALTER TABLE subscriptions ADD COLUMN votes_last_credited_at TEXT",
),
(
"0005_rename_votes_credited_until_to_votes_last_credited_at",
"ALTER TABLE subscriptions RENAME COLUMN votes_credited_until TO votes_last_credited_at",
),
]
def apply_pending() -> None:
conn = get_conn()
conn.execute(
"CREATE TABLE IF NOT EXISTS schema_migrations "
"(id TEXT PRIMARY KEY, applied_at TEXT NOT NULL)"
)
applied = {
row[0] for row in conn.execute("SELECT id FROM schema_migrations").fetchall()
}
now = datetime.now(timezone.utc).isoformat()
for migration_id, sql in _MIGRATIONS:
if migration_id not in applied:
try:
conn.execute(sql)
except sqlite3.OperationalError as exc:
# Sur une DB fraîche (schéma déjà à jour), certaines migrations
# sont sans effet : ADD COLUMN → "duplicate column name",
# RENAME COLUMN → "no such column". On les ignore.
err = str(exc)
if "duplicate column name" not in err and "no such column" not in err:
raise
conn.execute(
"INSERT INTO schema_migrations (id, applied_at) VALUES (?, ?)",
(migration_id, now),
)
conn.commit()