From 4ec4936a0f86c2e1839597b3f8d6ac4bc6f85ca3 Mon Sep 17 00:00:00 2001 From: tsygankoviva Date: Thu, 2 Jul 2026 09:59:16 +0300 Subject: [PATCH] =?UTF-8?q?websocket-projects:=20=D0=B2=D0=BE=D0=B7=D0=B2?= =?UTF-8?q?=D1=80=D0=B0=D1=89=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20line=5Fid,?= =?UTF-8?q?=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/api/v1/websocket.py | 35 +++++++++++++---- api/src/repository/budget_line_repository.py | 2 +- .../rf_project_report_line_repository.py | 39 +++++++++++++++++++ .../rf_project_report_repository.py | 33 ++++++++++++++++ .../rf_project_report_line_service.py | 34 ++++++++++++++++ api/src/services/rf_project_report_service.py | 31 +++++++++++++++ 6 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 api/src/repository/rf_project_report_line_repository.py create mode 100644 api/src/repository/rf_project_report_repository.py create mode 100644 api/src/services/rf_project_report_line_service.py create mode 100644 api/src/services/rf_project_report_service.py diff --git a/api/src/api/v1/websocket.py b/api/src/api/v1/websocket.py index d23a114..662b57c 100644 --- a/api/src/api/v1/websocket.py +++ b/api/src/api/v1/websocket.py @@ -14,6 +14,8 @@ from sqlalchemy.exc import IntegrityError from fastapi import APIRouter, WebSocket, WebSocketDisconnect, status from sqlalchemy.ext.asyncio import AsyncSession +from src.services.rf_project_report_service import RfProjectReportService +from src.services.rf_project_report_line_service import RfProjectReportLineService from src.repository.user_repository import UserRepository from src.services.budget_line_service import BudgetLineService from src.api.v1.deps import get_user_by_token @@ -490,7 +492,8 @@ class FormEventProcess: class ProjectEventProcess: def __init__(self, db: AsyncSession): self.project_service: ProjectService = ProjectService(db) - self.bf_service: BudgetFormService = BudgetFormService(db) + self.prl_service: RfProjectReportLineService = RfProjectReportLineService(db) + self.pr_service: RfProjectReportService = RfProjectReportService(db) self.user_service: UserService = UserService(db) async def process( @@ -573,11 +576,16 @@ class ProjectEventProcess: expense_item_id: Optional[int] = None } """ - project = await self.project_service.get(project_id=project_id, user=user) - if not project: + project_report = await self.pr_service.get( + year=year, + report_type=report_type, + project_id=project_id, + ) + if not project_report: return None - - return await self.project_service.add_form3_line( + + ids = await self.prl_service.get_ids(project_report_id=project_report.id) + result = await self.project_service.add_form3_line( project_id=project_id, year=year, report_type=report_type, @@ -585,6 +593,16 @@ class ProjectEventProcess: user=user, ) + final_result = { + "data": result, + "new_line_id": None, + } + for el in result: + if el[3]["line_id"] and el[3]["line_id"] not in ids: + final_result["new_line_id"] = el[3]["line_id"] + return final_result + return final_result + async def __del_row( self, event_data: dict, @@ -595,7 +613,7 @@ class ProjectEventProcess: ) -> list[tuple]: """ data = { - "line_id": int, + "row_id": int, } """ project = await self.project_service.get(project_id=project_id, user=user) @@ -606,7 +624,7 @@ class ProjectEventProcess: project_id=project_id, year=year, report_type=report_type, - line_id=event_data["line_id"], + line_id=event_data["row_id"], user=user, ) @@ -776,6 +794,7 @@ async def process_websocket( async with get_db_session(user_id=user_id) as db: processor = processor_cls(db) t0 = time.perf_counter() + data_old = data.copy() data["result"] = await processor.process( event_data=data, user_id=user_id, @@ -789,7 +808,7 @@ async def process_websocket( "time_ms": f"{db_ms:.2f}", "event": data.get("event"), } - extra.update(data) + extra.update(data_old) logger.info( f"db_time: {extra}", extra=extra, diff --git a/api/src/repository/budget_line_repository.py b/api/src/repository/budget_line_repository.py index 0ca3c71..ed113c0 100644 --- a/api/src/repository/budget_line_repository.py +++ b/api/src/repository/budget_line_repository.py @@ -12,7 +12,7 @@ class BudgetLineRepository: query = select(BudgetLine).where(BudgetLine.id == budget_line_id).limit(1) return (await self.db.execute(query)).scalar_one_or_none() - async def get_list(self, budget_line_ids: list[int]) -> BudgetLine | None: + async def get_list(self, budget_line_ids: list[int]) -> list[BudgetLine]: query = select(BudgetLine).where(BudgetLine.id.in_(budget_line_ids)) return (await self.db.execute(query)).scalars().all() diff --git a/api/src/repository/rf_project_report_line_repository.py b/api/src/repository/rf_project_report_line_repository.py new file mode 100644 index 0000000..3ec5abe --- /dev/null +++ b/api/src/repository/rf_project_report_line_repository.py @@ -0,0 +1,39 @@ +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from src.db.models.rf_project_report_line import RfProjectReportLine + + + +class RfProjectReportLineRepository: + def __init__(self, db: AsyncSession): + self.db = db + + async def get(self, line_id: int) -> RfProjectReportLine | None: + query = select( + RfProjectReportLine + ).where( + RfProjectReportLine.id == line_id + ).limit(1) + return (await self.db.execute(query)).scalar_one_or_none() + + async def get_list(self, line_ids: list[int]) -> list[RfProjectReportLine]: + query = select( + RfProjectReportLine + ).where( + RfProjectReportLine.id.in_(line_ids) + ) + return (await self.db.execute(query)).scalars().all() + + async def get_ids( + self, + project_report_id: int, + ) -> list[int]: + + query = select( + RfProjectReportLine.id + ).where( + RfProjectReportLine.rf_project_report_id == project_report_id + ) + return (await self.db.execute(query)).scalars().all() + diff --git a/api/src/repository/rf_project_report_repository.py b/api/src/repository/rf_project_report_repository.py new file mode 100644 index 0000000..6337a80 --- /dev/null +++ b/api/src/repository/rf_project_report_repository.py @@ -0,0 +1,33 @@ +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from src.db.models.rf_project_report import RfProjectReport + + + +class RfProjectReportRepository: + def __init__(self, db: AsyncSession): + self.db = db + + async def get( + self, + report_id: int | None = None, + year: int | None = None, + report_type: str | None = None, + project_id: int | None = None, + ) -> RfProjectReport | None: + assert report_id is not None or all((el is not None for el in (year, report_type, project_id))) + query = select( + RfProjectReport + ) + if report_id is not None: + query = query.where(RfProjectReport.id == report_id) + else: + query = query.where( + RfProjectReport.year == year, + RfProjectReport.report_type == report_type, + RfProjectReport.project_id == project_id + ) + + query = query.limit(1) + return (await self.db.execute(query)).scalar_one_or_none() diff --git a/api/src/services/rf_project_report_line_service.py b/api/src/services/rf_project_report_line_service.py new file mode 100644 index 0000000..e29c48d --- /dev/null +++ b/api/src/services/rf_project_report_line_service.py @@ -0,0 +1,34 @@ + +from sqlalchemy.ext.asyncio import AsyncSession + +from src.db.models.rf_project_report_line import RfProjectReportLine +from src.repository.rf_project_report_line_repository import RfProjectReportLineRepository +from src.db.models.app_user import AppUser + + + + +class RfProjectReportLineService: + def __init__(self, db: AsyncSession): + self.db = db + self.prl_repo = RfProjectReportLineRepository(db) + + async def get( + self, + user: AppUser, + line_id: int, + ) -> RfProjectReportLine | None: + return await self.prl_repo.get(line_id=line_id) + + async def get_list( + self, + user: AppUser, + line_ids: list[int], + ) -> list[RfProjectReportLine]: + return await self.prl_repo.get_list(line_ids=line_ids) + + async def get_ids( + self, + project_report_id: int, + ) -> list[int]: + return await self.prl_repo.get_ids(project_report_id=project_report_id) diff --git a/api/src/services/rf_project_report_service.py b/api/src/services/rf_project_report_service.py new file mode 100644 index 0000000..293bf03 --- /dev/null +++ b/api/src/services/rf_project_report_service.py @@ -0,0 +1,31 @@ + +from sqlalchemy.ext.asyncio import AsyncSession + +from src.db.models.rf_project_report import RfProjectReport +from src.repository.rf_project_report_repository import RfProjectReportRepository +from src.db.models.rf_project_report_line import RfProjectReportLine +from src.repository.rf_project_report_line_repository import RfProjectReportLineRepository +from src.db.models.app_user import AppUser + + + + +class RfProjectReportService: + def __init__(self, db: AsyncSession): + self.db = db + self.pr_repo = RfProjectReportRepository(db) + + async def get( + self, + user: AppUser| None = None, + report_id: int | None = None, + year: int | None = None, + report_type: str | None = None, + project_id: int | None = None, + ) -> RfProjectReport | None: + return await self.pr_repo.get( + report_id=report_id, + year=year, + report_type=report_type, + project_id=project_id, + )