feat(products): маркетинговые флаги is_new, is_popular, is_special

- Добавлены поля в BaseProductEntity (наследуются в Product, ProductKit)
- Исправлен формат флагов в Recommerce mappers (1/0 вместо true/false)
- Добавлены чекбоксы в админку Product и ProductKit
- special = is_special OR has_discount (ручное + автоматическое)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-13 00:27:04 +03:00
parent 52422ee8df
commit ec9fd1c78b
4 changed files with 85 additions and 7 deletions

View File

@@ -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'),

View File

@@ -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='Спецпредложение'),
),
]

View File

@@ -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,