""" Тестовый скрипт для проверки логики расчета себестоимости. Запускается без БД для проверки математической корректности. """ 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)