mirror of
https://github.com/almet/copanier.git
synced 2025-04-28 19:42:37 +02:00
Add support for price updates
This commit is contained in:
parent
f56471f6e1
commit
8db76c19d1
6 changed files with 78 additions and 8 deletions
5
TODO
5
TODO
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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> Gérer ce⋅tte producteur⋅rice</a>
|
<a class="button" href="/distribution/{{ delivery.id }}/{{ producer_obj.id }}/éditer"><i class="icon-ribbon"></i> Gérer ce⋅tte producteur⋅rice</a>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"]
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue