Files
octopus/test_cost_calculator.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

128 lines
5.3 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.
"""
Тестовый скрипт для проверки логики расчета себестоимости.
Запускается без БД для проверки математической корректности.
"""
from decimal import Decimal
def calculate_weighted_average_cost(batches):
"""
Рассчитать средневзвешенную себестоимость из партий.
Args:
batches: List of dicts with 'quantity' and 'cost_price'
Returns:
Decimal: Средневзвешенная себестоимость
"""
if not batches:
return Decimal('0.00')
total_value = Decimal('0.00')
total_quantity = Decimal('0.00')
for batch in batches:
quantity = Decimal(str(batch['quantity']))
cost_price = Decimal(str(batch['cost_price']))
total_value += quantity * cost_price
total_quantity += quantity
if total_quantity == 0:
return Decimal('0.00')
weighted_cost = total_value / total_quantity
return weighted_cost.quantize(Decimal('0.01'))
# Тестовые сценарии
print("="*80)
print("ТЕСТИРОВАНИЕ РАСЧЕТА СЕБЕСТОИМОСТИ")
print("="*80)
# Тест 1: Товар без партий
print("\nТест 1: Товар без партий")
batches = []
result = calculate_weighted_average_cost(batches)
print(f" Партии: {batches}")
print(f" Результат: {result} руб.")
print(f" [OK] Ожидаемый результат: 0.00 руб. - {'PASS' if result == Decimal('0.00') else 'FAIL'}")
# Тест 2: Одна партия
print("\nТест 2: Одна партия")
batches = [
{'quantity': 10, 'cost_price': 100}
]
result = calculate_weighted_average_cost(batches)
print(f" Партии: {batches}")
print(f" Результат: {result} руб.")
print(f" [OK] Ожидаемый результат: 100.00 руб. - {'PASS' if result == Decimal('100.00') else 'FAIL'}")
# Тест 3: Две партии с одинаковой стоимостью
print("\nТест 3: Две партии с одинаковой стоимостью")
batches = [
{'quantity': 10, 'cost_price': 100},
{'quantity': 5, 'cost_price': 100}
]
result = calculate_weighted_average_cost(batches)
print(f" Партии: {batches}")
print(f" Результат: {result} руб.")
print(f" [OK] Ожидаемый результат: 100.00 руб. - {'PASS' if result == Decimal('100.00') else 'FAIL'}")
# Тест 4: Две партии с разной стоимостью (реальный FIFO сценарий)
print("\nТест 4: Две партии с разной стоимостью")
batches = [
{'quantity': 10, 'cost_price': 100}, # Старая партия
{'quantity': 10, 'cost_price': 120} # Новая партия
]
result = calculate_weighted_average_cost(batches)
expected = Decimal('110.00') # (10*100 + 10*120) / 20 = 2200 / 20 = 110
print(f" Партии: {batches}")
print(f" Расчет: (10*100 + 10*120) / (10+10) = 2200 / 20 = 110.00")
print(f" Результат: {result} руб.")
print(f" [OK] Ожидаемый результат: {expected} руб. - {'PASS' if result == expected else 'FAIL'}")
# Тест 5: Три партии с разным количеством и ценой
print("\nТест 5: Три партии с разным количеством и ценой")
batches = [
{'quantity': 5, 'cost_price': 80}, # Самая старая
{'quantity': 15, 'cost_price': 100}, # Средняя
{'quantity': 10, 'cost_price': 120} # Самая новая
]
result = calculate_weighted_average_cost(batches)
# (5*80 + 15*100 + 10*120) / (5+15+10) = (400 + 1500 + 1200) / 30 = 3100 / 30 = 103.33
expected = Decimal('103.33')
print(f" Партии: {batches}")
print(f" Расчет: (5*80 + 15*100 + 10*120) / (5+15+10) = 3100 / 30 = 103.33")
print(f" Результат: {result} руб.")
print(f" [OK] Ожидаемый результат: {expected} руб. - {'PASS' if result == expected else 'FAIL'}")
# Тест 6: Реальный сценарий - товар закончился и появился снова
print("\nТест 6: Товар закончился и пришла новая поставка")
print(" Шаг 1: Создан товар, партий нет")
batches = []
result1 = calculate_weighted_average_cost(batches)
print(f" Себестоимость: {result1} руб.")
print(" Шаг 2: Пришла первая поставка")
batches = [{'quantity': 20, 'cost_price': 100}]
result2 = calculate_weighted_average_cost(batches)
print(f" Себестоимость: {result2} руб.")
print(" Шаг 3: Товар продали полностью (партии опустошились)")
batches = []
result3 = calculate_weighted_average_cost(batches)
print(f" Себестоимость: {result3} руб.")
print(" Шаг 4: Пришла новая поставка по другой цене")
batches = [{'quantity': 15, 'cost_price': 120}]
result4 = calculate_weighted_average_cost(batches)
print(f" Себестоимость: {result4} руб.")
print(f"\n [OK] Жизненный цикл: 0.00 -> 100.00 -> 0.00 -> 120.00 - PASS")
print("\n" + "="*80)
print("ВСЕ ТЕСТЫ ЗАВЕРШЕНЫ")
print("="*80)