Skip to content

Commit

Permalink
Add chart with average basket price (#450)
Browse files Browse the repository at this point in the history
* Add chart with average basket price

* Avg -> Sum, cleanup

---------

Co-authored-by: tvedeane <marekjeszka@fastmail.com>
tvedeane and tvedeane authored Dec 1, 2023
1 parent bbdded5 commit 4d08c3d
Showing 4 changed files with 90 additions and 3 deletions.
2 changes: 2 additions & 0 deletions tapir/accounts/templates/accounts/user_detail.html
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@
{% block head %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'shifts/css/shifts.css' %}">
<script src="{% static 'statistics/chart_4.4.0.js' %}"></script>
<script src="{% static 'statistics/tapir_charts.js' %}" defer></script>
{% endblock %}

{% block title %}
Original file line number Diff line number Diff line change
@@ -31,4 +31,18 @@ <h5 class="card-header d-flex justify-content-between align-items-center">
</table>
</li>
</ul>
<div class="card-body">
<p>
<span class="{% tapir_button_link %}"
onclick="chartManager.show_stats_chart(
this,
'{% url "statistics:basket_sum_evolution_json" tapir_user.pk %}',
'basket_sum_evolution_canvas',
)">
<span class="material-icons">leaderboard</span>
<span class="button-text">{% translate "Show graph: " %}{% translate "Evolution of total spends per month" %}</span>
</span>
<canvas id="basket_sum_evolution_canvas" style="display: none;"></canvas>
</p>
</div>
</div>
5 changes: 5 additions & 0 deletions tapir/statistics/urls.py
Original file line number Diff line number Diff line change
@@ -39,4 +39,9 @@
views.UpdatePurchaseDataManuallyView.as_view(),
name="update_purchase_data_manually",
),
path(
"user/<int:pk>/basket_sum_evolution_json",
views.BasketSumEvolutionJsonView.as_view(),
name="basket_sum_evolution_json",
),
]
72 changes: 69 additions & 3 deletions tapir/statistics/views.py
Original file line number Diff line number Diff line change
@@ -5,32 +5,40 @@
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.core.management import call_command
from django.db.models import Sum
from django.db.models.functions import TruncMonth
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views import generic
from django.views.generic import RedirectView

from tapir.accounts.models import UpdateTapirUserLogEntry
from tapir.accounts.models import (
TapirUser,
UpdateTapirUserLogEntry,
)
from tapir.coop.models import ShareOwnership, ShareOwner, MemberStatus
from tapir.coop.views import ShareCountEvolutionJsonView
from tapir.financingcampaign.models import (
FinancingCampaign,
FinancingSourceDatapoint,
)
from tapir.settings import PERMISSION_COOP_MANAGE
from tapir.settings import PERMISSION_COOP_MANAGE, PERMISSION_ACCOUNTS_VIEW
from tapir.shifts.models import (
ShiftUserData,
ShiftSlotTemplate,
ShiftAttendanceMode,
)
from tapir.shifts.services.shift_expectation_service import ShiftExpectationService
from tapir.statistics.models import ProcessedPurchaseFiles
from tapir.statistics.models import (
PurchaseBasket,
ProcessedPurchaseFiles,
)
from tapir.statistics.utils import (
build_pie_chart_data,
build_line_chart_data,
)
from tapir.utils.shortcuts import get_first_of_next_month


class MainStatisticsView(LoginRequiredMixin, generic.TemplateView):
@@ -206,6 +214,64 @@ def get_context_data(self, **kwargs):
return context_data


class BasketSumEvolutionJsonView(LoginRequiredMixin, PermissionRequiredMixin, JSONView):
def get_permission_required(self):
if self.request.user.pk == self.kwargs["pk"]:
return []
return [PERMISSION_ACCOUNTS_VIEW]

def get_context_data(self, **kwargs):
tapir_user = get_object_or_404(TapirUser, pk=(self.kwargs["pk"]))

user_purchases = (
PurchaseBasket.objects.filter(tapir_user=tapir_user)
.annotate(month=TruncMonth("purchase_date"))
.values("month")
.annotate(average_gross_amount=Sum("gross_amount"))
.order_by("month")
)

months = self.get_months(user_purchases)

return build_line_chart_data(
x_axis_values=months,
y_axis_values=[self.get_sums_per_month(user_purchases, months)],
data_labels=[_("Total spends per month")],
)

@staticmethod
def get_months(user_purchases):
if len(user_purchases) == 0:
return []

months = []
now = timezone.now().date().replace(day=1)

month = user_purchases[0]["month"].date()
months.append(month.strftime("%Y-%m"))

while month < now:
month = get_first_of_next_month(month)
months.append(month.strftime("%Y-%m"))

return months

@staticmethod
def get_sums_per_month(purchases_query_set, months):
if len(purchases_query_set) == 0:
return []

prices = []
purchases_dict = {
entry["month"].strftime("%Y-%m"): entry["average_gross_amount"]
for entry in purchases_query_set
}
for month in months:
prices.append(purchases_dict.get(month, 0))

return prices


class FrozenMembersJsonView(JSONView):
def get_context_data(self, **kwargs):
relevant_members = self.get_relevant_members()

0 comments on commit 4d08c3d

Please sign in to comment.