feat: modules dependencies
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -22,6 +22,7 @@ class ModuleSchema(BaseSchema):
|
||||
label: str
|
||||
icon_name: Optional[str] = None
|
||||
is_deleted: bool
|
||||
depends_on: list["ModuleSchema"] = []
|
||||
|
||||
|
||||
class ProjectSchema(ProjectGeneralInfoSchema):
|
||||
|
||||
@@ -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="Модули успешно обновлены")
|
||||
|
||||
Reference in New Issue
Block a user