You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1691 lines
66 KiB
1691 lines
66 KiB
<!-- CDN SweetAlert2 -->
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
<style>
|
|
/* Style pour les champs en lecture seule */
|
|
input[readonly], select[disabled], textarea[readonly] {
|
|
background-color: #e9ecef !important;
|
|
cursor: not-allowed !important;
|
|
color: #6c757d;
|
|
}
|
|
|
|
/* Style pour la légende */
|
|
.field-legend {
|
|
background-color: #f8f9fa;
|
|
border-left: 4px solid #007bff;
|
|
padding: 10px 15px;
|
|
margin-bottom: 20px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.field-legend i {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.field-legend .legend-item {
|
|
display: inline-block;
|
|
margin-right: 20px;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
/* Effet hover sur les champs éditables */
|
|
.form-control:not([readonly]):not([disabled]):hover {
|
|
border-color: #007bff;
|
|
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.15);
|
|
transition: all 0.2s ease-in-out;
|
|
}
|
|
|
|
/* Icône d'édition */
|
|
.fa-edit {
|
|
font-size: 12px;
|
|
}
|
|
</style>
|
|
<!-- Content Wrapper. Contains page content -->
|
|
<div class="content-wrapper">
|
|
<!-- Content Header (Page header) -->
|
|
<section class="content-header">
|
|
<h1>
|
|
Gestion des
|
|
<small>Décaissement</small>
|
|
</h1>
|
|
<ol class="breadcrumb">
|
|
<li><a href="#"><i class="fa fa-dashboard"></i> Accueil</a></li>
|
|
<li class="active">Décaissement</li>
|
|
</ol>
|
|
</section>
|
|
|
|
<!-- Main content -->
|
|
<section class="content">
|
|
<div class="row">
|
|
<div class="col-md-12 col-xs-12">
|
|
<div id="messages"></div>
|
|
|
|
<?php if (session()->getFlashdata('success')): ?>
|
|
<div class="alert alert-success alert-dismissible" role="alert">
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<?php echo session()->getFlashdata('success'); ?>
|
|
</div>
|
|
<?php elseif (session()->getFlashdata('error')): ?>
|
|
<div class="alert alert-error alert-dismissible" role="alert">
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<?php echo session()->getFlashdata('error'); ?>
|
|
</div>
|
|
<?php elseif (session()->getFlashdata('errors')): ?>
|
|
<div class="alert alert-warning alert-dismissible" role="alert">
|
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<?php echo session()->getFlashdata('errors'); ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (in_array('createSortieCaisse', $user_permission)): ?>
|
|
<button class="btn btn-primary" data-toggle="modal" data-target="#createModal">Décaissement</button>
|
|
<br><br>
|
|
<?php endif; ?>
|
|
|
|
|
|
<!-- FILTRES EN DESSUS DU TABLEAU -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-2">
|
|
<label for="startDate" class="form-label">Date de début</label>
|
|
<input type="date" id="startDate" class="form-control">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="endDate" class="form-label">Date de fin</label>
|
|
<input type="date" id="endDate" class="form-control">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="pvente" class="form-label">Point de vente</label>
|
|
<select id="pvente" class="form-control">
|
|
<option value="TOUS">TOUS</option>
|
|
<?php foreach ($stores as $value): ?>
|
|
<option value="<?= $value['name']; ?>"><?= $value['name']; ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="s_statut" class="form-label">Statut du décaissement</label>
|
|
<select id="s_statut" class="form-control">
|
|
<option value="TOUS">TOUS</option>
|
|
<option value="Valider">Valider</option>
|
|
<option value="En attente">En attente</option>
|
|
<option value="Refuser">Refuser</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-1">
|
|
<br>
|
|
<button id="filteredB1" class="btn btn-primary w-100">Filtrer 🔍</button>
|
|
</div>
|
|
|
|
<div class="col-md-1">
|
|
<br>
|
|
<?php $session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil";
|
|
$isCaissier = $users['group_name'] == "Caissière";
|
|
if($isAdmin): ?>
|
|
<button id="validate_filtered" class="btn btn-primary w-100">A valider</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<br>
|
|
|
|
<div class="box">
|
|
<div class="box-header">
|
|
<h3 class="box-title">Gérer les Décaissements</h3>
|
|
</div>
|
|
<div class="box-body">
|
|
<table id="manageTable" class="table table-bordered table-striped">
|
|
<thead>
|
|
<tr>
|
|
<?php
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
|
|
if ($users['group_name'] === 'Caissière') {
|
|
?>
|
|
<th>#</th>
|
|
<th>Montant</th>
|
|
<th>Date</th>
|
|
<th>Caissier</th>
|
|
<th>Motif</th>
|
|
<th>Statut</th>
|
|
<th>Raison</th>
|
|
<?php if (in_array('updateSortieCaisse', $user_permission)) { ?>
|
|
<th>Action</th>
|
|
<?php } ?>
|
|
<?php
|
|
} elseif ($users['group_name'] === 'Direction' || $users['group_name'] === 'DAF') {
|
|
?>
|
|
<th>#</th>
|
|
<th>Montant</th>
|
|
<th>Date</th>
|
|
<th>Caissier</th>
|
|
<th>Motif</th>
|
|
<th>Source de fond</th>
|
|
<th>Initiateur de demande</th>
|
|
<th>Point de vente</th>
|
|
<th>Commentaire</th>
|
|
<th>Statut</th>
|
|
<?php if (in_array('updateSortieCaisse', $user_permission) || in_array('validateSortieCaisse', $user_permission)) { ?>
|
|
<th>Action</th>
|
|
<?php } ?>
|
|
<?php
|
|
} else {
|
|
?>
|
|
<th>#</th>
|
|
<th>Montant</th>
|
|
<th>Date</th>
|
|
<th>Caissier</th>
|
|
<th>Motif</th>
|
|
<th>Statut</th>
|
|
<th>Raison de validation</th>
|
|
<?php if (in_array('updateSortieCaisse', $user_permission)) { ?>
|
|
<th>Action</th>
|
|
<?php } ?>
|
|
<?php } ?>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-md-12">
|
|
<div class="btn-group float-right" role="group">
|
|
<a href="<?= base_url('sortieCaisse/exportExcel') ?>"
|
|
class="btn btn-success">
|
|
<i class="fa fa-file-excel-o"></i> Exporter Excel
|
|
</a>
|
|
<a href="<?= base_url('sortieCaisse/exportCsv') ?>"
|
|
class="btn btn-info">
|
|
<i class="fa fa-file-text-o"></i> Exporter CSV
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Optionnel: Formulaire de filtres pour l'exportation -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h4>Exporter avec filtres</h4>
|
|
</div>
|
|
<div class="card-body">
|
|
<form id="exportFilterForm" class="form-inline">
|
|
<div class="form-group mr-2">
|
|
<label for="date_debut" class="mr-2">Date début:</label>
|
|
<input type="date" class="form-control" id="date_debut" name="date_debut">
|
|
</div>
|
|
|
|
<div class="form-group mr-2">
|
|
<label for="date_fin" class="mr-2">Date fin:</label>
|
|
<input type="date" class="form-control" id="date_fin" name="date_fin">
|
|
</div>
|
|
|
|
<div class="form-group mr-2">
|
|
<label for="statut" class="mr-2">Statut:</label>
|
|
<select class="form-control" id="statut" name="statut">
|
|
<option value="">Tous</option>
|
|
<option value="En attente">En attente</option>
|
|
<option value="Valider">Validé</option>
|
|
<option value="Refuser">Refusé</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="btn-group" role="group">
|
|
<button type="button" class="btn btn-success" onclick="exportFiltered('excel')">
|
|
<i class="fa fa-file-excel-o"></i> Excel
|
|
</button>
|
|
<button type="button" class="btn btn-info" onclick="exportFiltered('csv')">
|
|
<i class="fa fa-file-text-o"></i> CSV
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Modal pour la Création -->
|
|
<?php if (in_array('createSortieCaisse', $user_permission)): ?>
|
|
<div class="modal fade" tabindex="-1" role="dialog" id="createModal">
|
|
<div class="modal-dialog modal-lg" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title">Ajouter un décaissement</h4>
|
|
</div>
|
|
|
|
<form role="form" id="create_form_sortie" enctype="multipart/form-data">
|
|
<div class="modal-body">
|
|
<!-- FORMULAIRE IM1 (Décaissement simple) - CORRIGÉ -->
|
|
<div id="form-im1">
|
|
<div class="text-center" style="margin-bottom: 20px;">
|
|
<h3 style="border-bottom: 2px solid #333; padding-bottom: 10px;">DEMANDE DE SORTIE DE CAISSE</h3>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="nom" class="form-label">Nom</label>
|
|
<input type="text" class="form-control" id="nom" name="nom" placeholder="Votre nom" autocomplete="off" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="fonction" class="form-label">Fonction</label>
|
|
<input type="text" class="form-control" id="fonction" name="fonction" placeholder="Votre fonction" autocomplete="off" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="motif_select" class="form-label">Motif</label>
|
|
|
|
<!-- Select avec liste + option "Autre" -->
|
|
<select class="form-control" id="motif_select_dropdown" name="motif_select_dropdown">
|
|
<?php
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil";
|
|
$isCaissier = $users['group_name'] == "Caissière";
|
|
$options = $isAdmin ? $admin_options : $caissier_options;
|
|
|
|
echo "<option value=''>Veuillez sélectionner une raison</option>\n";
|
|
|
|
foreach ($options as $option) {
|
|
echo "<option value=\"" . htmlspecialchars($option) . "\">" . htmlspecialchars($option) . "</option>\n";
|
|
}
|
|
?>
|
|
<option value="AUTRE">✏️ Autre (saisir manuellement)</option>
|
|
</select>
|
|
|
|
<!-- Input caché qui s'affiche quand on choisit "Autre" -->
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="motif_select_custom"
|
|
name="motif_select_custom"
|
|
placeholder="Saisissez votre motif personnalisé"
|
|
style="display: none; margin-top: 10px;"
|
|
>
|
|
|
|
<!-- Champ caché pour envoyer la valeur finale -->
|
|
<input type="hidden" id="motif_select" name="motif_select" required>
|
|
|
|
<small class="text-muted" style="display: block; margin-top: 5px;">
|
|
<i class="fa fa-info-circle"></i> Sélectionnez un motif prédéfini ou choisissez "Autre" pour saisir librement
|
|
</small>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="mode_paiement" class="form-label">Mode de paiement</label>
|
|
<select class="form-control" id="mode_paiement" name="mode_paiement" required>
|
|
<option value="En espèce">En espèce</option>
|
|
<option value="MVOLA">MVOLA</option>
|
|
<option value="Virement Bancaire">Virement Bancaire</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="montant_retire" class="form-label">Montant</label>
|
|
<!-- CORRECTION ICI : id ET name doivent être "montant_retire" -->
|
|
<input type="text" class="form-control" id="montant_retire" name="montant_retire" placeholder="Montant à retirer" autocomplete="off" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="montant_lettre" class="form-label">Montant en lettre</label>
|
|
<input type="text" class="form-control" id="montant_lettre" name="montant_lettre" placeholder="Montant en toutes lettres" readonly>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="date_demande" class="form-label">Date</label>
|
|
<input type="date" class="form-control" id="date_demande" name="date_demande" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="reference" class="form-label">Référence</label>
|
|
<input type="text" class="form-control" id="reference" name="reference" placeholder="Référence" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row text-center" style="margin-top: 30px;">
|
|
<div class="col-md-4">
|
|
<strong>DEMANDEUR</strong>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<strong>DIRECTION</strong>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<strong>CAISSE/COMPTA</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FORMULAIRE IM2 et IM3 (Pour montant > 1,000,000 Ar) -->
|
|
<div id="form-im23" style="display: none;">
|
|
<!-- Bouton de retour -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-12">
|
|
<button type="button" id="back-to-im1" class="btn btn-default btn-sm">
|
|
<i class="fa fa-arrow-left"></i> Retour à la demande simple
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center" style="margin-bottom: 20px;">
|
|
<h3 style="border-bottom: 2px solid #333; padding-bottom: 10px;">FICHE D'ENGAGEMENT DE DEPENSE</h3>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="numero_fiche" class="form-label">N°</label>
|
|
<input type="text" class="form-control" id="numero_fiche" name="numero_fiche" placeholder="Numéro de fiche" autocomplete="off">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="date_fiche" class="form-label">Date</label>
|
|
<input type="date" class="form-control" id="date_fiche" name="date_fiche">
|
|
</div>
|
|
</div>
|
|
|
|
<h4>I. IDENTIFICATION DE LA DEPENSE</h4>
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="service_demandeur" class="form-label">Service demandeur</label>
|
|
<input type="text" class="form-control" id="service_demandeur" name="service_demandeur" placeholder="Service demandeur" autocomplete="off">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="nom_demandeur" class="form-label">Nom du demandeur</label>
|
|
<input type="text" class="form-control" id="nom_demandeur" name="nom_demandeur" placeholder="Nom du demandeur" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="fonction_demandeur" class="form-label">Fonction</label>
|
|
<input type="text" class="form-control" id="fonction_demandeur" name="fonction_demandeur" placeholder="Fonction" autocomplete="off">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="objet_depense" class="form-label">Objet de la dépense</label>
|
|
<textarea class="form-control" id="objet_depense" name="objet_depense" rows="2" placeholder="Objet de la dépense"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-12 mb-3">
|
|
<label class="form-label">Nature de la dépense</label><br>
|
|
<div class="form-check form-check-inline">
|
|
<input class="form-check-input" type="radio" name="nature_depense" id="achat_materiel" value="Achat matériel">
|
|
<label class="form-check-label" for="achat_materiel">Achat matériel</label>
|
|
</div>
|
|
<div class="form-check form-check-inline">
|
|
<input class="form-check-input" type="radio" name="nature_depense" id="prestation_service" value="Prestation de service">
|
|
<label class="form-check-label" for="prestation_service">Prestation de service</label>
|
|
</div>
|
|
<div class="form-check form-check-inline">
|
|
<input class="form-check-input" type="radio" name="nature_depense" id="frais_mission" value="Frais de mission / déplacement">
|
|
<label class="form-check-label" for="frais_mission">Frais de mission / déplacement</label>
|
|
</div>
|
|
<div class="form-check form-check-inline">
|
|
<input class="form-check-input" type="radio" name="nature_depense" id="avance_fonds" value="Avance de fonds">
|
|
<label class="form-check-label" for="avance_fonds">Avance de fonds</label>
|
|
</div>
|
|
<div class="form-check form-check-inline">
|
|
<input class="form-check-input" type="radio" name="nature_depense" id="autre_nature" value="Autre">
|
|
<label class="form-check-label" for="autre_nature">Autres (à préciser)</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-4 mb-3">
|
|
<label for="montant_estime" class="form-label">Montant estimatif (en ariary)</label>
|
|
<input type="text" class="form-control" id="montant_estime" name="montant_estime" placeholder="Montant estimatif" autocomplete="off">
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label class="form-label">Mode de règlement</label><br>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="mode_reglement" id="espece" value="En espèce">
|
|
<label class="form-check-label" for="espece">En espèce</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="mode_reglement" id="virement" value="Virement Bancaire">
|
|
<label class="form-check-label" for="virement">Virement Bancaire</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="mode_reglement" id="mvola" value="MVOLA">
|
|
<label class="form-check-label" for="mvola">MVOLA</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4 mb-3">
|
|
<label for="date_paiement_prevue" class="form-label">Date prévue de paiement</label>
|
|
<input type="date" class="form-control" id="date_paiement_prevue" name="date_paiement_prevue">
|
|
</div>
|
|
</div>
|
|
|
|
<h4>II. JUSTIFICATIFS</h4>
|
|
<div class="row">
|
|
<div class="col-md-12 mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="devis_facture" name="justificatifs[]" value="Devis / facture pro forma">
|
|
<label class="form-check-label" for="devis_facture">Devis / facture pro forma</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="contrat_commande" name="justificatifs[]" value="Contrat / bon de commande">
|
|
<label class="form-check-label" for="contrat_commande">Contrat / bon de commande</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="demande_interne" name="justificatifs[]" value="Demande interne">
|
|
<label class="form-check-label" for="demande_interne">Demande interne</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="autre_justificatif" name="justificatifs[]" value="Autre">
|
|
<label class="form-check-label" for="autre_justificatif">Autre :</label>
|
|
<input type="text" class="form-control mt-1" id="autre_justificatif_precis" name="autre_justificatif_precis" placeholder="Préciser">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h4>III. VISAS ET VALIDATIONS</h4>
|
|
<table class="table table-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th>Fonction</th>
|
|
<th>Nom et signature</th>
|
|
<th>Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Demandeur</td>
|
|
<td><input type="text" class="form-control" name="visa_demandeur" placeholder="Nom et signature"></td>
|
|
<td><input type="date" class="form-control" name="date_visa_demandeur"></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Chef de service / Responsable hiérarchique</td>
|
|
<td><input type="text" class="form-control" name="visa_chef_service" placeholder="Nom et signature"></td>
|
|
<td><input type="date" class="form-control" name="date_visa_chef_service"></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Direction</td>
|
|
<td><input type="text" class="form-control" name="visa_direction" placeholder="Nom et signature"></td>
|
|
<td><input type="date" class="form-control" name="date_visa_direction"></td>
|
|
</tr>
|
|
<tr>
|
|
<td>Conseil d'Administration</td>
|
|
<td><input type="text" class="form-control" name="visa_conseil" placeholder="Nom et signature"></td>
|
|
<td><input type="date" class="form-control" name="date_visa_conseil"></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h4>IV. OBSERVATIONS ET REMARQUES</h4>
|
|
<div class="row">
|
|
<div class="col-md-12 mb-3">
|
|
<textarea class="form-control" id="observations" name="observations" rows="3" placeholder="Observations et remarques"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert alert-info">
|
|
<strong>NB :</strong> Cette fiche doit être jointe à la demande de sortie de caisse pour toute dépense supérieure à 1 000 000 Ar ou toute dépense nécessitant une traçabilité spécifique
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer text-right" style="margin-top: 15px;">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
|
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Modal for updatting a recouvrement -->
|
|
<!-- Modal for updating a sortie caisse --><!-- Modal for updating a sortie caisse -->
|
|
<?php if (in_array('updateSortieCaisse', $user_permission)): ?>
|
|
<div class="modal fade" tabindex="-1" role="dialog" id="updateModal">
|
|
<div class="modal-dialog modal-lg" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
<h4 class="modal-title"><i class="fa fa-pencil"></i> Modifier un décaissement</h4>
|
|
</div>
|
|
|
|
<form role="form" id="update_form" enctype="multipart/form-data">
|
|
<div class="modal-body">
|
|
|
|
<!-- Légende des champs -->
|
|
<div class="field-legend">
|
|
<div>
|
|
<strong><i class="fa fa-info-circle"></i> Légende :</strong>
|
|
</div>
|
|
<div class="legend-item">
|
|
<i class="fa fa-lock text-muted"></i> Champs verrouillés (lecture seule)
|
|
</div>
|
|
<div class="legend-item">
|
|
<i class="fa fa-edit text-primary"></i> Champs modifiables
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Informations de base - VERROUILLÉES -->
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="nom_edit" class="form-label"><i class="fa fa-lock text-muted"></i> Nom</label>
|
|
<input type="text" class="form-control" id="nom_edit" name="nom_edit" placeholder="Votre nom" autocomplete="off" required readonly style="background-color: #e9ecef; cursor: not-allowed;">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="fonction_edit" class="form-label"><i class="fa fa-lock text-muted"></i> Fonction</label>
|
|
<input type="text" class="form-control" id="fonction_edit" name="fonction_edit" placeholder="Votre fonction" autocomplete="off" required readonly style="background-color: #e9ecef; cursor: not-allowed;">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Motif et Mode de paiement -->
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="motif_select_edit" class="form-label">
|
|
<i class="fa fa-lock text-muted"></i> Motif
|
|
</label>
|
|
|
|
<!-- Select désactivé pour l'affichage -->
|
|
<select class="form-control" id="motif_select_edit_dropdown" disabled style="background-color: #e9ecef; cursor: not-allowed;">
|
|
<?php
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil";
|
|
$options = $isAdmin ? $admin_options : $caissier_options;
|
|
|
|
echo "<option value=''>Veuillez sélectionner une raison</option>\n";
|
|
|
|
foreach ($options as $option) {
|
|
echo "<option value=\"" . htmlspecialchars($option) . "\">" . htmlspecialchars($option) . "</option>\n";
|
|
}
|
|
?>
|
|
</select>
|
|
|
|
<!-- Champ caché pour envoyer la valeur (car le select est disabled) -->
|
|
<input type="hidden" id="motif_select_edit" name="motif_select_edit">
|
|
|
|
<small class="motif-help-text">
|
|
<i class="fa fa-info-circle"></i> Le motif ne peut pas être modifié
|
|
</small>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="mode_paiement_edit" class="form-label"><i class="fa fa-edit text-primary"></i> Mode de paiement</label>
|
|
<select class="form-control" id="mode_paiement_edit" name="mode_paiement_edit" required>
|
|
<option value="En espèce">En espèce</option>
|
|
<option value="MVOLA">MVOLA</option>
|
|
<option value="Virement Bancaire">Virement Bancaire</option>
|
|
</select>
|
|
<small class="text-muted"><i class="fa fa-info-circle"></i> Assurez-vous que les fonds sont disponibles pour ce mode</small>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Montant - VERROUILLÉ -->
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="montant_retire_edit" class="form-label"><i class="fa fa-lock text-muted"></i> Montant</label>
|
|
<input type="text" class="form-control" id="montant_retire_edit" name="montant_retire_edit" placeholder="Montant à retirer" autocomplete="off" required readonly style="background-color: #e9ecef; cursor: not-allowed;">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="montant_lettre_edit" class="form-label"><i class="fa fa-lock text-muted"></i> Montant en lettre</label>
|
|
<input type="text" class="form-control" id="montant_lettre_edit" name="montant_lettre_edit" placeholder="Montant en toutes lettres" autocomplete="off" required readonly style="background-color: #e9ecef; cursor: not-allowed;">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Date et Référence - VERROUILLÉES -->
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="date_demande_edit" class="form-label"><i class="fa fa-lock text-muted"></i> Date</label>
|
|
<input type="date" class="form-control" id="date_demande_edit" name="date_demande_edit" required readonly style="background-color: #e9ecef; cursor: not-allowed;">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="reference_edit" class="form-label"><i class="fa fa-lock text-muted"></i> Référence</label>
|
|
<input type="text" class="form-control" id="reference_edit" name="reference_edit" placeholder="Référence" autocomplete="off" readonly style="background-color: #e9ecef; cursor: not-allowed;">
|
|
</div>
|
|
</div>
|
|
|
|
<hr style="border-top: 2px dashed #007bff; margin: 25px 0;">
|
|
<h5 style="color: #007bff; margin-bottom: 15px;"><i class="fa fa-edit"></i> Informations modifiables</h5>
|
|
|
|
<!-- Commentaire - ÉDITABLE -->
|
|
<div class="row">
|
|
<div class="col-md-12 mb-3">
|
|
<label for="sortie_commentaire_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> Commentaire
|
|
</label>
|
|
<textarea class="form-control" id="sortie_commentaire_edit" name="sortie_commentaire_edit" rows="3" style="resize: vertical;" placeholder="Votre commentaire" autocomplete="off"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Informations fournisseur - ÉDITABLES -->
|
|
<div class="row">
|
|
<div class="col-md-4 mb-3">
|
|
<label for="sortie_fournisseur_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> Fournisseur & Prestataire
|
|
</label>
|
|
<input type="text" class="form-control" id="sortie_fournisseur_edit" name="sortie_fournisseur_edit" placeholder="Entrer le fournisseur ou le prestataire" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="col-md-4 mb-3">
|
|
<label for="sortie_nif_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> NIF & CIN
|
|
</label>
|
|
<input type="text" class="form-control" id="sortie_nif_edit" name="sortie_nif_edit" placeholder="NIF ou CIN" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="col-md-4 mb-3">
|
|
<label for="sortie_statistique_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> Statistique
|
|
</label>
|
|
<input type="text" class="form-control" id="sortie_statistique_edit" name="sortie_statistique_edit" placeholder="Statistique du décaissement" autocomplete="off">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Coordonnées - ÉDITABLES -->
|
|
<div class="row">
|
|
<div class="col-md-4 mb-3">
|
|
<label for="sortie_phone_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> Numéro téléphone
|
|
</label>
|
|
<input type="text" class="form-control" id="sortie_phone_edit" name="sortie_phone_edit" placeholder="Entrer le numéro de téléphone" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="col-md-4 mb-3">
|
|
<label for="sortie_adresse_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> Code postal
|
|
</label>
|
|
<input type="text" class="form-control" id="sortie_adresse_edit" name="sortie_adresse_edit" placeholder="Entrer le code postal" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="col-md-4 mb-3">
|
|
<label for="sortie_preuve_edit" class="form-label">
|
|
<i class="fa fa-edit text-primary"></i> Preuve d'achat
|
|
<small class="text-muted">(Facultatif)</small>
|
|
</label>
|
|
<input type="file" accept=".pdf, .txt, .xls, .xlsx, .csv" class="form-control" id="sortie_preuve_edit" name="sortie_preuve_edit">
|
|
<small class="text-muted" id="current_preuve_text"></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer text-right" style="margin-top: 15px;">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
|
<i class="fa fa-times"></i> Annuler
|
|
</button>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fa fa-save"></i> Enregistrer les modifications
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Modal for validating a recouvrement -->
|
|
<?php if (in_array('validateSortieCaisse', $user_permission)): ?>
|
|
<div class="modal fade" tabindex="-1" role="dialog" id="validateModal">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
<h4 class="modal-title">Valider un décaissement</h4>
|
|
</div>
|
|
|
|
<form role="form" action="<?php echo base_url('sortieCaisse/validateSortieCaisse') ?>" method="post" id="validate_form">
|
|
<div class="modal-body">
|
|
<div class="row form-group">
|
|
<div class="col-lg-6">
|
|
<label for="validation" class="control-label">statut :</label>
|
|
</div>
|
|
|
|
<div class="col-lg-6">
|
|
<div class="form-group">
|
|
<label for="admin_raison">Raison de validation</label>
|
|
<input type="text" class="form-control" id="admin_raison" name="admin_raison">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="statut">Statut du décaissement</label>
|
|
<select name="statut" id="statut" class="form-control">
|
|
<option value="En attente" selected>En attente</option>
|
|
<option value="Valider">✔ Valider</option>
|
|
<option value="Refuser">✖ Refuser</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Annuler</button>
|
|
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<script>
|
|
// ============================================
|
|
// CONVERSION NOMBRE EN LETTRES (FRANÇAIS)
|
|
// ============================================
|
|
function numberToFrenchWords(n) {
|
|
const units = [
|
|
'', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf',
|
|
'dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize',
|
|
'dix-sept', 'dix-huit', 'dix-neuf'
|
|
];
|
|
const tens = [
|
|
'', '', 'vingt', 'trente', 'quarante', 'cinquante',
|
|
'soixante', 'soixante', 'quatre-vingt', 'quatre-vingt'
|
|
];
|
|
|
|
if (n === 0) return 'zéro';
|
|
if (n < 0) return 'moins ' + numberToFrenchWords(-n);
|
|
|
|
let words = '';
|
|
|
|
if (Math.floor(n / 1000000000) > 0) {
|
|
words += numberToFrenchWords(Math.floor(n / 1000000000)) + ' milliard' + (n >= 2000000000 ? 's ' : ' ');
|
|
n %= 1000000000;
|
|
}
|
|
|
|
if (Math.floor(n / 1000000) > 0) {
|
|
words += numberToFrenchWords(Math.floor(n / 1000000)) + ' million' + (n >= 2000000 ? 's ' : ' ');
|
|
n %= 1000000;
|
|
}
|
|
|
|
if (Math.floor(n / 1000) > 0) {
|
|
if (Math.floor(n / 1000) === 1) {
|
|
words += 'mille ';
|
|
} else {
|
|
words += numberToFrenchWords(Math.floor(n / 1000)) + ' mille ';
|
|
}
|
|
n %= 1000;
|
|
}
|
|
|
|
if (Math.floor(n / 100) > 0) {
|
|
if (Math.floor(n / 100) === 1) {
|
|
words += 'cent ';
|
|
} else {
|
|
words += numberToFrenchWords(Math.floor(n / 100)) + ' cent';
|
|
if (n % 100 === 0) words += 's';
|
|
words += ' ';
|
|
}
|
|
n %= 100;
|
|
}
|
|
|
|
if (n > 0) {
|
|
if (n < 20) {
|
|
words += units[n];
|
|
} else {
|
|
let ten = Math.floor(n / 10);
|
|
let unit = n % 10;
|
|
|
|
if (ten === 7 || ten === 9) {
|
|
ten--;
|
|
unit += 10;
|
|
}
|
|
|
|
words += tens[ten];
|
|
if (unit === 1 && (ten === 1 || (ten > 1 && ten < 8))) {
|
|
words += '-et-un';
|
|
} else if (unit > 0) {
|
|
words += '-' + units[unit];
|
|
}
|
|
|
|
if (ten === 8 && unit === 0) words += 's';
|
|
}
|
|
}
|
|
|
|
return words.trim();
|
|
}
|
|
|
|
// ============================================
|
|
// FORMATAGE PAR GROUPE DE 3
|
|
// ============================================
|
|
function formatNumberBy3(num) {
|
|
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
|
|
}
|
|
|
|
// ============================================
|
|
// FONCTION D'EXPORTATION FILTRÉE
|
|
// ============================================
|
|
function exportFiltered(format) {
|
|
const dateDebut = document.getElementById('date_debut').value;
|
|
const dateFin = document.getElementById('date_fin').value;
|
|
const statut = document.getElementById('statut').value;
|
|
|
|
let url = '<?= base_url('sortieCaisse/exportWithFilters') ?>?format=' + format;
|
|
|
|
if (dateDebut) url += '&date_debut=' + dateDebut;
|
|
if (dateFin) url += '&date_fin=' + dateFin;
|
|
if (statut) url += '&statut=' + encodeURIComponent(statut);
|
|
|
|
window.location.href = url;
|
|
}
|
|
|
|
// ============================================
|
|
// SCRIPT PRINCIPAL
|
|
// ============================================
|
|
$(document).ready(function() {
|
|
// Configuration DataTable FR
|
|
$.extend(true, $.fn.dataTable.defaults, {
|
|
language: {
|
|
sProcessing: "Traitement en cours...",
|
|
sSearch: "Rechercher :",
|
|
sLengthMenu: "Afficher _MENU_ éléments",
|
|
sInfo: "Affichage de l'élement _START_ à _END_ sur _TOTAL_ éléments",
|
|
sInfoEmpty: "Affichage de l'élement 0 à 0 sur 0 élément",
|
|
sInfoFiltered: "(filtré de _MAX_ éléments au total)",
|
|
sLoadingRecords: "Chargement en cours...",
|
|
sZeroRecords: "Aucun élément à afficher",
|
|
sEmptyTable: "Aucune donnée disponible dans le tableau",
|
|
oPaginate: {
|
|
sFirst: "Premier",
|
|
sPrevious: "Précédent",
|
|
sNext: "Suivant",
|
|
sLast: "Dernier"
|
|
},
|
|
oAria: {
|
|
sSortAscending: ": activer pour trier la colonne par ordre croissant",
|
|
sSortDescending: ": activer pour trier la colonne par ordre décroissant"
|
|
}
|
|
}
|
|
});
|
|
|
|
$("#sortie_caisse_menu").addClass('active');
|
|
|
|
var manageTable = $('#manageTable').DataTable({
|
|
ajax: '<?= base_url('sortieCaisse/fetchSortieCaisseData') ?>',
|
|
order: [],
|
|
columnDefs: [
|
|
{ targets: 1, className: 'text-right rowmontant' }
|
|
]
|
|
});
|
|
|
|
// ============================================
|
|
// INITIALISATION DES DATES
|
|
// ============================================
|
|
const today = new Date().toISOString().split('T')[0];
|
|
$('#date_demande').val(today);
|
|
$('#date_fiche').val(today);
|
|
|
|
// ============================================
|
|
// ✅ GESTION DU CHAMP MOTIF SELECT MODIFIABLE
|
|
// ============================================
|
|
|
|
// Gestion du select motif avec option personnalisée
|
|
$('#motif_select_dropdown').on('change', function() {
|
|
const selectedValue = $(this).val();
|
|
|
|
if (selectedValue === 'AUTRE') {
|
|
// Afficher le champ de saisie libre
|
|
$('#motif_select_custom').show().focus();
|
|
$('#motif_select').val(''); // Vider le champ caché
|
|
} else {
|
|
// Cacher le champ de saisie et utiliser la valeur sélectionnée
|
|
$('#motif_select_custom').hide().val('');
|
|
$('#motif_select').val(selectedValue);
|
|
}
|
|
});
|
|
|
|
// Mettre à jour le champ caché quand on tape dans le champ personnalisé
|
|
$('#motif_select_custom').on('input', function() {
|
|
const customValue = $(this).val();
|
|
$('#motif_select').val(customValue);
|
|
});
|
|
|
|
// ============================================
|
|
// GESTION DU MONTANT ET CONVERSION EN LETTRES
|
|
// ============================================
|
|
const montantInput = $('#montant_retire');
|
|
const montantLettreInput = $('#montant_lettre');
|
|
|
|
montantInput.on('input', function() {
|
|
let value = this.value.replace(/\s/g, '');
|
|
|
|
if (isNaN(value) || value === '') {
|
|
montantLettreInput.val('');
|
|
return;
|
|
}
|
|
|
|
const num = parseInt(value, 10);
|
|
this.value = formatNumberBy3(value);
|
|
|
|
const words = numberToFrenchWords(num);
|
|
montantLettreInput.val(words + ' ariary');
|
|
|
|
// ✅ Gestion du basculement de formulaire - CORRIGÉ >= 1000000
|
|
if (num >= 1000000) {
|
|
$('#nom_demandeur').val($('#nom').val());
|
|
$('#fonction_demandeur').val($('#fonction').val());
|
|
$('#montant_estime').val(this.value);
|
|
$('#date_fiche').val($('#date_demande').val());
|
|
|
|
$('#form-im1').hide();
|
|
$('#form-im23').show();
|
|
} else {
|
|
$('#form-im1').show();
|
|
$('#form-im23').hide();
|
|
}
|
|
});
|
|
|
|
// Retour au formulaire simple
|
|
$('#back-to-im1').on('click', function() {
|
|
$('#form-im23').hide();
|
|
$('#form-im1').show();
|
|
montantInput.val('999999');
|
|
montantInput.trigger('input');
|
|
});
|
|
|
|
// Synchronisation des montants
|
|
montantInput.on('change', function() {
|
|
$('#montant_estime').val($(this).val());
|
|
});
|
|
|
|
$('#montant_estime').on('change', function() {
|
|
montantInput.val($(this).val());
|
|
montantInput.trigger('input');
|
|
});
|
|
|
|
// ✅ Réinitialisation du modal - AVEC RÉINITIALISATION DU MOTIF
|
|
$('#createModal').on('hidden.bs.modal', function () {
|
|
$('#form-im1').show();
|
|
$('#form-im23').hide();
|
|
$('#create_form_sortie')[0].reset();
|
|
$('#date_demande').val(today);
|
|
$('#date_fiche').val(today);
|
|
montantLettreInput.val('');
|
|
|
|
// ✅ Réinitialiser les champs motif
|
|
$('#motif_select_dropdown').val('');
|
|
$('#motif_select_custom').hide().val('');
|
|
$('#motif_select').val('');
|
|
});
|
|
|
|
// ============================================
|
|
// FILTRES
|
|
// ============================================
|
|
$('#filteredB1').on('click', function () {
|
|
const startDate = $('#startDate').val();
|
|
const endDate = $('#endDate').val();
|
|
const pvente = $('#pvente').val();
|
|
const s_statut = $('#s_statut').val();
|
|
|
|
manageTable.ajax.url('<?= base_url('sortieCaisse/fetchSortieCaisseData') ?>').load(function () {
|
|
const filteredData = [];
|
|
|
|
manageTable.rows().every(function () {
|
|
const data = this.data();
|
|
const SortieDate = data[2].split(' ')[0];
|
|
|
|
<?php
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = $users['group_name'] == "Direction" || $users['group_name'] == "Conseil";
|
|
?>
|
|
|
|
<?php if($isAdmin): ?>
|
|
const sortie_statut1 = data[9].split(' ')[0];
|
|
const store = data[7];
|
|
<?php else: ?>
|
|
const sortie_statut1 = data[5].split(' ')[0];
|
|
const store = 'TOUS';
|
|
<?php endif; ?>
|
|
|
|
const dateMatch = (!startDate && !endDate) ||
|
|
(startDate && endDate && SortieDate >= startDate && SortieDate <= endDate) ||
|
|
(startDate && !endDate && SortieDate >= startDate) ||
|
|
(!startDate && endDate && SortieDate <= endDate);
|
|
|
|
const storeMatch = (pvente === 'TOUS' || pvente === store);
|
|
const statutMatch = (s_statut === 'TOUS' || s_statut === sortie_statut1);
|
|
|
|
if (dateMatch && storeMatch && statutMatch) {
|
|
filteredData.push(data);
|
|
}
|
|
});
|
|
|
|
manageTable.clear().rows.add(filteredData).draw();
|
|
});
|
|
});
|
|
|
|
$('#validate_filtered').on('click', function () {
|
|
manageTable.ajax.url('<?= base_url('sortieCaisse/fetchSortieCaisseData1') ?>').load();
|
|
});
|
|
|
|
// ============================================
|
|
// ✅ CRÉATION AVEC SWEETALERT2 + VALIDATION MOTIF
|
|
// ============================================
|
|
$("#create_form_sortie").unbind('submit').on('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
$(".text-danger").remove();
|
|
|
|
// ✅ Validation du motif
|
|
const motifValue = $('#motif_select').val();
|
|
|
|
if (!motifValue || motifValue.trim() === '') {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Motif requis',
|
|
text: 'Veuillez sélectionner ou saisir un motif',
|
|
confirmButtonColor: '#f39c12'
|
|
});
|
|
return false;
|
|
}
|
|
|
|
var formData = new FormData(this);
|
|
|
|
// CORRECTION : Nettoyer le montant des espaces avant validation
|
|
const montantRaw = $('#montant_retire').val();
|
|
const montantClean = montantRaw.replace(/\s/g, '');
|
|
|
|
// Vérification du montant avant l'envoi
|
|
const montant = parseFloat(montantClean);
|
|
|
|
if (isNaN(montant) || montant <= 0) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Montant invalide',
|
|
text: 'Veuillez saisir un montant valide supérieur à 0',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
return false;
|
|
}
|
|
|
|
// CORRECTION : Remplacer la valeur dans le FormData
|
|
formData.set('montant_retire', montantClean);
|
|
|
|
// Afficher un loader
|
|
Swal.fire({
|
|
title: 'Création en cours...',
|
|
html: 'Vérification des fonds disponibles...',
|
|
allowOutsideClick: false,
|
|
showConfirmButton: false,
|
|
didOpen: () => {
|
|
Swal.showLoading();
|
|
}
|
|
});
|
|
|
|
$.ajax({
|
|
url: '<?= base_url('sortieCaisse/createSortieCaisse') ?>',
|
|
type: 'post',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false,
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
manageTable.ajax.reload(null, false);
|
|
|
|
if (response.success === true) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Décaissement créé !',
|
|
html: response.messages,
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#28a745',
|
|
customClass: {
|
|
popup: 'animated fadeInDown'
|
|
}
|
|
}).then(() => {
|
|
$("#createModal").modal('hide');
|
|
$("#create_form_sortie")[0].reset();
|
|
$("#create_form_sortie .form-group").removeClass('has-error has-success');
|
|
$('#date_demande').val(today);
|
|
$('#date_fiche').val(today);
|
|
|
|
// ✅ Réinitialiser les champs motif
|
|
$('#motif_select_dropdown').val('');
|
|
$('#motif_select_custom').hide().val('');
|
|
$('#motif_select').val('');
|
|
});
|
|
|
|
} else {
|
|
// Gestion des erreurs avec SweetAlert
|
|
if (response.messages instanceof Object) {
|
|
let errorHtml = '<ul style="text-align: left; margin: 10px 0;">';
|
|
$.each(response.messages, function(index, value) {
|
|
errorHtml += '<li style="margin: 5px 0;">' + value + '</li>';
|
|
var id = $("#" + index);
|
|
id.closest('.form-group')
|
|
.removeClass('has-error has-success')
|
|
.addClass('has-error');
|
|
id.after('<span class="text-danger">' + value + '</span>');
|
|
});
|
|
errorHtml += '</ul>';
|
|
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Erreurs de validation',
|
|
html: errorHtml,
|
|
confirmButtonText: 'Corriger',
|
|
confirmButtonColor: '#f39c12',
|
|
customClass: {
|
|
popup: 'animated shake'
|
|
}
|
|
});
|
|
} else {
|
|
// Affichage amélioré pour les erreurs de fonds insuffisants
|
|
const isInsufficientFunds = response.messages.includes('insuffisants');
|
|
|
|
Swal.fire({
|
|
icon: isInsufficientFunds ? 'warning' : 'error',
|
|
title: isInsufficientFunds ? '⚠️ Fonds insuffisants' : 'Erreur',
|
|
html: '<div style="text-align: left;">' + response.messages + '</div>',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: isInsufficientFunds ? '#f39c12' : '#dc3545',
|
|
width: '600px',
|
|
customClass: {
|
|
popup: 'animated fadeInDown'
|
|
}
|
|
});
|
|
}
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('Erreur AJAX:', error);
|
|
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur serveur',
|
|
html: '<p>Une erreur est survenue lors de la création du décaissement.</p>' +
|
|
'<p><small>Détails techniques: ' + error + '</small></p>',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
}
|
|
});
|
|
|
|
return false;
|
|
});
|
|
|
|
// ============================================
|
|
// ✅ MODIFICATION AVEC SWEETALERT2 + GESTION MOTIF PERSONNALISÉ
|
|
// ============================================
|
|
window.editFunc = function(id) {
|
|
$.ajax({
|
|
url: '<?= base_url('sortieCaisse/fetchSortieCaisseSingle') ?>/' + id,
|
|
type: 'post',
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
// Remplir tous les champs
|
|
$("#montant_retire_edit").val(response.montant_retire);
|
|
$("#nom_edit").val(response.nom_demandeur);
|
|
$("#fonction_edit").val(response.fonction_demandeur);
|
|
$("#montant_lettre_edit").val(response.montant_lettre);
|
|
$("#date_demande_edit").val(response.date_demande);
|
|
$("#reference_edit").val(response.reference);
|
|
$("#sortie_commentaire_edit").val(response.commentaire);
|
|
$("#sortie_fournisseur_edit").val(response.fournisseur);
|
|
$("#sortie_nif_edit").val(response.nif_cin);
|
|
$("#sortie_statistique_edit").val(response.statistique);
|
|
$("#sortie_phone_edit").val(response.telephone);
|
|
$("#sortie_adresse_edit").val(response.code_postal);
|
|
|
|
const initialModePaiement = response.mode_paiement || 'En espèce';
|
|
$("#mode_paiement_edit").val(initialModePaiement);
|
|
|
|
// ✅ Gérer le motif - AVEC SUPPORT DES MOTIFS PERSONNALISÉS
|
|
const motif = response.motif;
|
|
const motifSelectDropdown = $("#motif_select_edit_dropdown");
|
|
|
|
// Vérifier si le motif existe dans la liste
|
|
const optionExists = motifSelectDropdown.find('option').filter(function() {
|
|
return $(this).val().trim().toLowerCase() === motif.trim().toLowerCase();
|
|
}).length > 0;
|
|
|
|
if (optionExists) {
|
|
motifSelectDropdown.val(motif);
|
|
} else {
|
|
// ✅ Si le motif n'existe pas, l'afficher quand même avec un indicateur
|
|
motifSelectDropdown.append('<option value="' + motif + '" selected>🔸 ' + motif + ' (personnalisé)</option>');
|
|
}
|
|
|
|
// Mettre la valeur dans le champ caché
|
|
$("#motif_select_edit").val(motif);
|
|
|
|
if (response.preuve_achat) {
|
|
$("#current_preuve_text").html('<br><i class="fa fa-file"></i> Fichier actuel: ' + response.preuve_achat);
|
|
} else {
|
|
$("#current_preuve_text").html('<br><i class="text-muted">Aucun fichier</i>');
|
|
}
|
|
|
|
// Listener sur le mode de paiement
|
|
$("#mode_paiement_edit").off('change').on('change', function() {
|
|
const nouveauMode = $(this).val();
|
|
|
|
if (nouveauMode !== initialModePaiement) {
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Changement de mode de paiement',
|
|
html: '<div style="text-align: center;">' +
|
|
'<strong>Attention !</strong><br><br>' +
|
|
'Vous changez le mode de paiement :<br><br>' +
|
|
'<span style="font-size: 18px;">' +
|
|
'<span style="color: #dc3545; font-weight: bold;">' + initialModePaiement + '</span>' +
|
|
' <i class="fa fa-arrow-right"></i> ' +
|
|
'<span style="color: #28a745; font-weight: bold;">' + nouveauMode + '</span>' +
|
|
'</span><br><br>' +
|
|
'<em style="color: #856404;">Assurez-vous que les fonds sont disponibles.</em>' +
|
|
'</div>',
|
|
showCancelButton: true,
|
|
confirmButtonText: '<i class="fa fa-check"></i> Confirmer',
|
|
cancelButtonText: '<i class="fa fa-times"></i> Annuler',
|
|
confirmButtonColor: '#007bff',
|
|
cancelButtonColor: '#6c757d'
|
|
}).then((result) => {
|
|
if (!result.isConfirmed) {
|
|
$("#mode_paiement_edit").val(initialModePaiement);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Soumission du formulaire - CORRIGÉ
|
|
$("#update_form").unbind('submit').bind('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
$(".text-danger").remove();
|
|
var formData = new FormData(this);
|
|
|
|
// CORRECTION : Nettoyer le montant des espaces pour l'édition
|
|
const montantRawEdit = $('#montant_retire_edit').val();
|
|
const montantCleanEdit = montantRawEdit.replace(/\s/g, '');
|
|
formData.set('montant_retire', montantCleanEdit);
|
|
|
|
Swal.fire({
|
|
title: 'Modification en cours...',
|
|
html: 'Vérification des fonds disponibles...',
|
|
allowOutsideClick: false,
|
|
showConfirmButton: false,
|
|
didOpen: () => {
|
|
Swal.showLoading();
|
|
}
|
|
});
|
|
|
|
$.ajax({
|
|
url: '<?= base_url('sortieCaisse/updateSortieCaisse') ?>/' + id,
|
|
type: 'post',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false,
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
manageTable.ajax.reload(null, false);
|
|
|
|
if (response.success === true) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Modification réussie !',
|
|
html: response.messages,
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#28a745'
|
|
}).then(() => {
|
|
$("#updateModal").modal('hide');
|
|
$("#update_form")[0].reset();
|
|
});
|
|
} else {
|
|
if (response.messages instanceof Object) {
|
|
let errorHtml = '<ul style="text-align: left;">';
|
|
$.each(response.messages, function(index, value) {
|
|
errorHtml += '<li>' + value + '</li>';
|
|
var input = $("#" + index);
|
|
input.closest('.form-group').addClass('has-error');
|
|
input.after('<span class="text-danger">' + value + '</span>');
|
|
});
|
|
errorHtml += '</ul>';
|
|
|
|
Swal.fire({
|
|
icon: 'warning',
|
|
title: 'Erreur de validation',
|
|
html: errorHtml,
|
|
confirmButtonText: 'Corriger',
|
|
confirmButtonColor: '#f39c12'
|
|
});
|
|
} else {
|
|
const isInsufficientFunds = response.messages.includes('insuffisants');
|
|
|
|
Swal.fire({
|
|
icon: isInsufficientFunds ? 'warning' : 'error',
|
|
title: isInsufficientFunds ? '⚠️ Fonds insuffisants' : 'Erreur',
|
|
html: '<div style="text-align: left;">' + response.messages + '</div>',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: isInsufficientFunds ? '#f39c12' : '#dc3545',
|
|
width: '600px'
|
|
});
|
|
}
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur serveur',
|
|
text: 'Une erreur est survenue lors de la modification.',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
}
|
|
});
|
|
|
|
return false;
|
|
});
|
|
},
|
|
error: function(xhr, status, error) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur',
|
|
text: 'Impossible de récupérer les données du décaissement',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
// ============================================
|
|
// VALIDATION
|
|
// ============================================
|
|
window.validateFunc = function(id) {
|
|
$.ajax({
|
|
url: '<?= base_url('sortieCaisse/fetchSortieCaisseSingle') ?>/' + id,
|
|
type: 'post',
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
var statut = response.statut;
|
|
|
|
if (statut === "En attente" || statut === "Refuser") {
|
|
$("#statut").val(response.statut);
|
|
$("#admin_raison").val(response.admin_raison);
|
|
$("#validateModal").modal('show');
|
|
|
|
$("#validate_form").unbind('submit').bind('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
$(".text-danger").remove();
|
|
|
|
$.ajax({
|
|
url: '<?= base_url('sortieCaisse/validateSortieCaisse') ?>/' + id,
|
|
type: 'post',
|
|
data: $(this).serialize(),
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
manageTable.ajax.reload(null, false);
|
|
|
|
if (response.success === true) {
|
|
$("#messages").html('<div class="alert alert-success alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert">×</button>' +
|
|
'<strong><span class="glyphicon glyphicon-ok-sign"></span></strong> ' + response.messages +
|
|
'</div>');
|
|
|
|
$("#validateModal").modal('hide');
|
|
$("#validate_form .form-group").removeClass('has-error has-success');
|
|
} else {
|
|
if (typeof response.messages === 'object') {
|
|
$.each(response.messages, function(index, value) {
|
|
var input = $("#" + index);
|
|
input.closest('.form-group')
|
|
.removeClass('has-error has-success')
|
|
.addClass(value.length > 0 ? 'has-error' : 'has-success');
|
|
input.after('<span class="text-danger">' + value + '</span>');
|
|
});
|
|
} else {
|
|
$("#messages").html('<div class="alert alert-warning alert-dismissible" role="alert">' +
|
|
'<button type="button" class="close" data-dismiss="alert">×</button>' +
|
|
'<strong><span class="glyphicon glyphicon-exclamation-sign"></span></strong> ' + response.messages +
|
|
'</div>');
|
|
}
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur',
|
|
text: 'Une erreur est survenue lors de la validation.',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#dc3545'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
} else {
|
|
Swal.fire({
|
|
icon: 'info',
|
|
title: 'Déjà validé',
|
|
html: '<p style="font-size: 16px;">Ce décaissement est déjà validé et ne peut pas être modifié.</p>',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#17a2b8',
|
|
width: '500px'
|
|
});
|
|
}
|
|
},
|
|
error: function() {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur',
|
|
text: 'Une erreur est survenue lors de la récupération des données.',
|
|
confirmButtonText: 'OK'
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
});
|
|
|
|
// ============================================
|
|
// MARQUER COMME PAYÉ
|
|
// ============================================
|
|
window.markAsPaidFunc = function(id_sortie) {
|
|
Swal.fire({
|
|
title: '💰 Confirmer le paiement',
|
|
html: '<div style="text-align: center;">' +
|
|
'<p style="font-size: 16px; margin: 20px 0;">Êtes-vous sûr(e) de vouloir marquer ce décaissement comme <strong>PAYÉ</strong> ?</p>' +
|
|
'<div style="background-color: #fff3cd; padding: 15px; border-radius: 5px; border-left: 4px solid #ffc107; margin-top: 15px;">' +
|
|
'<i class="fa fa-info-circle" style="color: #856404;"></i> ' +
|
|
'<strong style="color: #856404;">Cette action va :</strong><br>' +
|
|
'<ul style="text-align: left; margin-top: 10px; color: #856404;">' +
|
|
'<li>Changer le statut de "Validé" à "Payé"</li>' +
|
|
'<li>Notifier la Direction et le DAF</li>' +
|
|
'<li>Enregistrer la date de paiement</li>' +
|
|
'</ul>' +
|
|
'</div>' +
|
|
'</div>',
|
|
icon: 'question',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#28a745',
|
|
cancelButtonColor: '#6c757d',
|
|
confirmButtonText: '<i class="fa fa-check"></i> Oui, marquer comme payé',
|
|
cancelButtonText: '<i class="fa fa-times"></i> Annuler',
|
|
customClass: {
|
|
popup: 'animated fadeInDown'
|
|
}
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// Afficher un loader
|
|
Swal.fire({
|
|
title: 'Traitement en cours...',
|
|
html: 'Mise à jour du statut et envoi des notifications...',
|
|
allowOutsideClick: false,
|
|
allowEscapeKey: false,
|
|
showConfirmButton: false,
|
|
didOpen: () => {
|
|
Swal.showLoading();
|
|
}
|
|
});
|
|
|
|
// Envoi de la requête AJAX
|
|
$.ajax({
|
|
url: '<?= base_url('sortieCaisse/markAsPaid') ?>/' + id_sortie,
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
if (response.success === true) {
|
|
// ✅ SUCCÈS : Afficher le message puis actualiser
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Paiement enregistré !',
|
|
html: response.messages + '<br><br><em>La page va se recharger...</em>',
|
|
confirmButtonText: 'OK',
|
|
confirmButtonColor: '#28a745',
|
|
timer: 2500,
|
|
timerProgressBar: true,
|
|
allowOutsideClick: false,
|
|
customClass: {
|
|
popup: 'animated bounceIn'
|
|
}
|
|
}).then(() => {
|
|
// ✅ ACTUALISER LA PAGE
|
|
location.reload();
|
|
});
|
|
} else {
|
|
// ❌ ERREUR : Afficher le message puis actualiser
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur',
|
|
html: response.messages + '<br><br><em>La page va se recharger...</em>',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#dc3545',
|
|
timer: 3000,
|
|
timerProgressBar: true,
|
|
allowOutsideClick: false,
|
|
customClass: {
|
|
popup: 'animated shake'
|
|
}
|
|
}).then(() => {
|
|
// ✅ ACTUALISER LA PAGE MÊME EN CAS D'ERREUR
|
|
location.reload();
|
|
});
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('Erreur AJAX markAsPaid:', error);
|
|
console.error('Réponse complète:', xhr.responseText);
|
|
|
|
// ❌ ERREUR SERVEUR : Afficher puis actualiser
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Erreur serveur',
|
|
html: '<p>Une erreur est survenue lors du changement de statut.</p>' +
|
|
'<p><small>Détails : ' + error + '</small></p>' +
|
|
'<br><em>La page va se recharger...</em>',
|
|
confirmButtonText: 'Fermer',
|
|
confirmButtonColor: '#dc3545',
|
|
timer: 3000,
|
|
timerProgressBar: true,
|
|
allowOutsideClick: false
|
|
}).then(() => {
|
|
// ✅ ACTUALISER LA PAGE
|
|
location.reload();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
};
|
|
</script>
|
|
<style>
|
|
/* Style pour les champs en lecture seule */
|
|
input[readonly], select[disabled], textarea[readonly] {
|
|
background-color: #e9ecef !important;
|
|
cursor: not-allowed !important;
|
|
color: #6c757d;
|
|
}
|
|
|
|
/* Style pour la légende */
|
|
.field-legend {
|
|
background-color: #f8f9fa;
|
|
border-left: 4px solid #007bff;
|
|
padding: 10px 15px;
|
|
margin-bottom: 20px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.field-legend i {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.field-legend .legend-item {
|
|
display: inline-block;
|
|
margin-right: 20px;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
/* Effet hover sur les champs éditables */
|
|
.form-control:not([readonly]):not([disabled]):hover {
|
|
border-color: #007bff;
|
|
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.15);
|
|
transition: all 0.2s ease-in-out;
|
|
}
|
|
|
|
/* Icône d'édition */
|
|
.fa-edit {
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* ============================================ */
|
|
/* ✅ STYLES POUR LE CHAMP MOTIF MODIFIABLE */
|
|
/* ============================================ */
|
|
|
|
/* Animation pour l'apparition du champ personnalisé */
|
|
#motif_select_custom {
|
|
animation: slideDown 0.3s ease-in-out;
|
|
}
|
|
|
|
@keyframes slideDown {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(-10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Style pour l'option "Autre" */
|
|
#motif_select_dropdown option[value="AUTRE"] {
|
|
background-color: #fff3cd;
|
|
font-weight: bold;
|
|
color: #856404;
|
|
}
|
|
|
|
/* Mettre en évidence le champ actif */
|
|
#motif_select_custom:focus {
|
|
border-color: #28a745;
|
|
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
|
|
}
|
|
|
|
/* Style pour le champ personnalisé */
|
|
#motif_select_custom {
|
|
border-left: 4px solid #28a745;
|
|
}
|
|
|
|
/* Style pour le texte d'aide */
|
|
.motif-help-text {
|
|
font-size: 12px;
|
|
color: #6c757d;
|
|
margin-top: 5px;
|
|
display: block;
|
|
}
|
|
|
|
.motif-help-text i {
|
|
margin-right: 3px;
|
|
}
|
|
</style>
|