fix(inventory): создавать Sale после применения скидок в POS checkout

Добавлен механизм skip_sale_creation на базе thread-local storage
для управления моментом создания Sale через сигнал.

Проблема: сигнал create_sale_on_order_completion срабатывал при
Order.objects.create(status=completed) до применения скидок.

Решение: пропускать сигнал во время создания заказа, затем явно
создавать Sale после применения всех скидок через order.save().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 01:05:22 +03:00
parent 1e4b7598ae
commit 2dc36b3d01
2 changed files with 44 additions and 1 deletions

View File

@@ -15,6 +15,7 @@ import logging
from products.models import Product, ProductCategory, ProductKit, KitItem
from inventory.models import Showcase, Reservation, Warehouse, Stock
from inventory.services import ShowcaseManager
from inventory.signals import skip_sale_creation, reset_sale_creation
logger = logging.getLogger(__name__)
@@ -1526,13 +1527,17 @@ def pos_checkout(request):
# Атомарная операция
with db_transaction.atomic():
# ВАЖНО: Устанавливаем флаг для пропуска автоматического создания Sale в сигнале.
# Sale будет создан ЯВНО после применения всех скидок.
skip_sale_creation()
# 1. Создаём заказ с текущей датой и временем в локальном часовом поясе (Europe/Minsk)
from django.utils import timezone as tz
from orders.models import Delivery
now_utc = tz.now() # Текущее время в UTC
now_local = tz.localtime(now_utc) # Конвертируем в локальный часовой пояс (Europe/Minsk)
current_time = now_local.time() # Извлекаем время в минском часовом поясе
order = Order.objects.create(
customer=customer,
status=completed_status, # Сразу "Выполнен"
@@ -1714,6 +1719,11 @@ def pos_checkout(request):
cart_key = f'pos:cart:{request.user.id}:{warehouse_id}'
cache.delete(cart_key)
# 7. Явно создаём Sale после применения всех скидок
# Сбрасываем флаг пропуска и вызываем save() для активации сигнала
reset_sale_creation()
order.save() # Триггерит сигнал create_sale_on_order_completion
return JsonResponse({
'success': True,
'order_number': order.order_number,