Files
octopus/test_variant_stock.py
Andrey Smakotin 6c8af5ab2c fix: Улучшения системы ценообразования комплектов
Исправлены 4 проблемы:
1. Расчёт цены первого товара - улучшена валидация в getProductPrice и calculateFinalPrice
2. Отображение actual_price в Select2 вместо обычной цены
3. Количество по умолчанию = 1 для новых форм компонентов
4. Auto-select текста при клике на поле количества для удобства редактирования

Изменённые файлы:
- products/forms.py: добавлен __init__ в KitItemForm для quantity.initial = 1
- products/templates/includes/select2-product-init.html: обновлена formatSelectResult
- products/templates/productkit_create.html: добавлен focus handler для auto-select
- products/templates/productkit_edit.html: добавлен focus handler для auto-select

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 19:04:03 +03:00

280 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python
"""
Скрипт для тестирования системы наличия товаров и цен вариантов.
Проверяет:
1. Обновление Product.in_stock при создании Stock
2. Свойство ProductVariantGroup.in_stock (вариант в наличии если хотя бы один товар в наличии)
3. Свойство ProductVariantGroup.price (берётся цена по приоритету)
"""
import os
import sys
import django
# Добавляем путь к myproject
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'myproject'))
os.chdir(os.path.join(os.path.dirname(__file__), 'myproject'))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
from decimal import Decimal
from products.models import Product, ProductVariantGroup, ProductVariantGroupItem
from inventory.models import Stock, StockBatch, Warehouse, Incoming, IncomingBatch
from django.utils import timezone
def clear_data():
"""Очищаем тестовые данные"""
Product.objects.all().delete()
ProductVariantGroup.objects.all().delete()
Stock.objects.all().delete()
StockBatch.objects.all().delete()
Warehouse.objects.all().delete()
IncomingBatch.objects.all().delete()
print("OK Данные очищены")
def create_test_data():
"""Создаём тестовые данные"""
# Создаём склад
warehouse = Warehouse.objects.create(
name="Основной склад",
description="Тестовый склад",
is_active=True,
is_default=True
)
print(f"OK Создан склад: {warehouse.name}")
# Создаём товары (розы разной длины)
products = []
prices = [Decimal('50.00'), Decimal('60.00'), Decimal('70.00')]
for i, price in enumerate(prices, 1):
product = Product.objects.create(
name=f"Роза красная Freedom {50 + i*10}см",
sku=f"ROSE-RED-{50 + i*10}",
cost_price=Decimal('30.00'),
sale_price=price,
unit='шт',
is_active=True,
in_stock=False # По умолчанию нет в наличии
)
products.append(product)
print(f"OK Создан товар: {product.name} (цена: {price}, in_stock={product.in_stock})")
# Создаём группу вариантов
variant_group = ProductVariantGroup.objects.create(
name="Роза красная Freedom",
description="Розы разной высоты"
)
print(f"OK Создана группа вариантов: {variant_group.name}")
# Добавляем товары в группу с приоритетами
items = []
for priority, product in enumerate(products, 1):
item = ProductVariantGroupItem.objects.create(
variant_group=variant_group,
product=product,
priority=priority
)
items.append(item)
print(f" - {product.name} (приоритет {priority})")
return warehouse, products, variant_group, items
def test_scenario_1():
"""
Тест 1: Создание товара в наличии и проверка автоматического обновления in_stock
"""
print("\n" + "="*80)
print("ТЕСТ 1: Обновление Product.in_stock при создании Stock")
print("="*80)
warehouse, products, variant_group, items = create_test_data()
# Получаем первый товар
product = products[0]
print(f"\nПроверяем товар: {product.name}")
print(f"Текущий статус in_stock: {product.in_stock}")
# Создаём приход товара (это должно создать Stock и обновить in_stock)
incoming_batch = IncomingBatch.objects.create(
warehouse=warehouse,
document_number="IN-0001",
supplier_name="Тестовый поставщик"
)
print(f"\nOK Создана партия поступления: {incoming_batch.document_number}")
# Добавляем товар в приход
incoming = Incoming.objects.create(
batch=incoming_batch,
product=product,
quantity=Decimal('100.00'),
cost_price=product.cost_price
)
print(f"OK Добавлен товар в приход: {incoming.quantity} шт")
# Проверяем что Stock был создан и in_stock обновлён
stock = Stock.objects.get(product=product, warehouse=warehouse)
print(f"\nOK Stock создан:")
print(f" - quantity_available: {stock.quantity_available}")
print(f" - quantity_reserved: {stock.quantity_reserved}")
print(f" - quantity_free: {stock.quantity_free}")
# Обновляем товар из БД чтобы получить новое значение
product.refresh_from_db()
print(f"\nOK Product.in_stock обновлён: {product.in_stock}")
if product.in_stock:
print("PASS: ТЕСТ 1 ПРОЙДЕН: Product.in_stock = True")
else:
print("FAIL: ТЕСТ 1 ПРОВАЛЕН: Product.in_stock должен быть True")
return warehouse, products, variant_group, items
def test_scenario_2(warehouse, products, variant_group, items):
"""
Тест 2: Проверка свойства ProductVariantGroup.in_stock
"""
print("\n" + "="*80)
print("ТЕСТ 2: Свойство ProductVariantGroup.in_stock")
print("="*80)
# Обновляем товары из БД
for product in products:
product.refresh_from_db()
print(f"\nГруппа вариантов: {variant_group.name}")
print(f"Товары в группе:")
for item in variant_group.items.all():
print(f" - {item.product.name} (приоритет {item.priority}, in_stock={item.product.in_stock})")
# Первый товар в наличии, поэтому вариант должен быть в наличии
print(f"\nСвойство variant_group.in_stock: {variant_group.in_stock}")
if variant_group.in_stock:
print("PASS: ТЕСТ 2 ПРОЙДЕН: Вариант в наличии (хотя бы один товар доступен)")
else:
print("FAIL: ТЕСТ 2 ПРОВАЛЕН: Вариант должен быть в наличии")
def test_scenario_3(warehouse, products, variant_group, items):
"""
Тест 3: Проверка свойства ProductVariantGroup.price
"""
print("\n" + "="*80)
print("ТЕСТ 3: Свойство ProductVariantGroup.price")
print("="*80)
print(f"\nГруппа вариантов: {variant_group.name}")
# Обновляем товары из БД
for product in products:
product.refresh_from_db()
print(f"Товары в приоритете:")
for item in variant_group.items.all().order_by('priority'):
status = "OK В наличии" if item.product.in_stock else "NO Нет в наличии"
print(f" {item.priority}. {item.product.name} - {item.product.sale_price} руб {status}")
# Цена должна быть из первого в наличии (приоритет 1, цена 50.00)
price = variant_group.price
expected_price = Decimal('50.00')
print(f"\nЦена варианта: {price} руб")
print(f"Ожидаемая цена: {expected_price} руб")
if price == expected_price:
print("PASS: ТЕСТ 3 ПРОЙДЕН: Берётся цена товара с приоритетом 1")
else:
print(f"FAIL: ТЕСТ 3 ПРОВАЛЕН: Цена должна быть {expected_price}, получена {price}")
def test_scenario_4():
"""
Тест 4: Проверка цены когда нет товара в наличии (должна быть максимальная)
"""
print("\n" + "="*80)
print("ТЕСТ 4: Цена варианта когда ни один товар не в наличии")
print("="*80)
# Очищаем данные
clear_data()
# Создаём новые данные без Stock (товары не в наличии)
warehouse = Warehouse.objects.create(
name="Тестовый склад",
is_active=True,
is_default=True
)
# Создаём товары с разными ценами
products = []
prices = [Decimal('100.00'), Decimal('150.00'), Decimal('200.00')]
for i, price in enumerate(prices, 1):
product = Product.objects.create(
name=f"Товар {i}",
sku=f"PRODUCT-{i}",
cost_price=Decimal('50.00'),
sale_price=price,
unit='шт',
is_active=True,
in_stock=False # Нет в наличии
)
products.append(product)
# Создаём группу вариантов
variant_group = ProductVariantGroup.objects.create(
name="Группа товаров без наличия"
)
# Добавляем товары в группу
for priority, product in enumerate(products, 1):
ProductVariantGroupItem.objects.create(
variant_group=variant_group,
product=product,
priority=priority
)
print(f"\nГруппа: {variant_group.name}")
print(f"Товары (все без наличия):")
for item in variant_group.items.all().order_by('priority'):
print(f" {item.priority}. {item.product.name} - {item.product.sale_price} руб (in_stock={item.product.in_stock})")
# Цена должна быть максимальная = 200.00
price = variant_group.price
expected_price = Decimal('200.00')
print(f"\nЦена варианта (максимальная): {price} руб")
print(f"Ожидаемая цена (максимальная): {expected_price} руб")
if price == expected_price:
print("PASS: ТЕСТ 4 ПРОЙДЕН: Берётся максимальная цена из товаров")
else:
print(f"FAIL: ТЕСТ 4 ПРОВАЛЕН: Цена должна быть {expected_price}, получена {price}")
if __name__ == '__main__':
print("\n" + "="*80)
print("= ТЕСТИРОВАНИЕ СИСТЕМЫ НАЛИЧИЯ ТОВАРОВ И ЦЕН ВАРИАНТОВ")
print("="*80)
try:
# Очищаем старые данные
clear_data()
# Тесты 1-3
warehouse, products, variant_group, items = test_scenario_1()
test_scenario_2(warehouse, products, variant_group, items)
test_scenario_3(warehouse, products, variant_group, items)
# Тест 4
test_scenario_4()
print("\n" + "="*80)
print("= ТЕСТИРОВАНИЕ ЗАВЕРШЕНО")
print("="*80 + "\n")
except Exception as e:
print(f"\nОШИБКА: {e}")
import traceback
traceback.print_exc()