feat: deal attributes editing
This commit is contained in:
@ -72,9 +72,14 @@ class Attribute(BaseModel, IdMixin, SoftDeleteMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class AttributeValue(BaseModel, IdMixin):
|
class AttributeValue(BaseModel):
|
||||||
__tablename__ = "attribute_values"
|
__tablename__ = "attribute_values"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(
|
||||||
|
primary_key=True,
|
||||||
|
autoincrement=True,
|
||||||
|
)
|
||||||
|
|
||||||
value: Mapped[Optional[dict[str, any]]] = mapped_column(JSONB)
|
value: Mapped[Optional[dict[str, any]]] = mapped_column(JSONB)
|
||||||
|
|
||||||
deal_id: Mapped[int] = mapped_column(
|
deal_id: Mapped[int] = mapped_column(
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
|
from sqlalchemy import and_
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
from models import Attribute, AttributeLabel, AttributeType
|
from models import (
|
||||||
|
Attribute,
|
||||||
|
AttributeLabel,
|
||||||
|
AttributeType,
|
||||||
|
AttributeValue,
|
||||||
|
module_attribute,
|
||||||
|
)
|
||||||
from repositories.mixins import *
|
from repositories.mixins import *
|
||||||
from schemas.attribute import CreateAttributeSchema, UpdateAttributeSchema
|
from schemas.attribute import CreateAttributeSchema, UpdateAttributeSchema, UpdateDealModuleAttributeSchema
|
||||||
from utils.exceptions import ForbiddenException
|
from utils.exceptions import ForbiddenException
|
||||||
|
|
||||||
|
|
||||||
@ -71,3 +78,75 @@ class AttributeRepository(
|
|||||||
stmt = select(AttributeType).where(AttributeType.is_deleted.is_(False))
|
stmt = select(AttributeType).where(AttributeType.is_deleted.is_(False))
|
||||||
result = await self.session.execute(stmt)
|
result = await self.session.execute(stmt)
|
||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
async def get_deal_module_attributes(
|
||||||
|
self, deal_id: int, module_id: int
|
||||||
|
) -> list[tuple[Attribute, AttributeValue, AttributeLabel]]:
|
||||||
|
stmt = (
|
||||||
|
select(Attribute, AttributeValue, AttributeLabel)
|
||||||
|
.outerjoin(
|
||||||
|
AttributeValue,
|
||||||
|
and_(
|
||||||
|
AttributeValue.attribute_id == Attribute.id,
|
||||||
|
AttributeValue.module_id == module_id,
|
||||||
|
AttributeValue.deal_id == deal_id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.outerjoin(
|
||||||
|
AttributeLabel,
|
||||||
|
and_(
|
||||||
|
AttributeLabel.attribute_id == Attribute.id,
|
||||||
|
AttributeLabel.module_id == module_id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.join(
|
||||||
|
module_attribute,
|
||||||
|
and_(
|
||||||
|
module_attribute.c.attribute_id == Attribute.id,
|
||||||
|
module_attribute.c.module_id == module_id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
result = await self.session.execute(stmt)
|
||||||
|
return list(result.all())
|
||||||
|
|
||||||
|
async def _get_deal_attribute_values(
|
||||||
|
self, deal_id: int, module_id: int
|
||||||
|
) -> list[AttributeValue]:
|
||||||
|
stmt = (
|
||||||
|
select(AttributeValue)
|
||||||
|
.join(Attribute, AttributeValue.attribute_id == Attribute.id)
|
||||||
|
.where(
|
||||||
|
AttributeValue.deal_id == deal_id,
|
||||||
|
AttributeValue.module_id == module_id,
|
||||||
|
Attribute.is_deleted.is_(False),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
result = await self.session.execute(stmt)
|
||||||
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
async def update_or_create_deal_attribute_values(
|
||||||
|
self,
|
||||||
|
deal_id: int,
|
||||||
|
module_id: int,
|
||||||
|
attributes: list[UpdateDealModuleAttributeSchema],
|
||||||
|
):
|
||||||
|
old_deal_attribute_values: list[AttributeValue] = await self._get_deal_attribute_values(deal_id, module_id)
|
||||||
|
dict_old_attrs: dict[int, AttributeValue] = {obj.attribute_id: obj for obj in old_deal_attribute_values}
|
||||||
|
|
||||||
|
for attribute in attributes:
|
||||||
|
if attribute.attribute_id in dict_old_attrs:
|
||||||
|
# update
|
||||||
|
attribute_value = dict_old_attrs[attribute.attribute_id]
|
||||||
|
attribute_value.value = attribute.value
|
||||||
|
else:
|
||||||
|
# create
|
||||||
|
attribute_value = AttributeValue(
|
||||||
|
attribute_id=attribute.attribute_id,
|
||||||
|
deal_id=deal_id,
|
||||||
|
module_id=module_id,
|
||||||
|
value=attribute.value,
|
||||||
|
)
|
||||||
|
self.session.add(attribute_value)
|
||||||
|
|
||||||
|
await self.session.commit()
|
||||||
|
|||||||
@ -46,7 +46,7 @@ class ModuleRepository(
|
|||||||
Module.is_deleted.is_(False),
|
Module.is_deleted.is_(False),
|
||||||
or_(Attribute.id.is_(None), Attribute.is_deleted.is_(False)),
|
or_(Attribute.id.is_(None), Attribute.is_deleted.is_(False)),
|
||||||
)
|
)
|
||||||
.order_by(Attribute.id)
|
.order_by(Module.id, Attribute.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def get_with_attributes_as_tuples(
|
async def get_with_attributes_as_tuples(
|
||||||
|
|||||||
@ -76,3 +76,34 @@ async def get_attribute_types(
|
|||||||
session: SessionDependency,
|
session: SessionDependency,
|
||||||
):
|
):
|
||||||
return await AttributeService(session).get_attribute_types()
|
return await AttributeService(session).get_attribute_types()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
"/deal/{dealId}/module/{moduleId}",
|
||||||
|
response_model=GetDealModuleAttributesResponse,
|
||||||
|
operation_id="get_deal_module_attributes",
|
||||||
|
)
|
||||||
|
async def get_deal_module_attributes(
|
||||||
|
session: SessionDependency,
|
||||||
|
deal_id: int = Path(alias="dealId"),
|
||||||
|
module_id: int = Path(alias="moduleId"),
|
||||||
|
):
|
||||||
|
return await AttributeService(session).get_deal_module_attributes(
|
||||||
|
deal_id, module_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post(
|
||||||
|
"/deal/{dealId}/module/{moduleId}",
|
||||||
|
response_model=UpdateDealModuleAttributesResponse,
|
||||||
|
operation_id="update_deal_module_attributes",
|
||||||
|
)
|
||||||
|
async def update_deal_module_attributes(
|
||||||
|
session: SessionDependency,
|
||||||
|
request: UpdateDealModuleAttributesRequest,
|
||||||
|
deal_id: int = Path(alias="dealId"),
|
||||||
|
module_id: int = Path(alias="moduleId"),
|
||||||
|
):
|
||||||
|
return await AttributeService(session).update_deal_module_attributes(
|
||||||
|
deal_id, module_id, request
|
||||||
|
)
|
||||||
|
|||||||
@ -44,6 +44,25 @@ class ModuleAttributeSchema(AttributeSchema):
|
|||||||
original_label: str
|
original_label: str
|
||||||
|
|
||||||
|
|
||||||
|
class DealModuleAttributeSchema(BaseSchema):
|
||||||
|
attribute_id: int
|
||||||
|
label: str
|
||||||
|
original_label: str
|
||||||
|
value: Optional[dict[str, Any]]
|
||||||
|
type: AttributeTypeSchema
|
||||||
|
default_value: dict[str, Any]
|
||||||
|
description: str
|
||||||
|
is_applicable_to_group: bool
|
||||||
|
is_shown_on_dashboard: bool
|
||||||
|
is_highlight_if_expired: bool
|
||||||
|
is_nullable: bool
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDealModuleAttributeSchema(BaseSchema):
|
||||||
|
attribute_id: int
|
||||||
|
value: Optional[dict[str, Any]]
|
||||||
|
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Request
|
# region Request
|
||||||
@ -63,6 +82,9 @@ class UpdateAttributeLabelRequest(BaseSchema):
|
|||||||
label: str
|
label: str
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDealModuleAttributesRequest(BaseSchema):
|
||||||
|
attributes: list[UpdateDealModuleAttributeSchema]
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Response
|
# region Response
|
||||||
@ -92,4 +114,11 @@ class GetAllAttributeTypesResponse(BaseSchema):
|
|||||||
items: list[AttributeTypeSchema]
|
items: list[AttributeTypeSchema]
|
||||||
|
|
||||||
|
|
||||||
|
class GetDealModuleAttributesResponse(BaseSchema):
|
||||||
|
attributes: list[DealModuleAttributeSchema]
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDealModuleAttributesResponse(BaseResponse):
|
||||||
|
pass
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from models import Attribute
|
from models import Attribute, AttributeValue, AttributeLabel
|
||||||
from repositories import AttributeRepository
|
from repositories import AttributeRepository
|
||||||
from schemas.attribute import *
|
from schemas.attribute import *
|
||||||
from services.mixins import *
|
from services.mixins import *
|
||||||
@ -29,3 +29,37 @@ class AttributeService(
|
|||||||
return GetAllAttributeTypesResponse(
|
return GetAllAttributeTypesResponse(
|
||||||
items=[AttributeTypeSchema.model_validate(t) for t in types]
|
items=[AttributeTypeSchema.model_validate(t) for t in types]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def get_deal_module_attributes(
|
||||||
|
self, deal_id: int, module_id: int
|
||||||
|
) -> GetDealModuleAttributesResponse:
|
||||||
|
deal_attributes: list[
|
||||||
|
tuple[Attribute, AttributeValue, AttributeLabel]
|
||||||
|
] = await self.repository.get_deal_module_attributes(deal_id, module_id)
|
||||||
|
|
||||||
|
attributes = []
|
||||||
|
for attr, attr_value, attr_label in deal_attributes:
|
||||||
|
attribute = DealModuleAttributeSchema(
|
||||||
|
attribute_id=attr.id,
|
||||||
|
label=attr_label.label if attr_label else attr.label,
|
||||||
|
original_label=attr.label,
|
||||||
|
value=attr_value.value if attr_value else attr.default_value,
|
||||||
|
type=AttributeTypeSchema.model_validate(attr.type),
|
||||||
|
default_value=attr.default_value,
|
||||||
|
description=attr.description,
|
||||||
|
is_applicable_to_group=attr.is_applicable_to_group,
|
||||||
|
is_shown_on_dashboard=attr.is_shown_on_dashboard,
|
||||||
|
is_highlight_if_expired=attr.is_highlight_if_expired,
|
||||||
|
is_nullable=attr.is_nullable,
|
||||||
|
)
|
||||||
|
attributes.append(attribute)
|
||||||
|
|
||||||
|
return GetDealModuleAttributesResponse(attributes=attributes)
|
||||||
|
|
||||||
|
async def update_deal_module_attributes(
|
||||||
|
self, deal_id: int, module_id: int, request: UpdateDealModuleAttributesRequest
|
||||||
|
) -> UpdateDealModuleAttributesResponse:
|
||||||
|
await self.repository.update_or_create_deal_attribute_values(
|
||||||
|
deal_id, module_id, request.attributes
|
||||||
|
)
|
||||||
|
return UpdateDealModuleAttributesResponse(message="Успешно сохранено")
|
||||||
|
|||||||
Reference in New Issue
Block a user