csv export of a grouped order

This commit is contained in:
Laetitia Getti 2023-07-28 15:19:19 +02:00
parent 52b7804281
commit 25d0ef5604
5 changed files with 152 additions and 15 deletions

View file

@ -59,14 +59,14 @@
<li> <li>
<a id="partager-opener" class="tablinks" onclick="openTab('partager')"> <a id="partager-opener" class="tablinks" onclick="openTab('partager')">
<span class="is-hidden-desktop">Partager</span> <span class="is-hidden-desktop">Partager</span>
<span class="is-hidden-touch">Partager et imprimer</span> <span class="is-hidden-touch">Partager et exporter</span>
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<div id="partager" class="box tabcontent"> <div id="partager" class="box tabcontent">
<p class="title">Partager et imprimer</p> <p class="title">Partager et exporter</p>
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
{% if not grouped_order.is_to_be_delivered %} {% if not grouped_order.is_to_be_delivered %}
@ -87,9 +87,13 @@
{% endif %} {% endif %}
</div> </div>
<div class="column"> <div class="column">
<p>Pour vous aider à distribuer les produits le jour J, vous pouvez imprimer la liste des commandes :</p> <p>Pour vous aider à distribuer les produits le jour J, vous pouvez télécharger la liste des commandes
au format PDF pour l'<strong>imprimer</strong>, ou au format CSV pour l'<strong>afficher dans un tableur</strong> :</p>
<a class="button is-info" href="{% url 'order:grouped_order_sheet' grouped_order.id %}" target="_blank"> <a class="button is-info" href="{% url 'order:grouped_order_sheet' grouped_order.id %}" target="_blank">
<i class="fa fa-file mr-3" aria-hidden="true"></i>Liste des commandes <i class="fa fa-file-pdf-o mr-3" aria-hidden="true"></i>Commandes en PDF
</a>
<a class="button is-info" href="{% url 'order:grouped_order_csv_export' grouped_order.id %}" target="_blank">
<i class="fa fa-file-excel-o mr-3" aria-hidden="true"></i>Commandes en CSV
</a> </a>
</div> </div>
</div> </div>

View file

@ -1288,7 +1288,7 @@ class TestGroupedOrderSheetView:
class TestExportGroupedOrderEmailAddressesToCSVView: class TestExportGroupedOrderEmailAddressesToCSVView:
def test_user_not_logged_redirect(self, client, other_user): def test_user_not_logged_redirect(self, client, other_user):
""" """
A user that is not logged access the email list. They get redirected to the login view A user that is not logged accesses the email list. They get redirected to the login view
""" """
grouped_order = create_grouped_order( grouped_order = create_grouped_order(
days_before_delivery_date=5, days_before_delivery_date=5,
@ -1310,7 +1310,7 @@ class TestExportGroupedOrderEmailAddressesToCSVView:
def test_user_not_orga_forbidden(self, client_log, other_user): def test_user_not_orga_forbidden(self, client_log, other_user):
""" """
A user that is not orga cannot access the email list. A user that is not orga cannot accesses the email list.
They get a 403 forbidden error They get a 403 forbidden error
""" """
grouped_order = create_grouped_order( grouped_order = create_grouped_order(
@ -1328,9 +1328,9 @@ class TestExportGroupedOrderEmailAddressesToCSVView:
response = client_log.get(email_list_view_url) response = client_log.get(email_list_view_url)
assert response.status_code == 403 assert response.status_code == 403
def test_email_addresses(self, client_log, other_user): def test_email_addresses(self, client_log):
""" """
The grouped order orga accesses the email addresses list The grouped order orga accesseses the email addresses list
""" """
grouped_order = create_grouped_order( grouped_order = create_grouped_order(
days_before_delivery_date=5, days_before_delivery_date=5,
@ -1352,3 +1352,81 @@ class TestExportGroupedOrderEmailAddressesToCSVView:
response = client_log.get(email_list_view_url) response = client_log.get(email_list_view_url)
assert response.status_code == 200 assert response.status_code == 200
assert email in response.content.decode() assert email in response.content.decode()
class TestExportGroupedOrderToCSVView:
def test_user_not_logged_redirect(self, client, other_user):
"""
A user that is not logged accesses the csv view. They get redirected to the login view
"""
grouped_order = create_grouped_order(
days_before_delivery_date=5,
days_before_deadline=2,
name="gr order test",
orga_user=other_user,
)
csv_view_url = reverse(
"order:grouped_order_csv_export",
kwargs={
"pk": grouped_order.pk,
},
)
assert auth.get_user(client).is_anonymous
response = client.get(csv_view_url)
assert response.status_code == 302
assert response.url.startswith(reverse("accounts:login"))
assert response.url.endswith(csv_view_url)
def test_user_not_orga_forbidden(self, client_log, other_user):
"""
A user that is not orga cannot accesses the csv view.
They get a 403 forbidden error
"""
grouped_order = create_grouped_order(
days_before_delivery_date=5,
days_before_deadline=2,
name="gr order test",
orga_user=other_user,
)
csv_view_url = reverse(
"order:grouped_order_csv_export",
kwargs={
"pk": grouped_order.pk,
},
)
response = client_log.get(csv_view_url)
assert response.status_code == 403
def test_csv_export(self, client_log):
"""
The grouped order orga accesses the csv view
"""
grouped_order = create_grouped_order(
days_before_delivery_date=5,
days_before_deadline=2,
name="gr order test",
orga_user=auth.get_user(client_log),
)
order = order_items_in_grouped_order(grouped_order)
csv_view_url = reverse(
"order:grouped_order_csv_export",
kwargs={
"pk": grouped_order.pk,
},
)
response = client_log.get(csv_view_url)
assert response.status_code == 200
assert order.author.first_name in response.content.decode()
assert str(order.ordered_items.first().nb) in response.content.decode()
assert order.ordered_items.first().item.name in response.content.decode()
assert (
str(order.ordered_items.first().item.price).replace(".", ",")
in response.content.decode()
)
assert (
str(order.ordered_items.first().item.ordered_nb)
in response.content.decode()
)
assert order.author.email in response.content.decode()
assert order.author.phone in response.content.decode()

View file

@ -65,4 +65,9 @@ urlpatterns = [
views.ExportGroupedOrderEmailAddressesToCSVView.as_view(), views.ExportGroupedOrderEmailAddressesToCSVView.as_view(),
name="email_list", name="email_list",
), ),
path(
"<int:pk>/gerer/csv",
views.ExportGroupedOrderToCSVView.as_view(),
name="grouped_order_csv_export",
),
] ]

View file

@ -1,10 +1,11 @@
# fmt: off # fmt: off
from .grouped_order import (DownloadGroupedOrderSheetView, from .grouped_order import (DownloadGroupedOrderSheetView,
ExportGroupedOrderEmailAddressesToCSVView, ExportGroupedOrderEmailAddressesToCSVView,
ExportGroupedOrderToCSVView,
GroupedOrderAddItemsView, GroupedOrderCreateView, GroupedOrderAddItemsView, GroupedOrderCreateView,
GroupedOrderDeleteView, GroupedOrderDetailView, GroupedOrderDeleteView, GroupedOrderDetailView,
GroupedOrderDuplicateView, GroupedOrderOverview, GroupedOrderDuplicateView, GroupedOrderExportView,
GroupedOrderSheetView, GroupedOrderUpdateView, GroupedOrderOverview, GroupedOrderUpdateView,
IndexView) IndexView)
from .item import ItemCreateView, ItemDeleteView from .item import ItemCreateView, ItemDeleteView
from .order import OrderDeleteView, OrderDetailView, place_order from .order import OrderDeleteView, OrderDetailView, place_order

View file

@ -229,7 +229,7 @@ class GroupedOrderAddItemsView(UserPassesTestMixin, generic.ListView):
return GroupedOrder.objects.get(pk=grouped_order_id).orga == self.request.user return GroupedOrder.objects.get(pk=grouped_order_id).orga == self.request.user
class GroupedOrderSheetView(UserPassesTestMixin, generic.DetailView): class GroupedOrderExportView(UserPassesTestMixin, generic.DetailView):
"""View for gathering information about the groupedorder, in order to download it """View for gathering information about the groupedorder, in order to download it
in the DownloadGroupedOrderSheetView""" in the DownloadGroupedOrderSheetView"""
@ -242,7 +242,7 @@ class GroupedOrderSheetView(UserPassesTestMixin, generic.DetailView):
return self.get_object().orga == self.request.user return self.get_object().orga == self.request.user
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(GroupedOrderSheetView, self).get_context_data(**kwargs) context = super(GroupedOrderExportView, self).get_context_data(**kwargs)
grouped_order = self.get_object() grouped_order = self.get_object()
# Get ordered items # Get ordered items
@ -268,7 +268,7 @@ class GroupedOrderSheetView(UserPassesTestMixin, generic.DetailView):
return context return context
class DownloadGroupedOrderSheetView(WeasyTemplateResponseMixin, GroupedOrderSheetView): class DownloadGroupedOrderSheetView(WeasyTemplateResponseMixin, GroupedOrderExportView):
"""View for downloading the grouped order sheet, """View for downloading the grouped order sheet,
using django-weasyprint : https://pypi.org/project/django-weasyprint/""" using django-weasyprint : https://pypi.org/project/django-weasyprint/"""
@ -278,8 +278,7 @@ class DownloadGroupedOrderSheetView(WeasyTemplateResponseMixin, GroupedOrderShee
class ExportGroupedOrderEmailAddressesToCSVView(UserPassesTestMixin, generic.View): class ExportGroupedOrderEmailAddressesToCSVView(UserPassesTestMixin, generic.View):
# grouped_order_id = self.kwargs.get("grouped_order_id") """Export all participant email addresses in a csv line"""
# grouped_order = get_object_or_404(GroupedOrder, pk=grouped_order_id)
def test_func(self): def test_func(self):
"""Accessible only if the requesting user is the grouped order organizer""" """Accessible only if the requesting user is the grouped order organizer"""
@ -303,3 +302,53 @@ class ExportGroupedOrderEmailAddressesToCSVView(UserPassesTestMixin, generic.Vie
row = [participant.email for participant in participants] row = [participant.email for participant in participants]
writer.writerow(row) writer.writerow(row)
return response return response
class ExportGroupedOrderToCSVView(GroupedOrderExportView):
"""Export a csv with the same info as in pdf sheet"""
def get(self, request, *args, **kwargs):
super(ExportGroupedOrderToCSVView, self).get(self, request, *args, **kwargs)
context = self.get_context_data()
response = http.HttpResponse(
content_type="text/csv",
headers={
"Content-Disposition": f'attachment; filename="{ context["object"].name }-commandes"'
},
)
writer = csv.writer(response)
# write headers rows
row = [""]
for item in context["items"]:
row.append(item.name)
row.append("Prix de la commande")
row.append("Mail")
row.append("Téléphone")
writer.writerow(row)
row = ["Prix unitaire (€)"]
for item in context["items"]:
row.append(str(item.price).replace(".", ","))
writer.writerow(row)
# write ordered values rows
for order, ordered_items in context["orders_dict"].items():
row = [order.author]
for ordered_nb in ordered_items:
row.append(ordered_nb)
row.append(str(order.price).replace(".", ","))
row.append(order.author.email)
row.append(f"'{order.author.phone}")
writer.writerow(row)
# write total row
row = ["TOTAL"]
for item in context["items"]:
row.append(item.ordered_nb)
row.append(str(context["object"].total_price).replace(".", ","))
writer.writerow(row)
return response