generate pdf list with weasyprint

This commit is contained in:
Laetitia Getti 2023-07-20 14:01:39 +02:00
parent a6267ab711
commit 7d1fd312f4
6 changed files with 80 additions and 78 deletions

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<title>
{{ name }} - Liste des commandes
{{ grouped_order.name }} - Liste des commandes
</title>
<style type="text/css">
@page {
@ -13,12 +13,10 @@
size: A4;
{% endif %}
margin: 2cm 1.5cm;
@frame footer {
-pdf-frame-content: footer;
bottom: 0cm;
height: 1.5cm;
right: 0cm;
width: 10cm;
@bottom-right{
font-size: 10pt;
font-family: sans-serif;
content: "Liste générée par la Chariotte - chariotte.fr | Page " counter(page)"/" counter(pages);
}
}
@ -27,33 +25,37 @@
font-size: 11pt;
}
.bold {
font-weight: bold;
}
table {
border: 1px black solid;
border-collapse: collapse;
width: 100%;
}
th, td {
vertical-align: center;
padding: 3px 2px 2px 2px;
line-height: 0.8em;
border: 1px black solid;
font-weight: normal;
text-align: center;
}
th {
text-align: center;
page-break-inside: avoid;
word-break: break-all;
word-wrap: break-word;
font-weight: bold;
}
h2 {
margin-top: -1em;
margin-bottom: 2em;
}
</style>
</head>
<body>
<h1 style="text-align: center">
{{ name }} - {{ delivery_date }}
</h1>
<h2 style="text-align: center">
{{ grouped_order.name }} - {{ grouped_order.delivery_date }}
</h2>
{% if items %}
<table>
<thead>
@ -69,12 +71,13 @@
</thead>
<tbody>
<tr style="background-color: #bababa">
<th style="text-align: left">Prix unitaire</th>
<td style="text-align: left">Prix unitaire</td>
{% for item in items %}
<th>
<td>
{{ item.price }} €
</th>
</td>
{% endfor %}
<td></td>
</tr>
<tr style="background-color: #bababa">
<th style="text-align: left">TOTAL</th>
@ -83,21 +86,21 @@
{{ item.ordered_nb }}
</th>
{% endfor %}
<th>{{ total_price }} €</th>
<th>{{ grouped_order.total_price }} €</th>
</tr>
{% for order, ordered_items in orders_dict.items %}
<tr>
<th>
<td>
{{ order.author }}
</th>
</td>
{% for ordered_item in ordered_items %}
<th>
<td>
{{ ordered_item }}
</th>
</td>
{% endfor %}
<th>
<td>
{{ order.price }} €
</th>
</td>
</tr>
{% endfor %}
</tbody>
@ -106,11 +109,5 @@
Aucun produit n'a été commandé
{% endif %}
<div id="footer">
Liste générée par la Chariotte - chariotte.fr | Page
<pdf:pagenumber />
/
<pdf:pagecount />
</div>
</body>
</html>

View file

@ -1445,7 +1445,7 @@ class TestItemCreateView:
class TestGroupedOrderSheetView:
def test_get__not_orga(self, client_log, other_user):
"""A user that is not organiszer of the GO accesses the sheet view.
"""A user that is not organizer of the GO accesses the sheet view.
They get a 403 error"""
grouped_order = create_grouped_order(
days_before_delivery_date=5,
@ -1497,17 +1497,18 @@ class TestGroupedOrderSheetView:
)
response = client_log.get(generate_sheet_url)
assert response.status_code == 200
assert response.context["name"] == "gr order test"
assert response.context["delivery_date"] == grouped_order.delivery_date
assert response.context["grouped_order"] == grouped_order
assert response.context["items"].count() == 0
assert len(response.context["orders_dict"]) == 0
# we order some items in the grouped order
order = order_items_in_grouped_order(grouped_order)
response = client_log.get(generate_sheet_url)
assert response.status_code == 200
assert response.context["name"] == "gr order test"
assert response.context["delivery_date"] == grouped_order.delivery_date
assert response.context["grouped_order"] == grouped_order
assert response.context["items"].count() == 2
assert response.context["orders_dict"][order] == [3, 2]
assert response.context["total_price"] == 24
assert response.context["grouped_order"].total_price == 24
class TestExportGroupedOrderEmailAddressesToCSVView:

View file

@ -52,7 +52,7 @@ urlpatterns = [
),
path(
"<int:pk>/gerer/imprimer",
views.GroupedOrderSheetView.as_view(),
views.DownloadGroupedOrderSheetView.as_view(),
name="grouped_order_sheet",
),
path(

View file

@ -1,5 +1,6 @@
# fmt: off
from .grouped_order import (ExportGroupedOrderEmailAddressesToCSVView,
from .grouped_order import (DownloadGroupedOrderSheetView,
ExportGroupedOrderEmailAddressesToCSVView,
GroupedOrderAddItemsView, GroupedOrderCreateView,
GroupedOrderDeleteView, GroupedOrderDetailView,
GroupedOrderDuplicateView, GroupedOrderOverview,

View file

@ -8,6 +8,8 @@ from django.template.loader import get_template
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.views import generic
from django_weasyprint import WeasyTemplateResponseMixin
from django_weasyprint.views import WeasyTemplateResponse, WeasyTemplateView
from xhtml2pdf import pisa
from ..forms import GroupedOrderForm, Item
@ -217,11 +219,21 @@ class GroupedOrderAddItemsView(UserPassesTestMixin, generic.ListView):
return GroupedOrder.objects.get(pk=grouped_order_id).orga == self.request.user
class GroupedOrderSheetMixin:
"""Mixin for grouped order info export (pdf sheet and csv)"""
class GroupedOrderSheetView(UserPassesTestMixin, generic.DetailView):
"""View for gathering information about the groupedorder, in order to download it
in the DownloadGroupedOrderSheetView"""
def get_grouped_order_infos(self, grouped_order_id):
grouped_order = get_object_or_404(GroupedOrder, id=grouped_order_id)
model = GroupedOrder
template_name = "order/grouped_order_sheet.html"
context_object_name = "grouped_order"
def test_func(self):
"""Accessible only if the requesting user is the grouped order organizer"""
return self.get_object().orga == self.request.user
def get_context_data(self, **kwargs):
context = super(GroupedOrderSheetView, self).get_context_data(**kwargs)
grouped_order = self.get_object()
# Get ordered items
items = grouped_order.item_set.filter(ordered_nb__gt=0).order_by("name")
@ -238,30 +250,19 @@ class GroupedOrderSheetMixin:
ordered_values.append(value)
orders_dict[order] = ordered_values # order as key of the dict
return {
"name": grouped_order.name,
"delivery_date": grouped_order.delivery_date,
"items": items,
"orders_dict": orders_dict,
"total_price": grouped_order.total_price,
}
context["items"] = items
context["orders_dict"] = orders_dict
return context
class GroupedOrderSheetView(GroupedOrderOverview, GroupedOrderSheetMixin):
"""View to get a pdf sheet summing up the grouped order for delivery"""
class DownloadGroupedOrderSheetView(WeasyTemplateResponseMixin, GroupedOrderSheetView):
"""View for downloading the grouped order sheet,
using django-weasyprint : https://pypi.org/project/django-weasyprint/"""
template_name = "order/grouped_order_sheet.html"
def get(self, request, pk):
grouped_order_sheet_info = self.get_grouped_order_infos(pk)
# should_include_prices = True if request.GET.get("with_prices", False) else False
# delivery_sheet_info["include_prices"] = should_include_prices - à ajouter plus tard
template = get_template(self.template_name)
html = template.render(grouped_order_sheet_info)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), result)
return http.HttpResponse(result.getvalue(), content_type="application/pdf")
def get_pdf_filename(self):
# filename for download
return f"{self.get_object().delivery_date} - {self.get_object().name}"
class ExportGroupedOrderEmailAddressesToCSVView(UserPassesTestMixin, generic.View):

View file

@ -100,5 +100,7 @@ webencodings==0.5.1
# cssselect2
# html5lib
# tinycss2
weasyprint==58.0 #django-weasyprint doesn't work with weasyprint 59.0
django-weasyprint==2.2.0
xhtml2pdf==0.2.11
# via la-chariotte (pyproject.toml)