mirror of
https://github.com/almet/copanier.git
synced 2025-04-28 19:42:37 +02:00
Merge branch 'delivery-balance' into 'master'
Basic "manage delivery balance" page See merge request ybon/copanier!5
This commit is contained in:
commit
22da3d771c
4 changed files with 91 additions and 13 deletions
|
@ -5,7 +5,7 @@ import ujson as json
|
||||||
import minicli
|
import minicli
|
||||||
from jinja2 import Environment, PackageLoader, select_autoescape
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
||||||
from roll import Roll, Response, HttpError
|
from roll import Roll, Response, HttpError
|
||||||
from roll.extensions import cors, options, traceback, simple_server, static
|
from roll.extensions import traceback, simple_server, static
|
||||||
|
|
||||||
from . import config, reports, session, utils, emails, loggers, imports
|
from . import config, reports, session, utils, emails, loggers, imports
|
||||||
from .models import Delivery, Order, Person, Product, ProductOrder
|
from .models import Delivery, Order, Person, Product, ProductOrder
|
||||||
|
@ -75,6 +75,18 @@ app = Roll()
|
||||||
traceback(app)
|
traceback(app)
|
||||||
|
|
||||||
|
|
||||||
|
def staff_only(view):
|
||||||
|
async def decorator(request, response, *args, **kwargs):
|
||||||
|
user = session.user.get(None)
|
||||||
|
if not user or not user.is_staff:
|
||||||
|
response.message("Désolé, c'est réservé au staff par ici", "warning")
|
||||||
|
response.redirect = request.headers.get("REFERRER", "/")
|
||||||
|
return
|
||||||
|
return await view(request, response, *args, **kwargs)
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
@app.listen("request")
|
@app.listen("request")
|
||||||
async def auth_required(request, response):
|
async def auth_required(request, response):
|
||||||
# Should be handler Roll side?
|
# Should be handler Roll side?
|
||||||
|
@ -171,6 +183,7 @@ async def new_delivery(request, response):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/livraison", methods=["POST"])
|
@app.route("/livraison", methods=["POST"])
|
||||||
|
@staff_only
|
||||||
async def create_delivery(request, response):
|
async def create_delivery(request, response):
|
||||||
form = request.form
|
form = request.form
|
||||||
data = {}
|
data = {}
|
||||||
|
@ -186,6 +199,7 @@ async def create_delivery(request, response):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/livraison/{id}/importer/produits", methods=["POST"])
|
@app.route("/livraison/{id}/importer/produits", methods=["POST"])
|
||||||
|
@staff_only
|
||||||
async def import_products(request, response, id):
|
async def import_products(request, response, id):
|
||||||
delivery = Delivery.load(id)
|
delivery = Delivery.load(id)
|
||||||
delivery.products = []
|
delivery.products = []
|
||||||
|
@ -220,12 +234,14 @@ async def export_products(request, response, id):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/livraison/{id}/edit", methods=["GET"])
|
@app.route("/livraison/{id}/edit", methods=["GET"])
|
||||||
|
@staff_only
|
||||||
async def edit_delivery(request, response, id):
|
async def edit_delivery(request, response, id):
|
||||||
delivery = Delivery.load(id)
|
delivery = Delivery.load(id)
|
||||||
response.html("edit_delivery.html", {"delivery": delivery})
|
response.html("edit_delivery.html", {"delivery": delivery})
|
||||||
|
|
||||||
|
|
||||||
@app.route("/livraison/{id}/edit", methods=["POST"])
|
@app.route("/livraison/{id}/edit", methods=["POST"])
|
||||||
|
@staff_only
|
||||||
async def post_delivery(request, response, id):
|
async def post_delivery(request, response, id):
|
||||||
delivery = Delivery.load(id)
|
delivery = Delivery.load(id)
|
||||||
form = request.form
|
form = request.form
|
||||||
|
@ -325,6 +341,7 @@ async def signing_sheet(request, response, id):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/livraison/{id}/importer/commande", methods=["POST"])
|
@app.route("/livraison/{id}/importer/commande", methods=["POST"])
|
||||||
|
@staff_only
|
||||||
async def import_commande(request, response, id):
|
async def import_commande(request, response, id):
|
||||||
email = request.form.get("email")
|
email = request.form.get("email")
|
||||||
order = Order()
|
order = Order()
|
||||||
|
@ -355,14 +372,10 @@ async def xls_full_report(request, response, id):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/livraison/{id}/ajuster/{ref}", methods=["GET", "POST"])
|
@app.route("/livraison/{id}/ajuster/{ref}", methods=["GET", "POST"])
|
||||||
|
@staff_only
|
||||||
async def adjust_product(request, response, id, ref):
|
async def adjust_product(request, response, id, ref):
|
||||||
delivery = Delivery.load(id)
|
delivery = Delivery.load(id)
|
||||||
delivery_url = f"/livraison/{delivery.id}"
|
delivery_url = f"/livraison/{delivery.id}"
|
||||||
user = session.user.get(None)
|
|
||||||
if not user or not user.is_staff:
|
|
||||||
response.message("Désolé, c'est dangereux par ici", "warning")
|
|
||||||
response.redirect = delivery_url
|
|
||||||
return
|
|
||||||
for product in delivery.products:
|
for product in delivery.products:
|
||||||
if product.ref == ref:
|
if product.ref == ref:
|
||||||
break
|
break
|
||||||
|
@ -383,6 +396,22 @@ async def adjust_product(request, response, id, ref):
|
||||||
response.html("adjust_product.html", {"delivery": delivery, "product": product})
|
response.html("adjust_product.html", {"delivery": delivery, "product": product})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/livraison/{id}/soldes", methods=["GET", "POST"])
|
||||||
|
@staff_only
|
||||||
|
async def delivery_balance(request, response, id):
|
||||||
|
delivery = Delivery.load(id)
|
||||||
|
delivery_url = f"/livraison/{delivery.id}"
|
||||||
|
if request.method == "POST":
|
||||||
|
form = request.form
|
||||||
|
for email, order in delivery.orders.items():
|
||||||
|
order.paid = form.bool(email, False)
|
||||||
|
delivery.persist()
|
||||||
|
response.message(f"Les soldes ont bien été mis à jour!")
|
||||||
|
response.redirect = delivery_url
|
||||||
|
else:
|
||||||
|
response.html("delivery_balance.html", {"delivery": delivery})
|
||||||
|
|
||||||
|
|
||||||
def configure():
|
def configure():
|
||||||
config.init()
|
config.init()
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,11 @@
|
||||||
{% include "includes/modal_copy_emails.html" %}
|
{% include "includes/modal_copy_emails.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</li>
|
</li>
|
||||||
|
{% if delivery.is_passed %}
|
||||||
|
<li>
|
||||||
|
<a href="/livraison/{{ delivery.id }}/soldes"><i class="icon-wallet"></i> Gérer les soldes</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
20
copanier/templates/delivery_balance.html
Normal file
20
copanier/templates/delivery_balance.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<article>
|
||||||
|
<h3><a href="/livraison/{{ delivery.id }}">{{ delivery.producer }}</a> — Gérer les soldes</h3>
|
||||||
|
<form method="post">
|
||||||
|
<table>
|
||||||
|
<tr><th>Personne</th><th>Montant</th><th>Soldée</th></tr>
|
||||||
|
{% for email, order in delivery.orders.items() %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ email }}</td>
|
||||||
|
<td>{{ order.total(delivery.products) }} €</td>
|
||||||
|
<td class="with-input"><input type="checkbox" name="{{ email }}" {% if order.paid %}checked{% endif %}></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<input type="submit" value="Mettre à jour les soldes">
|
||||||
|
</form>
|
||||||
|
</article>
|
||||||
|
{% endblock body %}
|
|
@ -159,15 +159,13 @@ async def test_get_adjust_product(client, delivery):
|
||||||
resp = await client.get(f"/livraison/{delivery.id}/ajuster/123")
|
resp = await client.get(f"/livraison/{delivery.id}/ajuster/123")
|
||||||
doc = pq(resp.body)
|
doc = pq(resp.body)
|
||||||
assert doc('[name="foo@bar.org"]')
|
assert doc('[name="foo@bar.org"]')
|
||||||
assert doc('[name="foo@bar.org"]').attr("value") == '1'
|
assert doc('[name="foo@bar.org"]').attr("value") == "1"
|
||||||
|
|
||||||
|
|
||||||
async def test_post_adjust_product(client, delivery):
|
async def test_post_adjust_product(client, delivery):
|
||||||
delivery.order_before = datetime.now() - timedelta(days=1)
|
delivery.order_before = datetime.now() - timedelta(days=1)
|
||||||
delivery.products[0].packing = 6
|
delivery.products[0].packing = 6
|
||||||
delivery.orders["foo@bar.org"] = Order(
|
delivery.orders["foo@bar.org"] = Order(products={"123": ProductOrder(wanted=2)})
|
||||||
products={"123": ProductOrder(wanted=2)}
|
|
||||||
)
|
|
||||||
delivery.persist()
|
delivery.persist()
|
||||||
assert delivery.status == delivery.ADJUSTMENT
|
assert delivery.status == delivery.ADJUSTMENT
|
||||||
body = {"foo@bar.org": "1"}
|
body = {"foo@bar.org": "1"}
|
||||||
|
@ -181,9 +179,7 @@ async def test_post_adjust_product(client, delivery):
|
||||||
async def test_only_staff_can_adjust_product(client, delivery, monkeypatch):
|
async def test_only_staff_can_adjust_product(client, delivery, monkeypatch):
|
||||||
delivery.order_before = datetime.now() - timedelta(days=1)
|
delivery.order_before = datetime.now() - timedelta(days=1)
|
||||||
delivery.products[0].packing = 6
|
delivery.products[0].packing = 6
|
||||||
delivery.orders["foo@bar.org"] = Order(
|
delivery.orders["foo@bar.org"] = Order(products={"123": ProductOrder(wanted=2)})
|
||||||
products={"123": ProductOrder(wanted=2)}
|
|
||||||
)
|
|
||||||
delivery.persist()
|
delivery.persist()
|
||||||
monkeypatch.setattr("copanier.config.STAFF", ["someone@else.org"])
|
monkeypatch.setattr("copanier.config.STAFF", ["someone@else.org"])
|
||||||
resp = await client.get(f"/livraison/{delivery.id}/ajuster/123")
|
resp = await client.get(f"/livraison/{delivery.id}/ajuster/123")
|
||||||
|
@ -196,6 +192,34 @@ async def test_only_staff_can_adjust_product(client, delivery, monkeypatch):
|
||||||
assert delivery.orders["foo@bar.org"].products["123"].adjustment == 0
|
assert delivery.orders["foo@bar.org"].products["123"].adjustment == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_delivery_balance(client, delivery):
|
||||||
|
delivery.from_date = datetime.now() - timedelta(days=1)
|
||||||
|
delivery.orders["foo@bar.org"] = Order(products={"123": ProductOrder(wanted=2)})
|
||||||
|
delivery.persist()
|
||||||
|
resp = await client.get(f"/livraison/{delivery.id}/soldes")
|
||||||
|
doc = pq(resp.body)
|
||||||
|
assert doc('[name="foo@bar.org"]')
|
||||||
|
assert not doc('[name="foo@bar.org"]').attr("checked")
|
||||||
|
delivery.orders["foo@bar.org"] = Order(
|
||||||
|
products={"123": ProductOrder(wanted=2)}, paid=True
|
||||||
|
)
|
||||||
|
delivery.persist()
|
||||||
|
resp = await client.get(f"/livraison/{delivery.id}/soldes")
|
||||||
|
doc = pq(resp.body)
|
||||||
|
assert doc('[name="foo@bar.org"]').attr("checked")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post_delivery_balance(client, delivery):
|
||||||
|
delivery.order_before = datetime.now() - timedelta(days=1)
|
||||||
|
delivery.orders["foo@bar.org"] = Order(products={"123": ProductOrder(wanted=2)})
|
||||||
|
delivery.persist()
|
||||||
|
body = {"foo@bar.org": "on"}
|
||||||
|
resp = await client.post(f"/livraison/{delivery.id}/soldes", body=body)
|
||||||
|
assert resp.status == 302
|
||||||
|
delivery = Delivery.load(id=delivery.id)
|
||||||
|
assert delivery.orders["foo@bar.org"].paid is True
|
||||||
|
|
||||||
|
|
||||||
async def test_export_products(client, delivery):
|
async def test_export_products(client, delivery):
|
||||||
delivery.persist()
|
delivery.persist()
|
||||||
resp = await client.get(f"/livraison/{delivery.id}/exporter/produits")
|
resp = await client.get(f"/livraison/{delivery.id}/exporter/produits")
|
||||||
|
|
Loading…
Reference in a new issue