first commit
This commit is contained in:
BIN
app/providers/__pycache__/oracle.cpython-310.pyc
Normal file
BIN
app/providers/__pycache__/oracle.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/oracle.cpython-311.pyc
Normal file
BIN
app/providers/__pycache__/oracle.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/ozon.cpython-311.pyc
Normal file
BIN
app/providers/__pycache__/ozon.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/s3.cpython-311.pyc
Normal file
BIN
app/providers/__pycache__/s3.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/tinkoff.cpython-311.pyc
Normal file
BIN
app/providers/__pycache__/tinkoff.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/weaviate_provider.cpython-310.pyc
Normal file
BIN
app/providers/__pycache__/weaviate_provider.cpython-310.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/weaviate_provider.cpython-311.pyc
Normal file
BIN
app/providers/__pycache__/weaviate_provider.cpython-311.pyc
Normal file
Binary file not shown.
BIN
app/providers/__pycache__/wildberries.cpython-311.pyc
Normal file
BIN
app/providers/__pycache__/wildberries.cpython-311.pyc
Normal file
Binary file not shown.
62
app/providers/ozon.py
Normal file
62
app/providers/ozon.py
Normal file
@ -0,0 +1,62 @@
|
||||
import requests
|
||||
|
||||
|
||||
def load_all_products(client_id: str, api_key: str):
|
||||
headers = {
|
||||
"Client-Id": client_id,
|
||||
"Api-Key": api_key
|
||||
}
|
||||
|
||||
list_url = "https://api-seller.ozon.ru/v3/product/list"
|
||||
details_url = "https://api-seller.ozon.ru/v4/product/info/attributes"
|
||||
result, last_id = [], ""
|
||||
|
||||
while True:
|
||||
response = requests.post(list_url, headers=headers, json={
|
||||
"filter": {"visibility": "ALL"},
|
||||
"last_id": last_id,
|
||||
"limit": 100
|
||||
})
|
||||
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
product_ids = [item["product_id"] for item in data["result"]["items"]]
|
||||
if not product_ids:
|
||||
break
|
||||
|
||||
details_response = requests.post(details_url, headers=headers, json={
|
||||
"filter": {"product_id": product_ids, "visibility": "ALL"},
|
||||
"limit": 100,
|
||||
"sort_dir": "ASC"
|
||||
})
|
||||
|
||||
details_response.raise_for_status()
|
||||
details_data = details_response.json()
|
||||
|
||||
for product in details_data["result"]:
|
||||
attributes_by_id = {
|
||||
attribute["id"]: attribute
|
||||
for attribute in product["attributes"]
|
||||
}
|
||||
|
||||
brands = attributes_by_id.get(5076)
|
||||
colors = attributes_by_id.get(10096)
|
||||
compositions = attributes_by_id.get(6733)
|
||||
|
||||
result.append({
|
||||
"name": product.get("name"),
|
||||
"article": str(product["sku"]),
|
||||
"barcodes": product["barcodes"],
|
||||
"brand": ", ".join(brand["value"] for brand in brands['values']) if brands else None,
|
||||
"color": ", ".join(color["value"] for color in colors['values']) if colors else None,
|
||||
"composition": ", ".join(color["value"] for color in compositions['values']) if compositions else None,
|
||||
"imageUrl": product.get("primary_image")
|
||||
})
|
||||
|
||||
if not data["result"].get("last_id"):
|
||||
break
|
||||
|
||||
last_id = data["result"]["last_id"]
|
||||
|
||||
return result
|
||||
56
app/providers/tinkoff.py
Normal file
56
app/providers/tinkoff.py
Normal file
@ -0,0 +1,56 @@
|
||||
from datetime import timedelta, date
|
||||
from typing import Optional
|
||||
|
||||
from aiohttp import ClientSession
|
||||
from async_lru import alru_cache
|
||||
|
||||
TBANK_API_KEY = "t.DO5YeYvZhzf9mylRnFEdlUswA4mv1QX63HM2gj4ojHDcJgwVeY6u6R5Mc4ZnR-Qk6w7z2BPDUjnfg3ZuQAcaxQ"
|
||||
HEADERS = {
|
||||
"Authorization": f"Bearer {TBANK_API_KEY}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
BASE_URL = "https://business.tbank.ru/openapi/api/v1"
|
||||
|
||||
|
||||
async def create_bill(deal_id: int, total_price: float, client: Optional[dict]) -> dict:
|
||||
url = f"{BASE_URL}/invoice/send"
|
||||
data = {
|
||||
"invoiceNumber": str(deal_id),
|
||||
"dueDate": (date.today() + timedelta(days=7)).isoformat(),
|
||||
"items": [
|
||||
{
|
||||
"name": f"Оказание услуг фулфилмента (упаковка товара) и логистических услуг до маркетплейсов. Сделка ID {deal_id}",
|
||||
"price": total_price,
|
||||
"unit": "-",
|
||||
"vat": "None",
|
||||
"amount": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if client:
|
||||
data["payer"] = {
|
||||
"name": client["companyName"],
|
||||
"inn": client["details"]["inn"]
|
||||
}
|
||||
|
||||
async with ClientSession(headers=HEADERS) as session:
|
||||
async with session.post(url, json=data) as response:
|
||||
print(await response.text())
|
||||
|
||||
response.raise_for_status()
|
||||
return await response.json()
|
||||
|
||||
|
||||
@alru_cache(ttl=60)
|
||||
async def get_bill_status(bill_id: str) -> str:
|
||||
url = f"{BASE_URL}/openapi/invoice/{bill_id}/info"
|
||||
|
||||
async with ClientSession(headers=HEADERS) as session:
|
||||
async with session.get(url) as response:
|
||||
response.raise_for_status()
|
||||
data = await response.json()
|
||||
return data["status"]
|
||||
|
||||
|
||||
89
app/providers/wildberries.py
Normal file
89
app/providers/wildberries.py
Normal file
@ -0,0 +1,89 @@
|
||||
import requests
|
||||
|
||||
WB_SIZES = {
|
||||
"40": "XS",
|
||||
"42": "S",
|
||||
"44": "M",
|
||||
"46": "L",
|
||||
"48": "XL",
|
||||
"50": "XXL",
|
||||
"52": "3XL",
|
||||
"54": "4XL",
|
||||
"56": "5XL"
|
||||
}
|
||||
|
||||
|
||||
def get_wb_size(size):
|
||||
size_value = size.get("techSize") or size.get("wbSize")
|
||||
if not size_value or size_value == '0':
|
||||
return
|
||||
|
||||
if '-' in size_value:
|
||||
return WB_SIZES.get(size_value.split('-')[0], size_value)
|
||||
|
||||
return size_value.split('/')[0]
|
||||
|
||||
|
||||
def load_all_products(authorization: str):
|
||||
headers = {
|
||||
"Authorization": f"Bearer {authorization}"
|
||||
}
|
||||
|
||||
url = "https://content-api.wildberries.ru/content/v2/get/cards/list"
|
||||
products, cursor = [], {"limit": 100}
|
||||
|
||||
while True:
|
||||
response = requests.post(url, headers=headers, json={
|
||||
"settings": {
|
||||
"cursor": cursor,
|
||||
"filter": {
|
||||
"withPhoto": -1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
products.extend(data.get("cards", []))
|
||||
if data["cursor"]["total"] < cursor["limit"]:
|
||||
break
|
||||
|
||||
cursor.update({
|
||||
"updatedAt": data["cursor"]["updatedAt"],
|
||||
"nmID": data["cursor"]["nmID"]
|
||||
})
|
||||
|
||||
result = []
|
||||
for product in products:
|
||||
characteristics = product.get("characteristics", [])
|
||||
colors = next((item["value"] for item in characteristics if "Цвет" in item["name"]), None)
|
||||
composition = next((item["value"] for item in characteristics if "Состав" in item["name"]), None)
|
||||
|
||||
sizes = []
|
||||
barcodes = []
|
||||
barcodes_with_sizes = {}
|
||||
|
||||
for size in product["sizes"]:
|
||||
wb_size = get_wb_size(size)
|
||||
if wb_size:
|
||||
sizes.append(wb_size)
|
||||
|
||||
for barcode in size["skus"]:
|
||||
barcodes.append(str(barcode))
|
||||
barcodes_with_sizes[str(barcode)] = wb_size
|
||||
|
||||
result.append({
|
||||
"name": product["title"],
|
||||
"article": str(product["nmID"]),
|
||||
"vendorCode": product["vendorCode"],
|
||||
"barcodes": barcodes,
|
||||
"brand": product["brand"],
|
||||
"color": ", ".join(colors) if colors else None,
|
||||
"size": ", ".join(sizes) if sizes else None,
|
||||
"composition": ", ".join(composition) if composition else None,
|
||||
"imageUrl": product["photos"][0]["c516x688"] if product.get("photos") else None,
|
||||
"barcodesWithSizes": barcodes_with_sizes
|
||||
})
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user