Улучшения инвентаризации: автоматическое проведение документов, оптимизация запросов и улучшения UI
- Автоматическое проведение документов списания и оприходования после завершения инвентаризации - Оптимизация SQL-запросов: устранение N+1, bulk-операции для Stock, агрегация для StockBatch и Reservation - Изменение формулы расчета разницы: (quantity_fact + quantity_reserved) - quantity_available - Переименование поля 'По факту' в 'Подсчитано (факт, свободные)' - Добавлены столбцы 'В резервах' и 'Всего на складе' в таблицу инвентаризации - Перемещение столбца 'В системе (свободно)' после 'В резервах' с визуальным выделением - Центральное выравнивание значений в столбцах таблицы - Автоматическое выделение текста при фокусе на поле ввода количества - Исправление форматирования разницы (убраны лишние нули) - Изменение статуса 'Не обработана' на 'Не проведено' - Добавление номера документа для инвентаризаций (INV-XXXXXX) - Отображение всех типов списаний в debug-странице (WriteOff, WriteOffDocument, WriteOffDocumentItem) - Улучшение отображения документов в детальном просмотре инвентаризации с возможностью перехода к ним
This commit is contained in:
@@ -6,7 +6,7 @@ from decimal import Decimal
|
||||
from django.test import TestCase
|
||||
|
||||
from products.models import Product
|
||||
from inventory.models import Warehouse, StockBatch, Incoming, Sale, WriteOff, Transfer, Inventory, InventoryLine, Reservation, Stock
|
||||
from inventory.models import Warehouse, StockBatch, Sale, Transfer, Inventory, InventoryLine, Reservation, Stock
|
||||
from inventory.services import StockBatchManager, SaleProcessor, InventoryProcessor
|
||||
from orders.models import Order, OrderItem
|
||||
from customers.models import Customer
|
||||
@@ -302,17 +302,23 @@ class InventoryProcessorTest(TestCase):
|
||||
|
||||
# Проверяем результат
|
||||
self.assertEqual(result['processed_lines'], 1)
|
||||
self.assertEqual(result['writeoffs_created'], 1)
|
||||
self.assertEqual(result['incomings_created'], 0)
|
||||
self.assertIsNotNone(result['writeoff_document'])
|
||||
self.assertIsNone(result['incoming_document'])
|
||||
|
||||
# Проверяем, что создалось списание
|
||||
writeoffs = WriteOff.objects.filter(batch=batch)
|
||||
self.assertEqual(writeoffs.count(), 1)
|
||||
self.assertEqual(writeoffs.first().quantity, Decimal('15'))
|
||||
|
||||
# Проверяем остаток в партии
|
||||
# Проверяем, что создался документ списания (черновик)
|
||||
writeoff_doc = result['writeoff_document']
|
||||
self.assertEqual(writeoff_doc.status, 'draft')
|
||||
self.assertEqual(writeoff_doc.inventory, inventory)
|
||||
|
||||
# Проверяем, что в документе есть позиция
|
||||
items = writeoff_doc.items.all()
|
||||
self.assertEqual(items.count(), 1)
|
||||
self.assertEqual(items.first().product, self.product)
|
||||
self.assertEqual(items.first().quantity, Decimal('15'))
|
||||
|
||||
# Проверяем, что документ еще не проведен - остаток не изменился
|
||||
batch.refresh_from_db()
|
||||
self.assertEqual(batch.quantity, Decimal('85'))
|
||||
self.assertEqual(batch.quantity, Decimal('100')) # Остаток не изменился, т.к. документ не проведен
|
||||
|
||||
def test_process_inventory_surplus(self):
|
||||
"""Тест обработки излишка при инвентаризации."""
|
||||
@@ -341,13 +347,25 @@ class InventoryProcessorTest(TestCase):
|
||||
|
||||
# Проверяем результат
|
||||
self.assertEqual(result['processed_lines'], 1)
|
||||
self.assertEqual(result['writeoffs_created'], 0)
|
||||
self.assertEqual(result['incomings_created'], 1)
|
||||
self.assertIsNone(result['writeoff_document'])
|
||||
self.assertIsNotNone(result['incoming_document'])
|
||||
|
||||
# Проверяем, что создалось приходование
|
||||
incomings = Incoming.objects.filter(product=self.product)
|
||||
self.assertEqual(incomings.count(), 1)
|
||||
self.assertEqual(incomings.first().quantity, Decimal('20'))
|
||||
# Проверяем, что создался документ оприходования (черновик)
|
||||
incoming_doc = result['incoming_document']
|
||||
self.assertEqual(incoming_doc.status, 'draft')
|
||||
self.assertEqual(incoming_doc.inventory, inventory)
|
||||
self.assertEqual(incoming_doc.receipt_type, 'inventory')
|
||||
|
||||
# Проверяем, что в документе есть позиция
|
||||
items = incoming_doc.items.all()
|
||||
self.assertEqual(items.count(), 1)
|
||||
self.assertEqual(items.first().product, self.product)
|
||||
self.assertEqual(items.first().quantity, Decimal('20'))
|
||||
|
||||
# Проверяем, что документ еще не проведен - новый StockBatch не создан
|
||||
from inventory.models import StockBatch
|
||||
batches = StockBatch.objects.filter(product=self.product, warehouse=self.warehouse)
|
||||
self.assertEqual(batches.count(), 1) # Только исходная партия, новая не создана
|
||||
|
||||
|
||||
class ReservationSignalsTest(TestCase):
|
||||
|
||||
Reference in New Issue
Block a user