feat: attributes in cards and projects
This commit is contained in:
@@ -5,7 +5,7 @@ from sqlalchemy import select, and_
|
||||
|
||||
from card_attributes.exceptions import CardAttributeException
|
||||
from card_attributes.handlers.base_handler import BaseHandler
|
||||
from models import CardAttribute, Attribute, Card
|
||||
from models import CardAttribute, Attribute, Card, Project
|
||||
from .card_attributes_query_handler import CardAttributesQueryHandler
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class CardAttributesCommandHandler(BaseHandler):
|
||||
self.session.add(card_attribute)
|
||||
await self.session.flush()
|
||||
|
||||
async def _set_attribute_after_creation(self, card_id: int, project_attr: Attribute, attributes: Optional[dict]):
|
||||
async def _set_attribute_after_creation(self, card_id: int, project_attr: Attribute, attributes: Optional[dict] = None):
|
||||
if attributes and project_attr.name in attributes:
|
||||
passed_value = attributes[project_attr.name]
|
||||
return await self._create_card_attribute(card_id, project_attr.id, passed_value)
|
||||
@@ -65,7 +65,7 @@ class CardAttributesCommandHandler(BaseHandler):
|
||||
else:
|
||||
card_attribute.set_value(value)
|
||||
|
||||
async def set_attr_for_each_in_group(self, group_id: int, attribute_name: str, value):
|
||||
async def set_attr_for_each_card_in_group(self, group_id: int, attribute_name: str, value):
|
||||
query_handler = CardAttributesQueryHandler(self.session)
|
||||
card_ids: list[int] = await query_handler.get_card_ids_by_group_id(group_id)
|
||||
|
||||
@@ -81,10 +81,33 @@ class CardAttributesCommandHandler(BaseHandler):
|
||||
try:
|
||||
attr = next(attr for attr in project_attrs if attr.name == attr_name)
|
||||
if attr.is_applicable_to_group and card.group:
|
||||
await self.set_attr_for_each_in_group(card.group.id, attr_name, attr_value)
|
||||
await self.set_attr_for_each_card_in_group(card.group.id, attr_name, attr_value)
|
||||
else:
|
||||
await self._set_card_attribute(card.id, attr_name, attr_value)
|
||||
except StopIteration:
|
||||
pass
|
||||
except CardAttributeException:
|
||||
raise
|
||||
|
||||
async def set_project_attributes(self, project: Project, attribute_ids: list[int]):
|
||||
query_handler = CardAttributesQueryHandler(self.session)
|
||||
attributes = await query_handler.get_attributes_by_ids(attribute_ids)
|
||||
|
||||
attributes_to_create = []
|
||||
for attribute in attributes:
|
||||
project_attr = await query_handler.get_project_attr(project.id, attribute.id)
|
||||
if not project_attr:
|
||||
attributes_to_create.append(attribute)
|
||||
|
||||
async for card in query_handler.get_all_cards_for_project(project.id):
|
||||
await self._add_attributes_to_card(card, attributes_to_create)
|
||||
|
||||
project.attributes = attributes
|
||||
await self.session.commit()
|
||||
|
||||
async def _add_attributes_to_card(self, card: Card, attributes_to_create: list[Attribute]):
|
||||
card_attribute_ids: set[int] = set((attr.attribute_id for attr in card.attributes))
|
||||
|
||||
for attribute in attributes_to_create:
|
||||
if attribute.id not in card_attribute_ids:
|
||||
await self._set_attribute_after_creation(card.id, attribute)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import joinedload, selectinload
|
||||
from sqlalchemy import select, and_
|
||||
from sqlalchemy.ext.asyncio import AsyncResult
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from card_attributes.handlers.base_handler import BaseHandler
|
||||
from models import Attribute, project_attribute, card_relations
|
||||
from models import Attribute, project_attribute, card_relations, Card, Project, Board
|
||||
|
||||
|
||||
class CardAttributesQueryHandler(BaseHandler):
|
||||
@@ -12,7 +13,10 @@ class CardAttributesQueryHandler(BaseHandler):
|
||||
stmt = (
|
||||
select(Attribute)
|
||||
.join(project_attribute, project_attribute.c.attribute_id == Attribute.id)
|
||||
.where(project_attribute.c.project_id == project_id)
|
||||
.where(
|
||||
project_attribute.c.project_id == project_id,
|
||||
Attribute.is_deleted == False,
|
||||
)
|
||||
)
|
||||
attributes = (await self.session.scalars(stmt)).all()
|
||||
return list(attributes)
|
||||
@@ -23,7 +27,10 @@ class CardAttributesQueryHandler(BaseHandler):
|
||||
.options(
|
||||
selectinload(Attribute.projects),
|
||||
)
|
||||
.where(Attribute.name == attr_name)
|
||||
.where(
|
||||
Attribute.name == attr_name,
|
||||
Attribute.is_deleted == False,
|
||||
)
|
||||
)
|
||||
attribute = (await self.session.scalars(stmt)).first()
|
||||
return attribute
|
||||
@@ -35,3 +42,37 @@ class CardAttributesQueryHandler(BaseHandler):
|
||||
)
|
||||
ids = await self.session.scalars(stmt)
|
||||
return list(ids)
|
||||
|
||||
async def get_all_cards_for_project(self, project_id: int) -> AsyncResult[Card]:
|
||||
stmt = (
|
||||
select(Card)
|
||||
.join(Board)
|
||||
.join(Project)
|
||||
.where(Project.id == project_id)
|
||||
.options(selectinload(Card.attributes))
|
||||
.execution_options(yield_per=100)
|
||||
)
|
||||
rows: AsyncResult[tuple[Card]] = await self.session.stream(stmt)
|
||||
async for row in rows:
|
||||
yield row[0]
|
||||
|
||||
async def get_project_attr(self, project_id: int, attribute_id: int) -> project_attribute:
|
||||
stmt_is_attribute_already_added = (
|
||||
select(project_attribute)
|
||||
.where(
|
||||
and_(
|
||||
project_attribute.c.project_id == project_id,
|
||||
project_attribute.c.attribute_id == attribute_id,
|
||||
)
|
||||
)
|
||||
)
|
||||
project_attribute_inst = await self.session.execute(stmt_is_attribute_already_added)
|
||||
return project_attribute_inst.first()
|
||||
|
||||
async def get_attributes_by_ids(self, attribute_ids: list[int]) -> list[Attribute]:
|
||||
stmt = (
|
||||
select(Attribute)
|
||||
.where(Attribute.id.in_(attribute_ids))
|
||||
)
|
||||
attributes = (await self.session.scalars(stmt)).all()
|
||||
return list(attributes)
|
||||
|
||||
Reference in New Issue
Block a user