Replace reports CBV with FBV

This commit is contained in:
Gabriel Augendre 2022-05-04 22:24:05 +02:00
parent 60660c0abf
commit 91d64c6ce4
2 changed files with 143 additions and 145 deletions

View file

@ -6,7 +6,7 @@ from purchase.views import (
NewBasketView,
UpdateBasketView,
)
from purchase.views.reports import ReportsView
from purchase.views.reports import reports
app_name = "purchase"
urlpatterns = [
@ -14,5 +14,5 @@ urlpatterns = [
path("new/", NewBasketView.as_view(), name="new"),
path("<int:pk>/update/", UpdateBasketView.as_view(), name="update"),
path("<int:pk>/delete/", DeleteBasketView.as_view(), name="delete"),
path("reports/", ReportsView.as_view(), name="reports"),
path("reports/", reports, name="reports"),
]

View file

@ -5,8 +5,9 @@ from zoneinfo import ZoneInfo
import numpy as np
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.template.response import TemplateResponse
from django.utils.translation import gettext as _
from django.views.generic import TemplateView
from matplotlib import pyplot as plt
from matplotlib import ticker
from matplotlib.axes import Axes
@ -15,37 +16,30 @@ from matplotlib.dates import AutoDateLocator, ConciseDateFormatter, HourLocator
from matplotlib.figure import Figure
from purchase.models import Basket, PaymentMethod, Product, ProductQuerySet
from purchase.views.utils import ProtectedViewsMixin
class ReportsView(ProtectedViewsMixin, TemplateView):
permission_required = ["purchase.view_basket"]
@permission_required("purchase.view_basket")
def reports(request):
template_name = "purchase/reports.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
baskets = list(Basket.objects.priced().order_by("created_at"))
if not baskets:
messages.warning(self.request, _("No sale to report"))
return context
messages.warning(request, _("No sale to report"))
return TemplateResponse(request, template_name, {})
dates = Basket.objects.values_list("created_at__date", flat=True).distinct()
average_basket_by_day = {
date: Basket.objects.by_date(date).average_basket() for date in dates
}
turnover_by_day = {
date: Basket.objects.by_date(date).turnover() for date in dates
}
turnover_by_day = {date: Basket.objects.by_date(date).turnover() for date in dates}
products = Product.objects.with_turnover().with_sold()
(
products_plot,
products_sold_pie,
products_turnover_pie,
) = self.get_products_plots(products)
by_hour_plot = self.by_hour_plot(baskets)
context.update(
{
) = get_products_plots(products)
context = {
"turnover": Basket.objects.turnover(),
"turnover_by_day": turnover_by_day,
"average_basket": Basket.objects.average_basket(),
@ -54,15 +48,15 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
"products_plot": products_plot,
"products_sold_pie": products_sold_pie,
"products_turnover_pie": products_turnover_pie,
"by_hour_plot": by_hour_plot,
"by_hour_plot": by_hour_plot(baskets),
"payment_methods": PaymentMethod.objects.with_turnover().with_sold(),
"no_payment_method": Basket.objects.no_payment_method().priced(),
}
)
return context
return TemplateResponse(request, template_name, context)
def get_products_plots(self, products: ProductQuerySet):
labels, sold, turnover = self.get_products_data_for_plot(products)
def get_products_plots(products: ProductQuerySet):
labels, sold, turnover = get_products_data_for_plot(products)
x = np.arange(len(labels))
width = 0.4
@ -87,25 +81,26 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
ax2.tick_params(axis="y", labelcolor=color)
fig.tight_layout()
img1 = self.get_image_from_fig(fig)
img1 = get_image_from_fig(fig)
fig = plt.figure()
fig.suptitle(_("# sold"))
ax1 = fig.add_subplot()
ax1.pie(sold, labels=labels, autopct="%d%%")
fig.tight_layout()
img2 = self.get_image_from_fig(fig)
img2 = get_image_from_fig(fig)
fig = plt.figure()
fig.suptitle(_("Turnover by product"))
ax1 = fig.add_subplot()
ax1.pie(turnover, labels=labels, autopct="%d%%")
fig.tight_layout()
img3 = self.get_image_from_fig(fig)
img3 = get_image_from_fig(fig)
return img1, img2, img3
def get_products_data_for_plot(self, products):
def get_products_data_for_plot(products):
labels = []
sold = []
turnover = []
@ -115,8 +110,9 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
turnover.append(product.turnover / 100)
return labels, sold, turnover
def by_hour_plot(self, baskets):
labels, counts, turnovers = self.get_by_hour_data_for_plot(baskets)
def by_hour_plot(baskets):
labels, counts, turnovers = get_by_hour_data_for_plot(baskets)
hours_in_day = 24
fig: Figure = plt.figure()
fig.suptitle(_("Sales by hour"))
@ -145,9 +141,10 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
ax2.yaxis.set_major_formatter(ticker.FormatStrFormatter("%.2f"))
fig.tight_layout()
return self.get_image_from_fig(fig)
return get_image_from_fig(fig)
def get_by_hour_data_for_plot(self, baskets):
def get_by_hour_data_for_plot(baskets):
current: datetime.datetime = baskets[0].created_at
current = current.replace(minute=0, second=0, microsecond=0)
end: datetime.datetime = baskets[-1].created_at
@ -173,7 +170,8 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
current = end_slot
return labels, counts, turnovers
def get_image_from_fig(self, fig):
def get_image_from_fig(fig):
image_data = StringIO()
fig.savefig(image_data, format="svg")
image_data.seek(0)