Админка: раздел «Регистрации пользователей» (аккаунт, имя, способ, почта, дата, подписка)

Источник — WEB_ACCOUNTS (created_at, способ = префикс account_id) + обогащение
именем/почтой из последней сессии WEB_SESSIONS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
berkio_admin_gitea
2026-07-09 19:54:57 +00:00
parent 2df36dfe5f
commit b2fea7854d

View File

@@ -3161,6 +3161,12 @@ _ADMIN_HTML = """<!doctype html>
<tbody id="t-docs"></tbody></table></div>
</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>
<h2>Активные подписки</h2>
<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>';
}).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 дней, старые слева
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",
(now,))]
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(
"SELECT payment_id, amount, currency, status, purpose, email, created_at, paid_at "