84 lines
3.0 KiB
Python
84 lines
3.0 KiB
Python
import hashlib
|
||
import httpx
|
||
from typing import List, Any
|
||
from core.config import settings
|
||
from schemas.order import OrderResponse, OrderItem
|
||
|
||
def _get_summary_string(json_data: Any) -> str:
|
||
"""Рекурсивная конкатенация значений для формирования MD5 подписи."""
|
||
summary = ""
|
||
if isinstance(json_data, dict):
|
||
for key in sorted(json_data.keys()):
|
||
summary += _get_summary_string(json_data[key])
|
||
elif isinstance(json_data, list):
|
||
for item in json_data:
|
||
summary += _get_summary_string(item)
|
||
else:
|
||
if isinstance(json_data, bool):
|
||
summary += "1" if json_data else ""
|
||
elif json_data is not None:
|
||
summary += str(json_data)
|
||
return summary
|
||
|
||
async def fetch_cod_orders(status_name: str = "APPROVED") -> List[OrderResponse]:
|
||
payload = {
|
||
"apikey": settings.CRM_API_KEY,
|
||
"object": "Orders",
|
||
"method": "GetOrders",
|
||
"params": {
|
||
"sid": settings.CRM_STORE_SID,
|
||
"key": settings.CRM_STORE_KEY,
|
||
"Status": status_name,
|
||
"ReturnWaybill": True,
|
||
"ReturnGoods": True,
|
||
"ReturnTotals": True
|
||
}
|
||
}
|
||
|
||
# Формирование контрольной суммы MD5
|
||
summary_string = _get_summary_string(payload)
|
||
string_to_hash = summary_string + settings.CRM_API_SECRET
|
||
payload["md5sum"] = hashlib.md5(string_to_hash.encode('utf-8')).hexdigest()
|
||
|
||
headers = {'Content-Type': 'application/json; charset=utf-8'}
|
||
|
||
async with httpx.AsyncClient() as client:
|
||
response = await client.post(settings.CRM_API_URL, json=payload, headers=headers)
|
||
response.raise_for_status()
|
||
raw_data = response.json()
|
||
|
||
parsed_orders = []
|
||
|
||
# 1. Берем данные из ключа "result" (а не "orders")
|
||
orders_list = raw_data.get("result", [])
|
||
|
||
for order in orders_list:
|
||
# 2. Собираем товары из массива Goods
|
||
items = []
|
||
for item in order.get("Goods", []):
|
||
items.append(
|
||
OrderItem(
|
||
name=item.get("Name", ""),
|
||
quantity=float(item.get("Quantity", 1.0)),
|
||
price=float(item.get("Price", 0.0))
|
||
)
|
||
)
|
||
|
||
# 3. Извлекаем итоговую сумму из вложенного объекта Total.Amount
|
||
total_info = order.get("Total", {})
|
||
total_amount = float(total_info.get("Amount", 0.0))
|
||
|
||
# 4. Формируем объект ответа для Pydantic
|
||
parsed_orders.append(
|
||
OrderResponse(
|
||
id=str(order.get("ID")),
|
||
client_name=order.get("RecipientDName", "Неизвестно"),
|
||
client_phone=order.get("RecipientPhone", ""),
|
||
ttn=order.get("Waybill_Number", ""),
|
||
cod_amount=total_amount,
|
||
fiscal_status="pending",
|
||
items=items
|
||
)
|
||
)
|
||
|
||
return parsed_orders |