Проблема: При создании заказа instance.status может быть None,
что вызывало AttributeError при попытке доступа к .code
Решение: Добавлена проверка 'not instance.status' перед
обращением к instance.status.code
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Проблема: Сигнал post_save срабатывает несколько раз,
создавая дубликаты Sale для одного заказа.
Решения:
1. Добавлена проверка Sale.objects.filter(order=instance).exists()
перед созданием продаж (inventory/signals.py:74-75)
2. Создана management команда fix_duplicate_sales для исправления
существующих дубликатов
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Проблема: Order.status - это объект OrderStatus, а не строка.
Сравнение instance.status != 'completed' всегда возвращало True.
Решение: Сравниваем instance.status.code != 'completed'
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Изменения:
- Сигнал create_sale_on_order_shipment переименован в create_sale_on_order_completion
- Списание товаров (создание Sale) теперь происходит при статусе 'completed' вместо 'in_delivery'
- Исправлен выбор склада: используется Order.pickup_warehouse, если задан
- Та же логика применена к резервированию товаров
Обоснование для цветочного бизнеса:
- Букет может вернуться в магазин (клиента нет дома, перенос доставки)
- Товар физически находится в магазине до момента доставки
- Резерв показывает что товар занят - этого достаточно для промежуточных статусов
- Простота: списываем только когда ТОЧНО продали
🤖 Generated with [Claude Code](https://claude.com/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>
- Add management command to recalculate quantity_reserved for all Stock records
- Add signals to automatically update Stock when Reservation changes
- Implement post_save signal for Reservation creation/updates
- Implement post_delete signal for Reservation deletion
- Both signals call Stock.refresh_from_batches() to recalculate quantities
🤖 Generated with [Claude Code](https://claude.com/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>
Проблема: товары отображались как "нет в наличии" несмотря на наличие остатков на складе.
Причина: сигналы на обновление Product.in_stock срабатывают только при изменении Stock через Django ORM.
Если Stock была создана напрямую (импорт, миграция и т.д.), сигналы не срабатывали.
Решение:
1. Исправлена логика сигналов (inventory/signals.py):
- Добавлен импорт post_delete для правильной обработки удаления Stock
- Изменён pre_delete на post_delete для более надёжной проверки остатков
- Сигналы теперь правильно срабатывают при любом изменении Stock
2. Добавлена миграция (products/migrations/0004_fix_product_in_stock.py):
- Пересчитывает in_stock для всех существующих товаров на основе Stock.quantity_available
- Товар считается в наличии если есть хотя бы один Stock с quantity_available > 0
- Обратима и безопасна (может быть отменена)
3. Добавлена команда управления (products/management/commands/update_product_in_stock.py):
- Позволяет вручную пересчитать in_stock если потребуется
- Поддерживает параметр --verbose для подробного логирования
- Может быть запущена по расписанию или вручную
После этого исправления:
- Все товары с остатками на складе автоматически обновляют статус in_stock
- Сигналы срабатывают при любом изменении Stock (создание, обновление, удаление)
- Отображение наличия товаров в UI будет корректным
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Добавлена система управления наличием товаров на трёх уровнях:
1. Product.in_stock (поле БД)
- Булево значение: есть/нет в наличии
- Автоматически обновляется при изменении Stock
- Используется для быстрого поиска и фильтрации товаров
2. Сигналы для синхронизации (inventory/signals.py)
- При изменении Stock → обновляется Product.in_stock
- Логика: товар в наличии если есть Stock с quantity_available > 0
3. ProductVariantGroup.in_stock (свойство)
- Вариант в наличии если хотя бы один из товаров в наличии
- Динамически рассчитывается по Product.in_stock товаров в группе
4. ProductVariantGroup.price (свойство)
- Цена по приоритету: берём цену товара с приоритетом 1, если он в наличии
- Если никто не в наличии: берём максимальную цену из всех товаров
- Возвращает Decimal или None если группа пуста
Файлы:
- myproject/products/models.py: добавлено поле in_stock и свойства в ProductVariantGroup
- myproject/inventory/signals.py: добавлены сигналы для синхронизации
- myproject/products/migrations/0003_add_product_in_stock.py: миграция для поля in_stock
- VARIANT_STOCK_IMPLEMENTATION.md: полная документация архитектуры
- QUICK_REFERENCE.md: быстрая справка по использованию
Особенности:
✓ Система простая и элегантная (без костылей)
✓ Обратная совместимость не требуется
✓ Высокая производительность (индексирование, минимум JOIN'ов)
✓ Актуальные данные (сигналы гарантируют синхронизацию)
✓ Легко расширяемая (свойства можно менять без миграций)
🤖 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>