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()
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 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 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 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() async with request.app["db-pool"].acquire() as conn: q = "UPDATE client SET confirmed = true WHERE id = $1 RETURNING id" try: updated = await conn.fetchval(q, id_) if updated is None: raise except Exception: flash(request, ("danger", _("Vous ne pouvez pas être enregistré."))) return HTTPFound(request.app.router["register"].url_for()) else: flash(request, ( "info", _("Votre enregistrement est confirmé, vous pouvez vous connecter." ))) return HTTPFound(request.app.router["login"].url_for())
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"] email_address = token_data["email_address"] except Exception: flash(request, ("danger", _("Le lien est invalide ou a expiré"))) raise HTTPBadRequest() async with request.app["db-pool"].acquire() as conn: q = "UPDATE client SET email_address = $1 WHERE id = $2" try: await conn.execute(q, email_address, id_) except Exception: flash( request, ("danger", _("Votre adresse email ne peut pas être modifiée"))) else: flash(request, ("info", _("Votre adresse email a été modifiée"))) login = await authorized_userid(request) if login: return HTTPFound(request.app.router["home"].url_for()) else: return HTTPFound(request.app.router["login"].url_for())
async def delete_repository(request): async with request.app["db-pool"].acquire() as conn: id_ = int(request.match_info["id"]) try: await conn.execute("DELETE FROM repository WHERE id = $1", id_) except IntegrityConstraintViolationError: flash(request, ("warning", _("Le point de livraison ne peut pas être supprimé"))) else: flash(request, ("success", _("Le point de livraison a été supprimé"))) finally: return HTTPFound(request.app.router["list_repository"].url_for())
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()
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 toggle_client(request): client_id = int(request.match_info["id"]) async with request.app["db-pool"].acquire() as conn: q = "UPDATE client SET disabled = NOT disabled WHERE id = $1" await conn.execute(q, client_id) flash(request, ("success", _("Le statut du client a été modifié."))) return HTTPFound(request.app.router["list_client"].url_for())
async def delete_batch(request): async with request.app["db-pool"].acquire() as conn: id_ = int(request.match_info["id"]) try: async with conn.transaction(): await conn.execute("DELETE FROM batch WHERE id = $1", id_) except IntegrityConstraintViolationError: flash(request, ("warning", _("La fournée ne peut pas être supprimée"))) except Exception: flash(request, ("danger", _("La fournée ne peut pas être supprimée"))) else: flash(request, ("success", _("La fournée a été supprimée"))) finally: return HTTPFound(request.app.router["list_batch"].url_for())
def translate(msgid, domain=None, mapping=None, context=None, target_language=None, default=None): # _(message, plural_message=None, count=None, **kwargs): return str(_(msgid))
def add_awakening(self, date): logger.info( _("Ajout du réveil le {} à {} (id={})").format( date.strftime("%d/%m/%Y"), date.strftime("%H:%M"), self.id ) ) self.awakenings[self.id] = date self.id += 1 self.setup_awakening()
async def delete_profile(request): login = await authorized_userid(request) async with request.app["db-pool"].acquire() as conn: client = await conn.fetchrow( "SELECT id, super_user FROM client WHERE login = $1", login) client_id = client["id"] if client["super_user"]: flash(request, ("warning", _("Un administrateur ne peut pas supprimer son profil."))) return HTTPFound(request.app.router["home"].url_for()) try: async with conn.transaction(): # delete associations between orders and products q = "SELECT id FROM order_ WHERE client_id = $1" orders = await conn.fetch(q, client_id) order_ids = [order["id"] for order in orders] q = "DELETE FROM order_product_association WHERE order_id = any($1::int[])" await conn.execute(q, order_ids) # delete orders q = "DELETE FROM order_ WHERE client_id = $1" await conn.execute(q, client_id) # delete client q = "DELETE FROM client WHERE id = $1" await conn.execute(q, client_id) except Exception: flash(request, ("warning", _("Votre profil ne peut être supprimé"))) else: response = HTTPFound(request.app.router["login"].url_for()) await forget(request, response) flash(request, ("success", _("Votre profil a été supprimé"))) return response return HTTPFound(request.app.router["home"].url_for())
async def run_subprocess(self, command, adapter, id_): if self.processes[adapter]: logger.warning(_("Enregistreur occupé (id={})").format(id_)) else: logger.debug(command) self.processes[adapter] = True process = await asyncio.create_subprocess_shell(command) self.recordings[id_]["handle"] = None self.recordings[id_]["process"] = process logger.debug(_("Début de l'enregistrement (id={})").format(id_)) await process.wait() logger.debug(_("Fin de l'enregistrement (id={})").format(id_)) self.processes[adapter] = False if self.recordings[id_]["shutdown"]: logger.debug(_("Mise hors tension (id={})").format(id_)) process = await asyncio.create_subprocess_shell("sudo shutdown -h now") await process.wait() del(self.recordings[id_])
def setup_awakening(self): # remove expired awakenings now = datetime.now() wus = dict(filter(lambda x: x[1] > now, self.awakenings.items())) self.awakenings = wus if len(self.awakenings) == 0: logger.info(_("Annulation du réveil")) # utils function, not the method of this class ! cancel_awakening() else: # select the nearest awakening... wui, wut = sorted(self.awakenings.items(), key=lambda w: w[1])[0] logger.info( _("Programmation du réveil le {} à {} (id={})").format( wut.strftime("%d/%m/%Y"), wut.strftime("%H:%M"), wui ) ) # ...and schedule it schedule_awakening(wut)
def make_command_and_run_it(self, loop, adapter, channel, program_filename, duration, id_): logger.info(_("Enregistrement de {} (id={})").format(program_filename, id_)) if self.simulate: command = f"sleep {duration}" else: filename = op.join(self.recording_directory, program_filename) command = ( f"/usr/bin/gnutv -adapter {adapter} -channels {self.channels_conf} " f"-out file {filename} -timeout {duration} \"{channel}\"" ) loop.create_task(self.run_subprocess(command, adapter, id_))
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()
async def delete_order(request): order_id = int(request.match_info["id"]) login = await authorized_userid(request) async with request.app["db-pool"].acquire() as conn: client_id = await conn.fetchval( "SELECT id FROM client WHERE login = $1", login) # get and batch date batch_date = await conn.fetchval( "SELECT b.date FROM order_ AS o " "INNER JOIN batch AS b ON o.batch_id = b.id " "WHERE o.id = $1", order_id) if datetime.now() > batch_date - timedelta(hours=12): flash(request, ("warning", _("Il est trop tard pour annuler votre commande."))) return HTTPFound(request.app.router["list_order"].url_for()) try: async with conn.transaction(): # needs to be deleted before the order q = "DELETE FROM order_product_association WHERE order_id = $1" await conn.execute(q, order_id) # delete and check that the order belongs to the right client q = ("DELETE FROM order_ " "WHERE id = $1 AND client_id = $2" "RETURNING id") id_ = await conn.fetchval(q, order_id, client_id) if not id_: raise flash(request, ("success", _("Votre commande a été supprimée."))) except Exception: flash(request, ("warning", _("Votre commande n'a pas pu être supprimée."))) return HTTPFound(request.app.router["list_order"].url_for())
def cancel_recording(self, id_): if id_ in self.recordings: logger.info(_("Annulation de {} (id={})").format( self.recordings[id_]["program_name"], id_) ) process = self.recordings[id_]["process"] if process is not None: process.terminate() handle = self.recordings[id_]["handle"] if handle is not None: handle.cancel() del(self.recordings[id_])
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()
def record(self, adapter, channel, program_name, immediate, begin_date, end_date, duration, shutdown): logger.info( _( "Programmation de l'enregistrement de \"{}\" " "pendant {} minutes de \"{}\" sur l'enregistreur {} (id={})" ).format(program_name, round(duration / 60), channel, adapter, self.id) ) loop = asyncio.get_running_loop() program_filename = program_name.replace(' ', '-') + ".ts" if immediate: handle = loop.call_soon( self.make_command_and_run_it, loop, adapter, channel, program_filename, duration, self.id ) else: handle = loop.call_later( (begin_date - datetime.now()).total_seconds(), self.make_command_and_run_it, loop, adapter, channel, program_filename, duration, self.id ) self.recordings[self.id] = { "handle": handle, "process": None, "channel": channel, "program_name": program_name, "begin_date": begin_date, "end_date": end_date, "adapter": adapter, "shutdown": shutdown, "duration": duration } self.id += 1
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()
async def post(self): form = self.RecordingForm(await self.request.post()) form.adapter.choices = self.adapters_choices form.channel.choices = self.channels_choices if form.data["submit"]: if form.validate(): data = remove_special_data(form.data) error = False begin_date = data["begin_date"] if begin_date is None: immediate = True begin_date = datetime.now() else: immediate = False if begin_date <= datetime.now(): error = True message = _( "La date de début doit être dans le futur.") end_date = data["end_date"] if begin_date >= end_date: error = True message = _( "La date de début doit être antérieure à la date de fin." ) duration = (end_date - begin_date).total_seconds() if duration > int(self.recorder.max_duration): error = True message = _( "La durée de l'enregistrement est trop longue.") if error: flash(self.request, ("danger", message)) else: adapter = data["adapter"] shutdown = data["shutdown"] channel = self.channels_choices[data["channel"]][1] program_name = data["program_name"] self.recorder.record(adapter, channel, program_name, immediate, begin_date, end_date, duration, shutdown) message = _("L'enregistrement de \"{}\" est programmé " "pour le {} à {} pendant {} minutes de \"{}\" " "sur l'enregistreur {}").format( program_name, begin_date.strftime("%d/%m/%Y"), begin_date.strftime("%H:%M"), round(duration / 60), channel, adapter) flash(self.request, ("info", message)) return web.HTTPFound( self.request.app.router["index"].url_for()) else: flash(self.request, ("danger", _("Le formulaire contient des erreurs."))) form2 = self.AwakeningForm(await self.request.post()) if form2.data["submit2"]: if form2.validate(): data = remove_special_data(form2.data) awakening_date = data["awakening_date"] self.wakeup.add_awakening(awakening_date) return web.HTTPFound( self.request.app.router["index"].url_for()) else: flash(self.request, ("danger", _("Le formulaire contient des erreurs."))) form3 = self.ToolsForm(await self.request.post()) if form3.data["submit3"]: if form3.validate(): data = remove_special_data(form3.data) if data["shutdown"]: halt() else: flash(self.request, ("danger", _("Le formulaire contient des erreurs."))) return { "form": form, "recordings": self.recorder.get_recordings(), "form2": form2, "awakenings": self.wakeup.get_awakenings(), "form3": form3 }
async def translation(request): return { 'title': _('First page'), 'request': request, }
async def logout(request): response = HTTPFound(request.app.router["login"].url_for()) await forget(request, response) flash(request, ("info", _("Vous êtes déconnecté"))) return response
def cancel_awakening(self, id_): if id_ in self.awakenings: logger.info(_("Suppression du réveil (id={})").format(id_)) del(self.awakenings[id_]) self.setup_awakening()