feat: attr options and selects editing
This commit is contained in:
@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
||||
class AttributeSelect(BaseModel, IdMixin, SoftDeleteMixin):
|
||||
__tablename__ = "attribute_selects"
|
||||
|
||||
label: Mapped[str] = mapped_column()
|
||||
name: Mapped[str] = mapped_column()
|
||||
is_built_in: Mapped[bool] = mapped_column(
|
||||
default=False,
|
||||
comment="Если встроенный select, то запрещено редактировать пользователю",
|
||||
@ -33,7 +33,7 @@ class AttributeSelect(BaseModel, IdMixin, SoftDeleteMixin):
|
||||
class AttributeOption(BaseModel, IdMixin, SoftDeleteMixin):
|
||||
__tablename__ = "attribute_options"
|
||||
|
||||
label: Mapped[str] = mapped_column()
|
||||
name: Mapped[str] = mapped_column()
|
||||
|
||||
select_id: Mapped[int] = mapped_column(ForeignKey("attribute_selects.id"))
|
||||
select: Mapped[AttributeSelect] = relationship(
|
||||
|
||||
@ -7,3 +7,4 @@ from .deal_tag import DealTagRepository as DealTagRepository
|
||||
from .module import ModuleRepository as ModuleRepository
|
||||
from .project import ProjectRepository as ProjectRepository
|
||||
from .status import StatusRepository as StatusRepository
|
||||
from .attr_option import AttrOptionRepository as AttrOptionRepository
|
||||
|
||||
21
repositories/attr_option.py
Normal file
21
repositories/attr_option.py
Normal file
@ -0,0 +1,21 @@
|
||||
from sqlalchemy import Select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from models import AttributeOption
|
||||
from repositories.mixins import RepCrudMixin
|
||||
from schemas.attr_option import CreateAttrOptionSchema, UpdateAttrOptionSchema
|
||||
|
||||
|
||||
class AttrOptionRepository(
|
||||
RepCrudMixin[AttributeOption, CreateAttrOptionSchema, UpdateAttrOptionSchema],
|
||||
):
|
||||
session: AsyncSession
|
||||
entity_class = AttributeOption
|
||||
entity_not_found_msg = "Опция не найдена"
|
||||
|
||||
def _process_get_all_stmt_with_args(self, stmt: Select, *args) -> Select:
|
||||
select_id = args[0]
|
||||
return stmt.where(
|
||||
AttributeOption.select_id == select_id,
|
||||
AttributeOption.is_deleted.is_(False),
|
||||
).order_by(AttributeOption.id)
|
||||
@ -1,19 +1,12 @@
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from models import AttributeSelect, AttributeOption
|
||||
from repositories.base import BaseRepository
|
||||
from repositories.mixins import RepGetAllMixin
|
||||
from models import AttributeSelect
|
||||
from repositories.mixins import RepCrudMixin
|
||||
from schemas.attr_select import UpdateAttrSelectSchema, CreateAttrSelectSchema
|
||||
|
||||
|
||||
class AttrSelectRepository(BaseRepository, RepGetAllMixin[AttributeSelect]):
|
||||
class AttrSelectRepository(
|
||||
RepCrudMixin[AttributeSelect, CreateAttrSelectSchema, UpdateAttrSelectSchema],
|
||||
):
|
||||
session: AsyncSession
|
||||
entity_class = AttributeSelect
|
||||
|
||||
async def get_options(self, select_id: int) -> list[AttributeOption]:
|
||||
stmt = select(AttributeOption).where(
|
||||
AttributeOption.select_id == select_id,
|
||||
AttributeOption.is_deleted.is_(False),
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return list(result.scalars().all())
|
||||
|
||||
56
routers/crm/v1/attr_option.py
Normal file
56
routers/crm/v1/attr_option.py
Normal file
@ -0,0 +1,56 @@
|
||||
from fastapi import APIRouter, Path
|
||||
|
||||
from backend.dependecies import SessionDependency
|
||||
from schemas.attr_option import *
|
||||
from services import AttrOptionService
|
||||
|
||||
router = APIRouter(tags=["attr_option"])
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{selectId}",
|
||||
response_model=GetAllAttrSelectOptionsResponse,
|
||||
operation_id="get_attr_options",
|
||||
)
|
||||
async def get_attr_options(
|
||||
session: SessionDependency,
|
||||
select_id: int = Path(alias="selectId"),
|
||||
):
|
||||
return await AttrOptionService(session).get_all(select_id)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/",
|
||||
response_model=CreateAttrOptionResponse,
|
||||
operation_id="create_attr_option",
|
||||
)
|
||||
async def create_attr_select(
|
||||
session: SessionDependency,
|
||||
request: CreateAttrOptionRequest,
|
||||
):
|
||||
return await AttrOptionService(session).create(request)
|
||||
|
||||
|
||||
@router.patch(
|
||||
"/{pk}",
|
||||
response_model=UpdateAttrOptionResponse,
|
||||
operation_id="update_attr_option",
|
||||
)
|
||||
async def update_attr_option(
|
||||
session: SessionDependency,
|
||||
request: UpdateAttrOptionRequest,
|
||||
pk: int = Path(),
|
||||
):
|
||||
return await AttrOptionService(session).update(pk, request)
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/{pk}",
|
||||
response_model=DeleteAttrOptionResponse,
|
||||
operation_id="delete_attr_option",
|
||||
)
|
||||
async def delete_attr_option(
|
||||
session: SessionDependency,
|
||||
pk: int = Path(),
|
||||
):
|
||||
return await AttrOptionService(session).delete(pk)
|
||||
@ -18,13 +18,38 @@ async def get_attr_selects(
|
||||
return await AttrSelectService(session).get_all()
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{selectId}",
|
||||
response_model=GetAllAttrSelectOptionsResponse,
|
||||
operation_id="get_attr_select_options",
|
||||
@router.post(
|
||||
"/",
|
||||
response_model=CreateAttrSelectResponse,
|
||||
operation_id="create_attr_select",
|
||||
)
|
||||
async def get_attr_select_options(
|
||||
async def create_attr_select(
|
||||
session: SessionDependency,
|
||||
select_id: int = Path(alias="selectId"),
|
||||
request: CreateAttrSelectRequest,
|
||||
):
|
||||
return await AttrSelectService(session).get_options(select_id)
|
||||
return await AttrSelectService(session).create(request)
|
||||
|
||||
|
||||
@router.patch(
|
||||
"/{pk}",
|
||||
response_model=UpdateAttrSelectResponse,
|
||||
operation_id="update_attr_select",
|
||||
)
|
||||
async def update_attr_select(
|
||||
session: SessionDependency,
|
||||
request: UpdateAttrSelectRequest,
|
||||
pk: int = Path(),
|
||||
):
|
||||
return await AttrSelectService(session).update(pk, request)
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/{pk}",
|
||||
response_model=DeleteAttrSelectResponse,
|
||||
operation_id="delete_attr_select",
|
||||
)
|
||||
async def delete_attr_select(
|
||||
session: SessionDependency,
|
||||
pk: int = Path(),
|
||||
):
|
||||
return await AttrSelectService(session).delete(pk)
|
||||
|
||||
55
schemas/attr_option.py
Normal file
55
schemas/attr_option.py
Normal file
@ -0,0 +1,55 @@
|
||||
from schemas.base import BaseSchema, BaseResponse
|
||||
|
||||
|
||||
# region Entity
|
||||
|
||||
|
||||
class AttrOptionSchema(BaseSchema):
|
||||
id: int
|
||||
name: str
|
||||
|
||||
|
||||
class CreateAttrOptionSchema(BaseSchema):
|
||||
name: str
|
||||
select_id: int
|
||||
|
||||
|
||||
class UpdateAttrOptionSchema(BaseSchema):
|
||||
name: str
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region Request
|
||||
|
||||
|
||||
class CreateAttrOptionRequest(BaseSchema):
|
||||
entity: CreateAttrOptionSchema
|
||||
|
||||
|
||||
class UpdateAttrOptionRequest(BaseSchema):
|
||||
entity: UpdateAttrOptionSchema
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region Response
|
||||
|
||||
|
||||
class GetAllAttrSelectOptionsResponse(BaseSchema):
|
||||
items: list[AttrOptionSchema]
|
||||
|
||||
|
||||
class CreateAttrOptionResponse(BaseSchema):
|
||||
entity: AttrOptionSchema
|
||||
|
||||
|
||||
class UpdateAttrOptionResponse(BaseResponse):
|
||||
pass
|
||||
|
||||
|
||||
class DeleteAttrOptionResponse(BaseSchema):
|
||||
pass
|
||||
|
||||
|
||||
# endregion
|
||||
@ -1,4 +1,5 @@
|
||||
from schemas.base import BaseSchema
|
||||
from schemas.attr_option import AttrOptionSchema
|
||||
from schemas.base import BaseSchema, BaseResponse
|
||||
|
||||
|
||||
# region Entity
|
||||
@ -6,13 +7,16 @@ from schemas.base import BaseSchema
|
||||
|
||||
class AttrSelectSchema(BaseSchema):
|
||||
id: int
|
||||
label: str
|
||||
name: str
|
||||
is_built_in: bool
|
||||
|
||||
|
||||
class AttrOptionSchema(BaseSchema):
|
||||
id: int
|
||||
label: str
|
||||
class CreateAttrSelectSchema(BaseSchema):
|
||||
name: str
|
||||
|
||||
|
||||
class UpdateAttrSelectSchema(BaseSchema):
|
||||
name: str
|
||||
|
||||
|
||||
class AttrSelectWithOptionsSchema(AttrSelectSchema):
|
||||
@ -24,6 +28,14 @@ class AttrSelectWithOptionsSchema(AttrSelectSchema):
|
||||
# region Request
|
||||
|
||||
|
||||
class CreateAttrSelectRequest(BaseSchema):
|
||||
entity: CreateAttrSelectSchema
|
||||
|
||||
|
||||
class UpdateAttrSelectRequest(BaseSchema):
|
||||
entity: UpdateAttrSelectSchema
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region Response
|
||||
@ -33,8 +45,16 @@ class GetAllAttrSelectsResponse(BaseSchema):
|
||||
items: list[AttrSelectSchema]
|
||||
|
||||
|
||||
class GetAllAttrSelectOptionsResponse(BaseSchema):
|
||||
items: list[AttrOptionSchema]
|
||||
class CreateAttrSelectResponse(BaseResponse):
|
||||
entity: AttrSelectSchema
|
||||
|
||||
|
||||
class UpdateAttrSelectResponse(BaseResponse):
|
||||
pass
|
||||
|
||||
|
||||
class DeleteAttrSelectResponse(BaseResponse):
|
||||
pass
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
@ -6,3 +6,4 @@ from .deal_group import DealGroupService as DealGroupService
|
||||
from .deal_tag import DealTagService as DealTagService
|
||||
from .project import ProjectService as ProjectService
|
||||
from .status import StatusService as StatusService
|
||||
from .attr_option import AttrOptionService as AttrOptionService
|
||||
|
||||
27
services/attr_option.py
Normal file
27
services/attr_option.py
Normal file
@ -0,0 +1,27 @@
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from models import AttributeOption
|
||||
from repositories import AttrOptionRepository
|
||||
from schemas.attr_option import (
|
||||
AttrOptionSchema,
|
||||
CreateAttrOptionRequest,
|
||||
UpdateAttrOptionRequest,
|
||||
)
|
||||
from services.mixins import ServiceCrudMixin
|
||||
|
||||
|
||||
class AttrOptionService(
|
||||
ServiceCrudMixin[
|
||||
AttributeOption,
|
||||
AttrOptionSchema,
|
||||
CreateAttrOptionRequest,
|
||||
UpdateAttrOptionRequest,
|
||||
]
|
||||
):
|
||||
schema_class = AttrOptionSchema
|
||||
entity_deleted_msg = "Опция успешно удалена"
|
||||
entity_updated_msg = "Опция успешно обновлена"
|
||||
entity_created_msg = "Опция успешно создана"
|
||||
|
||||
def __init__(self, session: AsyncSession):
|
||||
self.repository = AttrOptionRepository(session)
|
||||
@ -4,21 +4,21 @@ from models import AttributeSelect
|
||||
from repositories import AttrSelectRepository
|
||||
from schemas.attr_select import (
|
||||
AttrSelectSchema,
|
||||
GetAllAttrSelectOptionsResponse,
|
||||
AttrOptionSchema,
|
||||
CreateAttrSelectRequest,
|
||||
UpdateAttrSelectRequest,
|
||||
)
|
||||
from services.mixins import ServiceGetAllMixin
|
||||
from services.mixins import ServiceCrudMixin
|
||||
|
||||
|
||||
class AttrSelectService(ServiceGetAllMixin[AttributeSelect, AttrSelectSchema]):
|
||||
class AttrSelectService(
|
||||
ServiceCrudMixin[
|
||||
AttributeSelect,
|
||||
AttrSelectSchema,
|
||||
CreateAttrSelectRequest,
|
||||
UpdateAttrSelectRequest,
|
||||
]
|
||||
):
|
||||
schema_class = AttrSelectSchema
|
||||
|
||||
def __init__(self, session: AsyncSession):
|
||||
self.repository = AttrSelectRepository(session)
|
||||
|
||||
async def get_options(self, select_id: int) -> GetAllAttrSelectOptionsResponse:
|
||||
options = await self.repository.get_options(select_id)
|
||||
|
||||
return GetAllAttrSelectOptionsResponse(
|
||||
items=[AttrOptionSchema.model_validate(option) for option in options]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user