Тексты воронки по ТЗ + смена ссылок из админки

Тексты:
- «Сколько лет игроку?» (было «…будущему ученику?») во всех местах;
- сообщение для «Младше 12 лет» приведено дословно к ТЗ (§4);
- убраны отсебятины-преамбулы, которых нет в ТЗ (приветствие, старт воронки,
  цены «Что дальше?», интенсив «Хотите записаться?»); кнопка младше-12 «Вернуться назад».

Смена ссылок в админке:
- таблица bot_links (key, url) + методы get_link/get_all_links/set_link;
- _link(key): БД-переопределение → дефолт из config/.env; используется на шагах оплаты;
- раздел «Ссылки 🔗» в админ-панели: список текущих адресов + «✏️ Изменить ссылку»
  (выбор из 8 кнопок → ввод URL с валидацией http/https). UTM добавляются автоматически.

Тесты: добавлен test_admin_edit_link. pytest 31 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenik
2026-07-23 19:45:47 +03:00
parent fac2e3808b
commit 261e5c2da0
5 changed files with 144 additions and 17 deletions
+37 -1
View File
@@ -188,7 +188,43 @@ class DatabaseManager:
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
# Table for editable bot links (переопределяют дефолты из config/.env)
cursor.execute("""
CREATE TABLE IF NOT EXISTS bot_links (
key TEXT PRIMARY KEY,
url TEXT NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
# ---------- Редактируемые ссылки (кнопки записи/оплаты) ----------
def get_link(self, key: str):
"""URL из БД (если админ переопределил) или None."""
with self._get_connection() as conn:
cursor = conn.cursor()
cursor.execute("SELECT url FROM bot_links WHERE key = ?", (key,))
row = cursor.fetchone()
return row[0] if row else None
def get_all_links(self) -> Dict[str, str]:
"""Все переопределённые ссылки из БД в виде {key: url}."""
with self._get_connection() as conn:
cursor = conn.cursor()
cursor.execute("SELECT key, url FROM bot_links")
return {k: u for k, u in cursor.fetchall()}
def set_link(self, key: str, url: str):
"""Задать/обновить ссылку (переопределяет дефолт из config)."""
with self._get_connection() as conn:
cursor = conn.cursor()
cursor.execute(
"INSERT INTO bot_links (key, url) VALUES (?, ?) "
"ON CONFLICT(key) DO UPDATE SET url = excluded.url, updated_at = CURRENT_TIMESTAMP",
(key, url)
)
conn.commit()
def get_user_data(self, user_id: int) -> Dict[str, Any]: