From 607fe553d40f715855d6fc92058e190eb08f2669 Mon Sep 17 00:00:00 2001 From: jfgiraud Date: Thu, 23 Jul 2026 09:56:47 +0200 Subject: [PATCH] Ajout du module gestion des actions et correction qq bugs --- app/routes.py | 101 ++++++- app/templates/gestion_actions.html | 354 ++++++++++++++++++++++++ app/templates/gestion_utilisateurs.html | 160 +++++++---- app/templates/menu.html | 6 +- 4 files changed, 554 insertions(+), 67 deletions(-) create mode 100644 app/templates/gestion_actions.html diff --git a/app/routes.py b/app/routes.py index fb4fd6e..4de0082 100644 --- a/app/routes.py +++ b/app/routes.py @@ -6,7 +6,7 @@ from datetime import datetime main = Blueprint('main', __name__) - +# Route pour la page d'accueil @main.route('/', methods=['GET', 'POST']) def index(): if 'user_id' in session: @@ -39,17 +39,20 @@ def index(): return render_template('index.html') +# Route pour la déconnexion +@main.route('/logout') +def logout(): + session.clear() + return redirect(url_for('main.index')) + +# Route pour le menu principal @main.route('/menu') def menu(): if 'user_id' not in session: return redirect(url_for('main.index')) return render_template('menu.html') -@main.route('/logout') -def logout(): - session.clear() - return redirect(url_for('main.index')) - +# Route pour la gestion des utilisateurs @main.route('/gestion-utilisateurs', methods=['GET', 'POST']) def gestion_utilisateurs(): if 'user_id' not in session: @@ -136,4 +139,88 @@ def gestion_utilisateurs(): 'actif': row.actif if row.actif is not None else 1 }) - return render_template('gestion_utilisateurs.html', users=users) \ No newline at end of file + return render_template('gestion_utilisateurs.html', users=users) + +# Route pour la gestion des actions +@main.route('/gestion-actions', methods=['GET', 'POST']) +def gestion_actions(): + if 'user_id' not in session: + return redirect(url_for('main.index')) + + if request.method == 'POST': + action_type = request.form.get('action') + # On récupère aussi l'id caché s'il s'agit d'une modification + action_id = request.form.get('id') + isin = request.form.get('isin') + ticker = request.form.get('ticker') + yahoo_code = request.form.get('yahoo_code') + company_name = request.form.get('company_name') + + if action_type == 'creer': + if isin: + try: + # Vérifier si l'ISIN existe déjà + check_query = text("SELECT COUNT(*) FROM actions WHERE isin = :isin") + exists = db.session.execute(check_query, {"isin": isin}).scalar() + + if exists > 0: + flash("L'action existe déjà, pas de création.", "warning") + else: + # L'id s'incrémente tout seul, on ne l'inclus pas dans l'INSERT + query = text(""" + INSERT INTO actions (isin, ticker, yahoo_code, company_name, updated_at) + VALUES (:isin, :ticker, :yahoo_code, :company_name, NOW()) + """) + db.session.execute(query, { + "isin": isin, + "ticker": ticker, + "yahoo_code": yahoo_code, + "company_name": company_name + }) + db.session.commit() + flash("Action créée", "success") + except Exception as e: + db.session.rollback() + flash("Erreur lors de la création de l'action.", "danger") + else: + flash("L'ISIN est obligatoire.", "danger") + + elif action_type == 'modifier' and action_id: + try: + # On met à jour en se basant sur l'id technique unique + query = text(""" + UPDATE actions + SET isin = :isin, ticker = :ticker, yahoo_code = :yahoo_code, company_name = :company_name, updated_at = NOW() + WHERE id = :id + """) + db.session.execute(query, { + "id": action_id, + "isin": isin, + "ticker": ticker, + "yahoo_code": yahoo_code, + "company_name": company_name + }) + db.session.commit() + flash("Modification effectuée", "success") + except Exception as e: + db.session.rollback() + flash("Erreur lors de la modification (Vérifiez si l'ISIN n'est pas déjà utilisé par une autre ligne).", "danger") + + return redirect(url_for('main.gestion_actions')) + + # On sélectionne l'id en plus dans la requête + actions_query = text("SELECT id, isin, ticker, yahoo_code, company_name, updated_at FROM actions ORDER BY company_name ASC") + result = db.session.execute(actions_query) + + actions_list = [] + for row in result: + actions_list.append({ + 'id': row.id, + 'isin': row.isin if row.isin else '', + 'ticker': row.ticker if row.ticker else '', + 'yahoo_code': row.yahoo_code if row.yahoo_code else '', + 'company_name': row.company_name if row.company_name else 'Sans nom', + 'updated_at': row.updated_at.strftime('%Y-%m-%d %H:%M:%S') if row.updated_at else '' + }) + + return render_template('gestion_actions.html', actions=actions_list) \ No newline at end of file diff --git a/app/templates/gestion_actions.html b/app/templates/gestion_actions.html new file mode 100644 index 0000000..bed31a9 --- /dev/null +++ b/app/templates/gestion_actions.html @@ -0,0 +1,354 @@ +{% extends "base.html" %} {% block title %}Gestion des actions - Bolsa{% +endblock %} {% block header_title %}Gestion actions{% endblock %} {% block +content %} +
+ +
+ {% set messages = get_flashed_messages(with_categories=true) %} {% if + messages %} {% for category, message in messages %} +
+ {{ message }} +
+ {% endfor %} {% endif %} +
+ + +
+ +
+
+

+ Administration des actions +

+

+ Gérez le référentiel des actions et valeurs boursières. +

+
+ + Retour au menu + +
+ + +
+ +
+
+ + +
+ +

+ Actions enregistrées +

+ +
+ {% for a in actions %} +
+
+ {{ a.company_name }} + {{ a.ticker or 'N/A' }} +
+ {{ a.isin }} +
+ {% endfor %} +
+
+ + +
+
+ + + +
+

+ Détails de l'action +

+ +
+ +
+ + +
+ + +
+ + +
+
+ +
+ +
+ + +
+ + +
+ + +
+
+ +
+ +
+ + +
+
+
+ + +
+ + + + +
+
+
+
+ +
+ Positions en bourse : Accès sécurisé. Veillez à fermer votre session après + chaque utilisation. +
+
+
+ + +{% endblock %} diff --git a/app/templates/gestion_utilisateurs.html b/app/templates/gestion_utilisateurs.html index 6592ffb..c154b83 100644 --- a/app/templates/gestion_utilisateurs.html +++ b/app/templates/gestion_utilisateurs.html @@ -1,7 +1,22 @@ {% extends "base.html" %} {% block title %}Gestion des utilisateurs - Bolsa{% endblock %} {% block header_title %}Gestion utilisateurs{% endblock %} {% block content %} -
+
+ +
+ {% set messages = get_flashed_messages(with_categories=true) %} {% if + messages %} {% for category, message in messages %} +
+ {{ message }} +
+ {% endfor %} {% endif %} +
+

- Gérez les accès et les comptes autorisés de l'application. + Gérez les comptes d'accès à l'application.

- +
- +
@@ -42,21 +57,23 @@ content %}
{% for u in users %}
- {{ u.prenom }} {{ u.nom }} + {{ u.prenom }} {{ u.nom }} ID: {{ u.id }} + {% if u.actif == 1 or u.actif == True %}Actif{% else %}Inactif{% + endif %} +
{% endfor %}
- +
@@ -66,42 +83,16 @@ content %} action="" class="space-y-4 flex-1 flex flex-col justify-between" > + + +

- Détails du compte + Détails de l'utilisateur

-
- -
- - -
- - -
- - -
-
-
@@ -112,6 +103,7 @@ content %} type="text" id="field-prenom" name="prenom" + required class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500" />
@@ -125,6 +117,7 @@ content %} type="text" id="field-nom" name="nom" + required class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500" />
@@ -140,6 +133,7 @@ content %} type="text" id="field-login" name="login" + required class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500" />
@@ -147,39 +141,60 @@ content %}
Email
-
+
Mot de passe (Laisser vide pour ne pas modifier)
+ + +
+ + +
- +
+
-
@@ -218,12 +232,28 @@ content %}
- - {% endblock %} diff --git a/app/templates/menu.html b/app/templates/menu.html index 0c134ee..d0c784f 100644 --- a/app/templates/menu.html +++ b/app/templates/menu.html @@ -11,14 +11,16 @@ header_title %}Tableau de bord{% endblock %} {% block content %} Accédez aux fonctions clés de l'application financière.

+