- Добавлен параметр 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 формы при выборе товара
- Отображение выбранного товара с фото и артикулом
- Автофокус на поле количества после выбора товара
- Пользователь видит только товары доступные на складе документа
- В WriteOffCreateView добавлена передача категорий и тегов в контекст
- Шаблон writeoff_form.html обновлен с использованием product_search_picker
- Автоматическая фильтрация партий по выбранному товару
- Отображение информации о выбранном товаре с фото
- Улучшенный UX при выборе товара для списания
- Подключены CSS и JS компонента поиска товаров
- WriteOffDocumentListView - список документов с пагинацией
- WriteOffDocumentCreateView - создание нового документа
- WriteOffDocumentDetailView - детальный просмотр документа
- WriteOffDocumentAddItemView - добавление позиции (AJAX)
- WriteOffDocumentUpdateItemView - обновление позиции (AJAX)
- WriteOffDocumentRemoveItemView - удаление позиции (AJAX)
- WriteOffDocumentConfirmView - проведение документа
- WriteOffDocumentCancelView - отмена документа
- Добавлены URL-маршруты для всех операций с документами списания
- Поддержка AJAX запросов для динамической работы с позициями
- Исправлен метод write_off_by_fifo() для учета зарезервированных партий
- Добавлено автоматическое проставление даты и времени при создании заказов в POS
- Исправлена ошибка фильтрации Product (is_active -> status='active') в transfers
- Предотвращает списание из зарезервированных партий, устраняя отрицательные остатки
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Проблема:
- Фильтр по заказу не работал
- order_number в форме передается как строка (ORD-103 или 103)
- В модели Order поле order_number имеет тип PositiveIntegerField
- Не было преобразования строки в число
Исправление:
- Добавлен парсинг номера заказа:
* Если формат 'ORD-103' -> извлекается число 103
* Если просто '103' -> преобразуется в число 103
- Добавлена обработка ошибок (try-except)
- Добавлена фильтрация таблицы заказов (показывать только выбранный)
Теперь фильтр работает с любым форматом ввода:
- ORD-103 ✓
- ord-103 ✓
- 103 ✓
Реализация:
- Создан view debug_inventory_page (только для суперюзеров)
- URL: /inventory/debug/
- Компактный дизайн с минимальными отступами (10-11px)
- Ссылка 🔧 Debug в navbar (видна только суперюзерам)
Функционал:
1. Показывает полную картину инвентаризации на одной странице:
- Заказы (Order) - номер, статус, покупатель, is_returned
- Остатки (Stock) - доступно, зарезервировано, свободно
- Партии (StockBatch) - количество, активность, дата поступления
- Резервы (Reservation) - статус, заказ, все даты
- Продажи (Sale) - количество, цена продажи, заказ
- Списания (SaleBatchAllocation) - откуда списано, сколько
2. Фильтры:
- По товару (dropdown)
- По номеру заказа (текстовое поле)
- По складу (dropdown)
3. UI:
- Цветовая индикация статусов резервов
- Бейджи для ключевых данных
- Компактные таблицы Bootstrap
- Неактивные партии выделены красным
Исправления:
- Reservation.created_at → reserved_at (у модели нет created_at)
- Sale.created_at → date (дата операции хранится в поле date)
- Product.is_active → archived_at__isnull=True (используется soft delete)
- Удалена колонка себестоимости из Sale (это поле не хранится в модели)
Файлы:
- inventory/views/debug_views.py - новый view
- inventory/templates/inventory/debug_page.html - шаблон
- inventory/urls.py - добавлен роут
- templates/navbar.html - добавлена ссылка
Юзкейс:
Суперюзер принимает товар → оформляет заказ → меняет статусы →
переходит на /inventory/debug/ → видит полную картину изменений
Проблема:
- У модели Reservation нет поля created_at
- Есть поле reserved_at для даты создания резерва
Исправление:
- В view изменена сортировка order_by('-reserved_at')
- В шаблоне изменено отображение даты res.reserved_at
Реализация:
- Создан view debug_inventory_page (только для суперюзеров)
- URL: /inventory/debug/
- Компактный дизайн с минимальными отступами и маленьким шрифтом (10-11px)
Функционал:
1. Показывает полную картину инвентаризации на одной странице:
- Заказы (Order) - номер, статус, покупатель, is_returned
- Остатки (Stock) - доступно, зарезервировано, свободно
- Партии (StockBatch) - количество, активность, дата поступления
- Резервы (Reservation) - статус (reserved/converted_to_sale/released), заказ, даты
- Продажи (Sale) - количество, цены, заказ
- Списания (SaleBatchAllocation) - откуда списано, сколько
2. Фильтры:
- По товару (dropdown с названием и SKU)
- По номеру заказа (текстовое поле)
- По складу (dropdown)
- Кнопка 'Применить' и 'Сбросить'
3. UI:
- Цветовая индикация статусов резервов
- Бейджи для ключевых данных
- Компактные таблицы Bootstrap
- Неактивные партии выделены красным
- Ограничение в 100 записей на таблицу для производительности
4. Навигация:
- Ссылка 🔧 Debug в navbar (видна только суперюзерам)
- Красный цвет для видимости
Юзкейс:
Суперюзер принимает товар на склад → оформляет заказ → меняет статусы →
переходит на /inventory/debug/ → видит полную картину всех изменений
Файлы:
- inventory/views/debug_views.py - новый view
- inventory/templates/inventory/debug_page.html - шаблон
- inventory/urls.py - добавлен роут
- templates/navbar.html - добавлена ссылка для суперюзеров
- 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>
PROBLEM:
Direct deletion/creation of reservations via web interface bypassed
POS business logic, creating data inconsistencies (orphaned showcase kits,
incorrect stock calculations).
SOLUTION:
Make reservations read-only in web interface. All reservation management
now happens only through:
- POS (showcase kits)
- Orders module
CHANGES:
- Remove reservation-create and reservation-update URL routes
- Delete ReservationCreateView and ReservationUpdateView
- Remove ReservationForm (no longer needed)
- Delete reservation_form.html and reservation_update.html templates
- Update reservation_list.html to read-only view with info banner
- Add showcase and order columns to reservation list
- Clean up imports in urls.py and views/__init__.py
Reservations are now read-only for monitoring purposes only.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add is_default field to Showcase model with unique constraint per warehouse
- Implement Showcase.save() to ensure only one default per warehouse
- Add SetDefaultShowcaseView for AJAX-based default selection
- Update ShowcaseForm to include is_default checkbox
- Add interactive checkbox UI in showcase list with AJAX functionality
- Update POS API to return showcase.is_default instead of warehouse.is_default
- Update terminal.js to auto-select showcase based on its is_default flag
- Add migration for is_default field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented complete web interface for managing showcases (display areas for ready-made bouquets) with:
**Backend:**
- ShowcaseForm with validation (unique name per warehouse)
- ShowcaseListView with filtering by warehouse and status
- ShowcaseCreateView, ShowcaseUpdateView with success messages
- ShowcaseDeleteView with active reservation validation
- URL routes: list, create, edit, delete
**Frontend:**
- List page with warehouse grouping, active reservations count
- Responsive table with filters (warehouse, status)
- Create/edit form with Bootstrap styling
- Delete confirmation with active reservations check
- Breadcrumb navigation
**Features:**
✅ One warehouse can have multiple showcases (ForeignKey relationship)
✅ Unique showcase names within each warehouse
✅ Display active reservation counts for each showcase
✅ Prevent deletion if showcase has active reservations
✅ Auto-select default warehouse when creating showcase
✅ Navigation link added to main navbar between "Касса" and "Склад"
✅ Active state highlighting in navigation
**Files created:**
- inventory/forms_showcase.py (ShowcaseForm)
- inventory/views/showcase.py (4 CBV views)
- inventory/templates/inventory/showcase/ (list, form, delete templates)
**Files modified:**
- inventory/urls.py (added showcase routes)
- inventory/forms.py (added Showcase import)
- templates/navbar.html (added "Витрины" link)
URL structure:
/inventory/showcases/ - list
/inventory/showcases/create/ - create
/inventory/showcases/<id>/edit/ - edit
/inventory/showcases/<id>/delete/ - delete
🤖 Generated with [Claude Code](https://claude.com/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>
## Changes
### 1. Fixed missing signal handler for Incoming edit (inventory/signals.py)
- Added new signal handler `update_stock_batch_on_incoming_edit()` that:
- Triggers when Incoming is edited (created=False)
- Synchronizes StockBatch with new quantity and cost_price values
- Automatically triggers cost price recalculation for the product
- Updates Stock (inventory balance) for the warehouse
- Includes proper logging and error handling
### 2. Created IncomingModelForm for editing individual incoming items (inventory/forms.py)
- New ModelForm: `IncomingModelForm` that:
- Inherits from forms.ModelForm (accepts 'instance' parameter required by UpdateView)
- Allows editing: product, quantity, cost_price, notes
- Includes validation for positive quantity and non-negative cost_price
- Filters only active products
### 3. Updated IncomingUpdateView (inventory/views/incoming.py)
- Changed form_class from IncomingForm to IncomingModelForm
- Updated imports to include IncomingModelForm
- Removed obsolete comments from form_valid method
## Architecture
When editing an Incoming item:
1. User submits form with new quantity/cost_price
2. form.save() triggers post_save signal (created=False)
3. update_stock_batch_on_incoming_edit() synchronizes StockBatch
4. StockBatch.save() triggers update_product_cost_on_batch_change()
5. Product.cost_price is recalculated with weighted average
## Problem Solved
Previously, editing an Incoming item would NOT:
- Update the related StockBatch
- Recalculate product cost_price
- Update warehouse inventory balance
- Maintain data consistency between Incoming and StockBatch
Now all these operations happen automatically through the signal chain.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Исправлены 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>
Основные изменения:
- Создана модель IncomingBatch для группировки товаров по документам
- Каждое поступление (Incoming) связано с одной батчем поступления
- Автоматическое создание StockBatch для каждого товара в приходе
- Реализована система нумерации партий (IN-XXXX-XXXX) с поиском максимума в БД
- Обновлены все представления (views) для работы с новой архитектурой
- Добавлены детальные страницы просмотра партий поступлений
- Обновлены шаблоны для отображения информации о партиях и их товарах
- Исправлена логика сигналов для создания StockBatch при приходе товара
- Обновлены формы для работы с новой структурой IncomingBatch
Архитектура FIFO:
- IncomingBatch: одна партия поступления (номер IN-XXXX-XXXX)
- Incoming: товар в партии поступления
- StockBatch: одна партия товара на складе (создается для каждого товара)
Это позволяет системе правильно применять FIFO при продаже товаров.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>