124 lines
3.9 KiB
Python
124 lines
3.9 KiB
Python
from jinja2 import Environment, FileSystemLoader
|
|
|
|
from fastapi import APIRouter, Request
|
|
from fastapi.responses import HTMLResponse
|
|
from sqlalchemy import func, select
|
|
|
|
from app.database import async_session_factory
|
|
from app.models.payment import Payment, PaymentStatus
|
|
from app.models.server import Server
|
|
from app.models.tariff import Tariff
|
|
from app.models.user import User
|
|
from app.repositories.payment import PaymentRepository
|
|
from app.repositories.server import ServerRepository
|
|
from app.repositories.tariff import TariffRepository
|
|
from app.repositories.user import UserRepository
|
|
|
|
router = APIRouter(prefix="/admin", tags=["admin"])
|
|
|
|
_env = Environment(loader=FileSystemLoader("app/templates"), auto_reload=False)
|
|
|
|
|
|
def _render(name: str, **context) -> str:
|
|
template = _env.get_template(name)
|
|
return template.render(**context)
|
|
|
|
|
|
@router.get("/", response_class=HTMLResponse)
|
|
async def dashboard(request: Request):
|
|
async with async_session_factory() as session:
|
|
|
|
async def _count(model, *filters):
|
|
stmt = select(func.count(model.id))
|
|
for f in filters:
|
|
stmt = stmt.where(f)
|
|
return (await session.execute(stmt)).scalar_one()
|
|
|
|
total_users = await _count(User)
|
|
active_users = await _count(User, User.is_active.is_(True))
|
|
total_tariffs = await _count(Tariff)
|
|
total_servers = await _count(Server)
|
|
active_servers = await _count(Server, Server.is_active.is_(True))
|
|
total_payments = await _count(Payment)
|
|
confirmed_payments = await _count(
|
|
Payment, Payment.status == PaymentStatus.CONFIRMED
|
|
)
|
|
|
|
rev_stmt = select(func.coalesce(func.sum(Payment.amount), 0)).where(
|
|
Payment.status == PaymentStatus.CONFIRMED
|
|
)
|
|
total_revenue = float((await session.execute(rev_stmt)).scalar_one())
|
|
|
|
return HTMLResponse(
|
|
_render(
|
|
"dashboard.html",
|
|
request=request,
|
|
total_users=total_users,
|
|
active_users=active_users,
|
|
total_tariffs=total_tariffs,
|
|
total_servers=total_servers,
|
|
active_servers=active_servers,
|
|
total_payments=total_payments,
|
|
confirmed_payments=confirmed_payments,
|
|
total_revenue=total_revenue,
|
|
)
|
|
)
|
|
|
|
|
|
@router.get("/users", response_class=HTMLResponse)
|
|
async def users_page(request: Request):
|
|
async with async_session_factory() as session:
|
|
repo = UserRepository(session)
|
|
users = await repo.get_all()
|
|
|
|
return HTMLResponse(
|
|
_render("users.html", request=request, users=users)
|
|
)
|
|
|
|
|
|
@router.get("/payments", response_class=HTMLResponse)
|
|
async def payments_page(request: Request):
|
|
async with async_session_factory() as session:
|
|
tariff_repo = TariffRepository(session)
|
|
|
|
stmt = select(Payment).order_by(Payment.created_at.desc())
|
|
result = await session.execute(stmt)
|
|
payments = list(result.scalars().all())
|
|
|
|
tariffs_map = {}
|
|
for p in payments:
|
|
if p.tariff_id not in tariffs_map:
|
|
t = await tariff_repo.get(p.tariff_id)
|
|
tariffs_map[p.tariff_id] = t.name if t else "—"
|
|
|
|
return HTMLResponse(
|
|
_render(
|
|
"payments.html",
|
|
request=request,
|
|
payments=payments,
|
|
tariffs_map=tariffs_map,
|
|
)
|
|
)
|
|
|
|
|
|
@router.get("/servers", response_class=HTMLResponse)
|
|
async def servers_page(request: Request):
|
|
async with async_session_factory() as session:
|
|
repo = ServerRepository(session)
|
|
servers = await repo.get_all()
|
|
|
|
return HTMLResponse(
|
|
_render("servers.html", request=request, servers=servers)
|
|
)
|
|
|
|
|
|
@router.get("/tariffs", response_class=HTMLResponse)
|
|
async def tariffs_page(request: Request):
|
|
async with async_session_factory() as session:
|
|
repo = TariffRepository(session)
|
|
tariffs = await repo.get_all()
|
|
|
|
return HTMLResponse(
|
|
_render("tariffs.html", request=request, tariffs=tariffs)
|
|
)
|