From ec9fd1c78b2dd20732c6e3c2faee37b57620cf6a Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Tue, 13 Jan 2026 00:27:04 +0300 Subject: [PATCH] =?UTF-8?q?feat(products):=20=D0=BC=D0=B0=D1=80=D0=BA?= =?UTF-8?q?=D0=B5=D1=82=D0=B8=D0=BD=D0=B3=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=84?= =?UTF-8?q?=D0=BB=D0=B0=D0=B3=D0=B8=20is=5Fnew,=20is=5Fpopular,=20is=5Fspe?= =?UTF-8?q?cial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Добавлены поля в BaseProductEntity (наследуются в Product, ProductKit) - Исправлен формат флагов в Recommerce mappers (1/0 вместо true/false) - Добавлены чекбоксы в админку Product и ProductKit - special = is_special OR has_discount (ручное + автоматическое) Co-Authored-By: Claude Opus 4.5 --- myproject/integrations/recommerce/mappers.py | 13 +++-- myproject/products/admin.py | 4 +- .../migrations/0003_add_marketing_flags.py | 58 +++++++++++++++++++ myproject/products/models/base.py | 17 ++++++ 4 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 myproject/products/migrations/0003_add_marketing_flags.py diff --git a/myproject/integrations/recommerce/mappers.py b/myproject/integrations/recommerce/mappers.py index a07be71..7deca94 100644 --- a/myproject/integrations/recommerce/mappers.py +++ b/myproject/integrations/recommerce/mappers.py @@ -90,13 +90,16 @@ def to_api_product( if photo.image: data[f'images[{idx}]'] = photo.image.url - # Обработка флагов товара (как строки "true"/"false" согласно документации API) + # Обработка флагов товара (формат: 1/0 для Recommerce API) if hasattr(product, 'is_new'): - data['is_new'] = "true" if product.is_new else "false" + data['is_new'] = 1 if product.is_new else 0 if hasattr(product, 'is_popular'): - data['is_popular'] = "true" if product.is_popular else "false" - # special - автоматически при наличии скидки (формат: 1/0, не is_special) - data['special'] = 1 if has_discount else 0 + data['is_popular'] = 1 if product.is_popular else 0 + # special - из модели is_special ИЛИ автоматически при скидке + if hasattr(product, 'is_special'): + data['special'] = 1 if (product.is_special or has_discount) else 0 + else: + data['special'] = 1 if has_discount else 0 return data diff --git a/myproject/products/admin.py b/myproject/products/admin.py index 2bc802b..7f94ea1 100644 --- a/myproject/products/admin.py +++ b/myproject/products/admin.py @@ -415,7 +415,7 @@ class ProductAdmin(TenantAdminOnlyMixin, admin.ModelAdmin): 'description': 'Себестоимость рассчитывается автоматически на основе партий товара (FIFO метод). Редактировать вручную невозможно.' }), ('Дополнительно', { - 'fields': ('tags', 'variant_groups', 'status') + 'fields': ('tags', 'variant_groups', 'status', 'is_new', 'is_popular', 'is_special') }), ('Архивирование', { 'fields': ('archived_at', 'archived_by'), @@ -608,7 +608,7 @@ class ProductKitAdmin(TenantAdminOnlyMixin, admin.ModelAdmin): 'description': 'Временные комплекты создаются для конкретных заказов и не показываются в каталоге.' }), ('Дополнительно', { - 'fields': ('tags', 'status') + 'fields': ('tags', 'status', 'is_new', 'is_popular', 'is_special') }), ('Архивирование', { 'fields': ('archived_at', 'archived_by'), diff --git a/myproject/products/migrations/0003_add_marketing_flags.py b/myproject/products/migrations/0003_add_marketing_flags.py new file mode 100644 index 0000000..be5223d --- /dev/null +++ b/myproject/products/migrations/0003_add_marketing_flags.py @@ -0,0 +1,58 @@ +# Generated by Django 5.0.10 on 2026-01-12 21:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0002_alter_configurableproduct_archived_by_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='configurableproduct', + name='is_new', + field=models.BooleanField(default=False, help_text='Отображать как новый товар', verbose_name='Новинка'), + ), + migrations.AddField( + model_name='configurableproduct', + name='is_popular', + field=models.BooleanField(default=False, help_text='Отображать как популярный товар', verbose_name='Популярный'), + ), + migrations.AddField( + model_name='configurableproduct', + name='is_special', + field=models.BooleanField(default=False, help_text='Отображать как спецпредложение (акция)', verbose_name='Спецпредложение'), + ), + migrations.AddField( + model_name='product', + name='is_new', + field=models.BooleanField(default=False, help_text='Отображать как новый товар', verbose_name='Новинка'), + ), + migrations.AddField( + model_name='product', + name='is_popular', + field=models.BooleanField(default=False, help_text='Отображать как популярный товар', verbose_name='Популярный'), + ), + migrations.AddField( + model_name='product', + name='is_special', + field=models.BooleanField(default=False, help_text='Отображать как спецпредложение (акция)', verbose_name='Спецпредложение'), + ), + migrations.AddField( + model_name='productkit', + name='is_new', + field=models.BooleanField(default=False, help_text='Отображать как новый товар', verbose_name='Новинка'), + ), + migrations.AddField( + model_name='productkit', + name='is_popular', + field=models.BooleanField(default=False, help_text='Отображать как популярный товар', verbose_name='Популярный'), + ), + migrations.AddField( + model_name='productkit', + name='is_special', + field=models.BooleanField(default=False, help_text='Отображать как спецпредложение (акция)', verbose_name='Спецпредложение'), + ), + ] diff --git a/myproject/products/models/base.py b/myproject/products/models/base.py index ad7a227..9bf88ca 100644 --- a/myproject/products/models/base.py +++ b/myproject/products/models/base.py @@ -165,6 +165,23 @@ class BaseProductEntity(models.Model): verbose_name="Статус" ) + # Маркетинговые флаги для внешних площадок (Recommerce и др.) + is_new = models.BooleanField( + default=False, + verbose_name="Новинка", + help_text="Отображать как новый товар" + ) + is_popular = models.BooleanField( + default=False, + verbose_name="Популярный", + help_text="Отображать как популярный товар" + ) + is_special = models.BooleanField( + default=False, + verbose_name="Спецпредложение", + help_text="Отображать как спецпредложение (акция)" + ) + # Временные метки created_at = models.DateTimeField( auto_now_add=True,