mirror of
https://github.com/almet/copanier.git
synced 2025-04-28 11:32:38 +02:00
Facilitate the transmission of information at the end of a delivery.
This is made in order to have moving reponsabilities, and avoid having people taking too much responsability.
This commit is contained in:
parent
b26f07ab5a
commit
d87efdbe7c
12 changed files with 249 additions and 12 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -6,4 +6,5 @@ db/*
|
|||
venv
|
||||
.env
|
||||
.vscode
|
||||
.pytest_cache
|
||||
.pytest_cache
|
||||
crac.env
|
||||
|
|
|
@ -20,7 +20,6 @@ SITE_URL = "http://localhost:2244"
|
|||
SITE_DESCRIPTION = "Shared orders"
|
||||
EMAIL_SIGNATURE = "The kind people behind copanier"
|
||||
|
||||
|
||||
def init():
|
||||
for key, value in globals().items():
|
||||
if key.isupper():
|
||||
|
|
|
@ -3,7 +3,7 @@ from emails import Message
|
|||
from . import config
|
||||
|
||||
|
||||
def send(to, subject, body, html=None, copy=None, attachments=None):
|
||||
def send(to, subject, body, html=None, copy=None, attachments=None, mail_from=None):
|
||||
if not attachments:
|
||||
attachments = []
|
||||
|
||||
|
@ -20,6 +20,7 @@ def send(to, subject, body, html=None, copy=None, attachments=None):
|
|||
|
||||
message.send(
|
||||
to=to,
|
||||
mail_from=mail_from,
|
||||
smtp={
|
||||
"host": config.SMTP_HOST,
|
||||
"user": config.SMTP_LOGIN,
|
||||
|
@ -30,11 +31,11 @@ def send(to, subject, body, html=None, copy=None, attachments=None):
|
|||
)
|
||||
|
||||
|
||||
def send_from_template(env, template, to, subject, **params):
|
||||
def send_from_template(env, template, to, subject, mail_from=None, **params):
|
||||
params["config"] = config
|
||||
html = env.get_template(f"emails/{template}.html").render(**params)
|
||||
txt = env.get_template(f"emails/{template}.txt").render(**params)
|
||||
send(to, subject, body=txt, html=html)
|
||||
send(to, subject, body=txt, html=html, mail_from=mail_from)
|
||||
|
||||
|
||||
def send_order(request, env, person, delivery, order, group_id, **kwargs):
|
||||
|
|
|
@ -784,4 +784,8 @@ small {
|
|||
}
|
||||
.progressbar li.active + li:after {
|
||||
background-color: #55b776;
|
||||
}
|
||||
|
||||
#instructions {
|
||||
height: 100px;
|
||||
}
|
61
copanier/templates/delivery/handover_delivery.html
Normal file
61
copanier/templates/delivery/handover_delivery.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block toplink %}{% if delivery.id %}<a href="{{ url_for('show_delivery', id=delivery.id) }}">↶ Retourner à la distribution</a>{% endif %}{% endblock %}
|
||||
{% block body %}
|
||||
<div>
|
||||
{% if delivery.id %}
|
||||
<h1>Passage de la référence (transmission)</h1>
|
||||
|
||||
<p>La distribution est maintenant terminée ! Il est temps de passer le relai à une autre personne.</p>
|
||||
<p>Le plus simple est de remplir les détails pour la prochaine distribution, ainsi que les informations pour les référent·es qui vont évoluer</p>
|
||||
<p>Et puis on créera la prochaine distribution et on enverra un petit mail à la nouvelle personne référente.</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<form method="post">
|
||||
<label>
|
||||
<p>Nom de la prochaine distribution</p>
|
||||
<input type="text" name="name" value="{{ delivery.name or '' }}">
|
||||
</label>
|
||||
<label>
|
||||
<p>Email du / de la référent⋅e</p>
|
||||
<input type="email" name="contact" value="{{ delivery.contact or request.user.email }}" required>
|
||||
</label>
|
||||
<label>
|
||||
<p>Téléphone pour joindre le / la référent⋅e</p>
|
||||
<input id="contact_phone" onInput="prettifyPhoneNumber('contact_phone')" type="phone" name="contact_phone" value="{{ delivery.contact_phone }}" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<p>Lieu</p>
|
||||
<input type="text" name="where" value="{{ delivery.where or '' }}" required>
|
||||
</label>
|
||||
<label>
|
||||
<p>Date de distribution</p>
|
||||
<input type="date" name="date" value="{{ delivery.from_date.date() if delivery.from_date else '' }}" required> de <input type="time" name="from_time" value="{{ delivery.from_date.time() if delivery.from_date else '' }}" required> à <input type="time" name="to_time" value="{{ delivery.to_date.time() if delivery.to_date else '' }}" required>
|
||||
</label>
|
||||
<label>
|
||||
<p>Date de limite de commande</p>
|
||||
<input type="date" name="order_before" value="{{ delivery.order_before.date() if delivery.order_before else '' }}" required>
|
||||
</label>
|
||||
<label>
|
||||
<p>Un petit message pour la qui reprend ?</p>
|
||||
<textarea id="instructions" name="email_body" cols="80" rows="100"></textarea>
|
||||
</label>
|
||||
|
||||
<h2>Emails des référent·es</h2>
|
||||
<p>Si il y a un changement de référence pour les producteurs·rices, mettez les info à jour :</p>
|
||||
|
||||
{% for producer_name, producer in delivery.producers.items() %}
|
||||
<h3>{{ producer.name }}</h3>
|
||||
|
||||
<input name="producer_{{ producer_name }}_referent_name" type="text" value="{{ producer.referent_name }}">
|
||||
<input name="producer_{{ producer_name }}_referent_email" type="text" value="{{ producer.referent }}">
|
||||
<input name="producer_{{ producer_name }}_referent_tel" type="text" value="{{ producer.referent_tel }}">
|
||||
{% endfor %}
|
||||
<div>
|
||||
<input type="submit" name="submit" value="Valider" class="primary">
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
{% endblock body %}
|
|
@ -48,6 +48,8 @@
|
|||
<div class="placeholder center">
|
||||
Tu es la personne contact pour l'organisation de cette distribution, merci :-) Pour t'aider, tu peux accéder à
|
||||
<a href="{{ url_for('show_delivery_toolbox', id=delivery.id) }}"><i class="icon-tools"></i> la boîte à outils</a> !
|
||||
|
||||
{% if delivery.status == delivery.CLOSED %}<p>La distribution est maintenant terminée. C'est le moment de <a href="{{ url_for('hand_over_delivery', id=delivery.id) }}">passer le relai, merci !</a></p>{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if delivery.has_products %}
|
||||
|
|
37
copanier/templates/emails/handover_delivery.html
Normal file
37
copanier/templates/emails/handover_delivery.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<p>Bonjour,</p>
|
||||
|
||||
<p>La personne référente de la dernière distribution vient de la clôturer, et a indiqué que vous étiez la personne référente pour la prochaine distribution.</p>
|
||||
|
||||
<p>Bravo :-)</p>
|
||||
|
||||
{% if email_body %}
|
||||
<p>Elle vous a même laissé un petit message : </p>
|
||||
|
||||
<p>{{ email_body}}</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<p>Voici les informations renseignées :</p>
|
||||
|
||||
<ul>
|
||||
<li>Nom : {{ delivery.name }}</li>
|
||||
<li>Date et heure : {{ delivery.from_date|date }} de {{ delivery.from_date|time }} à {{ delivery.to_date|time }}.</li>
|
||||
<li>Lieu : {{ delivery.location }}</li>
|
||||
<li>Commandes avant le {{ delivery.order_before|date }}</li>
|
||||
</ul>
|
||||
|
||||
Référent·es produits :
|
||||
|
||||
<ul>
|
||||
|
||||
</ul>
|
||||
{% for producer_name, producer in delivery.producers.items() %}
|
||||
<li>{{ producer.name }} : {{ producer.referent_name }} - <a href="mailto:{{ producer.referent }}">{{ producer.referent }}</a> - <a href="tel:{{ producer.referent_tel }}">{{ producer.referent_tel }}</a></li>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
<p>Si vous avez besoin de modifier ces informations, vous pouvez le faire <a href="{{ url_for('show_delivery', id=delivery.id) }}">en suivant ce lien.</a></p>
|
||||
|
||||
<p>Bonne journée,</p>
|
||||
|
||||
<p>{{ config.EMAIL_SIGNATURE }}</p>
|
30
copanier/templates/emails/handover_delivery.txt
Normal file
30
copanier/templates/emails/handover_delivery.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
Bonjour,
|
||||
|
||||
La personne référente de la dernière distribution vient de la clôturer, et a indiqué que vous étiez la personne référente pour la prochaine distribution.
|
||||
|
||||
Bravo :-)
|
||||
|
||||
{% if email_body %}
|
||||
Elle vous a même laissé un petit message : {{ email_body }}
|
||||
|
||||
{% endif %}
|
||||
Voici les informations renseignées :
|
||||
|
||||
Nom : {{ delivery.name }}
|
||||
Date et heure : {{ delivery.from_date|date }} de {{ delivery.from_date|time }} à {{ delivery.to_date|time }}.
|
||||
Lieu : {{ delivery.location }}
|
||||
Commandes avant le {{ delivery.order_before|date }}.
|
||||
|
||||
Référent·es produits :
|
||||
|
||||
{% for producer_name, producer in delivery.producers.items() %}
|
||||
- {{ producer.name }} : {{ producer.referent_name }} - {{ producer.referent }} - {{ producer.referent_tel }}
|
||||
{% endfor %}
|
||||
|
||||
Si vous avez besoin de modifier ces informations, vous pouvez le faire en suivant ce lien :
|
||||
|
||||
{{ url_for('show_delivery', id=delivery.id) }}
|
||||
|
||||
|
||||
Bonne journée,
|
||||
{{ config.EMAIL_SIGNATURE }}
|
57
copanier/templates/includes/delivery_dates_table.html
Normal file
57
copanier/templates/includes/delivery_dates_table.html
Normal file
|
@ -0,0 +1,57 @@
|
|||
<table class="pure-table fixed-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Quoi ?</th><th>Dates</th><th>Coordinatrice⋅eur</th><th>Référent⋅e⋅s produits</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Création de la distribution</th>
|
||||
<td>{{ delivery.dates.creation_date | date}}</td>
|
||||
<td>Rappeler aux référent⋅e⋅s produit de mettre leurs prix à jour, vérifier que tous les producteurs⋅rices sont bien présentes, en ajouter si besoin</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Mise à jour des prix</th>
|
||||
<td>Du {{ delivery.dates.price_update_start | date }} au {{ delivery.dates.price_update_deadline | date}}</td>
|
||||
<td>—</td>
|
||||
<td>Les référent⋅e⋅s produit mettent les prix à jour.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Commandes</td>
|
||||
<td>Du {{ delivery.dates.price_update_deadline | date }} au {{ delivery.dates.order_before | date }}</td>
|
||||
<td>Envoyer le lien de commande aux groupes pour qu'iels commandent</td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ajustements</th>
|
||||
<td>Du {{ delivery.dates.order_before | date }} au {{ delivery.dates.adjustment_deadline | date }}</td>
|
||||
<td>S'assurer que les ajustements sont bien faits par les participant⋅e⋅s</td>
|
||||
<td>Faire les ajustements à la main si besoin</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Approvisionnements</th>
|
||||
<td>Du {{ delivery.dates.adjustment_deadline | date }} au {{ delivery.dates.delivery_date | date }}</td>
|
||||
<td><a href="{{ url_for('send_referent_emails', id=delivery.id) }}">Envoyer les infos de commande aux référent⋅e⋅s</a></td>
|
||||
<td>Faire les commandes aux producteurs⋅rices, <strong>récupérer les produits</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Préparation de la distribution</th>
|
||||
<td>La veille du {{ delivery.dates.delivery_date | date }}</td>
|
||||
<td><a href="{{ url_for('show_orders_summary', id=delivery.id) }}">Imprimer les bons de commandes par colocation</a></td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Distribution</th>
|
||||
<td>{{ delivery.dates.delivery_date | date }}</td>
|
||||
<td>Coordonner la distribution, <a href="{{ url_for('compute_payments', id=delivery.id) }}">faire la répartition des chèques</a></td>
|
||||
<td>Arriver 30mn avant le début de la distribution, répartir les produits par coloc</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Transmission</th>
|
||||
<td>Après la distribution</td>
|
||||
<td><a href="{{ url_for('hand_over_delivery', id=delivery.id) }}">Passer le relai à la nouvelle personne référente</a></a></td>
|
||||
<td>—</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
|
@ -14,7 +14,7 @@
|
|||
</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<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>{% 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 }}.
|
||||
{% if not edit_mode and producer_obj.has_rupture_products(delivery) %}
|
||||
<p><em>Certains produits sont en rupture de stock.</em></p>
|
||||
{% endif %}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p>Total: {{ order.total(delivery.products, delivery, group_id) if order else 0 }} € (dont {{ order.compute_shipping(delivery, delivery.producers, group_id) | round(2) }} de port)</p>
|
||||
<p>Total: {{ order.total(delivery.products, delivery, group_id) if order else 0 }} € (dont {{ order.compute_shipping(delivery, delivery.producers, group_id) | round(2) }} de port)</p>
|
|
@ -33,22 +33,67 @@ async def home(request, response):
|
|||
async def new_delivery(request, response):
|
||||
response.html("delivery/edit_delivery.html", delivery={})
|
||||
|
||||
|
||||
@app.route("/distribution", methods=["POST"])
|
||||
async def create_delivery(request, response):
|
||||
form = request.form
|
||||
def create_delivery_from_form(form):
|
||||
data = {}
|
||||
data["from_date"] = f"{form.get('date')} {form.get('from_time')}"
|
||||
data["to_date"] = f"{form.get('date')} {form.get('to_time')}"
|
||||
for name in Delivery.__dataclass_fields__.keys():
|
||||
if name in form:
|
||||
data[name] = form.get(name)
|
||||
delivery = Delivery(**data)
|
||||
return Delivery(**data)
|
||||
|
||||
|
||||
@app.route("/distribution", methods=["POST"])
|
||||
async def create_delivery(request, response):
|
||||
delivery = create_delivery_from_form(request.form)
|
||||
delivery.persist()
|
||||
response.message("La distribution a bien été créée!")
|
||||
response.redirect = f"/distribution/{delivery.id}"
|
||||
|
||||
|
||||
@app.route("/distribution/{id}/transmettre", methods=["GET"])
|
||||
async def hand_over_delivery(request, response, id):
|
||||
delivery = Delivery.load(id)
|
||||
|
||||
response.html(
|
||||
"delivery/handover_delivery.html",
|
||||
delivery=delivery,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/distribution/{id}/transmettre", methods=["POST"])
|
||||
async def hand_over_delivery_post(request, response, id):
|
||||
old_delivery = Delivery.load(id)
|
||||
|
||||
form = request.form
|
||||
new_delivery = create_delivery_from_form(form)
|
||||
new_delivery.producers = old_delivery.producers
|
||||
new_delivery.products = old_delivery.products
|
||||
|
||||
# Update referent fields
|
||||
for producer_id, producer in new_delivery.producers.items():
|
||||
producer.referent = form.get(f'producer_{producer_id}_referent_email')
|
||||
producer.referent_name = form.get(f'producer_{producer_id}_referent_name')
|
||||
producer.referent_tel = form.get(f'producer_{producer_id}_referent_tel')
|
||||
new_delivery.producers[producer_id] = producer
|
||||
new_delivery.persist()
|
||||
|
||||
emails.send_from_template(
|
||||
env,
|
||||
"handover_delivery",
|
||||
new_delivery.contact,
|
||||
f"{config.SITE_NAME} - Passage de flambeau",
|
||||
old_delivery.contact,
|
||||
delivery=new_delivery,
|
||||
email_body = form.get('email_body'),
|
||||
hostname=request.host,
|
||||
url_for=app.url_for,
|
||||
)
|
||||
|
||||
response.message("La distribution à bien été créée et le mail envoyé, merci !")
|
||||
response.redirect = f"/distribution/{new_delivery.id}"
|
||||
|
||||
|
||||
@app.route("/distribution/{id}/{producer}/bon-de-commande.pdf", methods=["GET"])
|
||||
async def pdf_for_producer(request, response, id, producer):
|
||||
delivery = Delivery.load(id)
|
||||
|
|
Loading…
Reference in a new issue