- Переиспользован модуль select2-product-search.js из orders
- Заменен простой select на Select2 с AJAX поиском через API search_products_and_variants
- Добавлена поддержка привязки как ProductKit, так и Product к значениям атрибутов
- Обновлен метод _save_attributes_from_cards для обработки item_ids и item_types
- Удалены дублирующиеся подключения jQuery и Select2 (используются из base.html)
- Улучшен UX: живой поиск, отображение типа товара (🌹/💐), цены и наличия
- URL paths: configurable-kits/ → configurable/
- URL names: configurablekit-list → configurableproduct-list и т.д.
- Обновлены все ссылки в шаблонах и views
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Основные изменения:
- Переименование ConfigurableKitProduct → ConfigurableProduct
- Добавлена поддержка Product как варианта (не только ProductKit)
- Создан справочник атрибутов (ProductAttribute, ProductAttributeValue)
- CRUD для управления атрибутами с inline редактированием значений
- Пересозданы миграции с нуля для всех приложений
- Добавлена ссылка на атрибуты в навигацию
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Проблема: после оптимизации товары показывались только из категорий,
товары без категорий не отображались.
Решение: теперь загружаются все активные товары и комплекты напрямую,
дополняя список товарами, которые не были загружены через категории.
Логика загрузки:
1. Сначала из категорий (используя prefetch кеш) - оптимизация
2. Затем все активные товары напрямую - полнота данных
3. Дедупликация через словари (products_dict, kits_dict)
- Добавлено отображение свободных и общих остатков товаров в карточках каталога
- Информация показывается с цветовой индикацией (зеленый/красный)
- Формат: X свободно / Y всего (X = доступно - зарезервировано, Y = общее количество)
Оптимизация производительности:
- Устранена N+1 проблема с загрузкой фото товаров (вложенный Prefetch)
- Устранена N+1 проблема с загрузкой категорий товаров
- Удалено дублирование запросов - товары извлекаются из уже загруженных категорий
- Аннотации остатков добавлены в Prefetch для товаров
- Добавлен оптимизированный Prefetch для ProductKitPhoto
Результат: сокращение количества SQL-запросов с ~13 до ~6-7 (на 50%)
- Отделена модель Delivery от Order (OneToOne связь)
- Добавлены обязательные поля delivery_date, time_from, time_to в Delivery
- Delivery обязательна при создании заказа (кроме черновиков)
- Добавлены методы calculate_total() и reset_delivery_cost() в Order
- Добавлена валидация полей доставки в OrderForm
- Исправлено создание доменов - убран порт из домена в БД
- Исправлен редирект после установки пароля (правильный формат URL)
- Исправлена ошибка NoReverseMatch в navbar для public схемы
- Удалены все старые миграции (база создается с нуля)
- Обновлены views для работы с новой моделью Delivery
Moved order item selection logic from order_form.html to select2-product-search.js
for better code reusability and maintainability.
Changes:
- Extended select2-product-search.js with initOrderItemSelect2() function (~87 lines)
- Wraps initProductSelect2 for order item context
- Handles product/kit selection and form field updates
- Manages custom price indicators
- Supports data-ajax-url attribute for URL configuration
- Updated order_form.html:
- Added data-ajax-url to order item select elements
- Removed inline initOrderItemSelect2 function (~73 lines)
- Updated dependency check to use initOrderItemSelect2
Benefits:
- No code duplication - reuses existing initProductSelect2
- Cleaner template (79 lines removed)
- Consistent with existing patterns
- Easy to maintain in one place
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Introduced Recipient model to manage order recipients separately from customers.
- Updated Order model to link to Recipient, replacing recipient_name and recipient_phone fields.
- Enhanced OrderForm to include recipient selection modes: customer, history, and new.
- Added AJAX endpoint to fetch recipient history for customers.
- Updated admin interface to manage recipients and display recipient information in order details.
- Refactored address handling to accommodate new recipient logic.
- Improved demo order creation to include random recipients.
- Исправлен POS для использования миниатюр вместо оригиналов для быстрой загрузки
- Убран fallback на оригиналы - показываем миниатюру или ничего (лучше видно ошибки)
- Исправлен ImageService - возвращает пустую строку если миниатюра обработанного файла не найдена
- Исправлена ошибка JavaScript при массовом удалении фото (insertAdjacentElement на null)
- Добавлен контейнер photos-messages-container для надежного отображения сообщений
- Улучшено логирование ImageService для отладки путей к файлам
- Добавлена проверка exists() с детальным логированием в TenantAwareFileSystemStorage
- Fix MEDIA_ROOT path to match Docker volume mount (/app/myproject/media)
- Update docker-compose.yml volume mounts to match MEDIA_ROOT
- Add setup_directories() function in entrypoint.sh to create media directories with proper permissions
- Add logging to TenantAwareFileSystemStorage for debugging
- Fix is_returned flag logic improvements (from previous work)
- Добавлен Prefetch для активных товаров и комплектов в категориях
- Фильтрация и сортировка вынесены в Prefetch (избегаем повторных запросов)
- Изменен метод build_category_tree для использования предзагруженных данных
Результаты:
- Список категорий: 12→7 запросов, 26.76→~10мс
- Устранены 4 похожих N+1 запроса (products и kits для каждой категории)
Добавлено:
- Команда clear_tenant_data для полной очистки данных тенанта без удаления схемы
* Очищает все таблицы через TRUNCATE CASCADE
* Сбрасывает ID-последовательности
* Сохраняет схему БД и запись Client
* Поддержка флага --noinput для автоматизации
- Команда init_tenant_data для инициализации системных данных тенанта
* Создаёт системного клиента (АНОНИМНЫЙ ПОКУПАТЕЛЬ для POS)
* Создаёт 8 системных статусов заказов
* Создаёт 5 системных способов оплаты
* Поддержка флага --reset для пересоздания данных
Исправлено:
- Заменены устаревшие фильтры is_active на status='active' для Product и ProductKit
* products/views/category_views.py: исправлены фильтры в build_category_tree и get_context_data
* products/services/kit_pricing.py: исправлены фильтры при получении товаров из variant_group
* products/models/kits.py: исправлен фильтр в get_available_products
* Устранена ошибка FieldError при работе со списком категорий
Улучшено:
- Команда clear_tenant_data теперь предлагает пользователю инициализировать системные данные после очистки
- Добавлена детальная информация о процессе очистки и инициализации данных
- Строка поиска теперь отдельно на всю ширину (input-group)
- Переключатель вида (карточки/список) перенесён к фильтрам
- Переключатель прижат справа (ms-auto) рядом с чекбоксом
- Размер кнопок переключателя - btn-sm для компактности
- Чекбокс больше не прижат к краю (убран ms-auto)
- Более логичная группировка элементов
- Фильтры теперь в одну строку с flexbox
- Убраны обёртки col-auto, используется d-flex gap-2
- Селекты с width: auto для компактности
- Чекбокс 'Только в наличии' прижат к правому краю (ms-auto)
- Более компактный и чистый UI
- Убран класс product-picker-filters и удалён комментарий про счётчик
- Убран заголовок блока
- Строка поиска теперь большая (form-control-lg) и занимает всю ширину
- Добавлена иконка поиска слева от input
- Заголовок перенесен в placeholder строки поиска
- Переключатель вида теперь стандартного размера (не sm)
- Более чистый и современный UI
Проблема: можно было выбрать несколько товаров одновременно
Причина: при смене выделения старый товар не всегда корректно находился в DOM
Решение:
- Добавлен метод _clearAllSelections() для принудительной очистки всех выделений
- Исправлено сравнение ID (добавлен String() в строке 443)
- При выборе нового товара сначала снимаются ВСЕ выделения через querySelectorAll
- Затем выделяется только новый выбранный товар
- Обновлена версия JS (v=3) для сброса кэша
Теперь гарантирован истинный single-select режим
- Добавлено явное приведение к String при сравнении ID товаров
- Исправлена инициализация selected в методе destroy() (null вместо {})
- Добавлена версия к JS файлу (?v=2) для сброса кэша браузера
- Улучшены комментарии о том, что только ОДИН товар может быть выбран
- Гарантирован корректный single-select режим работы компонента
- Удалены иконки галочек (bi-circle/bi-check-circle-fill) из list view
- Выбор товара теперь показывается только через изменение фона (класс selected)
- В grid view галочка остаётся в правом верхнем углу
- Упрощён метод _updateProductUI - убрана логика переключения иконок
- Более чистый и понятный интерфейс для single-select режима
- Удалён весь функционал множественного выбора
- Удалены кнопки 'Выбрать все' и 'Сбросить'
- Удалён счётчик выбранных товаров
- state.selected теперь содержит один объект вместо словаря
- Убраны параметры multi_select, max_selection, show_select_all
- onAddSelected теперь возвращает объект вместо массива
- Удалены методы getSelectedIds() и setSelection()
- Упрощена логика _toggleProduct для single-select
- Обновлены все callback'и для работы с одним товаром
- Компонент стал значительно проще и понятнее
- Добавлен параметр warehouse в API search_products_and_variants
- API фильтрует товары по наличию на указанном складе через Stock
- Обновлен _apply_product_filters для поддержки warehouse_id
- ProductSearchPicker теперь поддерживает data-warehouse-id
- Warehouse автоматически передается в AJAX запросы
- В WriteOffDocumentDetailView добавлены categories и tags в контекст
- Компонент поиска встроен в detail.html с жестким фильтром по складу документа
- Single-select режим для выбора одного товара
- JS автоматически заполняет select формы при выборе товара
- Отображение выбранного товара с фото и артикулом
- Автофокус на поле количества после выбора товара
- Пользователь видит только товары доступные на складе документа
- Добавлены параметры фильтрации: category, tag, in_stock
- Функция _apply_product_filters() для применения фильтров к queryset
- Функция _get_product_photo_url() для получения главного фото товара
- В ответ API добавлено поле photo_url с URL фото товара
- Отключено кэширование при использовании фильтров
- Улучшена производительность запросов с использованием order_by и values
- product_search_picker.html - универсальный шаблон компонента поиска и выбора товаров
- product-search-picker.js - JavaScript модуль с поддержкой фильтрации по категориям, тегам, наличию
- product-search-picker.css - стили для компонента
- Поддержка одиночного и множественного выбора товаров
- Фильтрация по категориям, тегам и наличию на складе
- Отображение фото товара в результатах поиска
- Адаптивный интерфейс с прокруткой для больших списков
- API для программного управления (init, search, clearSelection и др.)
- Возможность кастомизации через параметры (заголовок, высота, текст кнопок)
- Удалены все файлы .md (30 файлов)
- Добавлена маска *.md в .gitignore для защиты от будущих коммитов
- Причина: .md файлы содержали примеры паролей и внутреннюю документацию
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add view mixins (RoleRequiredMixin, OwnerRequiredMixin, ManagerOwnerRequiredMixin) to user_roles/mixins.py
- Replace PermissionRequiredMixin with ManagerOwnerRequiredMixin in all product views
- Remove permission_required attributes from view classes
- Owner and Manager roles now grant access without Django model permissions
This allows owners to access all product functionality through their custom role,
without needing to be superusers or have explicit Django permissions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented responsive grid system for product form checkboxes to improve UX
when dealing with multiple categories and tags.
Changes:
- Added CSS Grid layout with adaptive columns (1-4 based on screen width)
- Mobile (< 768px): 1 column
- Tablet (≥ 768px): 2 columns
- Desktop (≥ 1200px): 3 columns
- Wide screens (≥ 1600px): 4 columns
- Compact spacing (0.35rem gap) for better density
- Enhanced checkbox styling with hover effects and selected state
- JavaScript fallback for forced grid application and responsive resizing
- Improved form container width (col-12 col-xl-10) for better space usage
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes deletion functionality for order items across frontend and backend:
- Remove restriction preventing deletion of last item
- Add confirmation dialog before deletion
- Properly track and send deleted item IDs to backend via autosave
- Update backend to handle item deletion by ID instead of index
- Fix visual feedback: deleted items are hidden immediately
- Auto-recalculate total sum after deletion
Technical changes:
- order_form.html: Add confirmation dialog, trigger autosave on delete
- autosave.js: Collect deleted item IDs, send to backend
- draft_service.py: Process deleted_item_ids, update items by ID
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented inline editing functionality for product prices directly in the catalog view with support for both regular and sale prices.
Features:
- Click-to-edit price fields with visual hover indicators
- Separate editing for price and sale_price fields
- Add/remove sale price with validation
- Real-time UI updates without page reload
- Permission-based access control
- Server-side validation for price constraints
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Improvements to category tree UX:
- Auto-expand parent category after creating subcategory at any nesting level
- Recursive ancestor expansion using elegant DOM traversal with .closest()
- Smooth scroll to newly created category with visual feedback
- Replace icon buttons with text: "Развернуть все" / "Свернуть все"
- Eliminates confusion between "+" for adding category vs expanding tree
Technical implementation:
- URL parameter ?expand=<parent_id> to preserve state after page reload
- Recursive expandAncestors() function traverses up the DOM tree
- Uses :scope selector for precise parent-child relationship queries
- Auto-cleans URL parameter after expansion using history.replaceState()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
Changed category rename behavior - clicking name now expands/collapses,
pencil icon appears on hover for renaming.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>