add balance prediction page and make it the default
This commit is contained in:
@@ -113,3 +113,66 @@ def predict_all(subjects: Iterable[Subject], past_days=30, future_days=60):
|
||||
prediction_list.append((subject, transactions, prediction_info))
|
||||
|
||||
return prediction_list
|
||||
|
||||
|
||||
min_pos_color = (Decimal("50"), Decimal("150"), Decimal("220"))
|
||||
max_pos_color = (Decimal("50"), Decimal("170"), Decimal("20"))
|
||||
min_neg_color = (Decimal("220"), Decimal("70"), Decimal("30"))
|
||||
max_neg_color = (Decimal("180"), Decimal("160"), Decimal("30"))
|
||||
|
||||
global_minimum = Decimal("-300")
|
||||
global_maximum = Decimal("300")
|
||||
|
||||
|
||||
def limit(amount: Decimal, first_bound: Decimal, second_bound: Decimal):
|
||||
lower = min(first_bound, second_bound)
|
||||
upper = max(first_bound, second_bound)
|
||||
return max(min(amount, upper), lower)
|
||||
|
||||
|
||||
def get_color_for_amount(amount: Decimal, minimum: Decimal, maximum: Decimal):
|
||||
if amount >= Decimal():
|
||||
minimum = Decimal()
|
||||
maximum = min(maximum, global_maximum)
|
||||
rmin, gmin, bmin = min_pos_color
|
||||
rmax, gmax, bmax = max_pos_color
|
||||
else:
|
||||
minimum = max(minimum, global_minimum)
|
||||
maximum = Decimal()
|
||||
rmin, gmin, bmin = min_neg_color
|
||||
rmax, gmax, bmax = max_neg_color
|
||||
assert minimum < maximum
|
||||
percentage = (amount - minimum) / (maximum - minimum)
|
||||
return "#%02x%02x%02x" % (
|
||||
round(limit(rmin + (percentage * (rmax - rmin)), rmin, rmax)),
|
||||
round(limit(gmin + (percentage * (gmax - gmin)), gmin, gmax)),
|
||||
round(limit(bmin + (percentage * (bmax - bmin)), bmin, bmax)),
|
||||
)
|
||||
|
||||
|
||||
def predict_balance(start_balance=Decimal("0")):
|
||||
prediction_list = predict_all(Subject.objects.order_by("name"))
|
||||
today = timezone.now().date()
|
||||
future_transactions = []
|
||||
minimum, maximum = Decimal(), Decimal()
|
||||
for _, transactions, _ in prediction_list:
|
||||
for transaction in transactions:
|
||||
if transaction.booking_date > today:
|
||||
future_transactions.append(transaction)
|
||||
minimum = min(minimum, transaction.amount)
|
||||
maximum = max(maximum, transaction.amount)
|
||||
|
||||
formatted_transactions = []
|
||||
current_balance = start_balance
|
||||
for transaction in sorted(future_transactions, key=lambda t: t.booking_date):
|
||||
current_balance += transaction.amount
|
||||
formatted_transactions.append({
|
||||
"date": transaction.booking_date,
|
||||
"subject": transaction.subject,
|
||||
"amount": transaction.amount,
|
||||
"balance": current_balance,
|
||||
"predicted": transaction.pk is None,
|
||||
"color": get_color_for_amount(transaction.amount, minimum, maximum),
|
||||
})
|
||||
|
||||
return formatted_transactions
|
||||
|
||||
Reference in New Issue
Block a user