feat: marketplaces endpoints

This commit is contained in:
2025-10-13 12:48:06 +04:00
parent d8eba188c9
commit 35869e2ea5
16 changed files with 441 additions and 10 deletions

View File

@ -14,3 +14,4 @@ from .deal_product import (
from .deal_service import DealService as DealService
from .product import Product as Product
from .service import Service as Service, ServiceCategory as ServiceCategory
from .marketplace import BaseMarketplace as BaseMarketplace, Marketplace as Marketplace

View File

@ -0,0 +1,32 @@
from typing import TYPE_CHECKING
from sqlalchemy import ForeignKey, JSON
from sqlalchemy.orm import Mapped, mapped_column, relationship
from models.base import BaseModel
from models.mixins import IdMixin, SoftDeleteMixin
if TYPE_CHECKING:
from modules.clients.models import Client
class BaseMarketplace(BaseModel, IdMixin):
__tablename__ = "fulfillment_base_base_marketplaces"
name: Mapped[str] = mapped_column()
icon_url: Mapped[str] = mapped_column()
class Marketplace(BaseModel, IdMixin, SoftDeleteMixin):
__tablename__ = "fulfillment_base_marketplaces"
base_marketplace_id: Mapped[str] = mapped_column(
ForeignKey("fulfillment_base_base_marketplaces.id")
)
base_marketplace: Mapped["BaseMarketplace"] = relationship(lazy="joined")
client_id: Mapped[int] = mapped_column(ForeignKey("clients.id"))
client: Mapped["Client"] = relationship()
name: Mapped[str] = mapped_column()
auth_data: Mapped[dict] = mapped_column(type_=JSON)

View File

@ -1,8 +1,9 @@
from .deal_product import DealProductRepository as DealProductRepository
from .product_service import ProductServiceRepository as ProductServiceRepository
from .deal_service import DealServiceRepository as DealServiceRepository
from .product import ProductRepository as ProductRepository
from .service import ServiceRepository as ServiceRepository
from .services_kit import ServicesKitRepository as ServicesKitRepository
from .service_category import ServiceCategoryRepository as ServiceCategoryRepository
from .barcode_template import BarcodeTemplateRepository as BarcodeTemplateRepository
from .deal_product import DealProductRepository as DealProductRepository
from .deal_service import DealServiceRepository as DealServiceRepository
from .marketplace import MarketplaceRepository as MarketplaceRepository
from .product import ProductRepository as ProductRepository
from .product_service import ProductServiceRepository as ProductServiceRepository
from .service import ServiceRepository as ServiceRepository
from .service_category import ServiceCategoryRepository as ServiceCategoryRepository
from .services_kit import ServicesKitRepository as ServicesKitRepository

View File

@ -0,0 +1,62 @@
from sqlalchemy.orm import joinedload
from modules.clients.models import Client
from modules.fulfillment_base.models import (
Marketplace,
BaseMarketplace,
)
from modules.fulfillment_base.schemas.marketplace import (
CreateMarketplaceSchema,
UpdateMarketplaceSchema,
)
from repositories.mixins import *
class MarketplaceRepository(
RepCrudMixin[Marketplace, CreateMarketplaceSchema, UpdateMarketplaceSchema],
):
session: AsyncSession
entity_class = Marketplace
entity_not_found_msg = "Маркетплейс не найден"
def _process_get_all_stmt_with_args(self, stmt: Select, *args) -> Select:
client_id: int = args[0]
return (
stmt.options(
joinedload(Marketplace.base_marketplace),
joinedload(Marketplace.client),
)
.where(
Marketplace.is_deleted.is_(False), Marketplace.client_id == client_id
)
.order_by(Marketplace.id)
)
def _process_get_by_id_stmt(self, stmt: Select) -> Select:
return stmt.options(
joinedload(Marketplace.base_marketplace), joinedload(Marketplace.client)
)
async def get_base_marketplaces(self) -> list[BaseMarketplace]:
stmt = select(BaseMarketplace)
result = await self.session.execute(stmt)
return list(result.scalars().all())
async def _prepare_create(self, data: CreateMarketplaceSchema) -> dict:
dict_data = data.model_dump()
dict_data["base_marketplace_id"] = data.base_marketplace.id
del dict_data["base_marketplace"]
dict_data["client_id"] = data.client.id
del dict_data["client"]
return dict_data
async def update(
self, template: Marketplace, data: UpdateMarketplaceSchema
) -> Marketplace:
if data.base_marketplace:
data.base_marketplace = BaseMarketplace(
**data.base_marketplace.model_dump()
)
if data.client:
data.client = Client(**data.client.model_dump())
return await self._apply_update_data_to_model(template, data, True)

View File

@ -0,0 +1,66 @@
from fastapi import APIRouter, Path
from backend.dependecies import SessionDependency
from modules.fulfillment_base.schemas.marketplace import *
from modules.fulfillment_base.services import MarketplaceService
router = APIRouter(tags=["marketplace"])
@router.get(
"/base",
response_model=GetBaseMarketplacesResponse,
operation_id="get_base_marketplaces",
)
async def get_base_marketplaces(
session: SessionDependency,
):
return await MarketplaceService(session).get_base_marketplaces()
@router.get(
"/{clientId}",
response_model=GetMarketplacesResponse,
operation_id="get_marketplaces",
)
async def get_marketplaces(
session: SessionDependency, client_id: int = Path(alias="clientId")
):
return await MarketplaceService(session).get_all(client_id)
@router.post(
"/",
response_model=CreateMarketplaceResponse,
operation_id="create_marketplace",
)
async def create_product(
session: SessionDependency,
request: CreateMarketplaceRequest,
):
return await MarketplaceService(session).create(request)
@router.patch(
"/{pk}",
response_model=UpdateMarketplaceResponse,
operation_id="update_marketplace",
)
async def update_marketplace(
session: SessionDependency,
request: UpdateMarketplaceRequest,
pk: int = Path(),
):
return await MarketplaceService(session).update(pk, request)
@router.delete(
"/{pk}",
response_model=DeleteMarketplaceResponse,
operation_id="delete_marketplace",
)
async def delete_marketplace(
session: SessionDependency,
pk: int = Path(),
):
return await MarketplaceService(session).delete(pk)

View File

@ -0,0 +1,77 @@
from typing import Optional
from modules.clients.schemas.client import ClientSchema
from schemas.base import BaseSchema, BaseResponse
# region Entity
class BaseMarketplaceSchema(BaseSchema):
id: int
name: str
icon_url: str
class MarketplaceSchema(BaseSchema):
id: int
base_marketplace_id: int
base_marketplace: BaseMarketplaceSchema
client: ClientSchema
name: str
auth_data: dict
class CreateMarketplaceSchema(BaseSchema):
base_marketplace: BaseMarketplaceSchema
client: ClientSchema
name: str
auth_data: dict
class UpdateMarketplaceSchema(BaseSchema):
base_marketplace: Optional[BaseMarketplaceSchema] = None
client: Optional[ClientSchema] = None
name: Optional[str] = None
auth_data: Optional[dict] = None
# endregion
# region Request
class CreateMarketplaceRequest(BaseSchema):
entity: CreateMarketplaceSchema
class UpdateMarketplaceRequest(BaseSchema):
entity: UpdateMarketplaceSchema
# endregion
# region Response
class GetBaseMarketplacesResponse(BaseSchema):
items: list[BaseMarketplaceSchema]
class GetMarketplacesResponse(BaseSchema):
items: list[MarketplaceSchema]
class CreateMarketplaceResponse(BaseResponse):
entity: MarketplaceSchema
class UpdateMarketplaceResponse(BaseResponse):
pass
class DeleteMarketplaceResponse(BaseResponse):
pass
# endregion

View File

@ -7,3 +7,4 @@ from .services_kit import ServicesKitService as ServicesKitService
from .service_category import ServiceCategoryService as ServiceCategoryService
from .barcode_template import BarcodeTemplateService as BarcodeTemplateService
from .barcode_printer_service import BarcodePrinterService as BarcodePrinterService
from .marketplace import MarketplaceService as MarketplaceService

View File

@ -20,9 +20,6 @@ class BarcodeTemplateService(
def __init__(self, session: AsyncSession):
self.repository = BarcodeTemplateRepository(session)
async def is_soft_delete(self, template: BarcodeTemplate) -> bool:
return True
async def get_attributes(self) -> GetBarcodeAttributesResponse:
attributes = await self.repository.get_attributes()
return GetBarcodeAttributesResponse(

View File

@ -0,0 +1,27 @@
from modules.fulfillment_base.models import Marketplace
from modules.fulfillment_base.repositories import MarketplaceRepository
from modules.fulfillment_base.schemas.marketplace import *
from services.mixins import *
class MarketplaceService(
ServiceCrudMixin[
Marketplace,
MarketplaceSchema,
CreateMarketplaceRequest,
UpdateMarketplaceRequest,
]
):
schema_class = MarketplaceSchema
entity_deleted_msg = "Маркетплейс успешно удален"
entity_updated_msg = "Маркетплейс успешно обновлен"
entity_created_msg = "Маркетплейс успешно создан"
def __init__(self, session: AsyncSession):
self.repository = MarketplaceRepository(session)
async def get_base_marketplaces(self) -> GetBaseMarketplacesResponse:
mps = await self.repository.get_base_marketplaces()
return GetBaseMarketplacesResponse(
items=[BaseMarketplaceSchema.model_validate(mp) for mp in mps]
)