From 6b327fa7e0bb029d8a0b2a1f7c9ce2816a315b3f Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Tue, 20 Jan 2026 23:40:27 +0300 Subject: [PATCH] =?UTF-8?q?fix(inventory):=20=D1=83=D1=87=D0=B8=D1=82?= =?UTF-8?q?=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D1=81=D0=BA=D0=B8=D0=B4=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B7=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=B8=20=D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B0=D1=81=D1=87=D1=91=D1=82=D0=B5=20=D1=86?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BF=D1=80=D0=BE=D0=B4=D0=B0=D0=B6=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Расширяем логику расчёта цены продажи для учёта как скидок на отдельные позиции, так и скидок на весь заказ. Скидка на заказ распределяется пропорционально доле каждой позиции в общей сумме заказа. Изменения внесены в SaleProcessor и сигнал создания продажи при завершении заказа. --- .../inventory/services/sale_processor.py | 23 +++++++++++++++---- myproject/inventory/signals.py | 23 +++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/myproject/inventory/services/sale_processor.py b/myproject/inventory/services/sale_processor.py index 4991156..16dea59 100644 --- a/myproject/inventory/services/sale_processor.py +++ b/myproject/inventory/services/sale_processor.py @@ -36,12 +36,27 @@ class SaleProcessor: # Определяем цену продажи из заказа или из товара if order and reservation.order_item: item = reservation.order_item - # Цена за единицу с учётом скидки - if item.discount_amount and item.quantity > 0: - subtotal = Decimal(str(item.price)) * Decimal(str(item.quantity)) - price_with_discount = (subtotal - Decimal(str(item.discount_amount))) / Decimal(str(item.quantity)) + # Цена за единицу с учётом всех скидок (позиция + заказ) + item_subtotal = Decimal(str(item.price)) * Decimal(str(item.quantity)) + + # Скидка на позицию + item_discount = Decimal(str(item.discount_amount)) if item.discount_amount else Decimal('0') + + # Скидка на заказ (распределяется пропорционально доле позиции в заказе) + # subtotal - сумма позиций С учётом скидок на позиции (без скидки на заказ) + order_total = order.subtotal if hasattr(order, 'subtotal') else Decimal('0') + if order_total > 0 and order.discount_amount: + order_discount = Decimal(str(order.discount_amount)) + item_order_discount = order_discount * (item_subtotal / order_total) + else: + item_order_discount = Decimal('0') + + total_discount = item_discount + item_order_discount + if total_discount and item.quantity > 0: + price_with_discount = (item_subtotal - total_discount) / Decimal(str(item.quantity)) else: price_with_discount = Decimal(str(item.price)) + # Пересчитываем цену в базовые единицы if item.sales_unit and item.conversion_factor_snapshot: sale_price = price_with_discount * item.conversion_factor_snapshot diff --git a/myproject/inventory/signals.py b/myproject/inventory/signals.py index 5e032f3..486ec54 100644 --- a/myproject/inventory/signals.py +++ b/myproject/inventory/signals.py @@ -480,10 +480,25 @@ def create_sale_on_order_completion(sender, instance, created, **kwargs): f"Используем quantity_in_base_units: {sale_quantity}" ) - # Цена за единицу с учётом скидки - if item.discount_amount and item.quantity > 0: - subtotal = Decimal(str(item.price)) * Decimal(str(item.quantity)) - price_with_discount = (subtotal - Decimal(str(item.discount_amount))) / Decimal(str(item.quantity)) + # Цена за единицу с учётом всех скидок (позиция + заказ) + item_subtotal = Decimal(str(item.price)) * Decimal(str(item.quantity)) + + # Скидка на позицию + item_discount = Decimal(str(item.discount_amount)) if item.discount_amount else Decimal('0') + + # Скидка на заказ (распределяется пропорционально доле позиции в заказе) + # subtotal - сумма позиций С учётом скидок на позиции (без скидки на заказ) + order_total = instance.subtotal if hasattr(instance, 'subtotal') else Decimal('0') + if order_total > 0 and instance.discount_amount: + order_discount = Decimal(str(instance.discount_amount)) + # Пропорциональная часть скидки заказа для этой позиции + item_order_discount = order_discount * (item_subtotal / order_total) + else: + item_order_discount = Decimal('0') + + total_discount = item_discount + item_order_discount + if total_discount and item.quantity > 0: + price_with_discount = (item_subtotal - total_discount) / Decimal(str(item.quantity)) else: price_with_discount = Decimal(str(item.price))