feat: a lot of a lot
This commit is contained in:
@@ -1,22 +1,44 @@
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from external.marketplace.wildberries.core import WildberriesMarketplaceApi
|
||||
from marketplaces.base.core import BaseMarketplaceController
|
||||
from models import Product, ProductBarcode, ProductImage, WildberriesProduct
|
||||
|
||||
|
||||
class WildberriesController(BaseMarketplaceController):
|
||||
api: WildberriesMarketplaceApi
|
||||
class WildberriesProductSynchronizer:
|
||||
products: list[Product]
|
||||
barcodes: list[ProductBarcode]
|
||||
images: list[ProductImage]
|
||||
wildberries_products: list[WildberriesProduct]
|
||||
|
||||
async def synchronize_products(self):
|
||||
products = []
|
||||
barcodes = []
|
||||
images = []
|
||||
wildberries_products = []
|
||||
def __init__(self, session, marketplace, api):
|
||||
self.session = session
|
||||
self.marketplace = marketplace
|
||||
self.api = api
|
||||
self.products = []
|
||||
self.barcodes = []
|
||||
self.images = []
|
||||
self.wildberries_products = []
|
||||
|
||||
marketplace_id: int = self.marketplace.id
|
||||
def _clear(self):
|
||||
self.products = []
|
||||
self.barcodes = []
|
||||
self.images = []
|
||||
self.wildberries_products = []
|
||||
|
||||
async def _write(self):
|
||||
instances = self.products + self.wildberries_products + self.barcodes + self.images
|
||||
start = time.time()
|
||||
self.session.add_all(instances)
|
||||
await self.session.commit()
|
||||
print(f'Write time: {time.time() - start}')
|
||||
|
||||
async def _get_synchronized_nm_uuids(self):
|
||||
marketplace_id = self.marketplace.id
|
||||
synchronized_nm_uuids = set(
|
||||
(
|
||||
await self.session.scalars(
|
||||
@@ -29,48 +51,163 @@ class WildberriesController(BaseMarketplaceController):
|
||||
)
|
||||
).all()
|
||||
)
|
||||
return synchronized_nm_uuids
|
||||
|
||||
async def _create_product(self, card, size_value):
|
||||
return Product(
|
||||
client_id=self.marketplace.client_id,
|
||||
name=card['title'],
|
||||
article=card['vendorCode'],
|
||||
size=size_value
|
||||
)
|
||||
|
||||
async def _create_barcodes(self, product, skus):
|
||||
barcodes = []
|
||||
for sku in skus:
|
||||
barcode = ProductBarcode(
|
||||
product=product,
|
||||
barcode=sku
|
||||
)
|
||||
barcodes.append(barcode)
|
||||
return barcodes
|
||||
|
||||
async def _create_images(self, product, photos):
|
||||
images = []
|
||||
for photo in photos[:1]:
|
||||
image = ProductImage(
|
||||
product=product,
|
||||
image_url=photo['big']
|
||||
)
|
||||
images.append(image)
|
||||
return images
|
||||
|
||||
async def _create_wildberries_product(self, product, nm_uuid):
|
||||
return WildberriesProduct(
|
||||
marketplace_id=self.marketplace.id,
|
||||
product=product,
|
||||
nm_uuid=nm_uuid
|
||||
)
|
||||
|
||||
async def _update_product_info(self, product, card):
|
||||
product.name = card['title']
|
||||
product.article = card['vendorCode']
|
||||
|
||||
async def _update_barcodes(self, product, skus):
|
||||
existing_barcodes = {barcode.barcode for barcode in product.barcodes}
|
||||
new_barcodes = []
|
||||
for sku in skus:
|
||||
if sku not in existing_barcodes:
|
||||
barcode = ProductBarcode(
|
||||
product=product,
|
||||
barcode=sku
|
||||
)
|
||||
new_barcodes.append(barcode)
|
||||
return new_barcodes
|
||||
|
||||
async def _update_images(self, product, photos):
|
||||
existing_images = {image.image_url for image in product.images}
|
||||
new_images = []
|
||||
for photo in photos[:1]:
|
||||
if photo['big'] not in existing_images:
|
||||
image = ProductImage(
|
||||
product=product,
|
||||
image_url=photo['big']
|
||||
)
|
||||
new_images.append(image)
|
||||
return new_images
|
||||
|
||||
async def _process_product(self, card, size_value, nm_uuid):
|
||||
product = await self._create_product(card, size_value)
|
||||
barcodes = await self._create_barcodes(product, card.get('sizes')[0].get('skus') or [])
|
||||
images = await self._create_images(product, card.get('photos') or [])
|
||||
wildberries_product = await self._create_wildberries_product(product, nm_uuid)
|
||||
|
||||
self.products.append(product)
|
||||
self.barcodes.extend(barcodes)
|
||||
self.images.extend(images)
|
||||
self.wildberries_products.append(wildberries_product)
|
||||
|
||||
async def create_products(self):
|
||||
self._clear()
|
||||
synchronized_nm_uuids = await self._get_synchronized_nm_uuids()
|
||||
async for card in self.api.get_all_products():
|
||||
nm_uuid = card['nmUUID']
|
||||
if nm_uuid in synchronized_nm_uuids:
|
||||
continue
|
||||
sizes: list[dict] = card.get('sizes') or []
|
||||
sizes = card.get('sizes') or []
|
||||
for size in sizes:
|
||||
tech_size = size.get('techSize')
|
||||
wb_size = size.get('wbSize')
|
||||
size_value = tech_size or wb_size
|
||||
product = Product(
|
||||
client_id=self.marketplace.client_id,
|
||||
name=card['title'],
|
||||
article=card['vendorCode'],
|
||||
size=size_value
|
||||
await self._process_product(
|
||||
card,
|
||||
size_value,
|
||||
nm_uuid
|
||||
)
|
||||
skus = size.get('skus') or []
|
||||
for sku in skus:
|
||||
barcode = ProductBarcode(
|
||||
product=product,
|
||||
barcode=sku
|
||||
await self._write()
|
||||
|
||||
async def synchronize_products(self):
|
||||
self._clear()
|
||||
synchronized_products_stmt = (
|
||||
select(Product)
|
||||
.join(
|
||||
WildberriesProduct
|
||||
)
|
||||
.options(
|
||||
selectinload(Product.barcodes),
|
||||
selectinload(Product.wildberries_products)
|
||||
)
|
||||
.where(WildberriesProduct.marketplace_id == self.marketplace.id)
|
||||
)
|
||||
synchronized_products = await self.session.execute(synchronized_products_stmt)
|
||||
synchronized_products = synchronized_products.scalars().all()
|
||||
synchronized_products_nm_id_dict = defaultdict(list)
|
||||
for product in synchronized_products:
|
||||
for wb_product in product.wildberries_products:
|
||||
synchronized_products_nm_id_dict[wb_product.nm_uuid].append(product)
|
||||
synchronized_nm_uuids = list(synchronized_products_nm_id_dict.keys())
|
||||
async for card in self.api.get_all_products():
|
||||
nm_uuid = card['nmUUID']
|
||||
if nm_uuid not in synchronized_nm_uuids:
|
||||
continue
|
||||
products = synchronized_products_nm_id_dict[nm_uuid]
|
||||
existing_sizes = {product.size for product in products}
|
||||
size_product_dict = {product.size: product for product in products}
|
||||
|
||||
sizes = card.get('sizes') or []
|
||||
for size in sizes:
|
||||
tech_size = size.get('techSize')
|
||||
wb_size = size.get('wbSize')
|
||||
size_value = tech_size or wb_size
|
||||
if size_value in existing_sizes:
|
||||
product = size_product_dict[size_value]
|
||||
await self._update_product_info(product, card)
|
||||
self.barcodes.extend(
|
||||
await self._update_barcodes(product, size.get('skus') or [])
|
||||
)
|
||||
barcodes.append(barcode)
|
||||
photos = card.get('photos') or []
|
||||
for photo in photos:
|
||||
image = ProductImage(
|
||||
product=product,
|
||||
image_url=photo['big']
|
||||
self.images.extend(
|
||||
await self._update_images(product, card.get('photos') or [])
|
||||
)
|
||||
images.append(image)
|
||||
break
|
||||
wildberries_product = WildberriesProduct(
|
||||
marketplace_id=self.marketplace.id,
|
||||
product=product,
|
||||
nm_uuid=nm_uuid
|
||||
continue
|
||||
await self._process_product(
|
||||
card,
|
||||
size_value,
|
||||
nm_uuid
|
||||
)
|
||||
wildberries_products.append(
|
||||
wildberries_product
|
||||
)
|
||||
products.append(product)
|
||||
instances = products + wildberries_products + barcodes + images
|
||||
start = time.time()
|
||||
self.session.add_all(instances)
|
||||
await self.session.commit()
|
||||
print(f'Add and commit elapsed: {time.time() - start}')
|
||||
await self._write()
|
||||
|
||||
|
||||
class WildberriesController(
|
||||
BaseMarketplaceController
|
||||
):
|
||||
api: WildberriesMarketplaceApi
|
||||
|
||||
def __init__(self, session, marketplace):
|
||||
super().__init__(session, marketplace)
|
||||
self.product_synchronizer = WildberriesProductSynchronizer(session, marketplace, self.api)
|
||||
|
||||
async def create_products(self):
|
||||
await self.product_synchronizer.create_products()
|
||||
|
||||
async def synchronize_products(self):
|
||||
await self.product_synchronizer.synchronize_products()
|
||||
|
||||
Reference in New Issue
Block a user