mirror of
https://github.com/Crocmagnon/checkout.git
synced 2024-11-22 08:08:04 +01:00
Add reports by hour
This commit is contained in:
parent
0e005cf815
commit
ca5e948477
8 changed files with 114 additions and 39 deletions
|
@ -7,3 +7,4 @@ __pycache__/
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.idea/
|
.idea/
|
||||||
|
*.mo
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -eux
|
set -eux
|
||||||
python manage.py migrate --noinput
|
python manage.py migrate --noinput
|
||||||
|
inv compilemessages
|
||||||
gunicorn checkout.wsgi -b 0.0.0.0:8000 --log-file -
|
gunicorn checkout.wsgi -b 0.0.0.0:8000 --log-file -
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-26 18:17+0200\n"
|
"POT-Creation-Date: 2022-04-26 20:06+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
|
@ -5,7 +5,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-26 18:17+0200\n"
|
"POT-Creation-Date: 2022-04-26 20:06+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-26 18:17+0200\n"
|
"POT-Creation-Date: 2022-04-26 20:06+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -46,11 +46,11 @@ msgstr ""
|
||||||
msgid "updated at"
|
msgid "updated at"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:37 purchase/models.py:66
|
#: purchase/models.py:37 purchase/models.py:69
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:42 purchase/models.py:149
|
#: purchase/models.py:42 purchase/models.py:152
|
||||||
msgid "payment method"
|
msgid "payment method"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -58,52 +58,52 @@ msgstr ""
|
||||||
msgid "payment methods"
|
msgid "payment methods"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:67
|
#: purchase/models.py:70
|
||||||
msgid "image"
|
msgid "image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:69
|
#: purchase/models.py:72
|
||||||
msgid "unit price (cents)"
|
msgid "unit price (cents)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:69
|
#: purchase/models.py:72
|
||||||
msgid "unit price in cents"
|
msgid "unit price in cents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:72
|
#: purchase/models.py:75
|
||||||
msgid "display order"
|
msgid "display order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:79 purchase/models.py:177
|
#: purchase/models.py:82 purchase/models.py:180
|
||||||
msgid "product"
|
msgid "product"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:80
|
#: purchase/models.py:83
|
||||||
msgid "products"
|
msgid "products"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:155 purchase/models.py:183
|
#: purchase/models.py:158 purchase/models.py:186
|
||||||
msgid "basket"
|
msgid "basket"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:156
|
#: purchase/models.py:159
|
||||||
msgid "baskets"
|
msgid "baskets"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:159
|
#: purchase/models.py:162
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Basket #%(id)s"
|
msgid "Basket #%(id)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:185
|
#: purchase/models.py:188
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:190
|
#: purchase/models.py:193
|
||||||
msgid "basket item"
|
msgid "basket item"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/models.py:191
|
#: purchase/models.py:194
|
||||||
msgid "basket items"
|
msgid "basket items"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -163,6 +163,7 @@ msgstr ""
|
||||||
#: purchase/templates/purchase/reports.html:14
|
#: purchase/templates/purchase/reports.html:14
|
||||||
#: purchase/templates/purchase/snippets/report_payment_methods.html:8
|
#: purchase/templates/purchase/snippets/report_payment_methods.html:8
|
||||||
#: purchase/templates/purchase/snippets/report_products.html:8
|
#: purchase/templates/purchase/snippets/report_products.html:8
|
||||||
|
#: purchase/views/reports.py:80
|
||||||
msgid "Turnover"
|
msgid "Turnover"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -170,15 +171,15 @@ msgstr ""
|
||||||
msgid "Average basket"
|
msgid "Average basket"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/templates/purchase/reports.html:27
|
#: purchase/templates/purchase/reports.html:29
|
||||||
msgid "Products"
|
msgid "Products"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/templates/purchase/reports.html:30
|
#: purchase/templates/purchase/reports.html:34
|
||||||
msgid "Turnover by payment method"
|
msgid "Turnover by payment method"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/templates/purchase/reports.html:33
|
#: purchase/templates/purchase/reports.html:37
|
||||||
msgid "Baskets without payment method"
|
msgid "Baskets without payment method"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -203,6 +204,7 @@ msgid "Product"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: purchase/templates/purchase/snippets/report_products.html:7
|
#: purchase/templates/purchase/snippets/report_products.html:7
|
||||||
|
#: purchase/views/reports.py:64
|
||||||
msgid "# sold"
|
msgid "# sold"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -217,3 +219,11 @@ msgstr ""
|
||||||
#: purchase/views/basket.py:45
|
#: purchase/views/basket.py:45
|
||||||
msgid "Basket successfully deleted."
|
msgid "Basket successfully deleted."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: purchase/views/reports.py:112
|
||||||
|
msgid "Basket count by hour"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: purchase/views/reports.py:117
|
||||||
|
msgid "Turnover by hour"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -5,7 +5,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-26 18:17+0200\n"
|
"POT-Creation-Date: 2022-04-26 20:06+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -43,11 +43,11 @@ msgstr "créé à"
|
||||||
msgid "updated at"
|
msgid "updated at"
|
||||||
msgstr "mis à jour à"
|
msgstr "mis à jour à"
|
||||||
|
|
||||||
#: purchase/models.py:37 purchase/models.py:66
|
#: purchase/models.py:37 purchase/models.py:69
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "nom"
|
msgstr "nom"
|
||||||
|
|
||||||
#: purchase/models.py:42 purchase/models.py:149
|
#: purchase/models.py:42 purchase/models.py:152
|
||||||
msgid "payment method"
|
msgid "payment method"
|
||||||
msgstr "moyen de paiement"
|
msgstr "moyen de paiement"
|
||||||
|
|
||||||
|
@ -55,52 +55,52 @@ msgstr "moyen de paiement"
|
||||||
msgid "payment methods"
|
msgid "payment methods"
|
||||||
msgstr "moyens de paiement"
|
msgstr "moyens de paiement"
|
||||||
|
|
||||||
#: purchase/models.py:67
|
#: purchase/models.py:70
|
||||||
msgid "image"
|
msgid "image"
|
||||||
msgstr "image"
|
msgstr "image"
|
||||||
|
|
||||||
#: purchase/models.py:69
|
#: purchase/models.py:72
|
||||||
msgid "unit price (cents)"
|
msgid "unit price (cents)"
|
||||||
msgstr "prix unitaire (centimes)"
|
msgstr "prix unitaire (centimes)"
|
||||||
|
|
||||||
#: purchase/models.py:69
|
#: purchase/models.py:72
|
||||||
msgid "unit price in cents"
|
msgid "unit price in cents"
|
||||||
msgstr "prix unitaire en centimes"
|
msgstr "prix unitaire en centimes"
|
||||||
|
|
||||||
#: purchase/models.py:72
|
#: purchase/models.py:75
|
||||||
msgid "display order"
|
msgid "display order"
|
||||||
msgstr "ordre d'affichage"
|
msgstr "ordre d'affichage"
|
||||||
|
|
||||||
#: purchase/models.py:79 purchase/models.py:177
|
#: purchase/models.py:82 purchase/models.py:180
|
||||||
msgid "product"
|
msgid "product"
|
||||||
msgstr "produit"
|
msgstr "produit"
|
||||||
|
|
||||||
#: purchase/models.py:80
|
#: purchase/models.py:83
|
||||||
msgid "products"
|
msgid "products"
|
||||||
msgstr "produits"
|
msgstr "produits"
|
||||||
|
|
||||||
#: purchase/models.py:155 purchase/models.py:183
|
#: purchase/models.py:158 purchase/models.py:186
|
||||||
msgid "basket"
|
msgid "basket"
|
||||||
msgstr "panier"
|
msgstr "panier"
|
||||||
|
|
||||||
#: purchase/models.py:156
|
#: purchase/models.py:159
|
||||||
msgid "baskets"
|
msgid "baskets"
|
||||||
msgstr "paniers"
|
msgstr "paniers"
|
||||||
|
|
||||||
#: purchase/models.py:159
|
#: purchase/models.py:162
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Basket #%(id)s"
|
msgid "Basket #%(id)s"
|
||||||
msgstr "Panier n°%(id)s"
|
msgstr "Panier n°%(id)s"
|
||||||
|
|
||||||
#: purchase/models.py:185
|
#: purchase/models.py:188
|
||||||
msgid "quantity"
|
msgid "quantity"
|
||||||
msgstr "quantité"
|
msgstr "quantité"
|
||||||
|
|
||||||
#: purchase/models.py:190
|
#: purchase/models.py:193
|
||||||
msgid "basket item"
|
msgid "basket item"
|
||||||
msgstr "article de panier"
|
msgstr "article de panier"
|
||||||
|
|
||||||
#: purchase/models.py:191
|
#: purchase/models.py:194
|
||||||
msgid "basket items"
|
msgid "basket items"
|
||||||
msgstr "articles de panier"
|
msgstr "articles de panier"
|
||||||
|
|
||||||
|
@ -160,6 +160,7 @@ msgstr "Par jour"
|
||||||
#: purchase/templates/purchase/reports.html:14
|
#: purchase/templates/purchase/reports.html:14
|
||||||
#: purchase/templates/purchase/snippets/report_payment_methods.html:8
|
#: purchase/templates/purchase/snippets/report_payment_methods.html:8
|
||||||
#: purchase/templates/purchase/snippets/report_products.html:8
|
#: purchase/templates/purchase/snippets/report_products.html:8
|
||||||
|
#: purchase/views/reports.py:80
|
||||||
msgid "Turnover"
|
msgid "Turnover"
|
||||||
msgstr "Chiffre d'affaires"
|
msgstr "Chiffre d'affaires"
|
||||||
|
|
||||||
|
@ -167,15 +168,15 @@ msgstr "Chiffre d'affaires"
|
||||||
msgid "Average basket"
|
msgid "Average basket"
|
||||||
msgstr "Panier moyen"
|
msgstr "Panier moyen"
|
||||||
|
|
||||||
#: purchase/templates/purchase/reports.html:27
|
#: purchase/templates/purchase/reports.html:29
|
||||||
msgid "Products"
|
msgid "Products"
|
||||||
msgstr "Produits"
|
msgstr "Produits"
|
||||||
|
|
||||||
#: purchase/templates/purchase/reports.html:30
|
#: purchase/templates/purchase/reports.html:34
|
||||||
msgid "Turnover by payment method"
|
msgid "Turnover by payment method"
|
||||||
msgstr "Chiffre d'affaires par moyen de paiement"
|
msgstr "Chiffre d'affaires par moyen de paiement"
|
||||||
|
|
||||||
#: purchase/templates/purchase/reports.html:33
|
#: purchase/templates/purchase/reports.html:37
|
||||||
msgid "Baskets without payment method"
|
msgid "Baskets without payment method"
|
||||||
msgstr "Paniers sans moyen de paiement"
|
msgstr "Paniers sans moyen de paiement"
|
||||||
|
|
||||||
|
@ -200,6 +201,7 @@ msgid "Product"
|
||||||
msgstr "Produit"
|
msgstr "Produit"
|
||||||
|
|
||||||
#: purchase/templates/purchase/snippets/report_products.html:7
|
#: purchase/templates/purchase/snippets/report_products.html:7
|
||||||
|
#: purchase/views/reports.py:64
|
||||||
msgid "# sold"
|
msgid "# sold"
|
||||||
msgstr "Nb. vendus"
|
msgstr "Nb. vendus"
|
||||||
|
|
||||||
|
@ -215,6 +217,14 @@ msgstr "Panier correctement modifié."
|
||||||
msgid "Basket successfully deleted."
|
msgid "Basket successfully deleted."
|
||||||
msgstr "Panier correctement supprimé."
|
msgstr "Panier correctement supprimé."
|
||||||
|
|
||||||
|
#: purchase/views/reports.py:112
|
||||||
|
msgid "Basket count by hour"
|
||||||
|
msgstr "Nombre de paniers par heure"
|
||||||
|
|
||||||
|
#: purchase/views/reports.py:117
|
||||||
|
msgid "Turnover by hour"
|
||||||
|
msgstr "Chiffre d'affaires par heure"
|
||||||
|
|
||||||
#, python-format
|
#, python-format
|
||||||
#~ msgid "Total turnover: %(total|currency)s"
|
#~ msgid "Total turnover: %(total|currency)s"
|
||||||
#~ msgstr "Chiffre d'affaires total : %(total|currency)s"
|
#~ msgstr "Chiffre d'affaires total : %(total|currency)s"
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{{ by_hour_plot|safe }}
|
||||||
|
|
||||||
<h2>{% translate "Products" %}</h2>
|
<h2>{% translate "Products" %}</h2>
|
||||||
{% include "purchase/snippets/report_products.html" %}
|
{% include "purchase/snippets/report_products.html" %}
|
||||||
{{ products_sold_plot|safe }}
|
{{ products_sold_plot|safe }}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import datetime
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
@ -5,7 +6,13 @@ 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 purchase.models import Basket, PaymentMethod, Product, ProductQuerySet
|
from purchase.models import (
|
||||||
|
Basket,
|
||||||
|
BasketQuerySet,
|
||||||
|
PaymentMethod,
|
||||||
|
Product,
|
||||||
|
ProductQuerySet,
|
||||||
|
)
|
||||||
from purchase.views.utils import ProtectedViewsMixin
|
from purchase.views.utils import ProtectedViewsMixin
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +33,8 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
|
||||||
products = Product.objects.with_turnover().with_sold()
|
products = Product.objects.with_turnover().with_sold()
|
||||||
products_sold_plot = self.get_products_sold_plot(products)
|
products_sold_plot = self.get_products_sold_plot(products)
|
||||||
products_turnover_plot = self.get_products_turnover_plot(products)
|
products_turnover_plot = self.get_products_turnover_plot(products)
|
||||||
|
baskets = list(Basket.objects.priced().order_by("created_at"))
|
||||||
|
by_hour_plot = self.by_hour_plot(baskets)
|
||||||
context.update(
|
context.update(
|
||||||
{
|
{
|
||||||
"turnover": Basket.objects.turnover(),
|
"turnover": Basket.objects.turnover(),
|
||||||
|
@ -35,6 +44,7 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
|
||||||
"products": products,
|
"products": products,
|
||||||
"products_sold_plot": products_sold_plot,
|
"products_sold_plot": products_sold_plot,
|
||||||
"products_turnover_plot": products_turnover_plot,
|
"products_turnover_plot": products_turnover_plot,
|
||||||
|
"by_hour_plot": by_hour_plot,
|
||||||
"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(),
|
||||||
}
|
}
|
||||||
|
@ -71,3 +81,44 @@ class ReportsView(ProtectedViewsMixin, TemplateView):
|
||||||
fig.savefig(image_data, format="svg")
|
fig.savefig(image_data, format="svg")
|
||||||
image_data.seek(0)
|
image_data.seek(0)
|
||||||
return image_data.getvalue()
|
return image_data.getvalue()
|
||||||
|
|
||||||
|
def by_hour_plot(self, baskets):
|
||||||
|
current: datetime.datetime = baskets[0].created_at
|
||||||
|
current = current.replace(minute=0, second=0, microsecond=0)
|
||||||
|
end: datetime.datetime = baskets[-1].created_at
|
||||||
|
basket_index = 0
|
||||||
|
labels = []
|
||||||
|
counts = []
|
||||||
|
turnovers = []
|
||||||
|
while current < end:
|
||||||
|
end_slot = current + datetime.timedelta(hours=1)
|
||||||
|
basket = baskets[basket_index]
|
||||||
|
count = 0
|
||||||
|
turnover = 0
|
||||||
|
while basket.created_at < end_slot and basket_index < len(baskets) - 1:
|
||||||
|
count += 1
|
||||||
|
turnover += basket.price / 100
|
||||||
|
basket_index += 1
|
||||||
|
basket = baskets[basket_index]
|
||||||
|
labels.append(current)
|
||||||
|
counts.append(count)
|
||||||
|
turnovers.append(turnover)
|
||||||
|
current = end_slot
|
||||||
|
fig, ax1 = plt.subplots()
|
||||||
|
hours_in_day = 24
|
||||||
|
color = "tab:orange"
|
||||||
|
ax1.bar(labels, counts, width=1 / hours_in_day, color=color)
|
||||||
|
ax1.tick_params(axis="x", rotation=15)
|
||||||
|
ax1.set_ylabel(_("Basket count by hour"), color=color)
|
||||||
|
|
||||||
|
color = "tab:blue"
|
||||||
|
ax2 = ax1.twinx()
|
||||||
|
ax2.bar(labels, turnovers, width=1 / (hours_in_day * 2), color=color)
|
||||||
|
ax2.set_ylabel(_("Turnover by hour"), color=color)
|
||||||
|
plt.gca().yaxis.set_major_formatter(ticker.FormatStrFormatter("%.2f€"))
|
||||||
|
|
||||||
|
fig.tight_layout()
|
||||||
|
image_data = StringIO()
|
||||||
|
fig.savefig(image_data, format="svg")
|
||||||
|
image_data.seek(0)
|
||||||
|
return image_data.getvalue()
|
||||||
|
|
Loading…
Reference in a new issue