149 lines
4.9 KiB
Python
149 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Test script to demonstrate and verify the weighted average cost calculation
|
||
Location: services/inventory/tests/test_weighted_average_cost.py
|
||
"""
|
||
import sys
|
||
from decimal import Decimal
|
||
|
||
|
||
def calculate_weighted_average(current_stock: float, current_avg_cost: float,
|
||
new_quantity: float, new_unit_cost: float) -> float:
|
||
"""
|
||
Calculate weighted average cost - mirrors the implementation in ingredient_repository.py
|
||
|
||
Args:
|
||
current_stock: Current stock quantity before purchase
|
||
current_avg_cost: Current average cost per unit
|
||
new_quantity: Quantity being purchased
|
||
new_unit_cost: Unit cost of new purchase
|
||
|
||
Returns:
|
||
New average cost per unit
|
||
"""
|
||
if current_stock <= 0:
|
||
return new_unit_cost
|
||
|
||
total_cost = (current_stock * current_avg_cost) + (new_quantity * new_unit_cost)
|
||
total_quantity = current_stock + new_quantity
|
||
return total_cost / total_quantity
|
||
|
||
|
||
def print_test_case(case_num: int, title: str, current_stock: float, current_avg_cost: float,
|
||
new_quantity: float, new_unit_cost: float):
|
||
"""Print a formatted test case with calculation details"""
|
||
print(f"\nTest Case {case_num}: {title}")
|
||
print("-" * 60)
|
||
print(f"Current Stock: {current_stock} kg @ €{current_avg_cost:.2f}/kg")
|
||
print(f"New Purchase: {new_quantity} kg @ €{new_unit_cost:.2f}/kg")
|
||
|
||
new_avg_cost = calculate_weighted_average(current_stock, current_avg_cost,
|
||
new_quantity, new_unit_cost)
|
||
|
||
if current_stock > 0:
|
||
total_cost = (current_stock * current_avg_cost) + (new_quantity * new_unit_cost)
|
||
total_quantity = current_stock + new_quantity
|
||
print(f"Calculation: ({current_stock} × €{current_avg_cost:.2f} + {new_quantity} × €{new_unit_cost:.2f}) / {total_quantity}")
|
||
print(f" = (€{current_stock * current_avg_cost:.2f} + €{new_quantity * new_unit_cost:.2f}) / {total_quantity}")
|
||
print(f" = €{total_cost:.2f} / {total_quantity}")
|
||
|
||
print(f"→ New Average Cost: €{new_avg_cost:.2f}/kg")
|
||
|
||
return new_avg_cost
|
||
|
||
|
||
def test_weighted_average_calculation():
|
||
"""Run comprehensive tests of the weighted average cost calculation"""
|
||
print("=" * 80)
|
||
print("WEIGHTED AVERAGE COST CALCULATION - COMPREHENSIVE TEST SUITE")
|
||
print("=" * 80)
|
||
|
||
# Test Case 1: First Purchase (Bootstrap case)
|
||
print_test_case(
|
||
1, "First Purchase (No Existing Stock)",
|
||
current_stock=0,
|
||
current_avg_cost=0,
|
||
new_quantity=100,
|
||
new_unit_cost=5.00
|
||
)
|
||
|
||
# Test Case 2: Same Price Purchase
|
||
print_test_case(
|
||
2, "Second Purchase at Same Price",
|
||
current_stock=100,
|
||
current_avg_cost=5.00,
|
||
new_quantity=50,
|
||
new_unit_cost=5.00
|
||
)
|
||
|
||
# Test Case 3: Price Increase
|
||
avg_cost = print_test_case(
|
||
3, "Purchase at Higher Price (Inflation)",
|
||
current_stock=150,
|
||
current_avg_cost=5.00,
|
||
new_quantity=50,
|
||
new_unit_cost=6.00
|
||
)
|
||
|
||
# Test Case 4: Large Volume Discount
|
||
avg_cost = print_test_case(
|
||
4, "Large Purchase with Volume Discount",
|
||
current_stock=200,
|
||
current_avg_cost=5.25,
|
||
new_quantity=200,
|
||
new_unit_cost=4.50
|
||
)
|
||
|
||
# Test Case 5: Small Purchase After Consumption
|
||
avg_cost = print_test_case(
|
||
5, "Purchase After Heavy Consumption",
|
||
current_stock=50,
|
||
current_avg_cost=4.88,
|
||
new_quantity=100,
|
||
new_unit_cost=5.50
|
||
)
|
||
|
||
# Test Case 6: Tiny Emergency Purchase
|
||
print_test_case(
|
||
6, "Small Emergency Purchase at Premium Price",
|
||
current_stock=150,
|
||
current_avg_cost=5.29,
|
||
new_quantity=10,
|
||
new_unit_cost=8.00
|
||
)
|
||
|
||
# Summary
|
||
print("\n" + "=" * 80)
|
||
print("KEY INSIGHTS")
|
||
print("=" * 80)
|
||
print("""
|
||
✓ The weighted average considers both QUANTITY and PRICE:
|
||
- Larger purchases have more impact on the average
|
||
- Smaller purchases have minimal impact
|
||
|
||
✓ Behavior with price changes:
|
||
- Price increases gradually raise the average (dampened by existing stock)
|
||
- Price decreases gradually lower the average (dampened by existing stock)
|
||
- Volume discounts can significantly lower costs when buying in bulk
|
||
|
||
✓ Business implications:
|
||
- Encourages bulk purchasing when prices are favorable
|
||
- Protects against price spike impacts (averaged over time)
|
||
- Provides accurate COGS for financial reporting
|
||
- Helps identify procurement opportunities (compare to standard_cost)
|
||
|
||
✓ Implementation notes:
|
||
- Calculation happens automatically on every stock addition
|
||
- No user intervention required
|
||
- Logged for audit purposes
|
||
- Works with FIFO stock consumption
|
||
""")
|
||
|
||
print("=" * 80)
|
||
print("✓ All tests completed successfully!")
|
||
print("=" * 80)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
test_weighted_average_calculation()
|