2026-07-22 16:37:53 +02:00
|
|
|
from flask import Blueprint, render_template, request, redirect, url_for, session, flash
|
2026-07-22 17:54:47 +02:00
|
|
|
from werkzeug.security import check_password_hash, generate_password_hash
|
2026-07-22 16:37:53 +02:00
|
|
|
from sqlalchemy import text
|
|
|
|
|
from app import db
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
main = Blueprint('main', __name__)
|
|
|
|
|
|
2026-07-23 09:56:47 +02:00
|
|
|
# Route pour la page d'accueil
|
2026-07-22 16:37:53 +02:00
|
|
|
@main.route('/', methods=['GET', 'POST'])
|
|
|
|
|
def index():
|
|
|
|
|
if 'user_id' in session:
|
|
|
|
|
return redirect(url_for('main.menu'))
|
|
|
|
|
|
|
|
|
|
if 'login_attempts' not in session:
|
|
|
|
|
session['login_attempts'] = 0
|
|
|
|
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
user_login = request.form.get('login')
|
|
|
|
|
user_pass = request.form.get('pass')
|
|
|
|
|
|
|
|
|
|
query = text("SELECT id, pass AS user_pass, nom, prenom FROM login WHERE login = :login AND actif = 1")
|
|
|
|
|
result = db.session.execute(query, {"login": user_login}).fetchone()
|
|
|
|
|
|
|
|
|
|
if result and check_password_hash(result.user_pass, user_pass):
|
|
|
|
|
session.pop('login_attempts', None)
|
|
|
|
|
session['user_id'] = result.id
|
|
|
|
|
session['user_name'] = f"{result.prenom} {result.nom}"
|
|
|
|
|
return redirect(url_for('main.menu'))
|
|
|
|
|
else:
|
|
|
|
|
session['login_attempts'] += 1
|
|
|
|
|
|
|
|
|
|
if session['login_attempts'] >= 3:
|
|
|
|
|
session.pop('login_attempts', None)
|
|
|
|
|
return redirect('https://giraud-finance.com')
|
|
|
|
|
|
|
|
|
|
essais_restants = 3 - session['login_attempts']
|
|
|
|
|
flash(f"Identifiant ou mot de passe incorrect. Il vous reste {essais_restants} essai(s).", "danger")
|
|
|
|
|
|
|
|
|
|
return render_template('index.html')
|
|
|
|
|
|
2026-07-23 09:56:47 +02:00
|
|
|
# Route pour la déconnexion
|
|
|
|
|
@main.route('/logout')
|
|
|
|
|
def logout():
|
|
|
|
|
session.clear()
|
|
|
|
|
return redirect(url_for('main.index'))
|
|
|
|
|
|
|
|
|
|
# Route pour le menu principal
|
2026-07-22 16:37:53 +02:00
|
|
|
@main.route('/menu')
|
|
|
|
|
def menu():
|
|
|
|
|
if 'user_id' not in session:
|
|
|
|
|
return redirect(url_for('main.index'))
|
|
|
|
|
return render_template('menu.html')
|
|
|
|
|
|
2026-07-23 09:56:47 +02:00
|
|
|
# Route pour la gestion des utilisateurs
|
2026-07-22 17:54:47 +02:00
|
|
|
@main.route('/gestion-utilisateurs', methods=['GET', 'POST'])
|
2026-07-22 16:37:53 +02:00
|
|
|
def gestion_utilisateurs():
|
|
|
|
|
if 'user_id' not in session:
|
|
|
|
|
return redirect(url_for('main.index'))
|
2026-07-22 17:54:47 +02:00
|
|
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
action = request.form.get('action')
|
|
|
|
|
user_id = request.form.get('id')
|
|
|
|
|
user_actif = request.form.get('actif', '1')
|
|
|
|
|
user_prenom = request.form.get('prenom')
|
|
|
|
|
user_nom = request.form.get('nom')
|
|
|
|
|
user_login = request.form.get('login')
|
|
|
|
|
user_mail = request.form.get('mail')
|
|
|
|
|
user_pass = request.form.get('pass')
|
|
|
|
|
|
|
|
|
|
if action == 'creer':
|
|
|
|
|
if user_pass:
|
|
|
|
|
hashed_pass = generate_password_hash(user_pass)
|
|
|
|
|
query = text("""
|
|
|
|
|
INSERT INTO login (login, nom, prenom, mail, pass, actif)
|
|
|
|
|
VALUES (:login, :nom, :prenom, :mail, :pass, :actif)
|
|
|
|
|
""")
|
|
|
|
|
db.session.execute(query, {
|
|
|
|
|
"login": user_login,
|
|
|
|
|
"nom": user_nom,
|
|
|
|
|
"prenom": user_prenom,
|
|
|
|
|
"mail": user_mail,
|
|
|
|
|
"pass": hashed_pass,
|
|
|
|
|
"actif": user_actif
|
|
|
|
|
})
|
|
|
|
|
db.session.commit()
|
|
|
|
|
flash("Utilisateur créé avec succès.", "success")
|
|
|
|
|
else:
|
|
|
|
|
flash("Le mot de passe est obligatoire pour créer un utilisateur.", "danger")
|
|
|
|
|
|
|
|
|
|
elif action == 'modifier' and user_id:
|
|
|
|
|
if user_pass:
|
|
|
|
|
hashed_pass = generate_password_hash(user_pass)
|
|
|
|
|
query = text("""
|
|
|
|
|
UPDATE login
|
|
|
|
|
SET login = :login, nom = :nom, prenom = :prenom, mail = :mail, pass = :pass, actif = :actif
|
|
|
|
|
WHERE id = :id
|
|
|
|
|
""")
|
|
|
|
|
db.session.execute(query, {
|
|
|
|
|
"id": user_id,
|
|
|
|
|
"login": user_login,
|
|
|
|
|
"nom": user_nom,
|
|
|
|
|
"prenom": user_prenom,
|
|
|
|
|
"mail": user_mail,
|
|
|
|
|
"pass": hashed_pass,
|
|
|
|
|
"actif": user_actif
|
|
|
|
|
})
|
|
|
|
|
else:
|
|
|
|
|
query = text("""
|
|
|
|
|
UPDATE login
|
|
|
|
|
SET login = :login, nom = :nom, prenom = :prenom, mail = :mail, actif = :actif
|
|
|
|
|
WHERE id = :id
|
|
|
|
|
""")
|
|
|
|
|
db.session.execute(query, {
|
|
|
|
|
"id": user_id,
|
|
|
|
|
"login": user_login,
|
|
|
|
|
"nom": user_nom,
|
|
|
|
|
"prenom": user_prenom,
|
|
|
|
|
"mail": user_mail,
|
|
|
|
|
"actif": user_actif
|
|
|
|
|
})
|
|
|
|
|
db.session.commit()
|
|
|
|
|
flash("Utilisateur modifié avec succès.", "success")
|
|
|
|
|
|
|
|
|
|
return redirect(url_for('main.gestion_utilisateurs'))
|
|
|
|
|
|
|
|
|
|
# Lecture exacte de la table login de votre base de données
|
|
|
|
|
users_query = text("SELECT id, login, nom, prenom, mail, actif FROM login ORDER BY id ASC")
|
|
|
|
|
result = db.session.execute(users_query)
|
|
|
|
|
|
|
|
|
|
users = []
|
|
|
|
|
for row in result:
|
|
|
|
|
users.append({
|
|
|
|
|
'id': row.id,
|
|
|
|
|
'login': row.login if row.login else '',
|
|
|
|
|
'nom': row.nom if row.nom else '',
|
|
|
|
|
'prenom': row.prenom if row.prenom else '',
|
|
|
|
|
'mail': row.mail if row.mail else '',
|
|
|
|
|
'actif': row.actif if row.actif is not None else 1
|
|
|
|
|
})
|
|
|
|
|
|
2026-07-23 09:56:47 +02:00
|
|
|
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 ''
|
|
|
|
|
})
|
|
|
|
|
|
2026-07-23 10:51:11 +02:00
|
|
|
return render_template('gestion_actions.html', actions=actions_list)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Route pour la gestion des sociétés
|
|
|
|
|
@main.route('/gestion-societes', methods=['GET', 'POST'])
|
|
|
|
|
def gestion_societes():
|
|
|
|
|
if 'user_id' not in session:
|
|
|
|
|
return redirect(url_for('main.index'))
|
|
|
|
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
|
action = request.form.get('action')
|
|
|
|
|
soc_id = request.form.get('id')
|
|
|
|
|
|
|
|
|
|
nom = request.form.get('Nom')
|
|
|
|
|
forme = request.form.get('Forme')
|
|
|
|
|
capital = request.form.get('Capital')
|
|
|
|
|
siren = request.form.get('siren')
|
|
|
|
|
siret = request.form.get('siret')
|
|
|
|
|
rcs = request.form.get('RCS')
|
|
|
|
|
tva = request.form.get('TVA')
|
|
|
|
|
naf = request.form.get('NAF')
|
|
|
|
|
tel = request.form.get('Tel')
|
|
|
|
|
web = request.form.get('Web')
|
|
|
|
|
mail = request.form.get('Mail')
|
|
|
|
|
|
|
|
|
|
if action == 'creer':
|
|
|
|
|
query = text("""
|
|
|
|
|
INSERT INTO societe (Nom, Forme, Capital, siren, siret, RCS, TVA, NAF, Tel, Web, Mail)
|
|
|
|
|
VALUES (:nom, :forme, :capital, :siren, :siret, :rcs, :tva, :naf, :tel, :web, :mail)
|
|
|
|
|
""")
|
|
|
|
|
db.session.execute(query, {
|
|
|
|
|
"nom": nom, "forme": forme, "capital": capital,
|
|
|
|
|
"siren": siren, "siret": siret, "rcs": rcs,
|
|
|
|
|
"tva": tva, "naf": naf, "tel": tel,
|
|
|
|
|
"web": web, "mail": mail
|
|
|
|
|
})
|
|
|
|
|
db.session.commit()
|
|
|
|
|
flash("Société créée avec succès.", "success")
|
|
|
|
|
|
|
|
|
|
elif action == 'modifier' and soc_id:
|
|
|
|
|
query = text("""
|
|
|
|
|
UPDATE societe
|
|
|
|
|
SET Nom = :nom, Forme = :forme, Capital = :capital, siren = :siren,
|
|
|
|
|
siret = :siret, RCS = :rcs, TVA = :tva, NAF = :naf,
|
|
|
|
|
Tel = :tel, Web = :web, Mail = :mail
|
|
|
|
|
WHERE id = :id
|
|
|
|
|
""")
|
|
|
|
|
db.session.execute(query, {
|
|
|
|
|
"id": soc_id, "nom": nom, "forme": forme, "capital": capital,
|
|
|
|
|
"siren": siren, "siret": siret, "rcs": rcs,
|
|
|
|
|
"tva": tva, "naf": naf, "tel": tel,
|
|
|
|
|
"web": web, "mail": mail
|
|
|
|
|
})
|
|
|
|
|
db.session.commit()
|
|
|
|
|
flash("Société modifiée avec succès.", "success")
|
|
|
|
|
|
|
|
|
|
return redirect(url_for('main.gestion_societes'))
|
|
|
|
|
|
|
|
|
|
# Lecture de la table societe
|
|
|
|
|
societes_query = text("SELECT id, Nom, Forme, Capital, siren, siret, RCS, TVA, NAF, Tel, Web, Mail FROM societe ORDER BY id ASC")
|
|
|
|
|
result = db.session.execute(societes_query)
|
|
|
|
|
|
|
|
|
|
societes = []
|
|
|
|
|
for row in result:
|
|
|
|
|
societes.append({
|
|
|
|
|
'id': row.id,
|
|
|
|
|
'Nom': row.Nom if row.Nom else '',
|
|
|
|
|
'Forme': row.Forme if row.Forme else '',
|
|
|
|
|
'Capital': row.Capital if row.Capital is not None else 0,
|
|
|
|
|
'siren': row.siren if row.siren is not None else '',
|
|
|
|
|
'siret': row.siret if row.siret is not None else '',
|
|
|
|
|
'RCS': row.RCS if row.RCS else '',
|
|
|
|
|
'TVA': row.TVA if row.TVA else '',
|
|
|
|
|
'NAF': row.NAF if row.NAF else '',
|
|
|
|
|
'Tel': row.Tel if row.Tel else '',
|
|
|
|
|
'Web': row.Web if row.Web else '',
|
|
|
|
|
'Mail': row.Mail if row.Mail else ''
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return render_template('gestion_societes.html', societes=societes)
|