81 lines
3.0 KiB
Python
81 lines
3.0 KiB
Python
from dateutil.relativedelta import relativedelta
|
|
from django.db.models import Q
|
|
|
|
from financeplanner.utils import current_date
|
|
|
|
|
|
class ActualTransaction:
|
|
|
|
def __init__(self, date, subject, amount):
|
|
self.date = date
|
|
self.subject = subject
|
|
self.amount = amount
|
|
|
|
|
|
class Statistics:
|
|
|
|
def __init__(self, user):
|
|
self.user = user
|
|
self.today = current_date()
|
|
self.start = self.today - relativedelta(months=6)
|
|
self.end = self.today + relativedelta(months=6)
|
|
self.calc_start = self.start
|
|
self.balances = []
|
|
self.transactions = []
|
|
self.actual_transactions = []
|
|
|
|
def _fetch_relevant_balances(self):
|
|
balances = []
|
|
balances_until_start = self.user.balances.filter(date__lte=self.start)
|
|
if balances_until_start.exists():
|
|
balances = [balances_until_start.latest("date")]
|
|
other_balances = self.user.balances.filter(date__gt=self.start, date__lte=self.end).order_by("date")
|
|
self.balances = balances + list(other_balances)
|
|
if self.balances:
|
|
self.calc_start = self.balances[0].date
|
|
|
|
def _fetch_relevant_transactions(self):
|
|
one_time_in_range = Q(
|
|
booking_date__gte=self.calc_start,
|
|
booking_date__lte=self.end,
|
|
recurring_months__isnull=True,
|
|
)
|
|
endlessly_recurring = Q(
|
|
booking_date__lte=self.end,
|
|
recurring_months__isnull=False,
|
|
not_recurring_after__isnull=True,
|
|
)
|
|
recurring_and_ending_in_range = Q(
|
|
booking_date__lte=self.end,
|
|
recurring_months__isnull=False,
|
|
not_recurring_after__gte=self.calc_start,
|
|
)
|
|
transactions = self.user.transactions.filter(
|
|
one_time_in_range | endlessly_recurring | recurring_and_ending_in_range
|
|
).order_by("booking_date")
|
|
self.transactions = list(transactions)
|
|
|
|
def _calculate_actual_transactions(self):
|
|
actual_transaction = []
|
|
for trans in self.transactions:
|
|
if trans.recurring_months:
|
|
iter_date = trans.booking_date
|
|
iter_step = 1
|
|
limit = min(trans.not_recurring_after, self.end) if trans.not_recurring_after else self.end
|
|
while iter_date < limit:
|
|
if iter_date >= self.calc_start:
|
|
actual_transaction.append(ActualTransaction(
|
|
date=iter_date,
|
|
subject=f"{trans.subject} #{iter_step}",
|
|
amount=trans.amount,
|
|
))
|
|
iter_date += relativedelta(months=trans.recurring_months)
|
|
iter_step += 1
|
|
else:
|
|
actual_transaction.append(ActualTransaction(
|
|
date=trans.booking_date,
|
|
subject=trans.subject,
|
|
amount=trans.amount,
|
|
))
|
|
self.actual_transactions = actual_transaction
|