Untitled

4ae4d avatar
4ae4d
plain_text
01/27/2026 11:56 AM
5.4 KB
7
Indexable
diff --git a/src/backend/app/api/v1/__init__.py b/src/backend/app/api/v1/__init__.py
index e9975d1..ecc6004 100644
--- a/src/backend/app/api/v1/__init__.py
+++ b/src/backend/app/api/v1/__init__.py
@@ -1,6 +1,13 @@
 from .city import api_router as city_router
 from .event import api_router as event_router
+from .report import api_router as report_router
 from .tag import api_router as tag_router
 from .user import api_router as user_router
 
-__all__ = ["user_router", "event_router", "city_router", "tag_router"]
+__all__ = [
+    "user_router",
+    "event_router",
+    "city_router",
+    "tag_router",
+    "report_router",
+]
diff --git a/src/backend/app/api/v1/report.py b/src/backend/app/api/v1/report.py
new file mode 100644
index 0000000..965747c
--- /dev/null
+++ b/src/backend/app/api/v1/report.py
@@ -0,0 +1,61 @@
+from __future__ import annotations
+
+from datetime import date
+from io import BytesIO
+from typing import Annotated
+
+from fastapi import APIRouter, Query
+from fastapi.responses import StreamingResponse
+from openpyxl import Workbook
+
+api_router = APIRouter(prefix="/reports", tags=["Reports"])
+
+REPORT_COLUMNS: list[tuple[str, str]] = [
+    ("event_name", "Название"),
+    ("city", "Город"),
+    ("location", "Локация"),
+    ("date", "Дата"),
+    ("time", "Время"),
+    ("participants_count", "Кол-во участников"),
+    ("points", "Кол-во баллов"),
+    ("tags", "Теги"),
+    ("organizer_fio", "ФИО организатора"),
+    ("beneficiaries_count", "Кол-во благополучателей"),
+    ("summary", "Описание"),
+]
+
+
+@api_router.get("/export")
+async def export_reports_xlsx(
+    date_from: Annotated[date | None, Query(description="YYYY-MM-DD")] = None,
+    date_to: Annotated[date | None, Query(description="YYYY-MM-DD")] = None,
+):
+    """
+    DEMO: экспорт отчётов в xlsx
+    пока без выборки из БД - возвращаем файл с шапкой
+    """
+    wb = Workbook()
+    ws = wb.active
+    ws.title = "Reports"
+
+    ws.append([title for _, title in REPORT_COLUMNS])
+
+    # пока без данных.
+
+    buf = BytesIO()
+    wb.save(buf)
+    buf.seek(0)
+
+    name_parts = ["reports"]
+    if date_from:
+        name_parts.append(str(date_from))
+    if date_to:
+        name_parts.append(str(date_to))
+    filename = "_".join(name_parts) + ".xlsx"
+
+    headers = {"Content-Disposition": f'attachment; filename="{filename}"'}
+    return StreamingResponse(
+        buf,
+        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        headers=headers,
+    )
diff --git a/src/backend/app/application.py b/src/backend/app/application.py
index cbd248d..3e752ed 100644
--- a/src/backend/app/application.py
+++ b/src/backend/app/application.py
@@ -5,7 +5,7 @@ from fastapi import FastAPI, Request
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.responses import PlainTextResponse
 
-from app.api.v1 import city_router, event_router, tag_router, user_router
+from app.api.v1 import city_router, event_router, tag_router, user_router, report_router
 from app.cache import redis_client
 from app.config.settings import settings
 from app.middlewares import LoggerMiddleware
@@ -55,6 +55,7 @@ api.add_middleware(LoggerMiddleware)
 
 api.include_router(city_router)
 api.include_router(event_router)
+api.include_router(report_router)
 api.include_router(tag_router)
 api.include_router(user_router)
 
diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt
index 1a5d884..23d1b36 100644
--- a/src/backend/requirements.txt
+++ b/src/backend/requirements.txt
@@ -35,6 +35,7 @@ Mako==1.3.6
 MarkupSafe==3.0.2
 multidict==6.1.0
 numpy==2.2.1
+openpyxl==3.1.5
 orjson==3.10.13
 packaging==24.2
 passlib==1.7.4
diff --git a/src/bot/core/handlers/__init__.py b/src/bot/core/handlers/__init__.py
index 2dec733..02e2438 100644
--- a/src/bot/core/handlers/__init__.py
+++ b/src/bot/core/handlers/__init__.py
@@ -89,3 +89,4 @@ __all__ = [
     "events_rt",
     "view_by_uuid_rt",
 ]
+
Editor is loading...
Leave a Comment