Commit Graph

10 Commits

Author SHA1 Message Date
ff0756498c Fix Product filtering and add kit disassembly functionality
Fixed:
- Replace is_active with status='active' for Product filtering in IncomingModelForm
- Product model uses status field instead of is_active

Added:
- Showcase field to ProductKit for tracking showcase placement
- product_kit field to Reservation for tracking kit-specific reservations
- Disassemble button in POS terminal for showcase kits
- API endpoint for kit disassembly (release reservations, mark discontinued)
- Improved reservation filtering when dismantling specific kits

Changes:
- ShowcaseManager now links reservations to specific kit instances
- POS terminal modal shows disassemble button in edit mode
- Kit disassembly properly updates stock aggregates

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 23:03:47 +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
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
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
46578382b0 Улучшения в моделях заказов и комплектов
## Изменения:

### 1. ProductKit - расчет цены для вариантов товаров
- Добавлена обработка variant_group в методах расчета base_price
- Теперь учитываются варианты товаров при расчете стоимости комплекта

### 2. DraftOrderService - упрощение логики автосохранения
- Удалена проверка is_draft() при обновлении (позволяет обновлять заказы в других статусах)
- Улучшена документация метода update_draft

### 3. Шаблоны и скрипты
- Обновлены шаблоны форм создания/редактирования комплектов
- Обновлены скрипты автосохранения

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-12 11:34:06 +03:00
7b78ad2a6e Добавлена поддержка временных комплектов в модель ProductKit
- Добавлено поле is_temporary для пометки временных комплектов
- Добавлено поле order для связи с заказом
- Добавлены индексы для производительности
- Добавлен метод make_permanent() для преобразования в постоянный комплект

Временные комплекты создаются для конкретных заказов и не показываются
в общем каталоге, но хранятся в БД для истории и анализа.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 14:59:09 +03:00
7506fee20a feat: Удалить поле примечание из компонентов комплектов
Удалено ненужное поле 'notes' из формы создания/редактирования комплектов:
- Удалено из модели KitItem
- Удалено из формы KitItemForm
- Удалено из template kititem_formset.html
- Удалено из formset'ов KitItemFormSetCreate и KitItemFormSetUpdate
- Создана миграция БД для удаления поля из базы данных

Теперь каждый товар в комплекте отображается с 4 полями:
- Товар (или Группа вариантов)
- Количество
- Кнопка удаления
- ID (скрытое)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 21:08:41 +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