mirror of
https://github.com/almet/copanier.git
synced 2025-04-28 11:32:38 +02:00
parent
9af506ba4b
commit
befb5fd1de
16 changed files with 249 additions and 115 deletions
|
@ -11,22 +11,48 @@ from roll.extensions import traceback, simple_server, static
|
|||
from slugify import slugify
|
||||
|
||||
from debts.solver import order_balance, check_balance, reduce_balance
|
||||
from weasyprint import HTML
|
||||
|
||||
from . import config, reports, session, utils, emails, loggers, imports
|
||||
from .models import Delivery, Order, Person, Product, ProductOrder, Groups, Group
|
||||
|
||||
|
||||
class Response(RollResponse):
|
||||
def html(self, template_name, *args, **kwargs):
|
||||
self.headers["Content-Type"] = "text/html; charset=utf-8"
|
||||
def render_template(self, template_name, *args, **kwargs):
|
||||
context = app.context()
|
||||
context.update(kwargs)
|
||||
context["request"] = self.request
|
||||
context["config"] = config
|
||||
context["request"] = self.request
|
||||
if self.request.cookies.get("message"):
|
||||
context["message"] = json.loads(self.request.cookies["message"])
|
||||
self.cookies.set("message", "")
|
||||
context["config"] = config
|
||||
self.body = env.get_template(template_name).render(*args, **context)
|
||||
return env.get_template(template_name).render(*args, **context)
|
||||
|
||||
def html(self, template_name, *args, **kwargs):
|
||||
self.headers["Content-Type"] = "text/html; charset=utf-8"
|
||||
self.body = self.render_template(template_name, *args, **kwargs)
|
||||
|
||||
def render_pdf(self, template_name, *args, **kwargs):
|
||||
html = self.render_template(template_name, *args, **kwargs)
|
||||
|
||||
static_folder = Path(__file__).parent / "static"
|
||||
stylesheets = [
|
||||
static_folder / "app.css",
|
||||
static_folder / "icomoon.css",
|
||||
static_folder / "page.css",
|
||||
]
|
||||
if "css" in kwargs:
|
||||
stylesheets.append(static_folder / kwargs["css"])
|
||||
|
||||
return HTML(string=html).write_pdf(stylesheets=stylesheets)
|
||||
|
||||
def pdf(self, template_name, *args, **kwargs):
|
||||
self.body = self.render_pdf(template_name, *args, **kwargs)
|
||||
mimetype = "application/pdf"
|
||||
filename = kwargs.get("filename", "file.pdf")
|
||||
self.headers["Content-Disposition"] = f'attachment; filename="{filename}"'
|
||||
self.headers["Content-Type"] = f"{mimetype}; charset=utf-8"
|
||||
|
||||
def xlsx(self, body, filename=f"{config.SITE_NAME}.xlsx"):
|
||||
self.body = body
|
||||
|
@ -228,9 +254,7 @@ async def create_group(request, response):
|
|||
members.append(request["user"].email)
|
||||
|
||||
group = Group.create(
|
||||
id=slugify(form.get("name")),
|
||||
name=form.get("name"),
|
||||
members=members,
|
||||
id=slugify(form.get("name")), name=form.get("name"), members=members
|
||||
)
|
||||
request["groups"].add_group(group)
|
||||
request["groups"].persist()
|
||||
|
@ -340,15 +364,31 @@ async def import_products(request, response, id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/producteurices")
|
||||
@app.route("/livraison/{id}/producteurices.pdf")
|
||||
async def list_producers(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.html(
|
||||
"list_products.html",
|
||||
{
|
||||
template_name = "list_products.html"
|
||||
template_params = {
|
||||
"edit_mode": True,
|
||||
"list_only": True,
|
||||
"delivery": delivery,
|
||||
"referent": request.query.get("referent", None),
|
||||
},
|
||||
},
|
||||
|
||||
if request.url.endswith(b".pdf"):
|
||||
response.pdf(template_name, template_params, filename=utils.prefix("producteurices.pdf", delivery),)
|
||||
else:
|
||||
response.html(template_name, template_params)
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/{producer}/bon-de-commande.pdf", methods=["GET"])
|
||||
async def pdf_for_producer(request, response, id, producer):
|
||||
delivery = Delivery.load(id)
|
||||
date = delivery.to_date.strftime("%Y-%m-%d")
|
||||
response.pdf(
|
||||
"list_products.html",
|
||||
{"list_only": True, "delivery": delivery, "producers": [producer]},
|
||||
filename=utils.prefix(f"bon-de-commande-{producer}.pdf", delivery),
|
||||
)
|
||||
|
||||
|
||||
|
@ -432,10 +472,10 @@ async def create_product(request, response, delivery_id, producer_id):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/gérer", methods=["GET"])
|
||||
async def manage_delivery(request, response, id):
|
||||
async def delivery_toolbox(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.html(
|
||||
"manage_delivery.html",
|
||||
"delivery_toolbox.html",
|
||||
{
|
||||
"delivery": delivery,
|
||||
"referents": [p.referent for p in delivery.producers.values()],
|
||||
|
@ -446,56 +486,47 @@ async def manage_delivery(request, response, id):
|
|||
@app.route("/livraison/{id}/envoi-email-referentes", methods=["GET", "POST"])
|
||||
async def send_referent_emails(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
date = delivery.to_date.strftime("%Y-%m-%d")
|
||||
if request.method == "POST":
|
||||
email_body = request.form.get("email_body")
|
||||
email_subject = request.form.get("email_subject")
|
||||
sent_mails = 0
|
||||
for referent in delivery.get_referents():
|
||||
producers = delivery.get_producers_for_referent(referent)
|
||||
if any(
|
||||
[delivery.producers[p].has_active_products(delivery) for p in producers]
|
||||
):
|
||||
summary = reports.summary(delivery, producers)
|
||||
attachments = []
|
||||
for producer in producers:
|
||||
if delivery.producers[producer].has_active_products(delivery):
|
||||
pdf_file = response.render_pdf(
|
||||
"list_products.html",
|
||||
{
|
||||
"list_only": True,
|
||||
"delivery": delivery,
|
||||
"producers": [producer],
|
||||
},
|
||||
)
|
||||
|
||||
attachments.append(
|
||||
(
|
||||
utils.prefix(f"{producer}.pdf", delivery),
|
||||
pdf_file,
|
||||
"application/pdf",
|
||||
)
|
||||
)
|
||||
|
||||
if attachments:
|
||||
sent_mails = sent_mails + 1
|
||||
emails.send(
|
||||
referent,
|
||||
email_subject,
|
||||
email_body,
|
||||
copy=delivery.contact,
|
||||
attachments=[
|
||||
(f"{config.SITE_NAME}-{date}-{referent}.xlsx", summary)
|
||||
],
|
||||
attachments=attachments,
|
||||
)
|
||||
response.message("Le mail à bien été envoyé")
|
||||
response.message(f"Un mail à été envoyé aux {sent_mails} référent⋅e⋅s")
|
||||
response.redirect = f"/livraison/{id}/gérer"
|
||||
|
||||
response.html("prepare_referent_email.html", {"delivery": delivery})
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/bon-de-commande-referent⋅e", methods=["GET"])
|
||||
async def download_referent_summary(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
date = delivery.to_date.strftime("%Y-%m-%d")
|
||||
if not request["user"].is_referent(delivery):
|
||||
return
|
||||
referent = request["user"].email
|
||||
producers = delivery.get_producers_for_referent(referent)
|
||||
summary = reports.summary(delivery, producers)
|
||||
response.xlsx(summary, filename=f"{config.SITE_NAME}-{date}-{referent}.xlsx")
|
||||
|
||||
|
||||
@app.route(
|
||||
"/livraison/{id}/product⋅eur⋅rice/{producer}/bon-de-commande",
|
||||
methods=["GET"],
|
||||
)
|
||||
async def download_producer_report(request, response, id, producer):
|
||||
delivery = Delivery.load(id)
|
||||
summary = reports.summary(delivery, [producer])
|
||||
date = delivery.to_date.strftime("%Y-%m-%d")
|
||||
response.xlsx(
|
||||
summary, filename=f"{config.SITE_NAME}-{date}-{producer}-bon-de-commande.xlsx"
|
||||
)
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/exporter", methods=["GET"])
|
||||
async def export_products(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
|
@ -636,7 +667,12 @@ async def send_order(request, response, id):
|
|||
@app.route("/livraison/{id}/émargement", methods=["GET"])
|
||||
async def signing_sheet(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
response.html("signing_sheet.html", {"delivery": delivery})
|
||||
response.pdf(
|
||||
"signing_sheet.html",
|
||||
{"delivery": delivery},
|
||||
css="signing-sheet.css",
|
||||
filename=utils.prefix("commandes-par-groupe.pdf", delivery),
|
||||
)
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/importer/commande", methods=["POST"])
|
||||
|
@ -730,6 +766,7 @@ async def adjust_product(request, response, id, ref):
|
|||
|
||||
|
||||
@app.route("/livraison/{id}/solde", methods=["GET"])
|
||||
@app.route("/livraison/{id}/solde.pdf", methods=["GET"])
|
||||
@staff_only
|
||||
async def delivery_balance(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
|
@ -770,17 +807,25 @@ async def delivery_balance(request, response, id):
|
|||
for debiter, amount, crediter in results:
|
||||
results_dict[debiter][crediter] = amount
|
||||
|
||||
response.html(
|
||||
"delivery_balance.html",
|
||||
{
|
||||
"delivery": delivery,
|
||||
"debiters": debiters,
|
||||
"crediters": crediters,
|
||||
"results": results_dict,
|
||||
"debiters_groups": groups.groups,
|
||||
"crediters_groups": producer_groups,
|
||||
},
|
||||
)
|
||||
template_name = "delivery_balance.html"
|
||||
template_args = {
|
||||
"delivery": delivery,
|
||||
"debiters": debiters,
|
||||
"crediters": crediters,
|
||||
"results": results_dict,
|
||||
"debiters_groups": groups.groups,
|
||||
"crediters_groups": producer_groups,
|
||||
}
|
||||
|
||||
if request.url.endswith(b".pdf"):
|
||||
date = delivery.to_date.strftime("%Y-%m-%d")
|
||||
response.pdf(
|
||||
template_name,
|
||||
template_args,
|
||||
filename=utils.prefix("répartition-des-chèques.pdf", delivery),
|
||||
)
|
||||
else:
|
||||
response.html(template_name, template_args)
|
||||
|
||||
|
||||
@app.route("/livraison/{id}/solde.xlsx", methods=["GET"])
|
||||
|
|
|
@ -11,13 +11,10 @@ def send(to, subject, body, html=None, copy=None, attachments=None):
|
|||
text=body, html=html, subject=subject, mail_from=config.FROM_EMAIL
|
||||
)
|
||||
|
||||
for filename, attachment in attachments:
|
||||
message.attach(
|
||||
filename=filename,
|
||||
data=attachment,
|
||||
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8",
|
||||
)
|
||||
for filename, attachment, mime in attachments:
|
||||
message.attach(filename=filename, data=attachment, mime=f"{mime} charset=utf-8")
|
||||
|
||||
config.SEND_EMAILS = False
|
||||
if not config.SEND_EMAILS:
|
||||
body = body.replace("https", "http")
|
||||
return print("Sending email", str(body))
|
||||
|
|
|
@ -597,4 +597,57 @@ table.paiements td {
|
|||
}
|
||||
table.paiements tr:hover td {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 600px;
|
||||
margin: 100px auto;
|
||||
}
|
||||
.progressbar {
|
||||
counter-reset: step;
|
||||
}
|
||||
.progressbar li {
|
||||
list-style-type: none;
|
||||
width: 20%;
|
||||
float: left;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
color: #7d7d7d;
|
||||
}
|
||||
.progressbar li:before {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
content: counter(step);
|
||||
counter-increment: step;
|
||||
line-height: 25px;
|
||||
border: 2px solid #7d7d7d;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin: 0 auto 10px auto;
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
}
|
||||
.progressbar li:after {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: #7d7d7d;
|
||||
top: 15px;
|
||||
left: -50%;
|
||||
z-index: -1;
|
||||
}
|
||||
.progressbar li:first-child:after {
|
||||
content: none;
|
||||
}
|
||||
.progressbar li.active {
|
||||
color: green;
|
||||
}
|
||||
.progressbar li.active:before {
|
||||
border-color: #55b776;
|
||||
}
|
||||
.progressbar li.active + li:after {
|
||||
background-color: #55b776;
|
||||
}
|
28
copanier/static/page.css
Normal file
28
copanier/static/page.css
Normal file
|
@ -0,0 +1,28 @@
|
|||
@page {
|
||||
size: "A4";
|
||||
margin: 0cm;
|
||||
size: landscape;
|
||||
}
|
||||
|
||||
#download {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media print {
|
||||
nav, .notification, .toolbox, .edit, .hide-on-print, .button{
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul.delivery-head {
|
||||
display: block !important;
|
||||
}
|
||||
ul.delivery-head li {
|
||||
margin-bottom: 1.5em !important;
|
||||
}
|
||||
table.delivery {
|
||||
page-break-after: always;
|
||||
}
|
||||
.page-break {
|
||||
page-break-after: always;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
table, tr, td {
|
||||
border: 0px;
|
||||
}
|
||||
tr:nth-child(even) {background: #CCC}
|
||||
tr:nth-child(odd) {background: #FFF}
|
||||
@page {
|
||||
size: portrait !important;
|
||||
}
|
|
@ -18,12 +18,11 @@
|
|||
{% endif %}
|
||||
<section class="menu">
|
||||
<h1><a href="/">{{ config.SITE_NAME }}</a> <small>{{ config.SITE_DESCRIPTION }}</small></h1>
|
||||
{% block title %}<h2>{% if delivery %}{{ delivery.name }}{% endif %}{% block actions %}{% endblock %}{% endblock %}</h2>
|
||||
|
||||
<nav>
|
||||
{% if request.user %}
|
||||
{% if request.user.is_staff %}
|
||||
<a class="button" href="/livraison"><i class="icon-hotairballoon"></i> Nouvelle livraison</a>
|
||||
{% endif %}
|
||||
<i class="icon-lock"></i> <span>{{ request["user"].email }} {% if request["user"].group_name %}({{ request["user"].group_name }}){% endif %}</span>
|
||||
<i class="icon-lock"></i> <span>{{ request["user"].email }} {% if request["user"].group_name %}({{ request["user"].group_name }}){% endif %} <a href="/déconnexion">déconnexion</a></span>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</section>
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block actions %}
|
||||
{% include "includes/order_button.html" %}
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<h3>{{ delivery.name }} {% include "includes/order_button.html" %}</h3>
|
||||
{% include "includes/delivery_head.html" %}
|
||||
|
||||
{% if request['user'].email == delivery.contact %}
|
||||
<div class="notification info"><i class="icon-lightbulb"></i> Vous êtes la personne référente de cette distribution <a class="button" href="/livraison/{{ delivery.id }}/gérer">Voir la boîte à outils</a></div>
|
||||
{% elif request['user'].email in delivery.get_referents() %}
|
||||
<div class="notification info"><i class="icon-lightbulb"></i> Vous êtes référent⋅e pour cette distribution (merci !). <a class="button" href="/livraison/{{ delivery.id }}/producteurices?referent={{request['user'].email}}">Gérer les produits dont vous vous occupez</a></div>
|
||||
{% endif %}
|
||||
<ul class="progressbar">
|
||||
<li {% if delivery.status == delivery.OPEN %}class="active"{% endif %}>Mise à jour des prix</li>
|
||||
<li {% if delivery.status == delivery.OPEN %}class="active"{% endif %}>Ouverture des commandes</li>
|
||||
<li {% if delivery.status == delivery.ADJUSTMENT %}class="active"{% endif %}>Ajustements</li>
|
||||
<li {% if delivery.can_generate_reports %}class="active"{% endif %}>Achats par les référent⋅e⋅s</li>
|
||||
<li>Distribution</li>
|
||||
</ul>
|
||||
<article class="delivery">
|
||||
{% if delivery.has_products %}
|
||||
{% include "includes/delivery_table.html" %}
|
||||
|
@ -22,7 +32,7 @@
|
|||
<ul class="toolbox">
|
||||
{% if not delivery.is_archived and delivery.status == delivery.CLOSED %}
|
||||
<li>
|
||||
<a href="/livraison/{{ delivery.id }}/bon-de-commande.xlsx"><i class="icon-ribbon"></i> Bon de commande</a>
|
||||
<a href="/livraison/{{ delivery.iddelivery }}/bon-de-commande.xlsx"><i class="icon-ribbon"></i> Bon de commande</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/livraison/{{ delivery.id }}/rapport-complet.xlsx"><i class="icon-grid"></i> Rapport complet</a>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}<h1><i class="icon-wallet"></i> Répartition des paiements <a id="download" class="button" href="/livraison/{{ delivery.id }}/solde.pdf">Télécharger</a></h1>{% endblock %}
|
||||
{% block body %}
|
||||
<h1><i class="icon-wallet"></i> <a href="/livraison/{{ delivery.id }}">{{ delivery.name }}</a><br />Répartition des paiements</h1>
|
||||
<p class="info">{{ delivery.name }} du {{ delivery.to_date | date }}.</p>
|
||||
<p class="info">Les personnes indiquées avec un <code>*</code> à côté de leur nom sont celles qui ont payé cette commande pour leur groupe.</p>
|
||||
<table class="paiements">
|
||||
<tr>
|
||||
|
|
|
@ -16,13 +16,12 @@
|
|||
<a class="button" href="/groupes"><i class="icon-globe"></i> Gérer les groupes / colocs</a>
|
||||
|
||||
<h3>Une fois les commandes passées (après le {{ delivery.order_before|date }})</h3>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/bon-de-commande.xlsx"><i class="icon-download"></i> Télécharger le bon de commande global</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/rapport-complet.xlsx"><i class="icon-download"></i> Télécharger le récap (global) des commandes</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/producteurices.pdf"><i class="icon-download"></i> Télécharger les bons de livraison</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/rapport-complet.xlsx"><i class="icon-download"></i> Télécharger le tableau des commandes</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/envoi-email-referentes"><i class="icon-envelope"></i> Envoyer les infos de commande aux référent⋅e⋅s</a>
|
||||
|
||||
<h3>Pour préparer la distribution (le {{ delivery.from_date|date }})</h3>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/émargement"><i class="icon-document"></i> Fiches de commandes par groupe</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/rapport-complet.xlsx"><i class="icon-grid"></i> Télécharger le résumé général des commandes</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/solde"><i class="icon-gears"></i> Faire la répartition des paiements</a>
|
||||
|
||||
{% endblock %}
|
|
@ -1,6 +1,5 @@
|
|||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
<h2>Livraisons à venir</h2>
|
||||
{% with deliveries=incoming %}
|
||||
{% include "includes/delivery_list.html" %}
|
||||
{% endwith %}
|
||||
|
@ -15,6 +14,11 @@
|
|||
<hr>
|
||||
{% endif %}
|
||||
<ul class="toolbox">
|
||||
{% if request.user.is_staff %}
|
||||
<li>
|
||||
<a class="button" href="/livraison"><i class="icon-hotairballoon"></i> Nouvelle livraison</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="/groupes" class="button"><i class="icon-globe"></i> Gérer les groupes / colocs</a>
|
||||
</li>
|
||||
|
|
|
@ -4,11 +4,10 @@
|
|||
{% if display_counts %}
|
||||
<li><i class="icon-lightbulb"></i> <strong>{{ delivery.orders|length }}</strong> colocs</strong>, <strong>{{ delivery.products|length }}</strong> produits et <strong>{{ delivery.producers | length}}</strong> product⋅eurs⋅rices, <strong>{{ delivery.total }}€</strong></li>
|
||||
{% else %}
|
||||
<li><i class="icon-strategy"></i> <strong>Référent⋅e</strong> <a href="mailto:{{ delivery.contact }}">{{ delivery.contact }}</a></li>
|
||||
<li class="hide-on-print"><i class="icon-strategy"></i> <strong>Référent⋅e</strong> <a href="mailto:{{ delivery.contact }}">{{ delivery.contact }}</a></li>
|
||||
{% endif %}
|
||||
<li><i class="icon-clock"></i> <strong>Date de livraison</strong> <time datetime="{{ delivery.from_date }}">{{ delivery.from_date|date|capitalize }} de {{ delivery.from_date|time }} à {{ delivery.to_date|time }}</time></li>
|
||||
<li><i class="icon-hourglass"></i> {% if delivery.status == delivery.OPEN %}<strong>Date limite de commande</strong> <time datetime="{{ delivery.order_before.date() }}">{{ delivery.order_before|date|capitalize }}</time>{% elif delivery.status == delivery.ADJUSTMENT %}<strong>Ajustement en cours</strong>{% elif delivery.status == delivery.CLOSED %}<strong>Fermée</strong>{% else %}<strong>Archivée</strong>{% endif %}</li>
|
||||
<li class="hide-on-print"><i class="icon-hourglass"></i> {% if delivery.status == delivery.OPEN %}<strong>Date limite de commande</strong> <time datetime="{{ delivery.order_before.date() }}">{{ delivery.order_before|date|capitalize }}</time>{% elif delivery.status == delivery.ADJUSTMENT %}<strong>Ajustement en cours</strong>{% elif delivery.status == delivery.CLOSED %}<strong>Fermée</strong>{% else %}<strong>Archivée</strong>{% endif %}</li>
|
||||
{% if delivery.instructions %}<li><i class="icon-lightbulb"></i> <strong>À savoir</strong> {{ delivery.instructions }}</li>{% endif %}
|
||||
{% if delivery.infos_url %}<li><i class="icon-global"></i><strong>Plus d'infos</strong> <a href="{{ delivery.infos_url }}" title="{{ delivery.infos_url }}">{{ delivery.infos_url|truncate(20)}}</a></li>{% endif %}
|
||||
|
||||
</ul>
|
||||
</ul>
|
|
@ -1,19 +1,22 @@
|
|||
{% if referent %}
|
||||
{% set producers = delivery.get_producers_for_referent(referent) %}
|
||||
{% else %}
|
||||
{% set producers = delivery.producers %}
|
||||
{% if not producers and referent %}
|
||||
{% set producers = delivery.get_producers_for_referent(referent) %}
|
||||
{% elif not producers %}
|
||||
{% set producers = delivery.producers %}
|
||||
{% endif %}
|
||||
{% for producer in producers %}
|
||||
{% set producer_obj = delivery.producers[producer] %}
|
||||
<h2>{{ producer }}
|
||||
{% if edit_mode or request.user.is_staff or delivery.producers[producer].referent == request.user.email %}
|
||||
{% if edit_mode or request.user.is_staff or producer_obj.referent == request.user.email %}
|
||||
<span class="edit">
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/{{ producer }}/éditer"><i class="icon-ribbon"></i> Éditer</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/{{ producer }}/ajouter-produit"><i class="icon-puzzle"></i> Ajouter un produit </a>
|
||||
{% if delivery.can_generate_reports %}
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/{{ producer }}/bon-de-commande"><i class="icon-grid"></i> Télécharger le bon de commande</a>
|
||||
<a class="button" href="/livraison/{{ delivery.id }}/{{ producer }}/bon-de-commande.pdf"><i class="icon-grid"></i> Télécharger le bon de commande</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<h5>{% if delivery.producers[producer].description %}{{ delivery.producers[producer].description }}{% endif %}. Référent⋅e : {{ delivery.producers[producer].referent }} / {{ delivery.producers[producer].referent_tel }}</h5>
|
||||
<h5>{% if producer_obj.description %}{{ producer_obj.description }}{% endif %}. Référent⋅e : <a href="mailto:{{ producer_obj.referent }}">{{ producer_obj.referent_name }}</a> / {{ producer_obj.referent_tel }}</h5>
|
||||
<table class="delivery">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -23,8 +26,8 @@
|
|||
<th class="packing">Conditionnement</th>
|
||||
{% endif %}
|
||||
{% if edit_mode %}<th>Éditer</th>{% endif %}
|
||||
{% if not list_only %}
|
||||
<th class="amount">Total</th>
|
||||
{% if not list_only %}
|
||||
{% for orderer, order in delivery.orders.items() %}
|
||||
{% set orderer_name = request.groups.groups[orderer].name %}
|
||||
<th class="person{% if delivery.is_passed and not order.paid %} not-paid{% endif %}">
|
||||
|
@ -47,20 +50,19 @@
|
|||
<td class="packing">{% if product.packing %}{{ product.packing }} x {% endif %} {{ product.unit }}</td>
|
||||
{% endif %}
|
||||
{% if edit_mode %}<td><a href="/livraison/{{ delivery.id }}/{{ product.producer }}/{{ product.ref }}/éditer">modifier</a></td>{% endif %}
|
||||
{% if not list_only %}
|
||||
<th{% if delivery.status == delivery.ADJUSTMENT and delivery.product_missing(product) %} class="missing" title="Les commandes individuelles ne correspondent pas aux conditionnements"{% endif %}>
|
||||
{{ delivery.product_wanted(product) }}
|
||||
{% if delivery.status == delivery.ADJUSTMENT and delivery.product_missing(product) %} (−{{ delivery.product_missing(product) }})
|
||||
{% if request.user.is_staff %}<a href="/livraison/{{ delivery.id }}/ajuster/{{ product.ref }}" class="button" title="ajuster le produit">ajuster</a>{% endif %}
|
||||
{% endif %}
|
||||
</th>
|
||||
{% if not list_only %}
|
||||
{% for email, order in delivery.orders.items() %}
|
||||
<td title="Commandé: {{ order[product.ref].wanted }} — Ajusté: {{ "%+d"|format(order[product.ref].adjustment) }}">{{ order[product.ref].quantity or "—" }}</td>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not list_only %}
|
||||
<tr>
|
||||
<th class="total"><i class="icon-pricetags"></i> Total</th><td>—</td>
|
||||
{% if delivery.has_packing %}
|
||||
|
@ -70,11 +72,12 @@
|
|||
<td>—</td>
|
||||
{% endif %}
|
||||
<th class="total">{{ delivery.total_for_producer(producer) }} €</th>
|
||||
{% for email, order in delivery.orders.items() %}
|
||||
<td>{{ order.total(delivery.get_products_by(producer)) }} €</td>
|
||||
{% endfor %}
|
||||
{% if not list_only %}
|
||||
{% for email, order in delivery.orders.items() %}
|
||||
<td>{{ order.total(delivery.get_products_by(producer)) }} €</td>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endfor %}
|
|
@ -1,8 +1,9 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block body %}
|
||||
<h3>{{ delivery.name }}</h3>
|
||||
{% if referent %}<p>Voici la liste des product⋅eurs⋅rices dont {{ referent }} est référent⋅e. <a class="button" href="/livraison/{{delivery.id}}/producteurices">voir tous les produits</a></p>{% endif %}
|
||||
<p class="hide-on-print">
|
||||
<a href="/livraison/{{ delivery.id }}/producteurices.pdf{% if referent %}?referent={{ referent }}{% endif %}">Télécharger la liste des commandes en PDF</a>
|
||||
{% if referent %}Voici la liste des product⋅eurs⋅rices dont {{ referent }} est référent⋅e. <a class="button" href="/livraison/{{delivery.id}}/producteurices">voir tous les produits</a>{% endif %}
|
||||
</p>
|
||||
<article class="delivery">
|
||||
{% include "includes/delivery_table.html" %}
|
||||
</article>
|
||||
|
|
|
@ -12,7 +12,7 @@ Bonjour,
|
|||
Et voilà, les commandes maintenant terminées, il est maintenant temps de passer à l'action !
|
||||
En pièce-jointe, les informations pour les producteurs⋅rices dont tu est référent⋅e.
|
||||
|
||||
Tu peux aussi retrouver le doc à cette URL : https://{{ request.host }}/livraison/{{ delivery.id }}/bon-de-commande-referent⋅e
|
||||
Tu peux aussi retrouver le doc à cette URL : https://{{ request.host }}/livraison/{{ delivery.id }}/producteurices
|
||||
|
||||
Rendez-vous pour la distribution, le {{ delivery.from_date|date }} de {{ delivery.from_date|time }} à {{ delivery.to_date|time }} à {{ delivery.where }}.
|
||||
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{% if title %}{{ title }} - {% endif %}{{ config.SITE_NAME }}</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" type="text/css" href="/static/signing-sheet.css">
|
||||
</head>
|
||||
<body>
|
||||
<h2>{{ delivery.name }} {{ delivery.from_date.date() }} - liste d'émargement</h2>
|
||||
{% extends "base.html" %}
|
||||
{% block body %}
|
||||
{% for email, order in delivery.orders.items() %}
|
||||
<h3>{{ request.groups.groups[email].name }}</h3>
|
||||
{% include "includes/order_summary.html" %}
|
||||
<hr>
|
||||
<hr class="page-break">
|
||||
{% endfor %}
|
||||
</body>
|
||||
{% endblock %}
|
|
@ -22,3 +22,8 @@ def read_token(token):
|
|||
return jwt.decode(token, config.SECRET, algorithms=[config.JWT_ALGORITHM])
|
||||
except (jwt.DecodeError, jwt.ExpiredSignatureError):
|
||||
return {}
|
||||
|
||||
|
||||
def prefix(string, delivery):
|
||||
date = delivery.to_date.strftime("%Y-%m-%d")
|
||||
return f"{config.SITE_NAME}-{date}-{string}"
|
||||
|
|
Loading…
Reference in a new issue