diff --git a/modules/fulfillment_base/models/__init__.py b/modules/fulfillment_base/models/__init__.py index cfa5105..1420f30 100644 --- a/modules/fulfillment_base/models/__init__.py +++ b/modules/fulfillment_base/models/__init__.py @@ -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 diff --git a/modules/fulfillment_base/models/marketplace.py b/modules/fulfillment_base/models/marketplace.py new file mode 100644 index 0000000..bc79b28 --- /dev/null +++ b/modules/fulfillment_base/models/marketplace.py @@ -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) diff --git a/modules/fulfillment_base/repositories/__init__.py b/modules/fulfillment_base/repositories/__init__.py index 3385055..5f39d8c 100644 --- a/modules/fulfillment_base/repositories/__init__.py +++ b/modules/fulfillment_base/repositories/__init__.py @@ -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 diff --git a/modules/fulfillment_base/repositories/marketplace.py b/modules/fulfillment_base/repositories/marketplace.py new file mode 100644 index 0000000..7ee67dc --- /dev/null +++ b/modules/fulfillment_base/repositories/marketplace.py @@ -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) diff --git a/modules/fulfillment_base/routers/marketplace.py b/modules/fulfillment_base/routers/marketplace.py new file mode 100644 index 0000000..72d623d --- /dev/null +++ b/modules/fulfillment_base/routers/marketplace.py @@ -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) diff --git a/modules/fulfillment_base/schemas/marketplace.py b/modules/fulfillment_base/schemas/marketplace.py new file mode 100644 index 0000000..712b0a7 --- /dev/null +++ b/modules/fulfillment_base/schemas/marketplace.py @@ -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 diff --git a/modules/fulfillment_base/services/__init__.py b/modules/fulfillment_base/services/__init__.py index e4d4210..ae69787 100644 --- a/modules/fulfillment_base/services/__init__.py +++ b/modules/fulfillment_base/services/__init__.py @@ -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 diff --git a/modules/fulfillment_base/services/barcode_template.py b/modules/fulfillment_base/services/barcode_template.py index 4958e21..a7543d2 100644 --- a/modules/fulfillment_base/services/barcode_template.py +++ b/modules/fulfillment_base/services/barcode_template.py @@ -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( diff --git a/modules/fulfillment_base/services/marketplace.py b/modules/fulfillment_base/services/marketplace.py new file mode 100644 index 0000000..24f2764 --- /dev/null +++ b/modules/fulfillment_base/services/marketplace.py @@ -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] + ) diff --git a/static/icons/denco.png b/static/icons/denco.png new file mode 100644 index 0000000..37146e7 Binary files /dev/null and b/static/icons/denco.png differ diff --git a/static/icons/denco.svg b/static/icons/denco.svg new file mode 100644 index 0000000..c76ad6e --- /dev/null +++ b/static/icons/denco.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/icons/ozon.png b/static/icons/ozon.png new file mode 100644 index 0000000..1effefc Binary files /dev/null and b/static/icons/ozon.png differ diff --git a/static/icons/ozon.svg b/static/icons/ozon.svg new file mode 100644 index 0000000..0e2622b --- /dev/null +++ b/static/icons/ozon.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/icons/wb.svg b/static/icons/wb.svg new file mode 100644 index 0000000..3fc2817 --- /dev/null +++ b/static/icons/wb.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/static/icons/ym.png b/static/icons/ym.png new file mode 100644 index 0000000..a19c517 Binary files /dev/null and b/static/icons/ym.png differ diff --git a/static/icons/ym.svg b/static/icons/ym.svg new file mode 100644 index 0000000..b90e1af --- /dev/null +++ b/static/icons/ym.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + +