rewritten crap
This commit is contained in:
111
updaters/base.py
111
updaters/base.py
@@ -1,65 +1,131 @@
|
||||
import time
|
||||
import json
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List
|
||||
from typing import List, Optional
|
||||
|
||||
import redis.asyncio
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
import queries.general
|
||||
from database import Marketplace
|
||||
from limiter import redis_client
|
||||
from marketplaces import MarketplaceApiFactory
|
||||
from marketplaces.base import BaseMarketplaceApi
|
||||
from queries.general import StockData
|
||||
from schemas.general import StockUpdate
|
||||
from sender.base import StockRequest
|
||||
from sender.factory import SenderFactory
|
||||
|
||||
|
||||
class BaseMarketplaceUpdater(ABC):
|
||||
marketplace: Marketplace
|
||||
marketplace_api: BaseMarketplaceApi
|
||||
session: AsyncSession
|
||||
lock_key: Optional[str]
|
||||
cache_key: Optional[str]
|
||||
redis_client: redis.asyncio.Redis
|
||||
|
||||
def __init__(self, marketplace: Marketplace, session: AsyncSession):
|
||||
self.marketplace = marketplace
|
||||
self.session = session
|
||||
self.marketplace_api = MarketplaceApiFactory.get_marketplace_api(marketplace)
|
||||
self.redis_client = redis_client.get_client()
|
||||
self.sender = SenderFactory.get_sender(self)
|
||||
|
||||
self.cache_key = None
|
||||
self.lock_key = None
|
||||
|
||||
def is_valid_updater(self) -> bool:
|
||||
if not self.marketplace_api:
|
||||
return False
|
||||
return self.marketplace_api.is_valid
|
||||
|
||||
@abstractmethod
|
||||
def get_update_for_marketplace(self,
|
||||
stock_data: StockData) -> dict:
|
||||
def get_stock_request(self,
|
||||
stock_data: StockData) -> StockRequest:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def _get_identifier(self) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
def __get_base_marketplace_key(self):
|
||||
base_marketplace = 'wb'
|
||||
if self.marketplace.base_marketplace == 1:
|
||||
base_marketplace = 'ozon'
|
||||
elif self.marketplace.base_marketplace == 2:
|
||||
base_marketplace = 'yandexmarket'
|
||||
return base_marketplace
|
||||
|
||||
def get_lock_key(self) -> str:
|
||||
identifier = self._get_identifier()
|
||||
base_marketplace = self.__get_base_marketplace_key()
|
||||
return f'{base_marketplace}_{identifier}_lock'
|
||||
|
||||
def get_cache_key(self):
|
||||
identifier = self._get_identifier()
|
||||
base_marketplace = self.__get_base_marketplace_key()
|
||||
return f'{base_marketplace}_{self.marketplace.warehouse_id}_{identifier}_cache'
|
||||
|
||||
def get_auth_data(self) -> dict:
|
||||
try:
|
||||
return json.loads(self.marketplace.auth_data)
|
||||
except Exception as e:
|
||||
return {}
|
||||
|
||||
async def filter_stocks_data(self, stock_data_list: list[StockData]) -> list[StockData]:
|
||||
cached_stocks: dict = await self.redis_client.hgetall(self.get_cache_key())
|
||||
cached_stocks = {int(k): int(v) for k, v in cached_stocks.items()}
|
||||
result = []
|
||||
for stock_data in stock_data_list:
|
||||
cached_stock = cached_stocks.get(stock_data['product_id'])
|
||||
if cached_stock is not None and cached_stock == stock_data['full_stock']:
|
||||
continue
|
||||
result.append(stock_data)
|
||||
return result
|
||||
|
||||
async def after_sender_sent(self, stock_requests: list[StockRequest], invalid_product_ids: list[int]):
|
||||
stock_requests = list(filter(lambda stock: stock['product_id'] not in invalid_product_ids, stock_requests))
|
||||
mapping = {stock['product_id']: stock['full_stock'] for stock in stock_requests}
|
||||
await self.redis_client.hset(self.get_cache_key(), mapping=mapping)
|
||||
|
||||
async def get_marketplace_updates(self, stock_data_list: list[StockData]) -> list[StockRequest]:
|
||||
marketplace_updates = []
|
||||
for stock_data in stock_data_list:
|
||||
marketplace_update = self.get_stock_request(stock_data)
|
||||
marketplace_updates.append(marketplace_update)
|
||||
return marketplace_updates
|
||||
|
||||
async def update(self, updates: List[StockUpdate]):
|
||||
if not self.marketplace_api:
|
||||
return
|
||||
product_ids = list(set([update.product_id for update in updates]))
|
||||
await self.update_products(product_ids)
|
||||
|
||||
async def update_products(self, product_ids: list[int]):
|
||||
if not self.is_valid_updater():
|
||||
return
|
||||
stock_data_list = await queries.general.get_stocks_data(
|
||||
session=self.session,
|
||||
marketplace=self.marketplace,
|
||||
product_ids=product_ids
|
||||
)
|
||||
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)
|
||||
stock_data_list = await self.filter_stocks_data(stock_data_list)
|
||||
stock_requests = await self.get_marketplace_updates(stock_data_list)
|
||||
invalid_product_ids = await self.sender.send(stock_requests)
|
||||
await self.after_sender_sent(stock_requests, invalid_product_ids)
|
||||
|
||||
async def update_all(self):
|
||||
if not self.marketplace_api:
|
||||
if not self.is_valid_updater():
|
||||
return
|
||||
stock_data_list = await queries.general.get_stocks_data(
|
||||
session=self.session,
|
||||
marketplace=self.marketplace,
|
||||
)
|
||||
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)
|
||||
stock_data_list = await self.filter_stocks_data(stock_data_list)
|
||||
stock_requests = await self.get_marketplace_updates(stock_data_list)
|
||||
invalid_product_ids = await self.sender.send(stock_requests)
|
||||
await self.after_sender_sent(stock_requests, invalid_product_ids)
|
||||
|
||||
async def get_all_stocks(self, only_available: bool) -> List[StockData]:
|
||||
if not self.marketplace_api:
|
||||
if not self.is_valid_updater():
|
||||
return []
|
||||
stock_data_list = await queries.general.get_stocks_data(
|
||||
session=self.session,
|
||||
@@ -74,14 +140,11 @@ class BaseMarketplaceUpdater(ABC):
|
||||
return stock_data_list
|
||||
|
||||
async def reset(self):
|
||||
if not self.marketplace_api:
|
||||
if not self.is_valid_updater():
|
||||
return
|
||||
stock_data_list = await queries.general.get_stocks_data(
|
||||
session=self.session,
|
||||
marketplace=self.marketplace
|
||||
)
|
||||
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)
|
||||
stock_requests = await self.get_marketplace_updates(stock_data_list)
|
||||
await self.sender.send(stock_requests)
|
||||
|
||||
@@ -23,3 +23,4 @@ class UpdaterFactory:
|
||||
return OzonUpdater(marketplace, session)
|
||||
case BaseMarketplace.YANDEX_MARKET:
|
||||
return YandexmarketUpdater(marketplace, session)
|
||||
raise ValueError()
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
from queries.general import StockData
|
||||
from sender.base import StockRequest
|
||||
from updaters.base import BaseMarketplaceUpdater
|
||||
|
||||
|
||||
class OzonUpdater(BaseMarketplaceUpdater):
|
||||
def get_update_for_marketplace(self, data: StockData) -> dict:
|
||||
|
||||
def _get_identifier(self) -> str:
|
||||
auth_data = self.get_auth_data()
|
||||
client_id = auth_data.get('clientId', -1)
|
||||
return str(client_id)
|
||||
|
||||
def get_stock_request(self, stock_data: StockData) -> StockRequest:
|
||||
return {
|
||||
'offer_id': str(data['article']),
|
||||
'stock': data['full_stock'],
|
||||
'warehouse_id': self.marketplace.warehouse_id
|
||||
'request_data': {
|
||||
'offer_id': str(stock_data['article']),
|
||||
'stock': stock_data['full_stock'],
|
||||
'warehouse_id': self.marketplace.warehouse_id
|
||||
},
|
||||
'product_id': stock_data['product_id'],
|
||||
'full_stock': stock_data['full_stock']
|
||||
}
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
import json
|
||||
|
||||
import jwt
|
||||
from celery.backends.database import retry
|
||||
|
||||
from queries.general import StockData
|
||||
from sender.base import StockRequest
|
||||
from updaters.base import BaseMarketplaceUpdater
|
||||
|
||||
|
||||
class WildberriesUpdater(BaseMarketplaceUpdater):
|
||||
|
||||
def get_update_for_marketplace(self, stock_data: StockData) -> dict:
|
||||
def _get_identifier(self) -> str:
|
||||
try:
|
||||
auth_data = self.get_auth_data()
|
||||
token = auth_data.get('token')
|
||||
decoded_token = jwt.decode(token, algorithms=["HS256"], options={"verify_signature": False})
|
||||
sid = decoded_token.get('sid')
|
||||
return str(sid)
|
||||
except Exception:
|
||||
return f'-1'
|
||||
|
||||
def get_stock_request(self, stock_data: StockData) -> StockRequest:
|
||||
return {
|
||||
'sku': stock_data['marketplace_product'].third_additional_article,
|
||||
'amount': stock_data['full_stock']
|
||||
'request_data': {
|
||||
'sku': stock_data['marketplace_product'].third_additional_article,
|
||||
'amount': stock_data['full_stock']
|
||||
},
|
||||
'product_id': stock_data['product_id'],
|
||||
|
||||
'full_stock': stock_data['full_stock']
|
||||
}
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
from queries.general import StockData
|
||||
from sender.base import StockRequest
|
||||
from updaters.base import BaseMarketplaceUpdater
|
||||
|
||||
|
||||
class YandexmarketUpdater(BaseMarketplaceUpdater):
|
||||
def get_update_for_marketplace(self, stock_data: StockData) -> dict:
|
||||
|
||||
def _get_identifier(self) -> str:
|
||||
return str(self.marketplace.campaign_id)
|
||||
|
||||
def get_stock_request(self, stock_data: StockData) -> StockRequest:
|
||||
return {
|
||||
'sku': str(stock_data['article']),
|
||||
'warehouseId': self.marketplace.warehouse_id,
|
||||
'items': [{
|
||||
'count': stock_data['full_stock'],
|
||||
}]
|
||||
'request_data': {
|
||||
'sku': str(stock_data['article']),
|
||||
'warehouseId': self.marketplace.warehouse_id,
|
||||
'items': [{
|
||||
'count': stock_data['full_stock'],
|
||||
}]
|
||||
},
|
||||
'product_id': stock_data['product_id'],
|
||||
'full_stock': stock_data['full_stock']
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user