feat: modules dependencies

This commit is contained in:
2025-03-15 09:37:14 +04:00
parent d4b6720188
commit a466e46f28
3 changed files with 59 additions and 5 deletions

View File

@@ -12,8 +12,16 @@ if TYPE_CHECKING:
project_module = Table(
'project_module',
BaseModel.metadata,
Column('project_id', ForeignKey('projects.id')),
Column('module_id', ForeignKey('modules.id')),
Column('project_id', ForeignKey('projects.id'), primary_key=True),
Column('module_id', ForeignKey('modules.id'), primary_key=True),
)
module_dependencies = Table(
'module_dependencies',
BaseModel.metadata,
Column('module_id', ForeignKey('modules.id'), primary_key=True),
Column('depends_on_id', ForeignKey('modules.id'), primary_key=True),
)
@@ -26,6 +34,24 @@ class Module(BaseModel):
icon_name: Mapped[Optional[str]] = mapped_column(unique=True, nullable=False)
is_deleted: Mapped[bool] = mapped_column(default=False)
depends_on: Mapped[list['Module']] = relationship(
'Module',
secondary=module_dependencies,
primaryjoin='Module.id == module_dependencies.c.module_id',
secondaryjoin='Module.id == module_dependencies.c.depends_on_id',
back_populates='depended_on_by',
lazy='immediate',
)
depended_on_by: Mapped[list['Module']] = relationship(
'Module',
secondary='module_dependencies',
primaryjoin='Module.id == module_dependencies.c.depends_on_id',
secondaryjoin='Module.id == module_dependencies.c.module_id',
back_populates='depends_on',
lazy='noload',
)
projects: Mapped[list['Project']] = relationship(
'Project',
uselist=True,

View File

@@ -22,6 +22,7 @@ class ModuleSchema(BaseSchema):
label: str
icon_name: Optional[str] = None
is_deleted: bool
depends_on: list["ModuleSchema"] = []
class ProjectSchema(ProjectGeneralInfoSchema):

View File

@@ -1,7 +1,7 @@
from datetime import datetime
from sqlalchemy import select, update, func, delete
from sqlalchemy.orm import selectinload
from sqlalchemy.orm import selectinload, immediateload
from card_attributes import CardAttributesCommandHandler
from models import Project, Board, Module
@@ -27,7 +27,8 @@ class ProjectService(BaseService):
.outerjoin(board_count_sub, Project.id == board_count_sub.c.project_id)
.options(
selectinload(Project.attributes),
selectinload(Project.modules),
selectinload(Project.modules)
.selectinload(Module.depends_on),
)
.where(Project.is_deleted == False)
.order_by(Project.id)
@@ -90,22 +91,48 @@ class ProjectService(BaseService):
stmt = (
select(Module)
.where(Module.is_deleted == False)
.options(
selectinload(Module.depends_on),
)
)
modules = await self.session.scalars(stmt)
return GetAllModulesResponse(modules=modules.all())
def get_module_with_dependencies(self, module: Module, visited_ids: set[int]) -> set[Module]:
result_modules = {module}
for dependency in module.depends_on:
if dependency.id not in visited_ids:
visited_ids.add(dependency.id)
result_modules.update(
self.get_module_with_dependencies(dependency, visited_ids)
)
return result_modules
async def update_project_modules(self, request: UpdateModulesRequest) -> UpdateModulesResponse:
project: Optional[Project] = await self.session.get(Project, request.project_id)
if not project:
return UpdateModulesResponse(ok=False, message=f"Проект с ID {request.project_id} не найден")
load_dependencies = immediateload(Module.depends_on)
for i in range(5):
load_dependencies = load_dependencies.immediateload(Module.depends_on)
modules_stmt = (
select(Module)
.where(Module.id.in_(request.module_ids))
.options(load_dependencies)
)
modules = (await self.session.scalars(modules_stmt)).all()
project.modules = modules
result_modules = set()
visited_module_ids = set(request.module_ids)
for module in modules:
result_modules.update(
self.get_module_with_dependencies(module, visited_module_ids)
)
project.modules = list(result_modules)
await self.session.commit()
return UpdateModulesResponse(ok=True, message="Модули успешно обновлены")