From c7bccbcf5e04fcd573845a066dc4beffeb58b5f1 Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 2 Apr 2025 00:27:14 +0300 Subject: [PATCH] feat: prefer fbo stocks over fbs, small refactor of existing models --- database/sipro/models/associations.py | 7 +++++ database/sipro/models/general.py | 9 +++++- database/sipro/models/warehouses.py | 27 ++++++++++++++++ queries/general.py | 45 ++++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 database/sipro/models/warehouses.py diff --git a/database/sipro/models/associations.py b/database/sipro/models/associations.py index 865d019..6f2f0b8 100644 --- a/database/sipro/models/associations.py +++ b/database/sipro/models/associations.py @@ -23,3 +23,10 @@ warehouse_company_warehouses = Table( Column('company_warehouse_id', ForeignKey('company_warehouses.id')), ) + +marketplace_fbo_warehouses = Table( + "marketplace_fbo_warehouses", + BaseSiproModel.metadata, + Column("marketplace_id", ForeignKey("marketplaces.id")), + Column("fbo_warehouse_id", ForeignKey("fbo_marketplace_warehouses.id")), +) diff --git a/database/sipro/models/general.py b/database/sipro/models/general.py index b5e6f22..9da5679 100644 --- a/database/sipro/models/general.py +++ b/database/sipro/models/general.py @@ -3,8 +3,10 @@ from typing import List from sqlalchemy import ForeignKey from sqlalchemy.orm import mapped_column, Mapped, relationship +from database.sipro.models.warehouses import FboMarketplaceWarehouse from .base import BaseSiproModel -from .associations import marketplace_warehouses, warehouse_company_warehouses, warehouse_suppliers +from .associations import marketplace_warehouses, warehouse_company_warehouses, warehouse_suppliers, \ + marketplace_fbo_warehouses class Company(BaseSiproModel): @@ -55,6 +57,7 @@ class Marketplace(BaseSiproModel): is_deleted: Mapped[bool] = mapped_column() is_paused: Mapped[bool] = mapped_column() send_stocks: Mapped[bool] = mapped_column() + prefer_fbo_over_fbs: Mapped[bool] = mapped_column() warehouses: Mapped[List["Warehouse"]] = relationship(secondary=marketplace_warehouses) warehouse_id: Mapped[str] = mapped_column() @@ -63,3 +66,7 @@ class Marketplace(BaseSiproModel): company: Mapped["Company"] = relationship() campaign_id: Mapped[str] = mapped_column() + fbo_warehouses: Mapped[List["FboMarketplaceWarehouse"]] = relationship( + secondary=marketplace_fbo_warehouses, + lazy="joined" + ) diff --git a/database/sipro/models/warehouses.py b/database/sipro/models/warehouses.py new file mode 100644 index 0000000..ed2cf03 --- /dev/null +++ b/database/sipro/models/warehouses.py @@ -0,0 +1,27 @@ +from typing import TYPE_CHECKING + +from sqlalchemy import UniqueConstraint, ForeignKey +from sqlalchemy.orm import mapped_column, Mapped, relationship + +from .base import BaseSiproModel +if TYPE_CHECKING: + from .products import MarketplaceProduct + + +class FboMarketplaceWarehouse(BaseSiproModel): + __tablename__ = 'fbo_marketplace_warehouses' + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(nullable=False, index=True) + base_marketplace: Mapped[int] = mapped_column(nullable=False) + inner_id: Mapped[int] = mapped_column(nullable=False, index=True) + __table_args__ = ( + UniqueConstraint('inner_id', 'base_marketplace', name='uq_inner_id_base_marketplace'), + ) + + +class MarketplaceProductFboWarehouseStock(BaseSiproModel): + __tablename__ = 'marketplace_product_fbo_warehouse_stocks' + warehouse_id: Mapped[int] = mapped_column(primary_key=True) + quantity: Mapped[int] = mapped_column() + marketplace_product_id: Mapped[int] = mapped_column(ForeignKey("marketplace_products.id")) + marketplace_product: Mapped["MarketplaceProduct"] = relationship() diff --git a/queries/general.py b/queries/general.py index ec0f01d..0f7b121 100644 --- a/queries/general.py +++ b/queries/general.py @@ -1,13 +1,12 @@ -from dataclasses import dataclass from typing import Union, TypedDict from sqlalchemy import select, func, and_, cast, String, case, or_ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import joinedload -from database import DailyStock from database.sipro import * from database.sipro.enums.product import ProductRelationType +from database.sipro.models.warehouses import MarketplaceProductFboWarehouseStock class StockData(TypedDict): @@ -45,11 +44,13 @@ async def get_stocks_data( suppliers, company_warehouses = get_marketplace_suppliers_and_company_warehouses(marketplace) supplier_ids = [supplier.id for supplier in suppliers] company_warehouse_ids = [warehouse.id for warehouse in company_warehouses] + fbo_warehouse_ids = [fbo_warehouse.id for fbo_warehouse in marketplace.fbo_warehouses] sell_mixes: bool = marketplace.sell_mixes sell_blocks: bool = marketplace.sell_blocks sell_warehouse_products: bool = marketplace.sell_warehouse_products sell_from_price: int = marketplace.sell_from_price + prefer_fbo_over_fbs: bool = marketplace.prefer_fbo_over_fbs is_paused = marketplace.is_paused supplier_stock_subquery = ( select( @@ -225,6 +226,28 @@ async def get_stocks_data( ) .subquery() ) + fbo_stock_subquery = ( + select( + MarketplaceProductFboWarehouseStock.marketplace_product_id.label('marketplace_product_id'), + func.sum(MarketplaceProductFboWarehouseStock.quantity).label('quantity') + ) + .select_from( + MarketplaceProductFboWarehouseStock + ) + .join( + MarketplaceProduct + ) + .where( + MarketplaceProduct.marketplace_id == marketplace.id, + MarketplaceProductFboWarehouseStock.warehouse_id.in_(fbo_warehouse_ids), + MarketplaceProductFboWarehouseStock.quantity > 0 + ) + .group_by( + MarketplaceProductFboWarehouseStock.marketplace_product_id + ) + .subquery() + ) + print(fbo_stock_subquery) stmt = ( select( @@ -244,7 +267,8 @@ async def get_stocks_data( is_master_subquery.c.is_master.label('is_master'), func.coalesce(slaves_stock_subquery.c.slaves_stock, 0).label('slaves_stock'), MarketplaceProduct.price_recommended.label('price_recommended'), - MarketplaceProduct.is_archived.label('is_archived') + MarketplaceProduct.is_archived.label('is_archived'), + func.coalesce(fbo_stock_subquery.c.quantity,0).label('fbo_stock') ) .select_from( MarketplaceProduct @@ -286,6 +310,10 @@ async def get_stocks_data( slaves_stock_subquery, slaves_stock_subquery.c.product_id == MarketplaceProduct.product_id ) + .outerjoin( + fbo_stock_subquery, + fbo_stock_subquery.c.marketplace_product_id == MarketplaceProduct.id + ) ) result = await session.execute(stmt) @@ -302,7 +330,9 @@ async def get_stocks_data( is_master, slaves_stock, price_recommended, - is_archived) in marketplace_products: + is_archived, + fbo_stock + ) in marketplace_products: if is_archived or (sell_from_price > price_recommended) or is_paused or reset: response.append({ 'article': denco_article, @@ -310,6 +340,13 @@ async def get_stocks_data( 'marketplace_product': marketplace_product, }) continue + if fbo_stock> 0 and prefer_fbo_over_fbs: + response.append({ + 'article': denco_article, + 'full_stock': 0, + 'marketplace_product': marketplace_product, + }) + continue is_mix = mix_stock is not None if not mix_stock: