Commit Graph

42 Commits

Author SHA1 Message Date
d566819367 Feat: Add inline category creation in catalog with clickable product names
Added inline category creation functionality to catalog page with user-friendly interface:
- Inline input fields for creating root and nested categories
- '+' button in category tree header for root categories
- '+' icon on hover for each category node to create subcategories
- Clickable product/kit names in catalog grid and list views
- AJAX API endpoint for category creation with validation
- User-friendly error messages for duplicate names and constraints
- Clean implementation using clearTimeout pattern to prevent duplicate requests

Technical details:
- New API endpoint: POST /products/api/categories/create/
- Auto-generates slug and SKU for new categories
- Validates uniqueness, parent existence, and circular references
- Single-request submission with proper race condition handling
- Removes debug logging for production-ready code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 00:24:05 +03:00
6517643e0d Feat: Add catalog page with inline category renaming
- Create catalog view with category tree and product grid
- Add grid/list view toggle for products
- Implement inline category name editing (click to rename)
- Add API endpoint for category rename
- Extract JS to separate catalog.js file
- Remove unused partial templates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 00:54:34 +03:00
4549b2c2c2 Feat: Add catalog page with category tree and product grid
- Create catalog view with recursive category tree building
- Add left-side category tree with expand/collapse functionality
- Add right-side product/kit grid with filtering and search
- Include category navigation with product/kit counts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 00:31:37 +03:00
493b6c212d Add bulk photo deletion feature for products.
Allows selecting and deleting multiple photos at once via checkboxes
and an AJAX endpoint. Key features:
- Checkboxes next to each photo in edit form
- Delete button that shows only when photos are selected
- AJAX request with JSON payload and success confirmation
- DOM removal and counter update after deletion
- Uses existing ImageProcessor cleanup logic

Files changed:
- product_form.html: Added checkboxes and delete button with JS handler
- photo_management.py: Added product_photos_delete_bulk AJAX view
- urls.py: Added /product/photos/delete-bulk/ endpoint
- views/__init__.py: Exported new function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 21:49:50 +03:00
d3d3c23695 Add stock availability display to product list and detail views
- Add total_available, total_reserved, total_free annotations to product queries
- Display free stock (green/red) with reserved count in product list
- Show detailed stock info in product detail page (moved to top)
- Make reservation count clickable to view filtered reservations
- Add product filter support to ReservationListView
- Add product link in reservation list for easy navigation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 00:31:38 +03:00
08a5527ba7 Fix cart lock validation and error handling improvements
## 1. Add cart lock validation to sell_from_showcase()
- Prevent selling showcase kits locked in another cashier's cart
- Check cart_lock_expires_at before allowing direct sales
- Return clear error message with lock holder's name and time remaining
- File: inventory/services/showcase_manager.py

## 2. Improve error handling in POS create_temp_kit_to_showcase()
- Add detailed logging for all error types (JSON, validation, generic)
- Provide user-friendly error messages instead of generic 500
- Log full context (kit name, showcase ID, items, user) for debugging
- Categorize errors: stock issues, integrity, locks, not found
- File: pos/views.py

## 3. Fix critical bug in create_temporary_kit()
- Replace non-existent is_active field with status='active'
- Affects 3 locations: kit creation, product lookup, kit duplication
- This was causing 500 errors when creating temporary kits from order edit
- File: products/services/kit_service.py

## 4. Improve error handling in create_temporary_kit_api()
- Add comprehensive logging for order creation endpoint
- Provide specific error messages for common failure scenarios
- Help diagnose issues when creating kits from order editing UI
- File: products/views/api_views.py

These changes complete the Soft Lock system and fix the 500 error issue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 00:24:59 +03:00
a1888b7745 Optimize order statuses list page with compact card layout
- Changed from table to card-based design for better space efficiency
- Reduced padding and margins to fit 15+ statuses on screen without scrolling
- Minimized font sizes and icon sizes for compact display
- Added proper styling for edit and delete buttons with hover effects
- Improved visual hierarchy with color indicators and badges
- Maintained all functionality while improving UX

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 23:00:29 +03:00
3f789785ca Add ProductKit binding to ConfigurableKitProductAttribute values
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>
2025-11-18 21:29:14 +03:00
def795f0ad Implement card-based interface for ConfigurableKitProduct attributes
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>
2025-11-18 20:54:14 +03:00
48938db04f Implement M2M architecture for ConfigurableKitProduct variants with dynamic attribute selection
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>
2025-11-18 20:04:22 +03:00
c4260f6b1c Добавлена модель атрибутов для вариативных товаров (ConfigurableKitProductAttribute)
- Создана модель ConfigurableKitProductAttribute с полями name, option, position, visible
- Добавлены формы и formsets для управления атрибутами родительского товара
- Обновлены CRUD представления для работы с атрибутами (создание/редактирование)
- Добавлен блок атрибутов в шаблоны создания/редактирования
- Обновлена страница детального просмотра с отображением атрибутов товара
- Добавлен JavaScript для динамического добавления форм атрибутов
- Реализована валидация дубликатов атрибутов в formset
- Атрибуты сохраняются в transaction.atomic() вместе с вариантами

Теперь можно определять схему атрибутов для экспорта на WooCommerce без использования JSON или ID, только name и option.
2025-11-18 09:24:49 +03:00
a073b1aa77 Добавлена проверка общего лимита фото при редактировании
- Проверяется количество уже существующих фото перед загрузкой новых
- Блокируется загрузка если уже есть 10 фото (максимум)
- При превышении загружается только доступное количество слотов
- Информативные сообщения об ошибках и предупреждения для пользователя
- Исправлена проблема с накоплением фото при многократном редактировании
2025-11-16 02:08:57 +03:00
0bac86264d Исправлена ошибка фильтрации в ProductTagDetailView
- Заменен несуществующий фильтр is_active на status='active' для моделей Product и ProductKit
- Устранена ошибка FieldError при отображении страницы тега
- Комментарии сохранены на русском языке
2025-11-15 23:07:00 +03:00
b8185f2f6c Объединение списков товаров и комплектов в единый интерфейс
- Создан единый шаблон products_list.html для отображения товаров и комплектов
- Удалены дублирующиеся шаблоны (product_list, productkit_list, products_unified_list, all_products_list)
- Добавлены фильтры: тип (все/товары/комплекты), категория, статус, наличие, теги
- Обновлен CombinedProductListView с поддержкой фильтрации по типу и тегам
- Изменены URL маршруты: главная страница /products/ теперь показывает объединенный список
- Обновлены success_url во всех CRUD представлениях для редиректа на объединенный список
- Добавлена фильтрация по тегам с отображением количества выбранных элементов
- Улучшена UX: компактный select для тегов с счетчиком выбранных
- Все комментарии в коде переведены на русский язык
2025-11-15 22:48:34 +03:00
9363527e50 Fix: Auto-cleanup temp files after photo processing
- 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
2025-11-15 22:28:41 +03:00
7132d2c910 feat: Замена is_active на status для архивирования товаров
Реализована трёхуровневая система статусов товаров и комплектов:
- 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>
2025-11-15 15:30:23 +03:00
079bd23829 feat: Добавить трёхуровневую защиту от дубликатов имён товаров, категорий, тегов и комплектов
Реализована полная система обеспечения уникальности названий:

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>
2025-11-15 13:49:52 +03:00
0bdb42401a fix: Обработка race condition при дублировании slug товаров
Реализована трёхуровневая защита от IntegrityError при создании товаров с одинаковым названием:

1. SlugService улучшен:
   - Добавлен метод _get_base_queryset() для работы с мягким удалением
   - Проверка всех объектов включая удалённые (all_objects)
   - Новый метод get_next_available_slug() для retry обработки
   - Максимум 100 попыток поиска уникального slug

2. BaseProductEntity.save() защищена:
   - transaction.atomic() для атомарности операции
   - Retry логика с 5 попытками при IntegrityError
   - При конфликте добавляется суффикс (-1, -2, -3...)
   - Fallback на timestamp если суффиксы исчерпаны

3. Views обрабатывают IntegrityError:
   - ProductCreateView.form_valid() перехватывает ошибку
   - ProductUpdateView.form_valid() перехватывает ошибку
   - Пользователю показывается дружелюбное сообщение об ошибке
   - Нет 500 ошибок - вместо этого form_invalid() с сообщением

Эффект:
- До: User создаёт товар "Роза красная" 2 раза → IntegrityError → 500 ошибка
- После: User создаёт товар "Роза красная" 2 раза → slug автоматически становится "roza-krasnaya-1"

Протестировано на Django shell и синтаксис проверен.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 11:57:11 +03:00
d9903cd721 feat: Улучшена система сообщений об ошибках и предупреждениях
Изменения:
- ProductCreateView/UpdateView теперь показывают warnings для предупреждений о лимите фото
- Разделение сообщений: error (красный) vs warning (желтый)
- Улучшен components/messages.html:
  * Добавлены иконки для каждого типа сообщения
  * Bootstrap Icons интеграция
  * Кастомные цвета для alerts
  * Лучший visual feedback для пользователя

Теперь пользователи видят понятные сообщения везде на сайте!

🤖 Generated with Claude Code
2025-11-15 11:27:08 +03:00
f7d1851418 fix: Сохранять первые 10 фото, остальные отклонять с уведомлением
Изменено поведение handle_photos():
- Если загружено больше 10 фото, сохраняются первые 10
- Остальные отклоняются с warning сообщением
- Товар теперь ВСЕГДА создается (даже если больше 10 фото)

Это позволяет пользователю загрузить 11+ фото,
но система обработает только первые 10 и уведомит об этом.

🤖 Generated with Claude Code
2025-11-15 11:20:51 +03:00
0791ebb13b fix: Сохранять файл фото ДО запуска Celery task
При асинхронной обработке фото нужно сначала сохранить файл в БД,
потом запустить Celery task. Иначе task не найдет файл.

Изменения:
- BasePhoto.save() теперь сохраняет файл перед запуском task
- Исправлена проблема 'Photo has no image file' в Celery worker

🤖 Generated with Claude Code
2025-11-15 11:11:08 +03:00
77064a274f Реализовано управление активностью тегов товаров и комплектов
## Что сделано:

### 1. Фильтрация тегов по активности
- ProductForm и ProductKitForm показывают только активные теги в селектах
- ProductListView, ProductKitListView передают только активные теги в контекст фильтров

### 2. Отображение тегов на страницах товаров/комплектов
- product_detail.html отображает только активные теги
- productkit_detail.html отображает только активные теги

### 3. Логика отображения в деталях тега
- Для активного тега: показываются только активные товары/комплекты
- Для неактивного тега: показываются ВСЕ товары/комплекты (для возможности ручной очистки)

### 4. API endpoint для переключения статуса
- Новый endpoint toggle_tag_status_api в api_views.py
- POST /products/api/tags/<id>/toggle/
- Переключает is_active и возвращает новый статус

### 5. AJAX toggle switch в таблице тегов
- Заменены бейджи на toggle switch в tag_list.html
- Переключатель в 1.3x больше (масштабирование через CSS)
- Мгновенное обновление без перезагрузки страницы
- Показывает сообщение об успехе/ошибке

### 6. Связь в БД остаётся неизменной
- При деактивации тег остаётся привязан к товарам в БД
- Просто скрывается в интерфейсе
- При реактивации вновь становится видимым

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-12 11:33:12 +03:00
1daee88cbd Добавлено быстрое создание тегов на странице списка
API функционал:
- Создан endpoint /api/tags/create/ для AJAX создания тегов
- Валидация: пустое имя, длина, уникальность (регистронезависимо)
- Автоматическая генерация slug через модель
- Возврат JSON с данными созданного тега

UI функционал на странице списка тегов:
- Панель быстрого создания с крупным полем ввода
- Автофокус на поле при загрузке страницы
- Создание тега по нажатию Enter или клику на кнопку
- Индикатор загрузки (спиннер) во время создания
- Блокировка поля/кнопки во время запроса
- Автоматическая перезагрузка страницы после создания
- Возврат фокуса в поле при ошибке
- Красивые alert-сообщения об успехе/ошибке
- CSRF защита

Workflow: ввёл название → Enter → тег создан → фокус снова в поле → можно вводить следующий

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 23:26:40 +03:00
1a0360f8c0 Реализован полный CRUD для тегов товаров
Упрощена модель ProductTag:
- Удалены поля soft delete (is_deleted, deleted_at, deleted_by)
- Добавлено поле is_active для управления статусом
- Упрощены менеджеры и методы модели

Создан CRUD функционал:
- ProductTagForm: форма с автогенерацией slug
- Views: список, создание, просмотр, редактирование, удаление
- URL маршруты: /products/tags/*
- Шаблоны: list, form, detail, confirm_delete

Особенности:
- Поиск по названию и slug
- Фильтрация по статусу активности
- Статистика использования тегов в товарах/комплектах
- Пагинация (20 на страницу)
- Предупреждение при удалении с отображением связанных объектов
- Добавлена ссылка "Теги" в навигацию

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 23:14:01 +03:00
5d5de1fe31 Рефакторинг: перенос логики создания временных комплектов в сервис
Изменения:
- Удалена функция create_temporary_kit из myproject/orders/views.py
- Перенесена в новый сервис myproject/products/services/kit_service.py
- Добавлен API endpoint products:api-temporary-kit-create для создания временных комплектов
- Обновлены URL-ы соответственно

Преимущества:
- Логика временных комплектов теперь находится в соответствующем приложении (products)
- Упрощена архитектура orders приложения
- Сервис может быть переиспользован в других контекстах
- Лучшее разделение ответственности между приложениями

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 23:44:05 +03:00
deb138f037 Исправлен импорт ProductKitMakePermanentView
Добавлен ProductKitMakePermanentView в:
- products/views/__init__.py импорты
- __all__ экспорт

Теперь view доступен через products.views и сервер запускается без ошибок.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 15:29:25 +03:00
a1df188b2a Реализовано преобразование временных комплектов в постоянные
Views (products/views/productkit_views.py):
- ProductKitMakePermanentView: view для преобразования временного комплекта
  * Доступен только для временных комплектов (is_temporary=True)
  * Позволяет отредактировать название, описание, категории, теги, цену
  * Вызывает метод make_permanent() модели
  * Перенаправляет на детальную страницу комплекта после успеха

URLs (products/urls.py):
- /products/kits/<pk>/make-permanent/ - страница преобразования

Templates:
- productkit_make_permanent.html: форма преобразования с составом и ценой
- order_detail.html: добавлена кнопка "Сделать постоянным" для временных комплектов

Теперь флорист может:
1. Увидеть временный комплект в заказе с badge "Временный"
2. Нажать "Сделать постоянным"
3. Отредактировать название, добавить категории
4. Сохранить - комплект появится в каталоге

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 15:19:56 +03:00
ea4bb5a43b Скрыты временные комплекты из каталога и поиска
Views:
- ProductKitListView: фильтр is_temporary=False
- CombinedProductListView: фильтр is_temporary=False для комплектов
- API search: фильтр is_temporary=False в поиске и популярных

Admin:
- Добавлен фильтр по is_temporary
- Добавлено отображение статуса временного комплекта в списке
- Добавлена ссылка на заказ для временных комплектов
- Добавлен раздел "Временный комплект" в fieldsets

Теперь временные комплекты не показываются в общем каталоге,
но доступны в админке и по прямой ссылке (для заказов).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 15:00:25 +03:00
ec0557c8cf feat: Добавлена функциональность управления заказами и улучшен поиск товаров
Заказы:
- Добавлены миграции для исторических записей с полями оплаты и получателя
- Расширен admin для заказов с инлайнами товаров/комплектов
- Реализованы представления списка, создания, редактирования и удаления заказов
- Добавлен шаблон подтверждения удаления заказа
- Настроены URL-маршруты для работы с заказами

Клиенты:
- Добавлена миграция с новыми полями адресов и подтверждений
- Обновлена модель клиентов с дополнительными полями
- Улучшен admin для работы с клиентами

Товары:
- Значительно улучшен API поиска товаров с поддержкой фильтрации
- Добавлен Select2 виджет для динамического поиска товаров
- Создан статический JS файл для интеграции Select2
- Оптимизирована обработка запросов и ответов API

Прочее:
- Добавлены новые настройки в settings.py
- Обновлена навигация в navbar.html
- Обновлены URL-маршруты проекта

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-07 16:10:19 +03:00
9e430bca18 refactor: оптимизирована обработка цен и запросов в группах вариантов
Улучшения:
- Исправлена отображение цены в таблице вариантов: заменено sale_price на actual_price
  чтобы правильно обрабатывать случаи когда скидка не установлена
- Оптимизирован property in_stock: вычисляется в памяти из prefetched данных
  вместо отдельного запроса EXISTS к БД
- Оптимизирован property price: использует actual_price (sale_price или price)
  вместо только sale_price, добавлена документация о требовании prefetch_related
- Оптимизирован DetailView.get_context_data: используется кешированный
  prefetch_related вместо создания нового queryset для items
- Исправлена AJAX функция _get_items_data: использует actual_price вместо sale_price

Результат:
- Исчезла проблема с выводом "None" вместо цены
- Сокращено количество запросов к БД с 4-5 до 3 для страницы detail
- Улучшена производительность при работе с группами вариантов

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:02:43 +03:00
3c62cce057 fix: Загружать сохранённые значения корректировки цены при редактировании
При редактировании комплекта поля корректировки цены остаются пустыми,
хотя в БД сохранены корректные значения (price_adjustment_type и value).

Исправлено:
1. Добавлен вызов validateSingleAdjustment() после заполнения полей
   - Это отключает остальные поля и помечает валидные
   - Реализует логику одного заполненного поля

2. Добавлено логирование в консоль браузера для отладки:
   - Показывает какие значения загружены из БД
   - Помогает выявить проблемы

Теперь при редактировании:
- Если есть сохранённая корректировка, она отображается
- Остальные поля автоматически отключаются
- Пересчитывается финальная цена

Файл: products/templates/products/productkit_edit.html
2025-11-02 19:52:42 +03:00
045f6a45da fix: Удалить вызов старого валидатора ценообразования
Был вызов KitValidator.validate_pricing_method_availability() который
пытался получить атрибут cost_calculation_info - это часть старой
системы ценообразования которая была заменена на новую.

Новая система не требует этой сложной валидации так как просто
вычисляет цену как сумму actual_price компонентов + опциональная корректировка.

Файл: products/views/productkit_views.py
2025-11-02 19:44:13 +03:00
6c8af5ab2c fix: Улучшения системы ценообразования комплектов
Исправлены 4 проблемы:
1. Расчёт цены первого товара - улучшена валидация в getProductPrice и calculateFinalPrice
2. Отображение actual_price в Select2 вместо обычной цены
3. Количество по умолчанию = 1 для новых форм компонентов
4. Auto-select текста при клике на поле количества для удобства редактирования

Изменённые файлы:
- products/forms.py: добавлен __init__ в KitItemForm для quantity.initial = 1
- products/templates/includes/select2-product-init.html: обновлена formatSelectResult
- products/templates/productkit_create.html: добавлен focus handler для auto-select
- products/templates/productkit_edit.html: добавлен focus handler для auto-select

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 19:04:03 +03:00
d92045c4c4 refactor: Создать базовый класс BaseProductEntity и реструктурировать Product/ProductKit
Основные изменения:

## Модели (models.py)
- Создан абстрактный класс BaseProductEntity с общими полями:
  * Идентификация: name, sku, slug
  * Описания: description, short_description (новое поле)
  * Статус: is_active, timestamps, soft delete
  * Managers: objects, all_objects, active

- Product:
  * Унаследован от BaseProductEntity
  * sale_price переименован в price (основная цена)
  * Добавлено новое поле sale_price (цена со скидкой, nullable)
  * Добавлено property actual_price

- ProductKit:
  * Унаследован от BaseProductEntity
  * fixed_price переименован в price (ручная цена)
  * pricing_method: 'fixed' → 'manual'
  * Добавлено поле sale_price (цена со скидкой)
  * Добавлено поле cost_price (nullable)
  * Добавлены properties: calculated_price, actual_price
  * Обновлен calculate_price_with_substitutions()

## Forms (forms.py)
- ProductForm: добавлено short_description, price, sale_price
- ProductKitForm: добавлено short_description, cost_price, price, sale_price

## Admin (admin.py)
- ProductAdmin: обновлены list_display и fieldsets с новыми полями
- ProductKitAdmin: добавлены fieldsets, метод get_price_display()

## Templates
- product_form.html: добавлены поля price, sale_price, short_description
- product_detail.html: показывает зачеркнутую цену + скидку + бейджик "Акция"
- product_list.html: отображение цен со скидкой и бейджиком "Акция"
- all_products_list.html: единообразное отображение цен
- productkit_detail.html: отображение скидок с бейджиком "Акция"

## API (api_views.py)
- Обновлены все endpoints для использования поля price вместо sale_price

Результат: единообразная архитектура с поддержкой скидок, DRY-принцип,
логичные названия полей, красивое отображение акций в UI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 00:49:01 +03:00
dbb94e9d2a refactor: Добавить в_stock в API и улучшить загрузку данных в форме вариантов
Изменения в API:
- Добавить поле in_stock в возвращаемые данные товаров
- Добавить поддержку запроса товара по ID (параметр ?id=) для получения актуальных данных
- Исправить дублирование информации одного товара на остальные в таблице вариантов

Изменения в форме:
- Добавить автоматическую загрузку данных товара при загрузке страницы для существующих строк
- Правильно отображать артикул, цену и наличие для каждого товара в группе

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 00:03:40 +03:00
e821d881a9 fix: Исправить сохранение приоритетов товаров в группе вариантов
Проблема: при перемещении товаров стрелками вверх/вниз приоритеты изменялись только в UI,
но при сохранении их значения не обновлялись в БД и возвращались в исходное состояние.

Причина: после сохранения формсета в view.form_valid() вызывалась функция _recalculate_priorities(),
которая перезаписывала все приоритеты по ID товаров, игнорируя значения из формсета.

Решение:

1. Удалена функция _recalculate_priorities() которая перезаписывала приоритеты
2. Теперь приоритеты сохраняются напрямую из формсета (inlineformset содержит поле 'priority')
3. Улучшен JavaScript селектор в updatePriorities() для более надёжного нахождения поля priority
4. Добавлено логирование в консоль для отладки (console.log)

Теперь при перемещении товаров стрелками и нажатии "Сохранить" приоритеты правильно сохраняются в БД.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 23:49:15 +03:00
9ff1f2d184 feat: Добавить отображение наличия товаров и цены вариантов во все шаблоны CRUD
Добавлена визуализация статуса наличия (in_stock) и цены вариантов во все CRUD шаблоны товаров и групп вариантов.

Product (товары):
- product_list.html: добавлена колонка "В наличии" с бейджами (зелёный/красный)
- product_detail.html: добавлена строка "В наличии" в таблицу данных товара
- product_form.html: добавлена информационная секция о наличии при редактировании
- all_products_list.html: добавлена колонка "В наличии" для товаров
- productkit_list.html: обновлены стили бейджей статуса

ProductVariantGroup (группы вариантов):
- variantgroup_list.html: добавлены колонки "В наличии" и "Цена" в таблицу групп
- variantgroup_detail.html: добавлены отображение наличия и цены в информационный блок слева
- variantgroup_detail.html: добавлена колонка "В наличии" в таблицу товаров группы
- variantgroup_form.html: добавлены отображение артикула, цены и статуса наличия в formset таблице
- variantgroup_form.html: добавлен JavaScript код для динамического обновления данных товара при выборе через Select2
- variantgroup_confirm_delete.html: добавлена информация о наличии и цене группы в окно подтверждения удаления

Views optimization:
- ProductVariantGroupListView: добавлен prefetch_related('items__product') для оптимизации N+1 запросов
- Все представления используют оптимизированные запросы для вычисления in_stock и price свойств

UI/UX улучшения:
- Используются Bootstrap 5 бейджи с иконками (bg-success/bg-danger)
- Визуальное выделение статуса наличия через цвет и значки
- Информативное отображение цены варианта во всех местах
- Динамическое обновление информации при выборе товаров в formset

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 23:33:11 +03:00
9ad9f604e9 Обновили шапку и вывод всехтоваров. Добавили фильтры 2025-10-24 23:11:29 +03:00
2fb6253d06 fix: Исправить сохранение множественных товаров в комплект
ПРОБЛЕМА:
При создании комплекта с несколькими товарами сохранялся только первый товар.

ПРИЧИНЫ И РЕШЕНИЯ:

1. Неправильный префикс в JavaScript (productkit_create.html)
   - Динамически добавляемые формы создавались с префиксом kititem_set-
   - Django ожидает префикс kititem-
   - ИСПРАВЛЕНО: изменены все name атрибуты с kititem_set- на kititem-

2. NULL constraint для quantity (models.py)
   - Поле KitItem.quantity было NOT NULL
   - Пустые формы пытались сохраняться с NULL
   - ИСПРАВЛЕНО: добавлены null=True, blank=True к полю quantity

3. Неправильная валидация пустых форм (forms.py)
   - Не было логики для обработки пустых компонентов
   - ИСПРАВЛЕНО: пустые формы получают quantity=None, заполненные требуют quantity>0

4. Неправильный порядок сохранения (productkit_views.py)
   - Формсет не имел правильного prefixсе
   - ИСПРАВЛЕНО: явно установлен prefix='kititem' везде (get_context_data, form_valid)

 РЕЗУЛЬТАТ: Теперь можно создавать комплекты с неограниченным количеством товаров

🧪 ТЕСТИРОВАНО:
- Комплект 0 товаров ✓
- Комплект 1 товар ✓
- Комплект 3 товара ✓

🤖 Generated with Claude Code
2025-10-23 23:48:39 +03:00
9d5ce11951 refactor: Двухэтапное создание комплектов товаров
Реализован современный двухэтапный подход к созданию комплектов:

**Шаг 1: Создание базовой информации** (productkit_create.html)
- Упрощённая форма только с базовой информацией
- Название, описание, категории, теги
- Фотографии с предпросмотром
- Настройки ценообразования
- Чистый современный UI с breadcrumbs
- Прогрессивное раскрытие (collapsible секции)

**Шаг 2: Добавление товаров** (productkit_edit.html)
- Автоматический redirect после создания
- Работа с товарами через существующий функционал
- Улучшенный заголовок с указанием шага

**Изменения в коде:**
- ProductKitCreateView: упрощён, убраны formsets
- ProductKitUpdateView: использует новый шаблон
- productkit_form.html → productkit_edit.html
- Новый шаблон productkit_create.html

**Преимущества:**
 Простая и надёжная логика сохранения
 Нет проблем с disabled полями в formsets
 Понятный UX с чёткими шагами
 Современный дизайн с иконками Bootstrap
 Предпросмотр фото перед загрузкой

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 16:05:13 +03:00
dd2b1f21f7 feat: Улучшенная форма создания комплектов товаров
Реализованы следующие улучшения для формы создания/редактирования комплектов:

1. **Улучшенный API поиска товаров:**
   - Добавлен поиск по полю search_keywords для более точных результатов
   - Добавлены дополнительные поля: display_name, display_price

2. **Предпросмотр загружаемых фото:**
   - Миниатюры выбранных файлов перед загрузкой
   - Счетчик выбранных файлов
   - Возможность удаления отдельных фото до отправки формы

3. **Динамическое добавление товаров:**
   - Кнопка "Добавить товар в комплект" для создания новых строк
   - Автопоиск товаров при вводе текста (задержка 300мс)
   - Автоматическое добавление при клике на результат
   - Визуальные уведомления об успешном добавлении
   - Прокрутка к новой форме после добавления

4. **Валидация на дубликаты:**
   - Предупреждение при попытке добавить существующий товар
   - Подсветка дубликата на 2 секунды
   - Предложение изменить количество в существующей строке

5. **Автоматический расчет цены:**
   - Информационный блок с суммой товаров и их количеством
   - Пересчет при добавлении/удалении товаров
   - Пересчет при изменении количества
   - Асинхронная загрузка цен для существующих товаров

6. **Исправления:**
   - Снятие disabled с полей select перед отправкой формы
   - Правильное создание новых форм при добавлении товаров через поиск
   - Использование display_name для корректного отображения

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 15:52:29 +03:00
85801c6c4a Обновили шапку и вывод всехтоваров. Добавили фильтры 2025-10-22 15:49:59 +03:00