This commit is contained in:
2024-07-01 06:01:50 +03:00
parent a6f7a9d65f
commit 386ee7e460
29 changed files with 727 additions and 296 deletions

3
marketplaces/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
from .ozon import OzonMarketplace
from .wildberries import WildberriesMarketplace
from .factory import MarketplaceFactory

37
marketplaces/base.py Normal file
View File

@@ -0,0 +1,37 @@
from abc import ABC, abstractmethod
from typing import Literal, Union
import aiohttp
from aiohttp import ClientResponse
from database import Marketplace
class BaseJsonMarketplace(ABC):
@abstractmethod
def __init__(self, marketplace: Marketplace):
pass
@abstractmethod
async def update_stocks(self, data: Union[list, dict]):
pass
@abstractmethod
def get_headers(self):
pass
@abstractmethod
@property
def api_url(self):
pass
async def _method(self, http_method: Literal['POST', 'GET', 'PATCH', 'PUT', 'DELETE'],
method: str,
data: dict) -> ClientResponse:
async with aiohttp.ClientSession as session:
async with session.request(http_method,
f'{self.api_url}{method}',
json=data,
headers=self.get_headers()
) as response:
return response

19
marketplaces/factory.py Normal file
View File

@@ -0,0 +1,19 @@
from typing import Union
from database import Marketplace
from database.sipro.enums.general import BaseMarketplace
from .wildberries import WildberriesMarketplace
from .ozon import OzonMarketplace
class MarketplaceFactory:
@staticmethod
def get_marketplace(marketplace: Marketplace) -> Union[
WildberriesMarketplace,
OzonMarketplace,
]:
match marketplace.base_marketplace:
case BaseMarketplace.OZON:
return OzonMarketplace(marketplace)
case BaseMarketplace.WILDBERRIES:
return WildberriesMarketplace(marketplace)

54
marketplaces/ozon.py Normal file
View File

@@ -0,0 +1,54 @@
import json
import logging
from typing import Union
from aiolimiter import AsyncLimiter
from asynciolimiter import StrictLimiter
import utils
from database import Marketplace
from limiter import BatchLimiter
from marketplaces.base import BaseJsonMarketplace
class OzonMarketplace(BaseJsonMarketplace):
def __init__(self, marketplace: Marketplace):
self.marketplace = marketplace
auth_data = json.loads(marketplace.auth_data)
self.headers = {
'Client-Id': auth_data.get('clientId'),
'Api-Key': auth_data.get('clientToken')
}
def get_headers(self):
return self.headers
def api_url(self):
return 'https://api-seller.ozon.ru'
async def update_stocks(self, data: Union[list, dict]):
if type(data) is not list:
return
max_stocks = 100
chunks = utils.chunk_list(data, max_stocks)
limiter = BatchLimiter(max_requests=80,
period=60)
for chunk in chunks:
try:
await limiter.acquire()
response = await self._method('POST',
'/v2/products/stocks',
data=chunk)
response = await response.json()
# response = await
error_message = response.get('message')
error_code = response.get('code')
if error_message:
logging.warning(
f'Error occurred when sending stocks to [{self.marketplace.id}]: {error_message} ({error_code})')
break
except Exception as e:
logging.error(
f'Exception occurred while sending stocks to marketplace ID [{self.marketplace.id}]: {str(e)}')

View File

@@ -0,0 +1,49 @@
import json
import logging
from typing import Union
import utils
from database import Marketplace
from limiter import BatchLimiter
from marketplaces.base import BaseJsonMarketplace
class WildberriesMarketplace(BaseJsonMarketplace):
def __init__(self, marketplace: Marketplace):
self.marketplace = marketplace
auth_data = json.loads(marketplace.auth_data)
self.headers = {
'Authorization': auth_data.get('token'),
'Content-Type': 'application/json'
}
def get_headers(self):
return self.headers
def api_url(self):
return 'https://suppliers-api.wildberries.ru'
async def update_stocks(self, data: Union[list, dict]):
if type(data) is not list:
return
max_stocks = 1000
chunks = utils.chunk_list(data, max_stocks)
limiter = BatchLimiter(max_requests=300,
period=60)
for chunk in chunks:
try:
await limiter.acquire()
response = await self._method('PUT',
'/api/v3/stocks/{warehouseId}',
chunk)
if response.status != 204:
response = await response.json()
error_message = response.get('message')
error_code = response.get('code')
logging.warning(
f'Error occurred when sending stocks to [{self.marketplace.id}]: {error_message} ({error_code})')
break
except Exception as e:
logging.error(
f'Exception occurred while sending stocks to marketplace ID [{self.marketplace.id}]: {str(e)}')