Админка: раздел «Регистрации пользователей» (аккаунт, имя, способ, почта, дата, подписка)
Источник — WEB_ACCOUNTS (created_at, способ = префикс account_id) + обогащение именем/почтой из последней сессии WEB_SESSIONS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
39
app/main.py
39
app/main.py
@@ -3161,6 +3161,12 @@ _ADMIN_HTML = """<!doctype html>
|
|||||||
<tbody id="t-docs"></tbody></table></div>
|
<tbody id="t-docs"></tbody></table></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Регистрации пользователей <span class="muted" id="reg-count"></span></h2>
|
||||||
|
<div class="scroll"><table><thead><tr><th>Пользователь</th><th>Имя</th><th>Способ</th><th>Почта</th><th>Дата</th><th>Подписка</th></tr></thead>
|
||||||
|
<tbody id="t-regs"></tbody></table></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Активные подписки</h2>
|
<h2>Активные подписки</h2>
|
||||||
<div class="scroll"><table><thead><tr><th>Аккаунт</th><th>Активна до</th><th class="num">Осталось</th></tr></thead>
|
<div class="scroll"><table><thead><tr><th>Аккаунт</th><th>Активна до</th><th class="num">Осталось</th></tr></thead>
|
||||||
@@ -3215,6 +3221,14 @@ _ADMIN_HTML = """<!doctype html>
|
|||||||
return '<tr><td>'+esc(s.account_id)+'</td><td>'+dOnly(s.sub_until)+'</td><td class="num">'+daysLeft(s.sub_until)+'</td></tr>';
|
return '<tr><td>'+esc(s.account_id)+'</td><td>'+dOnly(s.sub_until)+'</td><td class="num">'+daysLeft(s.sub_until)+'</td></tr>';
|
||||||
}).join('') : '<tr><td colspan="3" class="muted">Нет активных подписок</td></tr>';
|
}).join('') : '<tr><td colspan="3" class="muted">Нет активных подписок</td></tr>';
|
||||||
|
|
||||||
|
// Регистрации пользователей
|
||||||
|
var regs = (d.registrations && d.registrations.list) || [];
|
||||||
|
document.getElementById('reg-count').textContent = d.registrations ? '· всего ' + d.registrations.count : '';
|
||||||
|
document.getElementById('t-regs').innerHTML = regs.length ? regs.map(function(u){
|
||||||
|
return '<tr><td>'+esc(u.account_id)+'</td><td>'+esc(u.name||'—')+'</td><td>'+esc(u.method)+
|
||||||
|
'</td><td>'+esc(u.email||'—')+'</td><td>'+dts(u.created_at)+'</td><td>'+(u.sub_active?'✓':'—')+'</td></tr>';
|
||||||
|
}).join('') : '<tr><td colspan="6" class="muted">Пока нет регистраций</td></tr>';
|
||||||
|
|
||||||
// Активность по дням — три малых кратных (заходы / документы сайт+бот / страницы)
|
// Активность по дням — три малых кратных (заходы / документы сайт+бот / страницы)
|
||||||
var dl = d.daily || []; // 14 дней, старые слева
|
var dl = d.daily || []; // 14 дней, старые слева
|
||||||
function dd(x){ return x.day.slice(8)+'.'+x.day.slice(5,7); }
|
function dd(x){ return x.day.slice(8)+'.'+x.day.slice(5,7); }
|
||||||
@@ -3517,6 +3531,31 @@ def _admin_collect_stats() -> dict:
|
|||||||
"SELECT account_id, sub_until FROM WEB_ACCOUNTS WHERE sub_until > ? ORDER BY sub_until DESC",
|
"SELECT account_id, sub_until FROM WEB_ACCOUNTS WHERE sub_until > ? ORDER BY sub_until DESC",
|
||||||
(now,))]
|
(now,))]
|
||||||
out["subs"] = {"active_count": len(subs), "list": subs[:300]}
|
out["subs"] = {"active_count": len(subs), "list": subs[:300]}
|
||||||
|
# Регистрации пользователей (аккаунты сайта): способ = префикс account_id,
|
||||||
|
# имя/почту берём из последней сессии (WEB_SESSIONS), для email-входа — из самого id.
|
||||||
|
reg_rows = con.execute(
|
||||||
|
"SELECT a.account_id, a.created_at, a.sub_until, a.pm_email, "
|
||||||
|
"(SELECT s.name FROM WEB_SESSIONS s WHERE s.account_id=a.account_id ORDER BY s.created_at DESC LIMIT 1) AS s_name, "
|
||||||
|
"(SELECT s.email FROM WEB_SESSIONS s WHERE s.account_id=a.account_id ORDER BY s.created_at DESC LIMIT 1) AS s_email, "
|
||||||
|
"(SELECT s.provider FROM WEB_SESSIONS s WHERE s.account_id=a.account_id ORDER BY s.created_at DESC LIMIT 1) AS s_prov "
|
||||||
|
"FROM WEB_ACCOUNTS a ORDER BY a.created_at DESC LIMIT 300").fetchall()
|
||||||
|
_meth = {"tg": "Telegram", "telegram": "Telegram", "yandex": "Яндекс",
|
||||||
|
"vk": "VK", "email": "Почта"}
|
||||||
|
regs = []
|
||||||
|
for r in reg_rows:
|
||||||
|
aid = r["account_id"] or ""
|
||||||
|
prov, _sep, ident = aid.partition(":")
|
||||||
|
email = ident if prov == "email" else (r["s_email"] or r["pm_email"] or "")
|
||||||
|
regs.append({
|
||||||
|
"account_id": aid,
|
||||||
|
"name": r["s_name"] or "",
|
||||||
|
"method": _meth.get((r["s_prov"] or prov or "").lower(), prov or "—"),
|
||||||
|
"email": email,
|
||||||
|
"created_at": r["created_at"],
|
||||||
|
"sub_active": bool(r["sub_until"] and r["sub_until"] > now),
|
||||||
|
})
|
||||||
|
reg_total = con.execute("SELECT COUNT(*) c FROM WEB_ACCOUNTS").fetchone()["c"]
|
||||||
|
out["registrations"] = {"count": reg_total, "list": regs}
|
||||||
# Платежи
|
# Платежи
|
||||||
pays = [dict(r) for r in con.execute(
|
pays = [dict(r) for r in con.execute(
|
||||||
"SELECT payment_id, amount, currency, status, purpose, email, created_at, paid_at "
|
"SELECT payment_id, amount, currency, status, purpose, email, created_at, paid_at "
|
||||||
|
|||||||
Reference in New Issue
Block a user