示例#1
0
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()
示例#2
0
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()
示例#3
0
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()
示例#4
0
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())
示例#7
0
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()
示例#12
0
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())
示例#13
0
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())
示例#14
0
def translate(msgid,
              domain=None,
              mapping=None,
              context=None,
              target_language=None,
              default=None):
    # _(message, plural_message=None, count=None, **kwargs):
    return str(_(msgid))
示例#15
0
 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())
示例#17
0
    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_])
示例#18
0
    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)
示例#19
0
    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_))
示例#20
0
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()
示例#21
0
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())
示例#22
0
    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_])
示例#23
0
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()
示例#24
0
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()
示例#25
0
    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
示例#26
0
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()
示例#27
0
    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
        }
示例#28
0
async def translation(request):
    return {
        'title': _('First page'),
        'request': request,
    }
示例#29
0
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
示例#30
0
 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()