From 9fceab9de1d72cc0f57f5d7cb4ae0d3716e7ee29 Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Mon, 12 Jan 2026 03:51:08 +0300 Subject: [PATCH] =?UTF-8?q?feat(integrations):=20=D1=80=D0=B5=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D0=BE=D0=B4=D1=8B=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20?= =?UTF-8?q?=D1=81=20API=20Recommerce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлены методы для управления категориями и товарами (CRUD), а также получение списка заказов с поддержкой пагинации и фильтрации. --- ...ecommerceintegration_api_token_and_more.py | 29 ++++++++ .../services/marketplaces/recommerce.py | 66 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 myproject/integrations/migrations/0003_alter_recommerceintegration_api_token_and_more.py diff --git a/myproject/integrations/migrations/0003_alter_recommerceintegration_api_token_and_more.py b/myproject/integrations/migrations/0003_alter_recommerceintegration_api_token_and_more.py new file mode 100644 index 0000000..96e93c0 --- /dev/null +++ b/myproject/integrations/migrations/0003_alter_recommerceintegration_api_token_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 5.0.10 on 2026-01-11 23:29 + +import integrations.fields +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('integrations', '0002_alter_recommerceintegration_api_token_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='recommerceintegration', + name='api_token', + field=integrations.fields.EncryptedCharField(blank=True, help_text='Токен авторизации из панели управления Recommerce', max_length=2000, verbose_name='API Токен (x-auth-token)'), + ), + migrations.AlterField( + model_name='woocommerceintegration', + name='consumer_key', + field=integrations.fields.EncryptedCharField(blank=True, help_text='REST API Consumer Key (хранится зашифрованным)', max_length=1020, verbose_name='Consumer Key'), + ), + migrations.AlterField( + model_name='woocommerceintegration', + name='consumer_secret', + field=integrations.fields.EncryptedCharField(blank=True, help_text='REST API Consumer Secret (хранится зашифрованным)', max_length=1020, verbose_name='Consumer Secret'), + ), + ] diff --git a/myproject/integrations/services/marketplaces/recommerce.py b/myproject/integrations/services/marketplaces/recommerce.py index f2e76cc..23cf945 100644 --- a/myproject/integrations/services/marketplaces/recommerce.py +++ b/myproject/integrations/services/marketplaces/recommerce.py @@ -100,3 +100,69 @@ class RecommerceService: return False, 'Не удалось подключиться к серверу' except Exception as e: return False, str(e) + + # ========== Categories ========== + + def get_category(self, sku: str) -> Tuple[bool, dict, str]: + """Получить категорию по SKU""" + return self._request('GET', f'catalog/categories/{sku}') + + def create_category(self, data: dict) -> Tuple[bool, dict, str]: + """ + Создать категорию. + + Обязательные поля в data: + - sku: артикул категории + - title: название категории + """ + return self._request('POST', 'catalog/categories', data=data) + + def update_category(self, sku: str, data: dict) -> Tuple[bool, dict, str]: + """Обновить категорию (только переданные поля)""" + return self._request('POST', f'catalog/categories/{sku}', data=data) + + def delete_category(self, sku: str) -> Tuple[bool, dict, str]: + """Удалить категорию""" + return self._request('DELETE', f'catalog/categories/{sku}') + + # ========== Products ========== + + def get_product(self, sku: str) -> Tuple[bool, dict, str]: + """Получить товар по SKU""" + return self._request('GET', f'catalog/products/{sku}') + + def create_product(self, data: dict) -> Tuple[bool, dict, str]: + """ + Создать товар. + + Обязательные поля в data: + - name: название товара + - sku: артикул товара + - parent_category_sku: артикул категории + - price[amount]: цена + - price[currency]: валюта (BYN|RUB|USD|EUR|KZT) + """ + return self._request('POST', 'catalog/products', data=data) + + def update_product(self, sku: str, data: dict) -> Tuple[bool, dict, str]: + """Обновить товар (только переданные поля)""" + return self._request('POST', f'catalog/products/{sku}', data=data) + + def delete_product(self, sku: str) -> Tuple[bool, dict, str]: + """Удалить товар""" + return self._request('DELETE', f'catalog/products/{sku}') + + # ========== Orders ========== + + def get_orders(self, page: int = 1, updated_after: str = None) -> Tuple[bool, dict, str]: + """ + Получить список заказов. + + Args: + page: номер страницы (по 100 заказов) + updated_after: фильтр 'Y-m-d-H-i-s' - только заказы после даты + """ + params = {'page': page} + if updated_after: + params['updated_after'] = updated_after + return self._request('GET', 'orders', params=params)