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"
|
||||
|
||||
id: Mapped[int] = mapped_column(
|
||||
primary_key=True,
|
||||
autoincrement=True,
|
||||
)
|
||||
|
||||
value: Mapped[Optional[dict[str, any]]] = mapped_column(JSONB)
|
||||
|
||||
deal_id: Mapped[int] = mapped_column(
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
from sqlalchemy import and_
|
||||
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 schemas.attribute import CreateAttributeSchema, UpdateAttributeSchema
|
||||
from schemas.attribute import CreateAttributeSchema, UpdateAttributeSchema, UpdateDealModuleAttributeSchema
|
||||
from utils.exceptions import ForbiddenException
|
||||
|
||||
|
||||
@ -71,3 +78,75 @@ class AttributeRepository(
|
||||
stmt = select(AttributeType).where(AttributeType.is_deleted.is_(False))
|
||||
result = await self.session.execute(stmt)
|
||||
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),
|
||||
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(
|
||||
|
||||
@ -76,3 +76,34 @@ async def get_attribute_types(
|
||||
session: SessionDependency,
|
||||
):
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
# region Request
|
||||
@ -63,6 +82,9 @@ class UpdateAttributeLabelRequest(BaseSchema):
|
||||
label: str
|
||||
|
||||
|
||||
class UpdateDealModuleAttributesRequest(BaseSchema):
|
||||
attributes: list[UpdateDealModuleAttributeSchema]
|
||||
|
||||
# endregion
|
||||
|
||||
# region Response
|
||||
@ -92,4 +114,11 @@ class GetAllAttributeTypesResponse(BaseSchema):
|
||||
items: list[AttributeTypeSchema]
|
||||
|
||||
|
||||
class GetDealModuleAttributesResponse(BaseSchema):
|
||||
attributes: list[DealModuleAttributeSchema]
|
||||
|
||||
|
||||
class UpdateDealModuleAttributesResponse(BaseResponse):
|
||||
pass
|
||||
|
||||
# endregion
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from models import Attribute
|
||||
from models import Attribute, AttributeValue, AttributeLabel
|
||||
from repositories import AttributeRepository
|
||||
from schemas.attribute import *
|
||||
from services.mixins import *
|
||||
@ -29,3 +29,37 @@ class AttributeService(
|
||||
return GetAllAttributeTypesResponse(
|
||||
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