From b7db4cd16252e81ec000f70060702106dda3a5d6 Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Sun, 4 Jan 2026 16:18:57 +0300 Subject: [PATCH] conventional-commit feat(inventory): introduce stock deficit notifications and base quantity tracking - Added `quantity_base` field to reservation model for precise inventory calculations - Implemented non-blocking stock deficit warnings during kit creation process - Enhanced API responses with warning details for frontend display - Updated terminal interface to show formatted stock shortage alerts BREAKING CHANGE: API response structure now includes `warnings` array instead of previous stock warning format --- .../inventory/services/showcase_manager.py | 20 ++++++++++++++++++- myproject/pos/static/pos/js/terminal.js | 6 +++--- myproject/pos/views.py | 3 ++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/myproject/inventory/services/showcase_manager.py b/myproject/inventory/services/showcase_manager.py index c2f8e5f..7ffe3f4 100644 --- a/myproject/inventory/services/showcase_manager.py +++ b/myproject/inventory/services/showcase_manager.py @@ -47,6 +47,7 @@ class ShowcaseManager: 'success': False, 'showcase_items': [], 'reservations': [], + 'warnings': None, 'message': f'Витрина "{showcase.name}" не активна' } @@ -63,9 +64,23 @@ class ShowcaseManager: 'success': False, 'showcase_items': [], 'reservations': [], + 'warnings': None, 'message': f'Комплект "{product_kit.name}" не содержит компонентов' } + # Проверяем дефицит компонентов (предупреждение, не блокировка) + warnings = [] + for kit_item in kit_items: + product = kit_item.product + if not product: + continue + qty_needed = (kit_item.quantity or Decimal('1')) * quantity + stock = Stock.objects.filter(product=product, warehouse=warehouse).first() + free_qty = stock.quantity_free if stock else Decimal('0') + if free_qty < qty_needed: + deficit = qty_needed - free_qty + warnings.append(f"{product.name}: не хватает {deficit} шт.") + # Создаём N экземпляров for _ in range(quantity): # 1. Создаём ShowcaseItem @@ -96,6 +111,7 @@ class ShowcaseManager: product_kit=product_kit, showcase_item=showcase_item, # Связь с экземпляром! quantity=kit_item.quantity, + quantity_base=kit_item.quantity, # Для корректного учёта в Stock status='reserved' ) all_reservations.append(reservation) @@ -113,6 +129,7 @@ class ShowcaseManager: 'success': True, 'showcase_items': showcase_items, 'reservations': all_reservations, + 'warnings': warnings if warnings else None, 'message': f'Создано {quantity} экз. комплекта "{product_kit.name}" на витрине "{showcase.name}"' } @@ -121,6 +138,7 @@ class ShowcaseManager: 'success': False, 'showcase_items': [], 'reservations': [], + 'warnings': None, 'message': f'Ошибка резервирования: {str(e)}' } @@ -410,7 +428,7 @@ class ShowcaseManager: product_kit=product_kit, showcase_item=showcase_item, status='reserved', - defaults={'quantity': quantity_per_item}, + defaults={'quantity': quantity_per_item, 'quantity_base': quantity_per_item}, ) if not created: reservation.quantity = (reservation.quantity or Decimal('0')) + quantity_per_item diff --git a/myproject/pos/static/pos/js/terminal.js b/myproject/pos/static/pos/js/terminal.js index 52af180..5fa563a 100644 --- a/myproject/pos/static/pos/js/terminal.js +++ b/myproject/pos/static/pos/js/terminal.js @@ -2065,10 +2065,10 @@ document.getElementById('confirmCreateTempKit').onclick = async () => { Зарезервировано компонентов: ${data.reservations_count}`; // Если есть предупреждение о нехватке товара - добавляем его - if (data.stock_warning && data.stock_warnings && data.stock_warnings.length > 0) { + if (data.warnings && data.warnings.length > 0) { successMessage += '\n\n⚠️ ВНИМАНИЕ: Нехватка товара на складе!\n'; - data.stock_warnings.forEach(warning => { - successMessage += `\n• ${warning.product_name}: не хватает ${warning.overdraft} ед.`; + data.warnings.forEach(warning => { + successMessage += `\n• ${warning}`; }); successMessage += '\n\nПроверьте остатки и пополните склад.'; } diff --git a/myproject/pos/views.py b/myproject/pos/views.py index 07f7507..be8f3e5 100644 --- a/myproject/pos/views.py +++ b/myproject/pos/views.py @@ -1096,7 +1096,8 @@ def create_temp_kit_to_showcase(request): 'kit_price': str(kit.actual_price), 'reservations_count': len(result['reservations']), 'showcase_item_ids': showcase_item_ids, - 'available_count': created_count + 'available_count': created_count, + 'warnings': result.get('warnings') }) except json.JSONDecodeError as e: