Исправлено: резервирование и списание с учетом единиц продажи

- Проблема: при заказе 1 ветки резервировался 1 банч вместо 1/15

- Решение: используем quantity_in_base_units из OrderItem

- Изменения:

  - signals.py: reserve_stock_on_order_create использует quantity_in_base_units

  - signals.py: _create_or_update_reservation сохраняет sales_unit

  - signals.py: create_sale_on_order_completion берет quantity из резерва

  - sale_processor.py: уточнена документация параметра quantity
This commit is contained in:
2026-01-02 13:45:22 +03:00
parent 0d801680d7
commit c5e1ea06f9
2 changed files with 53 additions and 19 deletions

View File

@@ -61,19 +61,19 @@ class SaleProcessor:
Процесс:
1. Создаем запись Sale
2. Конвертируем количество в базовые единицы (если указана sales_unit)
3. Списываем товар по FIFO из партий
4. Фиксируем распределение в SaleBatchAllocation для аудита
2. Списываем товар по FIFO из партий
3. Фиксируем распределение в SaleBatchAllocation для аудита
Args:
product: объект Product
warehouse: объект Warehouse
quantity: Decimal - количество товара (в единицах продажи, если указана sales_unit)
quantity: Decimal - количество товара В БАЗОВЫХ ЕДИНИЦАХ.
Для списания со склада всегда используются базовые единицы.
sale_price: Decimal - цена продажи
order: (опционально) объект Order
document_number: (опционально) номер документа
sales_unit: (опционально) объект ProductSalesUnit - единица продажи.
Если указана, quantity конвертируется в базовые единицы товара.
Используется ТОЛЬКО для сохранения снимка (не для конверсии).
Returns:
Объект Sale
@@ -87,13 +87,9 @@ class SaleProcessor:
if sale_price < 0:
raise ValueError("Цена продажи не может быть отрицательной")
# Конвертируем количество в базовые единицы, если указана единица продажи
if sales_unit:
quantity_base = sales_unit.convert_to_base(quantity)
unit_name_snapshot = sales_unit.name
else:
quantity_base = quantity
unit_name_snapshot = ''
# quantity УЖЕ в базовых единицах, конверсия не нужна
quantity_base = quantity
unit_name_snapshot = sales_unit.name if sales_unit else ''
# Создаем запись Sale
# ВАЖНО: Устанавливаем processed=True сразу, чтобы сигнал process_sale_fifo не сработал
@@ -101,7 +97,7 @@ class SaleProcessor:
sale = Sale.objects.create(
product=product,
warehouse=warehouse,
quantity=quantity, # В единицах продажи (для истории/отчётов)
quantity=quantity_base, # В базовых единицах (для истории/отчётов)
quantity_base=quantity_base, # В базовых единицах (для списания)
sale_price=sale_price,
order=order,