fix(recommerce): использовать in_stock для определения наличия в API
- Добавить константу RECOMMERCE_INFINITY_COUNT = 999999 в mappers.py - Изменить логику: product.in_stock определяет count (0 или 999999) - Добавить test_count.py для тестирования поля count - Обновить документацию recommerce_api.md с секцией Product Availability Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
# Константа для "бесконечного" наличия в Recommerce
|
||||||
|
# Используется вместо "inf", который API не принимает
|
||||||
|
RECOMMERCE_INFINITY_COUNT = 999999
|
||||||
|
|
||||||
|
|
||||||
def to_api_product(
|
def to_api_product(
|
||||||
product: Any,
|
product: Any,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import List, Dict, Any, Optional
|
from typing import List, Dict, Any, Optional
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from .client import RecommerceClient
|
from .client import RecommerceClient
|
||||||
from .mappers import to_api_product, from_api_order
|
from .mappers import to_api_product, from_api_order, RECOMMERCE_INFINITY_COUNT
|
||||||
from .exceptions import RecommerceError
|
from .exceptions import RecommerceError
|
||||||
# Imports for typing only to avoid circular dependency issues at module level if possible
|
# Imports for typing only to avoid circular dependency issues at module level if possible
|
||||||
# but for simplicity in this structure we'll import inside methods if needed or use 'Any'
|
# but for simplicity in this structure we'll import inside methods if needed or use 'Any'
|
||||||
@@ -39,13 +39,10 @@ class RecommerceService:
|
|||||||
# Получаем остаток, если нужно
|
# Получаем остаток, если нужно
|
||||||
stock_count = None
|
stock_count = None
|
||||||
if fields is None or 'count' in fields:
|
if fields is None or 'count' in fields:
|
||||||
# Пытаемся получить остаток.
|
# Используем in_stock для определения наличия в формате Recommerce:
|
||||||
# Логика получения остатка может зависеть от вашей системы inventory.
|
# - in_stock=False → count=0 (нет в наличии)
|
||||||
# Здесь предполагаем, что у product есть метод или связь для получения общего остатка.
|
# - in_stock=True → count=999999 (есть в наличии, "бесконечность")
|
||||||
# Для простоты используем первый попавшийся Stock или 0
|
stock_count = RECOMMERCE_INFINITY_COUNT if product.in_stock else 0
|
||||||
# В реальном проекте тут должна быть логика выбора склада
|
|
||||||
stock = product.stocks.first()
|
|
||||||
stock_count = int(stock.quantity_free) if stock else 0
|
|
||||||
|
|
||||||
data = to_api_product(product, stock_count=stock_count, fields=fields)
|
data = to_api_product(product, stock_count=stock_count, fields=fields)
|
||||||
|
|
||||||
@@ -74,8 +71,8 @@ class RecommerceService:
|
|||||||
RecommerceError: Если отсутствует обязательное поле parent_category_sku
|
RecommerceError: Если отсутствует обязательное поле parent_category_sku
|
||||||
"""
|
"""
|
||||||
# Для создания нужны все поля
|
# Для создания нужны все поля
|
||||||
stock = product.stocks.first()
|
# Используем in_stock для определения наличия в формате Recommerce
|
||||||
stock_count = int(stock.quantity_free) if stock else 0
|
stock_count = RECOMMERCE_INFINITY_COUNT if product.in_stock else 0
|
||||||
|
|
||||||
data = to_api_product(product, stock_count=stock_count, fields=None, for_create=True)
|
data = to_api_product(product, stock_count=stock_count, fields=None, for_create=True)
|
||||||
|
|
||||||
|
|||||||
128
test_count.py
Normal file
128
test_count.py
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
"""
|
||||||
|
Тестовый скрипт для отладки поля count (Наличие) в Recommerce API
|
||||||
|
Без Django - напрямую через requests
|
||||||
|
"""
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# === НАСТРОЙКИ - ЗАПОЛНИ ===
|
||||||
|
STORE_URL = "https://mixflowers.by" # Замени на свой URL
|
||||||
|
API_TOKEN = "baac4380c190c4c3fed7a89977fd6155b846c7e8" # Замени на свой токен
|
||||||
|
# ===========================
|
||||||
|
|
||||||
|
SKU = "re-3560"
|
||||||
|
|
||||||
|
def get_headers():
|
||||||
|
return {
|
||||||
|
'x-auth-token': API_TOKEN,
|
||||||
|
'Accept': 'application/json',
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_product():
|
||||||
|
"""Получить товар и показать текущее наличие"""
|
||||||
|
print(f"\n=== GET товар {SKU} ===")
|
||||||
|
url = f"{STORE_URL}/api/v1/catalog/products/{SKU}"
|
||||||
|
try:
|
||||||
|
resp = requests.get(url, headers=get_headers(), timeout=15)
|
||||||
|
print(f"Status: {resp.status_code}")
|
||||||
|
if resp.status_code == 200:
|
||||||
|
result = resp.json()
|
||||||
|
# Показываем наличие
|
||||||
|
print(f" count: {result.get('count')}")
|
||||||
|
print(f" availability: {result.get('availability')}")
|
||||||
|
print(f" waiting_time: {result.get('waiting_time')}")
|
||||||
|
print(f"\nПолный ответ: {result}")
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
print(f"Ошибка: {resp.text}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Ошибка: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def update_product(data):
|
||||||
|
"""Обновить товар"""
|
||||||
|
url = f"{STORE_URL}/api/v1/catalog/products/{SKU}"
|
||||||
|
print(f"POST {url}")
|
||||||
|
print(f"Data: {data}")
|
||||||
|
try:
|
||||||
|
resp = requests.post(url, headers=get_headers(), data=data, timeout=15)
|
||||||
|
print(f"Status: {resp.status_code}")
|
||||||
|
print(f"Response: {resp.text[:500] if resp.text else 'empty'}")
|
||||||
|
return resp
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Ошибка: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def test_count_10():
|
||||||
|
"""Тест: count=10 (конкретное количество)"""
|
||||||
|
print(f"\n=== TEST: count=10 (конкретное количество) ===")
|
||||||
|
update_product({'count': 10})
|
||||||
|
|
||||||
|
def test_count_inf():
|
||||||
|
"""Тест: count=999999 (есть в наличии, без количества)"""
|
||||||
|
print(f"\n=== TEST: count=999999 (есть в наличии = 'inf') ===")
|
||||||
|
# Recommerce использует 999999 вместо inf
|
||||||
|
update_product({'count': 999999})
|
||||||
|
|
||||||
|
def test_count_0():
|
||||||
|
"""Тест: count=0 (нет в наличии)"""
|
||||||
|
print(f"\n=== TEST: count=0 (нет в наличии) ===")
|
||||||
|
update_product({'count': 0})
|
||||||
|
|
||||||
|
|
||||||
|
def test_count_custom():
|
||||||
|
"""Тест: произвольное количество или 'inf'"""
|
||||||
|
print(f"\n=== TEST: произвольное количество ===")
|
||||||
|
val = input("Введите количество (число или 'inf'): ").strip()
|
||||||
|
if val.lower() == 'inf':
|
||||||
|
update_product({'count': 999999})
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
update_product({'count': int(val)})
|
||||||
|
except ValueError:
|
||||||
|
print("Ошибка: введите число или 'inf'")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if "your-store" in STORE_URL or "your-api" in API_TOKEN:
|
||||||
|
print("=" * 50)
|
||||||
|
print("ОШИБКА: Заполни STORE_URL и API_TOKEN в скрипте!")
|
||||||
|
print("Открой test_count.py и замени значения")
|
||||||
|
print("=" * 50)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
print("=" * 50)
|
||||||
|
print("Тестирование поля count (Наличие) для Recommerce API")
|
||||||
|
print(f"Store: {STORE_URL}")
|
||||||
|
print(f"SKU: {SKU}")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Сначала смотрим текущее состояние
|
||||||
|
get_product()
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("Выберите тест:")
|
||||||
|
print("1 - GET (показать текущее состояние)")
|
||||||
|
print("2 - count=10 (конкретное количество)")
|
||||||
|
print("3 - count=inf (есть в наличии)")
|
||||||
|
print("4 - count=0 (нет в наличии)")
|
||||||
|
print("5 - произвольное (число или 'inf')")
|
||||||
|
print("0 - Выход")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
choice = input("\nВведите номер теста: ").strip()
|
||||||
|
|
||||||
|
if choice == "0":
|
||||||
|
break
|
||||||
|
elif choice == "1":
|
||||||
|
get_product()
|
||||||
|
elif choice == "2":
|
||||||
|
test_count_10()
|
||||||
|
elif choice == "3":
|
||||||
|
test_count_inf()
|
||||||
|
elif choice == "4":
|
||||||
|
test_count_0()
|
||||||
|
elif choice == "5":
|
||||||
|
test_count_custom()
|
||||||
|
else:
|
||||||
|
print("Неверный выбор")
|
||||||
Reference in New Issue
Block a user