Files
saldo/app/services/comparison_service.py
2026-04-21 21:17:36 +02:00

61 lines
2.5 KiB
Python

from __future__ import annotations
from decimal import Decimal
from app.models import MonthlyAllocation, MonthlyEntryValue, MonthlyIncome, to_decimal
class ComparisonService:
def month_delta(self, current_month, previous_month) -> dict:
if previous_month is None:
zero = Decimal("0.00")
return {
"income_delta": zero,
"cost_delta": zero,
"remainder_delta": zero,
"allocation_delta": zero,
}
return {
"income_delta": self._total_income(current_month) - self._total_income(previous_month),
"cost_delta": self._total_costs(current_month) - self._total_costs(previous_month),
"remainder_delta": self._remainder(current_month) - self._remainder(previous_month),
"allocation_delta": self._total_allocations(current_month)
- self._total_allocations(previous_month),
}
def top_entry_changes(self, current_month, previous_month, limit: int = 6) -> list[dict]:
if previous_month is None:
return []
previous_values = {
item.entry_id: to_decimal(item.planned_amount) for item in previous_month.entry_values
}
changes = []
for item in current_month.entry_values:
previous_amount = previous_values.get(item.entry_id, Decimal("0.00"))
current_amount = to_decimal(item.planned_amount)
delta = current_amount - previous_amount
if delta:
changes.append(
{
"entry_name": item.entry.name,
"category_name": item.entry.category.name,
"delta": delta,
"current_amount": current_amount,
"previous_amount": previous_amount,
}
)
changes.sort(key=lambda item: abs(item["delta"]), reverse=True)
return changes[:limit]
def _total_income(self, month) -> Decimal:
return sum((to_decimal(item.amount) for item in month.incomes), Decimal("0.00"))
def _total_costs(self, month) -> Decimal:
return sum((to_decimal(item.planned_amount) for item in month.entry_values), Decimal("0.00"))
def _total_allocations(self, month) -> Decimal:
return sum((to_decimal(item.amount) for item in month.allocations), Decimal("0.00"))
def _remainder(self, month) -> Decimal:
return self._total_income(month) - self._total_costs(month)