Add support for price updates

This commit is contained in:
Alexis MÃtaireau 2020-04-05 19:00:36 +02:00
parent c753036573
commit 55100260d3
6 changed files with 78 additions and 8 deletions

5
TODO
View file

@ -12,8 +12,11 @@ x Faciliter la duplication de distribution
x Si un produit est en rupture de stock, alors il n'est pas compté dans les totaux x Si un produit est en rupture de stock, alors il n'est pas compté dans les totaux
x Permettre la supression des produits x Permettre la supression des produits
x Permettre la suppression de producteurs x Permettre la suppression de producteurs
x Ajouter une info « prix mis à jour » pour les référent⋅e⋅s
Gérer le souci d'URL pour l'édition d'Apiluly
Rendre le formulaire d'édition producteur plus compact
Ajouter une info « prix mis à jour » pour les référent⋅e⋅s
Gérer les frais de livraison Gérer les frais de livraison
Rendre plus visible l'action de modifier une commande Rendre plus visible l'action de modifier une commande

View file

@ -1,7 +1,7 @@
import inspect import inspect
import threading import threading
import uuid import uuid
from datetime import datetime from datetime import datetime, timedelta
from dataclasses import dataclass, field, asdict from dataclasses import dataclass, field, asdict
from pathlib import Path from pathlib import Path
from typing import List, Dict from typing import List, Dict
@ -174,6 +174,10 @@ class Producer(Base):
products = delivery.get_products_by(self.id) products = delivery.get_products_by(self.id)
return any([not p.rupture for p in products]) return any([not p.rupture for p in products])
def needs_price_update(self, delivery):
products = delivery.get_products_by(self.id)
return delivery.products_need_price_update(products)
@dataclass @dataclass
class Product(Base): class Product(Base):
@ -258,9 +262,10 @@ class Delivery(PersistedBase):
__lock__ = threading.Lock() __lock__ = threading.Lock()
EMPTY = -1 EMPTY = -1
CLOSED = 0 CLOSED = 0
OPEN = 1 NEED_PRICE_UPDATE = 1
ADJUSTMENT = 2 OPEN = 2
ARCHIVED = 3 ADJUSTMENT = 3
ARCHIVED = 4
name: str name: str
from_date: datetime_field from_date: datetime_field
@ -283,12 +288,19 @@ class Delivery(PersistedBase):
return self.EMPTY return self.EMPTY
if self.is_archived: if self.is_archived:
return self.ARCHIVED return self.ARCHIVED
if self.products_need_price_update():
return self.NEED_PRICE_UPDATE
if self.is_open: if self.is_open:
return self.OPEN return self.OPEN
if self.needs_adjustment: if self.needs_adjustment:
return self.ADJUSTMENT return self.ADJUSTMENT
return self.CLOSED return self.CLOSED
def products_need_price_update(self, products=None):
products = products or self.products
max_age = self.from_date.date() - timedelta(days=60)
return any([product.last_update.date() < max_age for product in products])
@property @property
def has_products(self): def has_products(self):
return len(self.products) > 0 return len(self.products) > 0

View file

@ -3,7 +3,13 @@
<div class="header"> <div class="header">
<h1>{{ delivery.name }}</h1> <h1>{{ delivery.name }}</h1>
<h4>{% if delivery.products %}{% if delivery.status == delivery.OPEN %}Commandes ouvertes jusqu'au {{ delivery.order_before|date }}{% elif delivery.status == delivery.ADJUSTMENT %}Ajustements en cours{% elif delivery.status == delivery.CLOSED %}Fermée{% else %}Archivée{% endif %}{% endif %}. <h4>{% if delivery.products %}
{% if delivery.status == delivery.OPEN %}Commandes ouvertes jusqu'au {{ delivery.order_before|date }}
{% elif delivery.status == delivery.ADJUSTMENT %}Ajustements en cours
{% elif delivery.status == delivery.CLOSED %}Fermée
{% elif delivery.status == delivery.ARCHIVED %}Archivée
{% elif delivery.status == delivery.NEED_PRICE_UPDATE %}Mise à jour des prix*
{% endif %}{% endif %}
{% include "includes/order_button.html" %} {% include "includes/order_button.html" %}
</h4> </h4>
<h4> <h4>
@ -46,6 +52,11 @@
<article class="delivery"> <article class="delivery">
{% if delivery.has_products %} {% if delivery.has_products %}
{% for (id, producer) in delivery.get_producers_for_referent(request.user.email).items() %}
{% if producer.needs_price_update(delivery) %}
<p class="notification info">Merci de <a href="/distribution/{{ delivery.id}}/{{ producer.id}}/éditer">mettre à jour les prix pour « {{ producer.name }} ».</a></p>
{% endif %}
{% endfor %}
{% include "includes/delivery_table.html" %} {% include "includes/delivery_table.html" %}
{% else %} {% else %}
<div class="placeholder"> <div class="placeholder">

View file

@ -6,6 +6,7 @@
{% for producer in producers %} {% for producer in producers %}
{% set producer_obj = delivery.producers[producer] %} {% set producer_obj = delivery.producers[producer] %}
<h2>{{ producer_obj.name }} <h2>{{ producer_obj.name }}
{% if producer_obj.needs_price_update(delivery) %}*{% endif %}
{% if edit_mode or request.user.is_staff or producer_obj.referent == request.user.email %} {% if edit_mode or request.user.is_staff or producer_obj.referent == request.user.email %}
<span class="edit"> <span class="edit">
<a class="button" href="/distribution/{{ delivery.id }}/{{ producer_obj.id }}/éditer"><i class="icon-ribbon"></i>&nbsp; Gérer ce⋅tte producteur⋅rice</a> <a class="button" href="/distribution/{{ delivery.id }}/{{ producer_obj.id }}/éditer"><i class="icon-ribbon"></i>&nbsp; Gérer ce⋅tte producteur⋅rice</a>

View file

@ -13,19 +13,27 @@
<li class="pure-menu-item"> <li class="pure-menu-item">
<a class="pure-menu-link" href="/distribution/{{ delivery.id}}/{{ producer.id }}/supprimer">Supprimer</a> <a class="pure-menu-link" href="/distribution/{{ delivery.id}}/{{ producer.id }}/supprimer">Supprimer</a>
</li> </li>
{% if producer.needs_price_update(delivery) %}
<li class="pure-menu-item">
<a class="pure-menu-link" href="/distribution/{{ delivery.id}}/{{ producer.id }}/valider-prix">Marquer les prix comme OK</a>
</li>
{% endif %}
</ul> </ul>
</div> </div>
{% else %} {% else %}
<h1>Ajouter un⋅e producteur⋅rice</h1> <h1>Ajouter un⋅e producteur⋅rice</h1>
{% endif %} {% endif %}
</div> </div>
{% if producer.needs_price_update(delivery) %}
<p class="notification info">Les prix pour {{ producer.name }} ont besoin d'être validés.</p>
{% endif %}
<form method="post"> <form method="post">
{% if producer.id %} {% if producer.id %}
<input type="hidden" name="id" value="{{ producer.id }}"> <input type="hidden" name="id" value="{{ producer.id }}">
{% else %} {% else %}
<label> <label>
<p>Nom</p> <p>Nom</p>
<input type="text" name="name" value="{{ producer.name or '' }}"> <input type="text" name="name" value="{{ proneeds_price_updateducer.name or '' }}">
</label> </label>
{% endif %} {% endif %}
<label> <label>
@ -54,7 +62,12 @@
</form> </form>
{% if products %} {% if products %}
<h3>Produits <a class="button" href="/distribution/{{ delivery.id}}/{{ producer.id }}/ajouter-produit">Ajouter un produit</a></h3> <h3>Produits
<a class="button" href="/distribution/{{ delivery.id}}/{{ producer.id }}/ajouter-produit">Ajouter un produit</a>
{% if producer.needs_price_update(delivery) %}
<a class="button" href="/distribution/{{ delivery.id}}/{{ producer.id }}/valider-prix">Marquer les prix comme OK</a>
{% endif %}
</h3>
<p>Vous pouvez éditer les produits en cliquant sur leur nom.</p> <p>Vous pouvez éditer les produits en cliquant sur leur nom.</p>
<table class="pure-table"> <table class="pure-table">
<thead> <thead>

View file

@ -1,3 +1,5 @@
from datetime import datetime
from slugify import slugify from slugify import slugify
from .core import app from .core import app
from ..models import Delivery, Product, Producer from ..models import Delivery, Product, Producer
@ -161,6 +163,34 @@ async def edit_product(request, response, delivery_id, producer_id, product_ref)
) )
@app.route("/distribution/{delivery_id}/{producer_id}/valider-prix", methods=["GET"])
async def mark_prices_as_ok(request, response, delivery_id, producer_id):
delivery = Delivery.load(delivery_id)
producer = delivery.producers.get(producer_id)
for product in delivery.products:
if product.producer == producer_id:
product.last_update = datetime.now()
delivery.persist()
response.message(
f"Les prix ont été marqués comme OK pour « { producer.name } », merci !"
)
response.redirect = f"/distribution/{delivery_id}/{producer_id}/éditer"
@app.route("/distribution/{delivery_id}/valider-prix", methods=["GET"])
async def mark_prices_as_ok(request, response, delivery_id):
delivery = Delivery.load(delivery_id)
for product in delivery.products:
product.last_update = datetime.now()
delivery.persist()
response.message(f"Les prix ont été marqués comme OK pour toute la distribution !")
response.redirect = f"/distribution/{delivery_id}/produits"
@app.route( @app.route(
"/distribution/{delivery_id}/{producer_id}/{product_ref}/supprimer", methods=["GET"] "/distribution/{delivery_id}/{producer_id}/{product_ref}/supprimer", methods=["GET"]
) )