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