async def create_repository(request): if request.method == "POST": form = RepositoryForm(await request.post(), meta=await generate_csrf_meta(request)) if form.validate(): data = remove_special_data(form.data) data = days_to_array(data) async with request.app["db-pool"].acquire() as conn: q = "INSERT INTO repository ({}) VALUES ({})".format( field_list(data), place_holders(data) ) try: await conn.execute(q, *data.values()) except IntegrityConstraintViolationError: flash(request, ("warning", _("Le point de livraison ne peut pas être créé"))) return {"form": form} flash(request, ("success", _("Le point de livraison a été créé"))) return HTTPFound(request.app.router["list_repository"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form} elif request.method == "GET": form = RepositoryForm(meta=await generate_csrf_meta(request)) return {"form": form} else: raise HTTPMethodNotAllowed()
def __call__(self): method = self.request.method.lower() if method in self.methods: return (yield from getattr(self, method)()) else: raise HTTPMethodNotAllowed(method, self.methods)
async def handler(request): if request.method == "POST": form = EmailForm(await request.post(), meta=await generate_csrf_meta(request)) if form.validate(): data = dict(form.data.items()) email_address = data["email_address"] async with request.app["db-pool"].acquire() as conn: q = "SELECT id, email_address, login FROM client WHERE email_address = $1" client = await conn.fetchrow(q, email_address) if client is None: flash(request, ("danger", _("Il n'y a pas de profil dont l'adresse email est {}"). format(email_address))) else: await send_text_message( request, client["email_address"], _("Rappel de Votre identifiant"), _("Votre identifiant est {}").format(client["login"]), ) flash(request, ("info", _("Un email de confirmation a été envoyé à {}"). format(email_address))) return HTTPFound(request.app.router["login"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form} elif request.method == "GET": form = EmailForm(meta=await generate_csrf_meta(request)) return {"form": form} else: raise HTTPMethodNotAllowed()
async def login(request): if request.method == "POST": form = LoginForm(await request.post(), meta=await generate_csrf_meta(request)) if form.validate(): response = HTTPFound(request.app.router["home"].url_for()) login = form.login.data password = form.password.data db_pool = request.app["db-pool"] if await check_credentials(db_pool, login, password): async with request.app["db-pool"].acquire() as conn: q = ( "UPDATE client SET last_seen = NOW() WHERE login = $1 " "RETURNING first_name, super_user") client = await conn.fetchrow(q, login) await remember(request, response, login) if not client["super_user"]: flash(request, ( "info", _("Bonjour {} ! Ravi de vous revoir à nouveau").format( client["first_name"]))) return response flash(request, ("danger", _("La combinaison identifiant/mot de passe est invalide"))) return {"form": form} elif request.method == "GET": form = LoginForm(meta=await generate_csrf_meta(request)) return {"form": form} else: raise HTTPMethodNotAllowed()
async def edit_repository(request): async with request.app["db-pool"].acquire() as conn: id_ = int(request.match_info["id"]) data = dict(await conn.fetchrow("SELECT * FROM repository WHERE id = $1", id_)) data = array_to_days(data) if request.method == "POST": form = RepositoryForm( await request.post(), data=data, meta=await generate_csrf_meta(request) ) if form.validate(): data = remove_special_data(form.data) data = days_to_array(data) q = "UPDATE repository SET {} WHERE id = ${:d}".format( settings(data), len(data) + 1 ) try: await conn.execute(q, *data.values(), id_) except IntegrityConstraintViolationError: flash(request, ("warning", _("Le point de livraison ne peut pas être modifié"))) else: flash(request, ("success", _("Le point de livraison a été modifié"))) return HTTPFound(request.app.router["list_repository"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"id": str(id_), "form": form} elif request.method == "GET": form = RepositoryForm(data=data, meta=await generate_csrf_meta(request)) return {"id": str(id_), "form": form} else: raise HTTPMethodNotAllowed()
async def __call__(self): method = self.request.method.lower() if method in self.methods: return await getattr(self, method)() else: raise HTTPMethodNotAllowed(method, self.methods)
def start(self, request): if request.method != 'GET': raise HTTPMethodNotAllowed(request.method, ['GET']) resp_impl = super().start(request) self._prepare_sse(request.app.loop) return resp_impl
async def dispatch(self, request, view=None, **kwargs): """Dispatch request.""" if view is None and request.method not in self.methods: raise HTTPMethodNotAllowed(request.method, self.methods) method = getattr(self, view or request.method.lower()) response = await method(request, **kwargs) return await self.make_response(request, response)
def dispatch(self, request, view=None, **kwargs): """ Dispatch request. """ if request.method not in self.methods: raise HTTPMethodNotAllowed(request.method, self.methods) method = getattr(self, view or request.method.lower()) response = yield from method(request, **kwargs) return (yield from self.make_response(request, response))
def __init__(self, request: Request) -> None: super().__init__(request) self.methods = {} self._get_class_methods() method_name = self.request.method.upper() if not method_name: raise HTTPMethodNotAllowed(method_name) setattr(self, method_name.lower(), self._serializer_wrapper(self.methods[method_name]))
async def list_client(request): if request.method == "GET": async with request.app["db-pool"].acquire() as conn: q = ( "SELECT id, first_name, last_name, login, confirmed, disabled " "FROM client " "WHERE NOT super_user " "ORDER BY last_name, first_name") clients = await conn.fetch(q) return {"clients": clients} else: raise HTTPMethodNotAllowed()
async def mailing(request): async with request.app["db-pool"].acquire() as conn: rows = await conn.fetch("SELECT id, name FROM repository WHERE opened") repository_choices = [(row["id"], row["name"]) for row in rows] if request.method == "POST": form = MailingForm(await request.post(), meta=await generate_csrf_meta(request)) form.repository_id.choices = repository_choices if form.validate(): data = remove_special_data(form.data) subject = data["subject"] message = data["message"] if data["all_repositories"]: q = ( "SELECT first_name, email_address, login FROM client " "WHERE confirmed AND mailing" ) rows = await conn.fetch(q) else: repository_id = data.get("repository_id") q = ( "SELECT first_name, email_address, login FROM client " "WHERE confirmed AND mailing AND repository_id = $1" ) rows = await conn.fetch(q, repository_id) if not rows: flash(request, ("warning", _("Il n'y a pas de destinataire."))) return HTTPFound(request.app.router["mailing"].url_for()) if "<first_name>" in message or "<login>" in message: for r in rows: message_ = message.replace("<first_name>", r["first_name"]) message_ = message_.replace("<login>", r["login"]) await send_text_message(request, r["email_address"], subject, message_) else: email_addresses = [r["email_address"] for r in rows] await send_mailing_message(request, email_addresses, subject, message) flash(request, ("info", _("Les messages ont été envoyés."))) return HTTPFound(request.app.router["mailing"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return HTTPFound(request.app.router["mailing"].url_for()) elif request.method == "GET": form = MailingForm(meta=await generate_csrf_meta(request)) form.repository_id.choices = repository_choices return {"form": form} else: raise HTTPMethodNotAllowed()
def prepare(self, request): """Prepare for streaming and send HTTP headers. :param request: regular aiohttp.web.Request. """ if request.method != 'GET': raise HTTPMethodNotAllowed(request.method, ['GET']) resp_impl = self._start_pre_check(request) if resp_impl is not None: return resp_impl resp_impl = yield from super().prepare(request) self._prepare_sse(request.app.loop) return resp_impl
async def edit_profile(request): async with request.app["db-pool"].acquire() as conn: rows = await conn.fetch( "SELECT id, name, latitude, longitude FROM repository WHERE opened" ) repository_choices = [(row["id"], row["name"]) for row in rows] login = await authorized_userid(request) data = dict(await conn.fetchrow("SELECT * FROM client WHERE login = $1", login)) del data["password_hash"] if request.method == "POST": form = ProfileForm(await request.post(), data=data, meta=await generate_csrf_meta(request)) form.repository_id.choices = repository_choices if form.validate(): data = remove_special_data(form.data) del data["password2"] password = data.pop("password") if password: if len(password) < 6: flash(request, ("warning", _("Le mot de passe est trop court"))) return {"form": form} data["password_hash"] = sha256_crypt.hash(password) q = "UPDATE client SET {} WHERE login = ${}".format( settings(data), len(data) + 1) try: await conn.execute(q, *data.values(), login) except UniqueViolationError: flash(request, ("warning", _("Votre profil ne peut être modifié"))) else: flash(request, ("success", _("Votre profil a été modifié"))) return HTTPFound(request.app.router["home"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form, "repositories": rows} elif request.method == "GET": form = ProfileForm(data=data, meta=await generate_csrf_meta(request)) form.repository_id.choices = repository_choices return {"form": form, "repositories": rows} else: raise HTTPMethodNotAllowed()
async def confirm(request): token = request.match_info["token"] try: token_data = get_token_data( token, request.app["config"]["application"]["secret_key"] ) id_ = token_data["id"] except Exception: flash(request, ("danger", _("Le lien est invalide ou a expiré"))) raise HTTPBadRequest() if request.method == "POST": form = PasswordForm(await request.post(), meta=await generate_csrf_meta(request)) if form.validate(): password_hash = sha256_crypt.hash(form.password.data) async with request.app["db-pool"].acquire() as conn: q = "UPDATE client SET password_hash = $1 WHERE id = $2" try: await conn.execute(q, password_hash, id_) except Exception: flash( request, ( "danger", _("Votre mot de passe ne peut être modifié") ) ) return {"form": form, "token": token} else: flash( request, ( "info", _( "Votre mot de passe a été modifié, " "vous pouvez vous connecter" ) ) ) return HTTPFound(request.app.router["login"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form, "token": token} elif request.method == "GET": form = PasswordForm(meta=await generate_csrf_meta(request)) return {"form": form, "token": token} else: raise HTTPMethodNotAllowed()
async def handler(request): async with request.app["db-pool"].acquire() as conn: rows = await conn.fetch( "SELECT id, name, latitude, longitude FROM repository WHERE opened" ) repository_choices = [(row["id"], row["name"]) for row in rows] if request.method == "POST": form = RegisterForm(await request.post(), meta=await generate_csrf_meta(request)) form.repository_id.choices = repository_choices if form.validate(): data = remove_special_data(form.data) del data["password2"] data["password_hash"] = sha256_crypt.hash(data.pop("password")) try: async with conn.transaction(): q = "INSERT INTO client ({}) VALUES ({}) RETURNING *".format( field_list(data), place_holders(data)) try: client = await conn.fetchrow(q, *data.values()) except UniqueViolationError: flash(request, ("warning", _("Votre profil ne peut être créé, cet " "identifiant est déjà utilisé"))) raise # rollback the transaction : client not created await send_confirmation( request, client["email_address"], {"id": client["id"]}, "confirm_register", _("Confirmation de votre enregistrement"), "register-confirmation") flash(request, ("info", _("Un email de confirmation a été envoyé à {}"). format(client["email_address"]))) return HTTPFound(request.app.router["login"].url_for()) except Exception: return HTTPFound(request.app.router["register"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form, "repositories": rows} elif request.method == "GET": form = RegisterForm(meta=await generate_csrf_meta(request)) form.repository_id.choices = repository_choices return {"form": form, "repositories": rows} else: raise HTTPMethodNotAllowed()
async def prepare(self, request): """Prepare for streaming and send HTTP headers. :param request: regular aiohttp.web.Request. """ if request.method != 'GET': raise HTTPMethodNotAllowed(request.method, ['GET']) if not self.prepared: writer = await super().prepare(request) self._loop = request.app.loop self._ping_task = self._loop.create_task(self._ping()) # explicitly enabling chunked encoding, since content length # usually not known beforehand. self.enable_chunked_encoding() return writer
async def dispatch(self, request: Request): method = self.methods.get(request.method.upper()) if not method: raise HTTPMethodNotAllowed('', DEFAULT_METHODS) wanted_args = list(signature(method).parameters.keys()) available_args = request.match_info.copy() available_args.update({'request': request}) unsatisfied_args = set(wanted_args) - set(available_args.keys()) if unsatisfied_args: # Expected match info that doesn't exist raise HTTPBadRequest return await method( **{arg_name: available_args[arg_name] for arg_name in wanted_args})
async def handler(request): login = await authorized_userid(request) async with request.app["db-pool"].acquire() as conn: q = "SELECT id, email_address FROM client WHERE login = $1" client = await conn.fetchrow(q, login) if request.method == "POST": form = EmailForm(await request.post(), meta=await generate_csrf_meta(request)) if form.validate(): data = dict(form.data.items()) email_address = data["email_address"] q = "SELECT COUNT(*) FROM client WHERE email_address = $1" if await conn.fetchval(q, email_address) != 0: flash(request, ("danger", _("Veuillez choisir une autre adresse email"))) return {"form": form, "email": client["email_address"]} await send_confirmation(request, email_address, { "id": client["id"], "email_address": email_address }, "confirm_email", _("Changement d'adresse email"), "email-confirmation") flash(request, ("info", _("Un email de confirmation a été envoyé à {}"). format(email_address))) return HTTPFound(request.app.router["home"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form, "email": client["email_address"]} elif request.method == "GET": form = EmailForm(meta=await generate_csrf_meta(request)) return {"form": form, "email": client["email_address"]} else: raise HTTPMethodNotAllowed()
def start(self, request): """Prepare for streaming and send HTTP headers. :param request: regular aiohttp.web.Request. """ if request.method != 'GET': raise HTTPMethodNotAllowed(request.method, ['GET']) self._loop = request.app.loop self._finish_fut = asyncio.Future(loop=self._loop) self._finish_fut.add_done_callback(self._cancel_ping) resp_impl = self._start_pre_check(request) if resp_impl is not None: return resp_impl self._req = request self._keep_alive = True resp_impl = self._resp_impl = ResponseImpl(request._writer, self._status, request.version, close=not self._keep_alive, reason=self._reason) self._copy_cookies() # explicitly enabling chunked encoding, since content length # usually not known beforehand. self._chunked = True resp_impl.enable_chunked_encoding() headers = self.headers.items() for key, val in headers: resp_impl.add_header(key, val) resp_impl.send_headers() self._ping_task = asyncio.Task(self._ping(), loop=self._loop) return resp_impl
async def prepare(self, request): """Prepare for streaming and send HTTP headers. :param request: regular aiohttp.web.Request. """ if request.method != 'GET': raise HTTPMethodNotAllowed(request.method, ['GET']) if not self.prepared: writer = await super().prepare(request) self._loop = request.app.loop self._ping_task = self._loop.create_task(self._ping()) # explicitly enabling chunked encoding, since content length # usually not known beforehand. self.enable_chunked_encoding() return writer else: # hackish way to check if connection alive # should be updated once we have proper API in aiohttp # https://github.com/aio-libs/aiohttp/issues/3105 if request.protocol.transport is None: # request disconnected raise asyncio.CancelledError()
async def edit_batch(request): async with request.app["db-pool"].acquire() as conn: id_ = int(request.match_info["id"]) data = dict(await conn.fetchrow("SELECT * FROM batch WHERE id = $1", id_)) if request.method == "POST": form = BatchForm(await request.post(), data=data, meta=await generate_csrf_meta(request)) if form.validate(): data = remove_special_data(form.data) # as the date only is chosen by the user, the time part is set to 6:00 am data["date"] = datetime.combine(data["date"], time(hour=6)) q = "UPDATE batch SET {} WHERE id = ${:d}".format( settings(data), len(data) + 1) try: await conn.execute(q, *data.values(), id_) except IntegrityConstraintViolationError: flash( request, ("warning", _("La fournée ne peut pas être modifiée"))) else: flash(request, ("success", _("La fournée a été modifiée"))) return HTTPFound( request.app.router["list_batch"].url_for()) else: flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"id": str(id_), "form": form} elif request.method == "GET": form = BatchForm(data=data, meta=await generate_csrf_meta(request)) return {"id": str(id_), "form": form} else: raise HTTPMethodNotAllowed()
async def create_batch(request): async with request.app["db-pool"].acquire() as conn: if request.method == "POST": form = BatchForm(await request.post(), meta=await generate_csrf_meta(request)) data = remove_special_data(form.data) # just for csrf ! if not form.validate(): flash(request, ("danger", _("Le formulaire contient des erreurs."))) return {"form": form} # as the date only is chosen by the user, the time part is set to 6:00 am data["date"] = datetime.combine(data["date"], time(hour=6)) try: async with conn.transaction(): # create the batch q = ( "INSERT INTO batch (date, capacity, opened) VALUES ($1, $2, $3)" ) await conn.execute(q, data["date"], data["capacity"], data["opened"]) flash(request, ("success", _("La fournée a été créée"))) except Exception: flash(request, ("warning", _("La fournée ne peut pas être créée"))) return {"form": form} return HTTPFound(request.app.router["list_batch"].url_for()) elif request.method == "GET": form = BatchForm(meta=await generate_csrf_meta(request)) return {"form": form} else: raise HTTPMethodNotAllowed()
async def edit_order(request): order_id = int(request.match_info["id"]) login = await authorized_userid(request) async with request.app["db-pool"].acquire() as conn: q = ("SELECT c.id, c.disabled, r.days " "FROM client AS c " "INNER JOIN repository AS r ON c.repository_id = r.id " "WHERE c.login = $1 ") client = await conn.fetchrow(q, login) client_id = client["id"] if client["disabled"]: flash( request, ("warning", _("Vous ne pouvez pas modifier votre commande."))) return HTTPFound(request.app.router["list_order"].url_for()) # check that the order belongs to the right client q = ("SELECT COUNT(*) FROM order_ " "WHERE id = $1 AND client_id = $2") count = await conn.fetchval(q, order_id, client_id) if count != 1: return HTTPFound(request.app.router["list_order"].url_for()) # get batch id and batch date q = ("SELECT batch_id, b.date, b.capacity FROM order_ AS o " "INNER JOIN batch AS b ON b.id = batch_id " "WHERE o.id = $1") row = await conn.fetchrow(q, order_id) batch_date = row["date"] batch_id = row["batch_id"] batch_capacity = row["capacity"] # check that's its not too late to modify the order if datetime.now() > batch_date - timedelta(hours=12): flash(request, ("warning", _("Il est trop tard pour modifier votre commande."))) return HTTPFound(request.app.router["list_order"].url_for()) # get all available products q = ("SELECT * FROM product WHERE available") rows = await conn.fetch(q) products = products_for_context(rows, get_current_locale()) template_context = { "batch_date": batch_date, "batch_id": batch_id, "order_id": order_id, "products": products.values() } if request.method == "POST": data = await request.post() form = FillOrderForm(await request.post(), meta=await generate_csrf_meta(request)) data = remove_special_data(dict(data)) template_context["form"] = form # just for csrf ! if not form.validate(): flash(request, ("danger", _("Le formulaire contient des erreurs."))) return template_context # compute total price and total_load of the order total_price = 0 total_load = 0 for product_id, product in products.items(): ordered = data["product_qty_{}".format(product_id)].strip() if ordered == '': ordered = 0 else: try: ordered = int(ordered) if ordered < 0: raise ValueError("negative quantity") except ValueError: flash(request, ("danger", _("Quantité(s) invalide(s)."))) return template_context product["ordered"] = ordered total_price += ordered * products[product_id]["price"] total_load += ordered * products[product_id]["load"] # check that at least one product has been ordered if total_load == 0: flash(request, ("warning", _("Veuillez choisir au moins un produit"))) return template_context # checked that the load of ordered products is less than batch capacity products_load = await get_ordered_products_load(conn, batch_id, excluded=order_id) if total_load + products_load > batch_capacity: flash(request, ("warning", _("Votre commande dépasse la capacité de la fournée."))) return template_context # delete and re-create the order in a transaction try: async with conn.transaction(): # delete order to products association records q = "DELETE FROM order_product_association WHERE order_id = $1" await conn.execute(q, order_id) # and re-create them # create order to products for product_id, product in products.items(): ordered = product["ordered"] if ordered != 0: q = ("INSERT INTO order_product_association (" " quantity, order_id, product_id" ") " "VALUES ($1, $2, $3)") await conn.execute(q, ordered, order_id, product_id) # update order total q = ("UPDATE order_ SET total = $1, date=NOW() " "WHERE id = $2") await conn.fetchval(q, total_price, order_id) except Exception: flash( request, ("warning", _("Votre commande n'a pas pu être modifiée."))) return template_context flash(request, ("success", _("Votre commande a été modifiée."))) return HTTPFound(request.app.router["list_order"].url_for()) elif request.method == "GET": # select all the products from the order q = ("SELECT p.id, quantity " "FROM order_product_association AS opa " "INNER JOIN product AS p ON opa.product_id = p.id " "WHERE p.available AND opa.order_id = $1") rows = await conn.fetch(q, order_id) # update the batch products with the order products for row in rows: products[row["id"]]["ordered"] = row["quantity"] form = FillOrderForm(meta=await generate_csrf_meta(request)) template_context["form"] = form return template_context else: raise HTTPMethodNotAllowed()
async def create_order(request): login = await authorized_userid(request) async with request.app["db-pool"].acquire() as conn: q = ("SELECT c.id, c.disabled, r.days " "FROM client AS c " "INNER JOIN repository AS r ON c.repository_id = r.id " "WHERE c.login = $1 ") client = await conn.fetchrow(q, login) client_id = client["id"] if client["disabled"]: flash(request, ("warning", _("Vous ne pouvez pas passer de commande."))) return HTTPFound(request.app.router["list_order"].url_for()) # select opened batches that have no order from the client # select opened batches that have no order on them # from all above selected batches, select batches : # - whose date is 12 hours in the future # - client's delivery days corresponds to the batch date q = ( "WITH batch_choices AS ( " " SELECT b.id AS batch_id, b.date AS batch_date_, c.id AS client_id FROM batch AS b " " LEFT JOIN order_ AS o ON b.id = o.batch_id " " LEFT JOIN client AS c ON c.id = o.client_id " " WHERE b.opened AND b.date > (NOW() + INTERVAL '12 hour') AND " " (string_to_array($2, ',')::BOOLEAN[])[EXTRACT(DOW FROM b.date) + 1] " " GROUP BY b.id, b.date, c.id " " ORDER BY b.id, b.date" ") " "SELECT DISTINCT batch_id, TO_CHAR(batch_date_::DATE, 'dd-mm-yyyy') AS batch_date " "FROM batch_choices " "WHERE batch_id NOT IN (" " SELECT batch_id FROM batch_choices " " WHERE client_id = $1" ")") rows = await conn.fetch(q, client_id, str(client["days"]).strip("[]")) batch_choices = [(row["batch_id"], row["batch_date"]) for row in rows] if not batch_choices: flash(request, ("warning", _("Il n'y a pas de fournée disponible."))) return HTTPFound(request.app.router["list_order"].url_for()) # get all available products q = ("SELECT * FROM product WHERE available") rows = await conn.fetch(q) products = products_for_context(rows, get_current_locale()) template_context = {"products": products.values()} if request.method == "POST": data = await request.post() form = CreateOrderForm(data, meta=await generate_csrf_meta(request)) form.batch_id.choices = batch_choices data = remove_special_data(dict(data)) batch_id = int(data["batch_id"]) # just for csrf ! if not form.validate(): flash(request, ("danger", _("Le formulaire contient des erreurs."))) return HTTPFound(request.app.router["list_order"].url_for()) # get the batch date and capacity q = "SELECT date, capacity FROM batch WHERE id = $1" row = await conn.fetchrow(q, batch_id) batch_date = row["date"] batch_capacity = row["capacity"] # check that the batch corresponds to the delivery days if not client["days"][(batch_date.weekday() + 1) % 7]: flash(request, ("warning", _("La fournée choisie ne permet de vous livrer."))) return HTTPFound(request.app.router["list_order"].url_for()) template_context["form"] = form # compute total price and total_load of the order total_price = 0 total_load = 0 for product_id, product in products.items(): ordered = data["product_qty_{}".format(product_id)].strip() if ordered == '': ordered = 0 else: try: ordered = int(ordered) if ordered < 0: raise ValueError("negative quantity") except ValueError: flash(request, ("danger", _("Quantité(s) invalide(s)."))) return template_context product["ordered"] = ordered total_price += ordered * products[product_id]["price"] total_load += ordered * products[product_id]["load"] # check that at least one product has been ordered if total_load == 0: flash(request, ("warning", _("Veuillez choisir au moins un produit"))) return template_context # checked that the load of ordered products is less than the batch capacity products_load = await get_ordered_products_load(conn, batch_id) if total_load + products_load > batch_capacity: flash(request, ("warning", _("Votre commande dépasse la capacité de la fournée."))) return template_context try: async with conn.transaction(): # create the order q = ("INSERT INTO order_ (total, client_id, batch_id) " "VALUES ($1, $2, $3) RETURNING id") order_id = await conn.fetchval(q, total_price, client_id, batch_id) # create order to products for product_id, product in products.items(): ordered = product["ordered"] if ordered != 0: q = ("INSERT INTO order_product_association (" " quantity, order_id, product_id" ") " "VALUES ($1, $2, $3)") await conn.execute(q, ordered, order_id, product_id) except Exception: flash(request, ("warning", _("Votre commande n'a pas pu être passée."))) return template_context flash(request, ("success", _("Votre commande a été passée avec succès"))) return HTTPFound(request.app.router["list_order"].url_for()) elif request.method == "GET": form = CreateOrderForm(meta=await generate_csrf_meta(request)) form.batch_id.choices = batch_choices template_context["form"] = form return template_context else: raise HTTPMethodNotAllowed()
def _raise_allowed_methods(self) -> None: allowed_methods = { m for m in hdrs.METH_ALL if hasattr(self, m.lower()) } raise HTTPMethodNotAllowed(self.request.method, allowed_methods)