From cd12223d6db6f2f44db97cc2cc4e00c9e84a0a02 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 19 Mar 2019 23:18:01 +0100 Subject: [PATCH] Basic messages, config and XLSX export --- kaba/__init__.py | 64 ++++++++++++++++++++++++--------- kaba/templates/base.html | 9 +++-- kaba/templates/home.html | 4 ++- kaba/templates/place_order.html | 20 ++++++++--- tests/conftest.py | 19 +++++----- tests/test_models.py | 9 +++++ 6 files changed, 93 insertions(+), 32 deletions(-) diff --git a/kaba/__init__.py b/kaba/__init__.py index ee25a62..e539533 100644 --- a/kaba/__init__.py +++ b/kaba/__init__.py @@ -1,13 +1,17 @@ import csv +from pathlib import Path from time import perf_counter import ujson as json import hupper import minicli from jinja2 import Environment, PackageLoader, select_autoescape +from openpyxl import Workbook +from openpyxl.writer.excel import save_virtual_workbook from roll import Roll, Response -from roll.extensions import cors, options, traceback, simple_server +from roll.extensions import cors, options, traceback, simple_server, static +from . import config from .models import Delivery, Order, Person, Product, ProductOrder @@ -28,6 +32,9 @@ class Response(Response): redirect = property(None, redirect) + def message(self, text, status="success"): + self.cookies.set("message", json.dumps((text, status))) + class Roll(Roll): Response = Response @@ -61,7 +68,7 @@ async def attach_request(request, response): @app.listen("startup") async def on_startup(): - connect() + configure() @app.route("/", methods=["GET"]) @@ -83,8 +90,8 @@ async def create_delivery(request, response): data[name] = form.get(name) delivery = Delivery(**data) delivery.persist() - response.status = 302 - response.headers["Location"] = f"/livraison/{delivery.id}" + response.message("La livraison a bien été créée!") + response.redirect = f"/livraison/{delivery.id}" @app.route("/livraison/{id}/importer/produits", methods=["POST"]) @@ -97,6 +104,7 @@ async def import_products(request, response, id): for row in reader: delivery.products.append(Product(**row)) delivery.persist() + response.message("Les produits de la livraison ont bien été mis à jour!") response.redirect = f"/livraison/{delivery.id}" @@ -114,8 +122,8 @@ async def post_delivery(request, response, id): if name in form: setattr(delivery, name, form.get(name)) delivery.persist() - response.status = 302 - response.headers["Location"] = f"/livraison/{delivery.id}" + response.message("La livraison a bien été mise à jour!") + response.redirect = f"/livraison/{delivery.id}" @app.route("/livraison/{id}", methods=["GET"]) @@ -128,7 +136,7 @@ async def view_delivery(request, response, id): async def order_form(request, response, id): delivery = Delivery.load(id) email = request.query.get("email") - order = delivery.orders.get(email) + order = delivery.orders.get(email) or Order() response.html( "place_order.html", {"delivery": delivery, "person": email, "order": order} ) @@ -148,6 +156,7 @@ async def place_order(request, response, id): delivery.orders = {} delivery.orders[email] = order delivery.persist() + response.message("Jour de fête! Votre commande a bien été prise en compte!") response.redirect = request.url.decode() @@ -165,22 +174,42 @@ async def import_commande(request, response, id): delivery = Delivery.load(id) delivery.orders[email] = order delivery.persist() + response.message(f"Yallah! La commande de {email} a bien été importée!") response.redirect = f"/livraison/{delivery.id}" -def connect(): - # db = os.environ.get("KABA_DB", "mongodb://localhost/kaba") - # client = MongoClient(db) - # db = client.get_database() - # Person.bind(db) - # Delivery.bind(db) - # return client - pass +@app.route("/livraison/{id}/rapport.xlsx", methods=["GET"]) +async def xls_report(request, response, id): + delivery = Delivery.load(id) + wb = Workbook() + ws = wb.active + ws.title = f"Commande Epinamap - {delivery.producer} - {delivery.when.date()}" + ws.append(["ref", "produit", "prix", "unités", "total"]) + for product in delivery.products: + wanted = delivery.product_wanted(product) + ws.append( + [ + product.ref, + product.name, + product.price, + wanted, + round(product.price * wanted, 2), + ] + ) + ws.append(["", "", "", "Total", delivery.total]) + response.body = save_virtual_workbook(wb) + mimetype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + response.headers["Content-Disposition"] = f'attachment; filename="export.xlsx"' + response.headers["Content-Type"] = f"{mimetype}; charset=utf-8" + + +def configure(): + config.init() @minicli.cli() def shell(): - """Run an ipython already connected to Mongo.""" + """Run an ipython in app context.""" try: from IPython import start_ipython except ImportError: @@ -200,7 +229,7 @@ def shell(): @minicli.wrap def cli_wrapper(): - connect() + configure() start = perf_counter() yield elapsed = perf_counter() - start @@ -213,6 +242,7 @@ def serve(reload=False): if reload: hupper.start_reloader("kaba.serve") traceback(app) + static(app, root=Path(__file__).parent / "static") simple_server(app, port=2244) diff --git a/kaba/templates/base.html b/kaba/templates/base.html index 9922526..4190401 100644 --- a/kaba/templates/base.html +++ b/kaba/templates/base.html @@ -4,13 +4,18 @@ {% if title %}{{ title }} - {% endif %}Commandes Epinamap - - + + {% block head %} {% endblock head %} +
+ {% if message %} +
{{ message[0] }}
+ {% endif %} +
{% block body %} {% endblock body %} diff --git a/kaba/templates/home.html b/kaba/templates/home.html index c1910b5..da758b8 100644 --- a/kaba/templates/home.html +++ b/kaba/templates/home.html @@ -7,9 +7,11 @@

Date: {{ delivery.when }}

- +
Résumé de la livraison +
{% endfor %} +Nouvelle livraison {% endblock body %} diff --git a/kaba/templates/place_order.html b/kaba/templates/place_order.html index 8c4db0e..5055c25 100644 --- a/kaba/templates/place_order.html +++ b/kaba/templates/place_order.html @@ -2,15 +2,27 @@ {% block body %}

< Commandes

-

Producteur: {{ delivery.producer }}

-

Lieu: {{ delivery.where }}

-

Date: {{ delivery.when }}

+

Producteur: {{ delivery.producer }} — Lieu: {{ delivery.where }} — Date: {{ delivery.when }} — Date limite de commande: {{ delivery.order_before }}

Commande de «{{ person }}»

{% for product in delivery.products %} - + + + {% endfor %}
ProduitPrixQuantité
{{ product.name }}{{ product.price }} €
{{ product.name }} + + +
+

{{ product.description }}

+

{% if product.img %} + + {% else %} + + {% endif %}

+ +
+
{{ product.price }} €

Total: {{ order.total(delivery.products) if order else 0 }} €

diff --git a/tests/conftest.py b/tests/conftest.py index f91071f..0471f5f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,23 +1,24 @@ import os +from datetime import timedelta import pytest from roll.extensions import traceback from kaba import app as kaba_app +from kaba import config as kconfig from kaba import utils from kaba.models import Delivery, Person def pytest_configure(config): - from kaba import models - models.Base.ROOT = "tmp/db" + os.environ["KABA_DATA_ROOT"] = "tmp/db" + kconfig.init() + assert str(kconfig.DATA_ROOT) == "tmp/db" -# def pytest_runtest_setup(item): -# # assert get_db().name == "test_eurordis" -# for cls in [Delivery]: -# collection = cls.collection -# collection.drop() +def pytest_runtest_setup(item): + for path in Delivery.get_root().glob("*.yml"): + path.unlink() @pytest.fixture @@ -29,7 +30,9 @@ def app(): # Requested by Roll testing utilities. @pytest.fixture def delivery(): return Delivery( - producer="Andines", when=utils.utcnow(), order_before=utils.utcnow() + producer="Andines", + when=utils.utcnow() + timedelta(days=10), + order_before=utils.utcnow() + timedelta(days=7), ) diff --git a/tests/test_models.py b/tests/test_models.py index b042354..03cf3fc 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,3 +1,5 @@ +from datetime import timedelta + import pytest from kaba import utils @@ -19,6 +21,13 @@ def test_wrong_datetime_raise_valueerror(): Delivery(producer="Andines", order_before=utils.utcnow(), when="pouet") +def test_delivery_is_open_when_order_before_is_in_the_future(delivery): + delivery.order_before = utils.utcnow() + timedelta(hours=1) + assert delivery.is_open + delivery.order_before = utils.utcnow() - timedelta(hours=1) + assert not delivery.is_open + + def test_can_create_product(): product = Product(name="Lait 1.5L", ref="123", price=1.5) assert product.ref == "123"