2026-08-03 10:02:12 +02:00
{% extends "base.html" %} {% block title %}Gestion des Comptes - Bolsa{%
endblock %} {% block header_title %}Gestion des comptes{% endblock %} {% block
content %}
< div
class = "flex flex-col items-center justify-center w-full h-full overflow-hidden px-2"
>
<!-- Système de Toasts -->
< div
id = "toast-container"
class = "fixed top-6 left-1/2 transform -translate-x-1/2 z-50 space-y-3 w-full max-w-md px-4 pointer-events-none"
>
{% set messages = get_flashed_messages(with_categories=true) %} {% if
messages %} {% for category, message in messages %}
< div
class = "toast-message pointer-events-auto flex items-center justify-center px-4 py-3 rounded-xl shadow-2xl text-white text-sm font-medium transition-all duration-300 transform translate-y-0 opacity-100 text-center {% if category == 'success' %} bg-emerald-600 border border-emerald-500 {% elif category == 'warning' %} bg-amber-600 border border-amber-500 {% else %} bg-rose-600 border border-rose-500 {% endif %}"
>
< span > {{ message }}</ span >
</ div >
{% endfor %} {% endif %}
</ div >
<!-- Box principale -->
< div
class = "bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] h-full flex flex-col overflow-hidden"
>
<!-- Header fixe de la box -->
< div
class = "p-4 sm:p-6 pb-3 border-b border-gray-800 flex justify-between items-center shrink-0"
>
< div >
< h2 class = "text-2xl font-extrabold text-white flex items-center gap-2" >
< i class = "fa-solid fa-wallet text-blue-500" ></ i > Comptes -
< span class = "text-amber-400" > {{ selected_societe }}</ span >
</ h2 >
< p class = "text-gray-400 text-sm" >
Suivi des écritures comptables de la société.
</ p >
</ div >
< div class = "flex items-center gap-4" >
< form
method = "POST"
2026-08-09 09:50:49 +02:00
action = "{{ url_for('comptes.gestion_comptes') }}"
2026-08-03 10:02:12 +02:00
class = "m-0"
>
< input type = "hidden" name = "csrf_token" value = "{{ csrf_token() }}" />
< select
name = "societe_id"
id = "select-societe-id"
class = "bg-gray-800 border border-gray-700 text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-blue-500 cursor-pointer"
onchange = "this.form.submit()"
>
{% for soc in societes %} {% if soc.id == selected_societe_id %}
< option value = "{{ soc.id }}" data-nom = "{{ soc.nom }}" selected >
{{ soc.nom }}
</ option >
{% else %}
< option value = "{{ soc.id }}" data-nom = "{{ soc.nom }}" >
{{ soc.nom }}
</ option >
{% endif %} {% endfor %}
</ select >
</ form >
<!-- Génération automatique des écritures depuis les ordres -->
< form
method = "POST"
2026-08-09 09:50:49 +02:00
action = "{{ url_for('comptes.generer_ecritures_ordres') }}"
2026-08-03 10:02:12 +02:00
class = "m-0"
onsubmit = "return confirm('Générer / régénérer les écritures comptables à partir des ordres de cette société ? Les écritures générées existantes seront remplacées.');"
>
< input type = "hidden" name = "csrf_token" value = "{{ csrf_token() }}" />
< input type = "hidden" name = "id_societe" value = "{{ selected_societe_id }}" />
< button
type = "submit"
class = "px-4 py-2 bg-amber-600 hover:bg-amber-500 text-white text-sm font-medium rounded-lg transition duration-200 flex items-center gap-2 cursor-pointer"
title = "Générer les écritures depuis les ordres"
>
< i class = "fa-solid fa-wand-magic-sparkles" ></ i > Générer
</ button >
</ form >
< a
2026-08-09 09:50:49 +02:00
href = "{{ url_for('menu.menu') }}"
2026-08-03 10:02:12 +02:00
class = "px-4 py-2 bg-gray-800 hover:bg-gray-700 text-gray-200 text-sm font-medium rounded-lg transition duration-200"
>
Retour au menu
</ a >
</ div >
</ div >
<!-- Corps scrollable -->
< div class = "p-4 sm:p-6 overflow-y-auto flex-1" >
< div
class = "bg-gray-950 border border-gray-800 rounded-xl p-2 overflow-x-auto"
>
< table class = "w-full text-left border-collapse text-sm" >
< thead >
< tr
class = "bg-blue-950/60 text-gray-400 uppercase tracking-wider text-xs border-b border-gray-800"
>
< th class = "py-2 px-3" > Date</ th >
< th class = "py-2 px-3" > Libellé</ th >
< th class = "py-2 px-3 text-right" > Crédit</ th >
< th class = "py-2 px-3 text-right" > Débit</ th >
< th class = "py-2 px-3 text-end" >
< button
type = "button"
onclick = "ouvrirModalCreation()"
class = "px-3.5 py-1.5 bg-emerald-600 hover:bg-emerald-500 text-white text-xs font-semibold rounded shadow transition cursor-pointer"
>
Créer
</ button >
</ th >
</ tr >
</ thead >
< tbody class = "divide-y divide-gray-800 text-gray-300" >
{% if ecritures %} {% for e in ecritures %}
< tr class = "hover:bg-gray-900/50 transition" >
< td class = "py-2 px-3 whitespace-nowrap" > {{ e.date_operation }}</ td >
< td class = "py-2 px-3 text-gray-400" >
{% if e.source == 'ordre' %}{{ e.libelle | safe }}{% else %}{{ e.libelle or '-' }}{% endif %}
</ td >
< td class = "py-2 px-3 text-right" >
{% if e.credit and e.credit > 0 %} {{ "{:,.2f}".format(e.credit)
}} {% else %} - {% endif %}
</ td >
< td class = "py-2 px-3 text-right" >
{% if e.debit and e.debit > 0 %} {{ "{:,.2f}".format(e.debit) }}
{% else %} - {% endif %}
</ td >
< td class = "py-2 px-3 text-end" >
{% if e.source == 'manuel' %}
< button
type = "button"
onclick = "ouvrirModalModification('{{ e.id }}', '{{ e.date_operation }}', '{{ e.debit }}', '{{ e.credit }}', '{{ e.libelle | e }}')"
class = "px-3.5 py-1.5 bg-blue-600 hover:bg-blue-500 text-white text-xs font-semibold rounded shadow transition inline-flex items-center justify-center cursor-pointer"
title = "Modifier"
>
Modifier
</ button >
{% else %}
< span
class = "text-[10px] text-gray-600 italic uppercase tracking-wider"
title = "Écriture générée automatiquement depuis un ordre"
> Auto</ span
>
{% endif %}
</ td >
</ tr >
{% endfor %} {% else %}
< tr >
< td colspan = "5" class = "text-center text-gray-500 py-8" >
Aucune écriture pour cette société.
</ td >
</ tr >
{% endif %}
<!-- Ligne TOTAL -->
< tr
class = "bg-blue-950/60 text-white uppercase tracking-wider text-xs border-t border-b border-gray-800 font-bold"
>
< td class = "py-2.5 px-3" > TOTAL :</ td >
< td class = "py-2.5 px-3" ></ td >
< td class = "py-2.5 px-3 text-right" >
{{ "{:,.2f}".format(total_credit or 0) }}
</ td >
< td class = "py-2.5 px-3 text-right" >
{{ "{:,.2f}".format(total_debit or 0) }}
</ td >
< td class = "py-2.5 px-3" ></ td >
</ tr >
<!-- Ligne DISPO (récapitulatif financier) -->
< tr class = "bg-blue-950 text-white border-b border-gray-800" >
< td class = "py-3 px-4" colspan = "5" >
< div class = "flex flex-wrap items-center gap-x-6 gap-y-2 text-sm font-extrabold" >
< span >
SOLDE :
< span class = "ml-1 {% if solde >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}" >
{{ "{:,.2f}".format(solde | abs) }} €{% if solde < 0 %} ( - ){% endif %}
</ span >
</ span >
< span class = "text-gray-400" > |</ span >
< span >
DISPO :
< span class = "ml-1 {% if dispo >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}" >
{{ "{:,.2f}".format(dispo | abs) }} €{% if dispo < 0 %} ( - ){% endif %}
</ span >
</ span >
< span class = "text-gray-400" > |</ span >
< span >
ENGA. :
< span class = "ml-1 {% if engagement >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}" >
{{ "{:,.2f}".format(engagement | abs) }} €{% if engagement < 0 %} ( - ){% endif %}
</ span >
</ span >
< span class = "text-gray-400" > |</ span >
< span >
Depot :
< span class = "ml-1 {% if tcredit >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}" >
{{ "{:,.2f}".format(tcredit | abs) }} €{% if tcredit < 0 %} ( - ){% endif %}
</ span >
</ span >
< span class = "text-gray-400" > |</ span >
< span >
Retrait :
< span class = "ml-1 {% if tdebit >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}" >
{{ "{:,.2f}".format(tdebit | abs) }} €{% if tdebit < 0 %} ( - ){% endif %}
</ span >
</ span >
< span class = "text-gray-400" > |</ span >
< span >
PV :
< span class = "ml-1 {% if pv >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}" >
{{ "{:,.2f}".format(pv | abs) }} €{% if pv < 0 %} ( - ){% endif %}
</ span >
</ span >
</ div >
</ td >
</ tr >
</ tbody >
</ table >
</ div >
</ div >
<!-- Footer -->
< div
class = "px-6 py-3 border-t border-gray-800 text-xs text-gray-400 text-center shrink-0 bg-gray-900"
>
Comptes : Accès sécurisé. Veillez à fermer votre session après chaque
utilisation.
</ div >
</ div >
</ div >
<!-- Popup unique (Création et Modification d'écriture) -->
< div
id = "modal-compte-ecriture"
class = "fixed inset-0 bg-black/70 backdrop-blur-sm z-50 flex items-center justify-center hidden"
>
< div
class = "bg-gray-900 border border-gray-800 rounded-2xl p-6 w-full max-w-lg shadow-2xl text-white relative"
>
< button
onclick = "fermerModal()"
class = "absolute top-4 right-4 text-gray-400 hover:text-white cursor-pointer"
>
< i class = "fa-solid fa-xmark text-xl" ></ i >
</ button >
< h3 id = "modal-title" class = "text-xl font-bold mb-4 flex items-center gap-2" >
< i class = "fa-solid fa-plus-circle text-emerald-500" ></ i > Nouvelle écriture
</ h3 >
< form
id = "form-modal-ecriture"
method = "POST"
2026-08-09 09:50:49 +02:00
action = "{{ url_for('comptes.creer_compte_traitement') }}"
2026-08-03 10:02:12 +02:00
class = "space-y-4"
>
< input type = "hidden" name = "csrf_token" value = "{{ csrf_token() }}" />
< input type = "hidden" name = "id_societe" id = "input-id-societe" value = "{{ selected_societe_id }}" />
<!-- Nom de la société (affichage en lecture seule) -->
< div >
< label class = "text-xs text-gray-400" > Société</ label >
< input
type = "text"
id = "input-nom-societe"
readonly
class = "w-full mt-1 bg-gray-950 border border-gray-800 rounded-lg px-3 py-2 text-sm text-amber-400 font-semibold focus:outline-none cursor-default"
/>
</ div >
<!-- Date + Libellé -->
< div class = "grid grid-cols-2 gap-3" >
< div >
< label class = "text-xs text-gray-400" > Date d'opération</ label >
< input
type = "date"
name = "date_operation"
id = "input-date-operation"
required
class = "w-full mt-1 bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-blue-500"
/>
</ div >
< div >
< label class = "text-xs text-gray-400" > Libellé</ label >
< input
type = "text"
name = "libelle"
id = "input-libelle"
placeholder = "Optionnel..."
class = "w-full mt-1 bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-blue-500"
/>
</ div >
</ div >
<!-- Crédit + Débit -->
< div class = "grid grid-cols-2 gap-3" >
< div >
< label class = "text-xs text-gray-400" > Crédit (€)</ label >
< input
type = "number"
step = "0.01"
name = "credit"
id = "input-credit"
value = "0.00"
class = "w-full mt-1 bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-blue-500"
/>
</ div >
< div >
< label class = "text-xs text-gray-400" > Débit (€)</ label >
< input
type = "number"
step = "0.01"
name = "debit"
id = "input-debit"
value = "0.00"
class = "w-full mt-1 bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-blue-500"
/>
</ div >
</ div >
< div class = "flex justify-end gap-2 pt-2" >
< button
type = "button"
onclick = "fermerModal()"
class = "px-4 py-2 bg-gray-800 hover:bg-gray-700 text-gray-300 rounded-lg text-sm transition cursor-pointer"
>
Annuler
</ button >
< button
type = "submit"
id = "btn-valider"
class = "px-4 py-2 bg-emerald-600 hover:bg-emerald-500 text-white rounded-lg text-sm transition cursor-pointer"
>
Enregistrer
</ button >
</ div >
</ form >
</ div >
</ div >
< script >
document . addEventListener ( "DOMContentLoaded" , () => {
const toasts = document . querySelectorAll ( ".toast-message" );
toasts . forEach (( toast ) => {
setTimeout (() => {
toast . style . opacity = "0" ;
toast . style . transform = "translateY(-10px)" ;
setTimeout (() => toast . remove (), 300 );
}, 4000 );
});
});
function getInfosSocieteActive () {
const select = document . getElementById ( "select-societe-id" );
if ( ! select ) return { id : "" , nom : "" };
const selectedOption = select . options [ select . selectedIndex ];
return {
id : select . value ,
nom : selectedOption ? selectedOption . getAttribute ( "data-nom" ) : "" ,
};
}
function ouvrirModalCreation () {
const modal = document . getElementById ( "modal-compte-ecriture" );
const form = document . getElementById ( "form-modal-ecriture" );
const title = document . getElementById ( "modal-title" );
modal . classList . remove ( "hidden" );
2026-08-09 09:50:49 +02:00
form . action = "{{ url_for('comptes.creer_compte_traitement') }}" ;
2026-08-03 10:02:12 +02:00
title . innerHTML =
'<i class="fa-solid fa-plus-circle text-emerald-500"></i> Nouvelle écriture' ;
const societe = getInfosSocieteActive ();
document . getElementById ( "input-id-societe" ). value = societe . id ;
document . getElementById ( "input-nom-societe" ). value = societe . nom ;
document . getElementById ( "input-date-operation" ). value = "" ;
document . getElementById ( "input-libelle" ). value = "" ;
document . getElementById ( "input-credit" ). value = "0.00" ;
document . getElementById ( "input-debit" ). value = "0.00" ;
document . getElementById ( "btn-valider" ). textContent = "Enregistrer" ;
}
function ouvrirModalModification ( id , dateOp , debit , credit , libelle ) {
const modal = document . getElementById ( "modal-compte-ecriture" );
const form = document . getElementById ( "form-modal-ecriture" );
const title = document . getElementById ( "modal-title" );
modal . classList . remove ( "hidden" );
form . action = "/modifier_compte/" + id ;
title . innerHTML =
'<i class="fa-solid fa-pen text-blue-500"></i> Modifier l\'écriture' ;
const societe = getInfosSocieteActive ();
document . getElementById ( "input-id-societe" ). value = societe . id ;
document . getElementById ( "input-nom-societe" ). value = societe . nom ;
document . getElementById ( "input-date-operation" ). value = dateOp ;
document . getElementById ( "input-libelle" ). value =
libelle === "None" ? "" : libelle ;
document . getElementById ( "input-credit" ). value = credit ;
document . getElementById ( "input-debit" ). value = debit ;
document . getElementById ( "btn-valider" ). textContent = "Modifier" ;
}
function fermerModal () {
document . getElementById ( "modal-compte-ecriture" ). classList . add ( "hidden" );
}
</ script >
{% endblock %}