This commit is contained in:
2024-07-02 08:55:24 +03:00
parent 386ee7e460
commit 7ba3426989
18 changed files with 228 additions and 155 deletions

View File

@@ -1,15 +1,41 @@
from abc import ABC, abstractmethod
from typing import List
from sqlalchemy.ext.asyncio import AsyncSession
import queries.general
from database import Marketplace
from updaters.stocks_updater import StockUpdate
from marketplaces import MarketplaceApiFactory
from marketplaces.base import BaseMarketplaceApi
from queries.general import StockData
from schemas.general import StockUpdate
class BaseMarketplaceUpdater(ABC):
@abstractmethod
def __init__(self, marketplace: Marketplace):
pass
marketplace: Marketplace
marketplace_api: BaseMarketplaceApi
session: AsyncSession
def __init__(self, marketplace: Marketplace, session: AsyncSession):
self.marketplace = marketplace
self.session = session
self.marketplace_api = MarketplaceApiFactory.get_marketplace_api(marketplace)
@abstractmethod
async def update(self, updates: List[StockUpdate]):
def get_update_for_marketplace(self,
stock_data: StockData) -> dict:
pass
async def update(self, updates: List[StockUpdate]):
product_ids = list(set([update.product_id for update in updates]))
stock_data_list = await queries.general.get_stocks_data(
session=self.session,
marketplace=self.marketplace,
product_ids=product_ids
)
return
marketplace_updates = []
for stock_data in stock_data_list:
marketplace_update = self.get_update_for_marketplace(stock_data)
marketplace_updates.append(marketplace_update)
await self.marketplace_api.update_stocks(marketplace_updates)

18
updaters/factory.py Normal file
View File

@@ -0,0 +1,18 @@
from typing import Union
from sqlalchemy.ext.asyncio import AsyncSession
from database import Marketplace
from database.sipro.enums.general import BaseMarketplace
from updaters.ozon_updater import OzonUpdater
from updaters.wildberries_updater import WildberriesUpdater
class UpdaterFactory:
@staticmethod
def get_updater(session: AsyncSession, marketplace: Marketplace) -> Union[OzonUpdater, WildberriesUpdater]:
match marketplace.base_marketplace:
case BaseMarketplace.WILDBERRIES:
return WildberriesUpdater(marketplace, session)
case BaseMarketplace.OZON:
return OzonUpdater(marketplace, session)

View File

@@ -1,14 +1,11 @@
from typing import List
from database import Marketplace
from marketplaces import MarketplaceFactory, OzonMarketplace
from queries.general import StockData
from updaters.base import BaseMarketplaceUpdater
from updaters.stocks_updater import StockUpdate
class OzonUpdater(BaseMarketplaceUpdater):
def __init__(self, marketplace: Marketplace):
self.ozon_marketplace: OzonMarketplace = MarketplaceFactory.get_marketplace(marketplace)
async def update(self, updates: List[StockUpdate]):
pass
def get_update_for_marketplace(self, data: StockData) -> dict:
return {
'offer_id': str(data['article']),
'stock': 0, # $data['full_stock'],
'warehouse_id': self.marketplace.warehouse_id
}

View File

@@ -1,53 +1,47 @@
import asyncio
from collections import defaultdict
from dataclasses import dataclass
from enum import unique, IntEnum
from typing import List, Union
from typing import List
from sqlalchemy import select
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload
import database
from database import Marketplace, MarketplaceProduct, DailyStock
@unique
class StockUpdateType(IntEnum):
SALE = 0
SUPPLIER_UPDATE = 1
WAREHOUSE_UPDATE = 2
@dataclass
class StockUpdate:
product_id: int
type: StockUpdateType
quantity: int
from database import Marketplace, MarketplaceProduct, Warehouse, Company
from schemas.general import StockUpdate
from updaters.factory import UpdaterFactory
class StocksUpdater:
def __init__(self, session: AsyncSession):
self.session = session
async def get_marketplace(self, marketplace_id: int):
marketplace = await self.session.get(Marketplace, marketplace_id, options=[
joinedload(Marketplace.warehouses).joinedload(Warehouse.suppliers),
joinedload(Marketplace.warehouses).joinedload(Warehouse.company_warehouses),
joinedload(Marketplace.company).joinedload(Company.warehouse)
])
return marketplace
async def update_marketplace(self, marketplace_id: int, updates: List[StockUpdate]):
pass
marketplace = await self.get_marketplace(marketplace_id)
updater = UpdaterFactory.get_updater(self.session, marketplace)
if not updater:
return
await updater.update(updates)
async def update(self, updates: list[StockUpdate]):
updates_dict = defaultdict(list)
stock_update_values = []
for update in updates:
# Working with sold today
if update.type == StockUpdateType.SALE:
stock_update_values.append({
'product_id': update.product_id,
'sold_today': update.quantity
})
# Working with marketplaces
stmt = (
select(
MarketplaceProduct.marketplace_id.distinct()
)
.where(
MarketplaceProduct.product_id == update.product_id
MarketplaceProduct.product_id == update.product_id,
MarketplaceProduct.marketplace_id.in_([9, 41])
)
)
stmt_result = await self.session.execute(stmt)
@@ -57,27 +51,9 @@ class StocksUpdater:
for marketplace_id in marketplace_ids:
updates_dict[marketplace_id].append(update)
updates_list = list(updates_dict.items())
updates_list = sorted(updates_list, key=lambda x: x[1])
# Updating DailyStock-s
insert_stmt = (
insert(
DailyStock
)
.values(
stock_update_values
)
)
insert_stmt = (
insert_stmt.on_conflict_do_update(
index_elements=['product_id'],
set_={
'sold_today': DailyStock.sold_today + insert_stmt.excluded.sold_today
}
)
)
await self.session.execute(insert_stmt)
await self.session.commit()
updates_list = sorted(updates_list, key=lambda x: len(x[1]))
tasks = []
for marketplace_id, marketplace_updates in updates_list:
await self.update_marketplace(marketplace_id, marketplace_updates)
tasks.append(self.update_marketplace(marketplace_id, marketplace_updates))
await asyncio.gather(*tasks)

View File

@@ -1 +1,11 @@
from queries.general import StockData
from updaters.base import BaseMarketplaceUpdater
class WildberriesUpdater(BaseMarketplaceUpdater):
def get_update_for_marketplace(self, stock_data: StockData) -> dict:
return {
'sku': stock_data['marketplace_product'].third_additional_article,
'amount': 0 # stock_data['full_stock']
}