# Быстрый гид: Динамическая себестоимость товаров ## Как это работает Себестоимость товара теперь **автоматически рассчитывается** на основе партий товара (StockBatch) по формуле средневзвешенной стоимости: ``` cost_price = Σ(количество × стоимость) / Σ(количество) ``` ## Автоматическое обновление Себестоимость обновляется **автоматически** при: - ✅ Создании новой партии (поступление товара) - ✅ Изменении количества в партии - ✅ Изменении стоимости партии - ✅ Удалении партии **Никаких дополнительных действий не требуется!** ## Просмотр деталей ### На странице товара 1. Откройте страницу товара: `http://grach.localhost:8000/products/1/` 2. Найдите строку "Себестоимость" 3. Нажмите кнопку **"Детали расчета"** 4. Увидите: - Кешированную стоимость (из БД) - Рассчитанную стоимость (из партий) - Таблицу с разбивкой по партиям - Дату создания каждой партии ## Примеры сценариев ### Сценарий 1: Новый товар ``` Товар создан → cost_price = 0.00 (нет партий) ``` ### Сценарий 2: Первая поставка ``` Поступление: 10 шт по 100 руб → Автоматически: cost_price = 100.00 ``` ### Сценарий 3: Вторая поставка ``` Текущее: 10 шт по 100 руб (cost_price = 100.00) Поступление: 10 шт по 120 руб → Автоматически: cost_price = 110.00 Расчет: (10×100 + 10×120) / 20 = 110.00 ``` ### Сценарий 4: Товар закончился ``` Продажа: весь товар продан → Автоматически: cost_price = 0.00 ``` ### Сценарий 5: Новая поставка после опустошения ``` Поступление: 15 шт по 130 руб → Автоматически: cost_price = 130.00 ``` ## Ручной пересчет (если нужно) Если по какой-то причине себестоимость "слетела", можно пересчитать вручную: ```bash # Пересчитать для тенанта grach python manage.py recalculate_product_costs --schema=grach # С подробным выводом python manage.py recalculate_product_costs --schema=grach --verbose # Предварительный просмотр без сохранения python manage.py recalculate_product_costs --schema=grach --dry-run --verbose # Показать только изменившиеся товары python manage.py recalculate_product_costs --schema=grach --only-changed ``` ## Влияние на комплекты (ProductKit) Стоимость комплектов теперь автоматически учитывает актуальную себестоимость компонентов! ```python # Раньше: использовалась статическая стоимость # Теперь: использует динамическую стоимость из партий kit_cost = sum(component.cost_price × quantity) ``` ## Проверка синхронизации На странице товара в секции "Детали расчета": - 🟢 **Зеленый статус** - все синхронизировано - 🟡 **Желтый статус** - требуется синхронизация (запустите команду пересчета) ## API для разработчиков ### Получить детали расчета ```python from products.models import Product product = Product.objects.get(id=1) # Получить детали details = product.cost_price_details print(f"Кешированная стоимость: {details['cached_cost']}") print(f"Рассчитанная стоимость: {details['calculated_cost']}") print(f"Синхронизировано: {details['is_synced']}") print(f"Всего в партиях: {details['total_quantity']}") # Перебрать партии for batch in details['batches']: print(f"Склад: {batch['warehouse_name']}") print(f"Количество: {batch['quantity']}") print(f"Стоимость: {batch['cost_price']}") ``` ### Ручное обновление стоимости ```python from products.services.cost_calculator import ProductCostCalculator # Рассчитать новую стоимость new_cost = ProductCostCalculator.calculate_weighted_average_cost(product) # Обновить в БД old_cost, new_cost, was_updated = ProductCostCalculator.update_product_cost(product) if was_updated: print(f"Стоимость обновлена: {old_cost} → {new_cost}") ``` ## Логирование Все операции логируются в стандартный Django logger: ```python import logging logger = logging.getLogger('products.services.cost_calculator') ``` Примеры сообщений: - `INFO: Обновлена себестоимость товара SKU-001: 100.00 -> 110.00` - `ERROR: Ошибка при расчете себестоимости для товара SKU-001: ...` ## Производительность ### Чтение cost_price - **0 дополнительных запросов** - значение читается из БД ### Создание/изменение партии - **1 дополнительный UPDATE** - автоматическое обновление cost_price ### Просмотр деталей (cost_price_details) - **1 SELECT** - запрос партий товара ## FAQ **Q: Нужно ли что-то делать после создания партии?** A: Нет! Себестоимость обновляется автоматически через Django signals. **Q: Что если у товара нет партий?** A: cost_price = 0.00 (автоматически) **Q: Можно ли вручную установить себестоимость?** A: Можно, но при следующем изменении партий значение пересчитается автоматически. **Q: Как проверить правильность расчета?** A: Откройте "Детали расчета" на странице товара - там видна вся математика. **Q: Влияет ли это на ProductKit?** A: Да! Стоимость комплектов теперь использует актуальную себестоимость компонентов. **Q: Что если синхронизация нарушилась?** A: Запустите `python manage.py recalculate_product_costs --schema=grach` ## Техническая документация Подробная техническая документация доступна в файле: `DYNAMIC_COST_PRICE_IMPLEMENTATION.md` ## Контакты и поддержка При возникновении проблем проверьте: 1. Логи Django (ошибки при расчете) 2. Страницу товара (секция "Детали расчета") 3. Запустите команду с --dry-run для проверки --- Версия: 1.0 Дата: 2025-01-01