highlight today's bar, calculate daily stats considering irregular expenses and show them interactively
This commit is contained in:
@@ -30,13 +30,16 @@ class ActualTransaction:
|
||||
|
||||
|
||||
class DailyStat:
|
||||
def __init__(self, date, balance_amount, actual_transactions, resulting_amount):
|
||||
def __init__(self, stat_id, date, balance_amount, actual_transactions, resulting_amount):
|
||||
self.id = stat_id
|
||||
self.date = date
|
||||
self.balance_amount = balance_amount
|
||||
self.actual_transactions = actual_transactions
|
||||
self.resulting_amount = resulting_amount
|
||||
self.highlighted = False
|
||||
self.percentage = 40
|
||||
self.resulting_amount_irregular = self.resulting_amount
|
||||
self.percentage_irregular = self.percentage
|
||||
|
||||
def __str__(self):
|
||||
return f"DailyStat({self.date}, {self.balance_amount}, " \
|
||||
@@ -46,6 +49,11 @@ class DailyStat:
|
||||
self.highlighted = self.date == today
|
||||
if self.resulting_amount is not None:
|
||||
self.percentage = int((self.resulting_amount / amount_scale) * 100)
|
||||
self.percentage_irregular = self.percentage
|
||||
|
||||
def generate_irregular_graph_bar_attributes(self, amount_scale):
|
||||
if self.resulting_amount_irregular is not None:
|
||||
self.percentage_irregular = int((self.resulting_amount_irregular / amount_scale) * 100)
|
||||
|
||||
|
||||
class Statistics:
|
||||
@@ -78,6 +86,7 @@ class Statistics:
|
||||
self._calculate_daily_amount_scale()
|
||||
self._generate_graph_bar_attributes()
|
||||
self._calculate_analysis()
|
||||
self._add_statistics_considering_analysis()
|
||||
|
||||
def _fetch_relevant_balances(self):
|
||||
self.balances = []
|
||||
@@ -136,6 +145,7 @@ class Statistics:
|
||||
|
||||
def _calculate_daily_stats(self):
|
||||
self.daily_stats = []
|
||||
iter_id = 0
|
||||
iter_date = self.real_calc_start
|
||||
iter_amount = None
|
||||
while iter_date < self.calc_end:
|
||||
@@ -156,11 +166,13 @@ class Statistics:
|
||||
|
||||
if iter_amount is not None:
|
||||
self.daily_stats.append(DailyStat(
|
||||
stat_id=iter_id,
|
||||
date=iter_date,
|
||||
balance_amount=balance_amount,
|
||||
actual_transactions=actual_transactions,
|
||||
resulting_amount=iter_amount,
|
||||
))
|
||||
iter_id += 1
|
||||
iter_date += relativedelta(days=1)
|
||||
|
||||
def _calculate_daily_amount_scale(self):
|
||||
@@ -213,5 +225,21 @@ class Statistics:
|
||||
|
||||
self.avg_monthly_result_complete = self.avg_monthly_result + self.avg_monthly_irregular_expenses
|
||||
|
||||
def _add_statistics_considering_analysis(self):
|
||||
previous_original_amount = None
|
||||
iter_amount = None
|
||||
for stat in self.daily_stats:
|
||||
if stat.resulting_amount is not None:
|
||||
relevant_balances = [bal for bal in self.balances if bal.date == stat.date]
|
||||
if relevant_balances or previous_original_amount is None:
|
||||
iter_amount = stat.resulting_amount + self.avg_daily_irregular_expenses
|
||||
else:
|
||||
orig_diff = stat.resulting_amount - previous_original_amount
|
||||
new_diff = orig_diff + self.avg_daily_irregular_expenses
|
||||
iter_amount += new_diff
|
||||
stat.resulting_amount_irregular = iter_amount
|
||||
stat.generate_irregular_graph_bar_attributes(self.daily_amount_scale)
|
||||
previous_original_amount = stat.resulting_amount
|
||||
|
||||
def get_daily_stats_in_range(self):
|
||||
return [s for s in self.daily_stats if self.display_start <= s.date <= self.display_end]
|
||||
|
||||
@@ -179,10 +179,11 @@ tr:hover {
|
||||
border-radius: 2px;
|
||||
background-color: #FFCC99;
|
||||
z-index: 10;
|
||||
transition: height 250ms;
|
||||
}
|
||||
|
||||
.graph-bar.highlighted {
|
||||
border: 1px solid #FFFCF9;
|
||||
background-color: #CC6622;
|
||||
}
|
||||
|
||||
.graph-bar:hover {
|
||||
|
||||
@@ -14,17 +14,11 @@
|
||||
<div id="date-panel">-</div>
|
||||
<div id="graph">
|
||||
{% for stat in daily_stats %}
|
||||
{% if stat.percentage is None %}
|
||||
<div class="graph-bar"
|
||||
onmouseover="showGraphBarDate('{{ stat.date|date:"d.m.y" }}')"
|
||||
onmouseleave="clearGraphBarDate()">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="graph-bar" style="height: {{ stat.percentage }}%;"
|
||||
onmouseover="showGraphBarDate('{{ stat.date|date:"d.m.y" }}')"
|
||||
onmouseleave="clearGraphBarDate()">
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="graph-bar{% if stat.highlighted %} highlighted{% endif %}"
|
||||
id="graph-bar-{{ stat.id }}"
|
||||
onmouseover="showGraphBarDate('{{ stat.date|date:"d.m.y" }}')"
|
||||
onmouseleave="clearGraphBarDate()">
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
@@ -161,6 +155,12 @@
|
||||
<script type="text/javascript">
|
||||
const graph = document.getElementById('graph');
|
||||
const datePanel = document.getElementById('date-panel');
|
||||
const irrExpCheckbox = document.getElementById('irregular-expenses-checkbox');
|
||||
|
||||
{% for stat in daily_stats %}
|
||||
const graphBar{{ stat.id }} = document.getElementById('graph-bar-{{ stat.id }}');
|
||||
{% endfor %}
|
||||
|
||||
let scrolling = false;
|
||||
let initX;
|
||||
let initScrollLeft;
|
||||
@@ -194,9 +194,23 @@
|
||||
datePanel.innerText = '-';
|
||||
}
|
||||
|
||||
function applyGraphBarHeights() {
|
||||
if (irrExpCheckbox.checked) {
|
||||
{% for stat in daily_stats %}
|
||||
graphBar{{ stat.id }}.style.height = '{{ stat.percentage_irregular }}%';
|
||||
{% endfor %}
|
||||
} else {
|
||||
{% for stat in daily_stats %}
|
||||
graphBar{{ stat.id }}.style.height = '{{ stat.percentage }}%';
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
|
||||
graph.addEventListener('mousedown', (event) => startDragScroll(event));
|
||||
graph.addEventListener('mouseleave', () => stopDragScroll());
|
||||
graph.addEventListener('mouseup', () => stopDragScroll());
|
||||
graph.addEventListener('mousemove', (event) => doDragScroll(event));
|
||||
irrExpCheckbox.addEventListener('change', () => applyGraphBarHeights());
|
||||
window.onload = applyGraphBarHeights;
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user