Updated UI to show ProductKit associations for attribute values:
- configurablekit_detail.html:
* Added 'Комплект' column to attributes table
* Shows linked ProductKit as clickable badge
* Shows '—' for unbound attributes
- configurablekit_list.html:
* Added 'Атрибутов' column showing attribute count
* Updated colspan for empty state message (6->7)
Now users can see which ProductKit each attribute value is bound to in:
1. Detail view: Click product -> view attributes with kit bindings
2. List view: See total attribute count for each product
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Implementation of kit binding feature for ConfigurableKitProduct variants:
- Added ForeignKey field `kit` to ConfigurableKitProductAttribute
* References ProductKit with CASCADE delete
* Optional field (blank=True, null=True)
* Indexed for efficient queries
- Created migration 0007_add_kit_to_attribute
* Handles existing data (NULL values for all current records)
* Properly indexed for performance
- Updated template configurablekit_form.html
* Injected available ProductKits into JavaScript
* Added kit selector dropdown in card interface
* Each value now has associated kit selection
* JavaScript validates kit selection alongside values
- Updated JavaScript in card interface
* serializeAttributeValues() now collects kit IDs
* Creates parallel JSON arrays: values and kits
* Stores in hidden fields: attributes-X-values and attributes-X-kits
- Updated views _save_attributes_from_cards() in both Create and Update
* Reads kit IDs from POST JSON
* Looks up ProductKit objects
* Creates ConfigurableKitProductAttribute with FK populated
* Gracefully handles missing kits
- Fixed _should_delete_form() method
* More robust handling of formset deletion_field
* Works with all formset types
- Updated __str__() method
* Handles NULL kit case
Example workflow:
Dlina: 50 -> Kit A, 60 -> Kit B, 70 -> Kit C
Upakovka: BEZ -> Kit A, V_UPAKOVKE -> (no kit)
Tested with test_kit_binding.py - all tests passing
- Kit creation and retrieval
- Attribute creation with kit FK
- Mixed kit-bound and unbound attributes
- Querying attributes by kit
- Reverse queries (get kit for attribute value)
Added documentation: KIT_BINDING_IMPLEMENTATION.md
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
The parameter name field had readonly='readonly' which prevented users from entering values.
This fix allows users to:
- Enter parameter name directly in the form field
- Modify parameter names during editing
- Type any parameter name they need
The readonly attribute was from a mistaken assumption that values would be pre-filled by JavaScript.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces a new user-friendly interface for managing product attributes:
1. **Form Changes** (products/forms.py):
- Removed 'option' field from ConfigurableKitOptionForm (values now inline)
- Updated ConfigurableKitProductAttributeFormSetCreate to only include name, position, visible
- Updated BaseConfigurableKitProductAttributeFormSet validation for new structure
2. **Template Updates** (products/templates/products/configurablekit_form.html):
- Replaced row-based attribute interface with card-based design
- Each card contains:
- Parameter name field
- Position field
- Visibility toggle
- Inline value inputs with add/remove buttons
- "Add parameter" button creates new cards
- "Add value" button adds inline value inputs
3. **JavaScript Enhancements**:
- addValueField(): Creates new value input with delete button
- initAddValueBtn(): Initializes add value button for each card
- addParameterBtn: Dynamically generates new parameter cards
- serializeAttributeValues(): Converts inline values to JSON for POST submission
- Form submission intercept to serialize data before sending
4. **View Updates** (products/views/configurablekit_views.py):
- Both Create and Update views now have _save_attributes_from_cards() method
- Reads attributes-X-values JSON from POST data
- Creates ConfigurableKitProductAttribute for each parameter+value combination
- Handles parameter deletion and visibility toggling
**Key Features**:
✓ One-time parameter name entry with multiple inline values
✓ Add/remove values without reloading page
✓ Add/remove entire parameters with one click
✓ No database changes required
✓ Better UX: card layout more intuitive than rows
✓ Proper JSON serialization for value transmission
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces a complete refactoring of the variable product system:
1. **New Model**: ConfigurableKitOptionAttribute - M2M relationship between variants and attribute values
- Replaces TextField-based attribute storage with proper database relationships
- Ensures one value per attribute per variant through unique_together constraint
- Includes indexes on both option and attribute fields for query performance
2. **Form Refactoring**:
- Removed static 'attributes' field from ConfigurableKitOptionForm
- Added dynamic field generation in __init__ based on parent attributes
- Creates ModelChoiceField for each attribute (e.g., attribute_Длина, attribute_Упаковка)
- Enhanced BaseConfigurableKitOptionFormSet validation to check all attributes are filled
3. **View Updates**:
- Modified ConfigurableKitProductCreateView.form_valid() to save M2M relationships
- Modified ConfigurableKitProductUpdateView.form_valid() with same logic
- Uses transaction.atomic() for data consistency
4. **Template & JS Enhancements**:
- Reordered form so attributes section appears before variants
- Fixed template syntax: changed from field.name.startswith to "attribute_" in field.name
- Updated JavaScript to dynamically generate attribute select fields when adding variants
- Properly handles formset naming convention (options-{idx}-attribute_{name})
5. **Database Migrations**:
- Created migration 0005 to alter ConfigurableKitOption.attributes to JSONField (for future use)
- Created migration 0006 to add ConfigurableKitOptionAttribute model
6. **Tests**:
- Added test_configurable_simple.py for model/form verification
- Added test_workflow.py for complete end-to-end testing
- All tests passing successfully
Features:
✓ All attributes required for each variant if defined on parent
✓ One value per attribute per variant (unique_together constraint)
✓ One default variant per product (formset validation)
✓ Dynamic form field generation based on parent attributes
✓ Atomic transactions for multi-part operations
✓ Proper error messages per variant number
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Создана модель ConfigurableKitProductAttribute с полями name, option, position, visible
- Добавлены формы и formsets для управления атрибутами родительского товара
- Обновлены CRUD представления для работы с атрибутами (создание/редактирование)
- Добавлен блок атрибутов в шаблоны создания/редактирования
- Обновлена страница детального просмотра с отображением атрибутов товара
- Добавлен JavaScript для динамического добавления форм атрибутов
- Реализована валидация дубликатов атрибутов в formset
- Атрибуты сохраняются в transaction.atomic() вместе с вариантами
Теперь можно определять схему атрибутов для экспорта на WooCommerce без использования JSON или ID, только name и option.
- Аннотация товаров остатками (available_qty) и резервами (reserved_qty) через Subquery
- Компактный формат отображения: X(−Y) где X - доступно, Y - зарезервировано
- Визуальная стилизация: крупное число для остатков, мелкое для резервов
- Цветовая индикация: зелёный (≥5), жёлтый (<5), красный (≤0)
- Без дополнительных SQL-запросов, оптимизировано через подзапросы
- Уменьшен размер шрифта с 0.95rem до 0.85rem для лучшей читаемости
- Уменьшен line-height с 1.2 до 1.1 для компактного расположения текста
- Текст теперь полностью помещается внутри кнопок без выхода за границы
- Сохранена возможность переноса текста на две строки для кнопки 'Отложенный заказ'
- Добавлено исключение для кнопки #scheduleLater
- Для этой кнопки white-space: normal вместо nowrap
- Текст переносится на две строки для лучшей читаемости
- Остальные кнопки остаются в одну строку
- Увеличен размер шрифта кнопок с 0.75rem до 0.95rem
- Добавлен жирный шрифт (font-weight: 700)
- Изменено white-space с normal на nowrap для избежания переносов строк
- Убраны word-wrap: break-word (не нужен при nowrap)
- Кнопки теперь более читабельны на планшете
- Убрана стартовая загрузка витринных комплектов (теперь только по API)
- showcase_kits_json теперь пустой массив на старте
- Витринные букеты загружаются динамически при клике на ВИТРИНА
- Оптимизирована get_showcase_kits_for_pos - устранены N+1 запросы
- Один запрос для всех резервов вместо N запросов на комплект
- Используется prefetch для kit_items (без дополнительных запросов)
- Добавлена группировка резервов в памяти вместо повторных обращений к БД
- Оптимизирована загрузка фото товаров и комплектов
- Используется Prefetch только для первого фото (thumbnail)
- Вместо photos.first() (который тянет все фото) - ограниченный queryset
- Prefetch с to_attr='first_photo_list' для минимизации запросов
- Результат: значительное сокращение нагрузки на БД при открытии POS
- Добавлены API endpoints для получения и обновления витринных комплектов
- GET /pos/api/product-kits/<id>/ - получение деталей комплекта
- POST /pos/api/product-kits/<id>/update/ - обновление комплекта
- Реализовано редактирование комплектов из POS интерфейса
- Кнопка редактирования (карандаш) на карточках витринных букетов
- Модальное окно предзаполняется данными комплекта
- Поддержка изменения состава, цен, описания и фото
- Умное управление резервами при изменении состава
- Введено изолированное состояние tempCart для модального окна
- Основная корзина (cart) больше не затрагивается при редактировании
- tempCart используется для создания и редактирования комплектов
- Автоочистка tempCart при закрытии модального окна
- Устранён побочный эффект загрузки состава комплекта в основную корзину
- Добавлен API endpoint GET /pos/api/showcase-kits/ для получения актуальных витринных букетов
- Изменена переменная SHOWCASE_KITS на изменяемую showcaseKits
- Добавлена функция refreshShowcaseKits() для обновления данных с сервера
- Кнопка ВИТРИНА теперь загружает свежие данные перед отображением
- После создания временного букета автоматически обновляется список и переключается вид на витрину
- Исправлена проблема с отображением только что созданных витринных букетов
- Reduced spacing around 'Итого:' line for more compact design
- Changed from h5 to strong tags for better space utilization
- Removed bottom margin from cart list
- Set symmetric padding (py-1) for total section
- More vertical space now available for cart items
- Added Bootstrap icon (bi-box-seam) for kit items in POS cart
- Kits and showcase kits now display with blue icon for visual distinction
- Regular products remain without icons for cleaner look
- Maintains consistency with product list view styling
- Added get_showcase_kits_for_pos() function to retrieve showcase kits with active reservations
- Modified POS terminal to show showcase kits when 'Витрина' button is clicked
- Showcase kits displayed as product cards with showcase name badge (🌺 icon)
- Added isShowcaseView flag to toggle between regular and showcase view modes
- Implemented distinct styling for active showcase button:
* Bright orange background (#ff6600)
* Black text for contrast
* Thicker border (3px)
* Enhanced shadow and scale effect (1.05)
- Showcase kits can be added to cart for sale from POS interface
- Добавлен API endpoint для создания временного комплекта из корзины
- Реализован endpoint получения списка активных витрин
- Создано модальное окно для настройки комплекта и выбора витрины
- JavaScript логика: валидация корзины, отправка данных, очистка после успеха
- Автоматическая генерация названия комплекта с датой и временем
- Агрегация дубликатов товаров в корзине перед созданием
- Резервирование компонентов на витрину через ShowcaseManager
- Расчёт и отображение итоговой цены комплекта
- Создана модель Showcase (витрина) привязанная к складу
- Расширена Reservation для поддержки витринных резервов
- Добавлены поля в OrderItem для маркировки витринных продаж
- Реализован ShowcaseManager с методами резервирования, продажи и разбора
- Обновлён админ-интерфейс для управления витринами
- Добавлена кнопка Витрина в POS (категории) и API для просмотра
- Добавлена кнопка На витрину в панели действий POS
- Миграции готовы к применению
- Проверяется количество уже существующих фото перед загрузкой новых
- Блокируется загрузка если уже есть 10 фото (максимум)
- При превышении загружается только доступное количество слотов
- Информативные сообщения об ошибках и предупреждения для пользователя
- Исправлена проблема с накоплением фото при многократном редактировании
- Добавлен retry на 5 сек при DoesNotExist для ожидания коммита транзакции
- temp_path сохраняется в PhotoProcessingStatus.result_data при постановке задачи
- При окончательной неудаче not_found удаляется осиротевший temp файл
- Предотвращает накопление temp файлов при гонке создания фото
- Создан отдельный CSS файл products/static/products/css/gallery.css для стилей галереи
- Перенесены все стили модальной карусели из quality_indicator.css в gallery.css
- Добавлены современные стрелки навигации с широкой областью нажатия (80px)
- Улучшена видимость элементов управления: контрастные обводки, тени, градиенты
- Круглые индикаторы с полупрозрачной подложкой для видимости на любом фоне
- Адаптивные размеры для планшетов (60px) и мобильных (50px)
- Убраны визуальные индикаторы качества фото из углов изображений
- Оставлена только текстовая информация о качестве под фотографиями
- Упрощена разметка списка товаров - удалены ненужные обёртки и стили
- Заменен несуществующий фильтр is_active на status='active' для моделей Product и ProductKit
- Устранена ошибка FieldError при отображении страницы тега
- Комментарии сохранены на русском языке
- Добавлен столбец 'Теги' в таблицу товаров и комплектов
- Реализовано умное отображение тегов: показываются первые 2 тега + многоточие
- При наведении на ячейку тегов показывается полный список во всплывающей подсказке
- Исправлены все ссылки с устаревших URL (product-list, productkit-list) на новый (products-list)
- Обновлены шаблоны: product_detail, product_form, product_confirm_delete, productkit_detail, productkit_create, productkit_edit
- Обновлен компонент category_filter_buttons с поддержкой фильтра ?type=products и ?type=kits
- Удалена ненужная подсказка 'Ctrl+Click' под полем выбора тегов в фильтрах
- Создан единый шаблон products_list.html для отображения товаров и комплектов
- Удалены дублирующиеся шаблоны (product_list, productkit_list, products_unified_list, all_products_list)
- Добавлены фильтры: тип (все/товары/комплекты), категория, статус, наличие, теги
- Обновлен CombinedProductListView с поддержкой фильтрации по типу и тегам
- Изменены URL маршруты: главная страница /products/ теперь показывает объединенный список
- Обновлены success_url во всех CRUD представлениях для редиректа на объединенный список
- Добавлена фильтрация по тегам с отображением количества выбранных элементов
- Улучшена UX: компактный select для тегов с счетчиком выбранных
- Все комментарии в коде переведены на русский язык
- Added temp file deletion in Celery task after successful processing
- Added temp file cleanup in sync fallback method
- Added temp file removal in delete() if processing never completed
- Prevents accumulation of orphaned files in media/<entity>/temp/ folders
Изменения:
- Заменено жёсткое кодирование статусов ('draft', 'new' и т.д.) на динамическое отображение из OrderStatus объекта
- Теперь статусы берут цвет (color) и название (label/name) из модели OrderStatus
- Обновлена логика отображения статуса оплаты: заменено payment_status на is_paid и amount_paid
- Добавлены иконки для наглядности (check-circle, exclamation-circle, x-circle)
- Для частичной оплаты теперь показывается сумма уже оплаченного
Это позволяет:
- Добавлять новые статусы без изменения шаблона
- Менять цвета статусов через admin панель
- Использовать правильные поля из модели Order
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Реализована трёхуровневая система статусов товаров и комплектов:
- active (Активный) - товар доступен для продажи
- archived (Архивный) - скрыт, можно восстановить в следующем сезоне
- discontinued (Снят) - морально устарел, готов к удалению
Изменения:
1. Модели (BaseProductEntity, Product, ProductKit):
- Заменено поле is_deleted (Boolean) на status (CharField)
- Добавлены архивные метаданные (archived_at, archived_by)
- Обновлены методы: archive(), restore(), discontinue(), delete()
- Уникальное ограничение изменено на conditional (status='active')
2. Менеджеры (ActiveManager, SoftDeleteQuerySet):
- Полиморфная поддержка обеих систем (status и is_active)
- Использует hasattr() для совместимости с наследниками
- Методы: archive(), restore(), discontinue(), archived_only(), active_only()
3. Формы (ProductForm, ProductKitForm):
- Включены поле status в формы
- Валидация уникальности по status='active'
- CSS классы для статус-селектора
4. Admin панель:
- DeletedFilter переименован в StatusFilter с тремя опциями
- get_status_display() с цветным отображением статуса
- Actions: restore_items, hard_delete_selected, delete_selected
- Readonly поля для архивирования
5. Представления:
- ProductListView: фильтр status вместо is_active
- CombinedProductListView: поддержка фильтра status для товаров и комплектов
- API views обновлены для работы со статусом
6. Шаблоны:
- product_form.html: form.status вместо form.is_active
- productkit_create.html: form.status вместо form.is_active
- productkit_edit.html: form.status вместо form.is_active
7. Миграции:
- Удалены все старые миграции (чистый перезапуск по требованию пользователя)
- Создана новая миграция 0001_initial с полной структурой status-системы
- Удален старый код преобразования is_deleted -> status
Проведённые проверки:
- Django system check passed ✓
- Полиморфные менеджеры работают с обеими системами
- Уникальные ограничения корректно работают с условиями
- История заказов сохраняется даже после архивирования товара (django-simple-history)
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Реализована полная система обеспечения уникальности названий:
1. **Уровень БД (Model Constraints)** - добавлены UniqueConstraint для:
- Product: уникальность имени среди активных товаров
- ProductCategory: уникальность имени среди активных категорий
- ProductTag: уникальность имени только для активных тегов (неактивные могут повторяться)
- ProductKit: уникальность имени среди активных, непроизвременных комплектов
2. **Уровень формы (Form Validation)** - добавлены clean() методы для:
- ProductForm, ProductKitForm, ProductCategoryForm, ProductTagForm
- Валидация до попытки сохранения в БД
- Сохранение введённых данных при ошибке валидации
3. **Уровень представления (IntegrityError Handling)** - добавлена обработка в views:
- ProductCategoryCreateView, ProductCategoryUpdateView
- ProductTagCreateView, ProductTagUpdateView
- ProductKitCreateView, ProductKitUpdateView
- create_tag_api: защита от race conditions с fallback поиском
Три уровня защиты гарантируют:
- Профилактика ошибок на уровне формы
- Обработка исключительных ситуаций в views
- Защита БД от одновременных запросов (race conditions)
- Пользователь видит понятное сообщение об ошибке вместо 500 ошибки
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>