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.
 
 
 
 
 
 

1628 lines
56 KiB

<style>
/* ============================================
VARIABLES CSS - Design System Couleurs Unies
============================================ */
.treasury-summary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
overflow: hidden;
margin: 20px 0;
}
.treasury-summary .box-header {
background: rgba(255, 255, 255, 0.95);
border-bottom: 3px solid #667eea;
padding: 20px 25px;
}
.treasury-summary .box-title {
color: #667eea;
font-size: 22px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.treasury-summary .box-body {
background: #ffffff;
padding: 35px 25px;
}
/* Blocs de montants */
.amount-block {
background: #f8f9fa;
border-radius: 12px;
padding: 25px 15px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.amount-block::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(90deg, transparent, currentColor, transparent);
opacity: 0;
transition: opacity 0.3s ease;
}
.amount-block:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
.amount-block:hover::before {
opacity: 1;
}
/* Bloc Total Brut */
.amount-block.brut {
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
border-left: 5px solid #4caf50;
}
.amount-block.brut::before {
color: #4caf50;
}
/* Bloc Décaissements */
.amount-block.sorties {
background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%);
border-left: 5px solid #f44336;
}
.amount-block.sorties::before {
color: #f44336;
}
/* Bloc Solde Net */
.amount-block.net {
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
border-left: 5px solid #2196f3;
border: 3px solid #2196f3;
}
.amount-block.net::before {
color: #2196f3;
}
/* En-têtes des montants */
.amount-header {
font-size: 32px;
font-weight: 800;
margin: 15px 0 10px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.05);
}
.amount-label {
font-size: 15px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 5px;
display: block;
}
.amount-sublabel {
font-size: 12px;
color: #6c757d;
font-style: italic;
}
/* Opérateurs mathématiques */
.math-operator {
font-size: 48px;
font-weight: 300;
color: #9e9e9e;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
min-height: 120px;
}
/* Séparateur stylisé */
.custom-divider {
height: 2px;
background: linear-gradient(90deg, transparent, #667eea, transparent);
margin: 30px 0;
border: none;
}
/* Détail par mode de paiement */
.payment-detail-block {
background: #ffffff;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
border: 2px solid transparent;
}
.payment-detail-block:hover {
transform: scale(1.05);
border-color: currentColor;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
}
.payment-detail-block.espece {
border-left: 4px solid #4caf50;
}
.payment-detail-block.mvola {
border-left: 4px solid #ff9800;
}
.payment-detail-block.banque {
border-left: 4px solid #2196f3;
}
.payment-icon {
font-size: 32px;
margin-bottom: 10px;
display: inline-block;
}
.payment-icon.espece {
color: #4caf50;
}
.payment-icon.mvola {
color: #ff9800;
}
.payment-icon.banque {
color: #2196f3;
}
.payment-amount {
font-size: 22px;
font-weight: 700;
color: #212529;
margin: 10px 0;
}
.payment-label {
font-size: 13px;
font-weight: 600;
text-transform: uppercase;
color: #6c757d;
letter-spacing: 0.5px;
}
/* Animation au chargement */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.treasury-summary {
animation: fadeInUp 0.6s ease-out;
}
/* Responsive */
@media (max-width: 768px) {
.math-operator {
font-size: 32px;
min-height: 60px;
}
.amount-header {
font-size: 24px;
}
.treasury-summary .box-body {
padding: 20px 15px;
}
}
</style>
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
Tableau de bord
<small>Panneau de configuration</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> Accueil</a></li>
<li class="active">Tableau de bord</li>
</ol>
</section>
<!-- Main content -->
<section class="content">
<!-- SECTION CAISSIER - SIMPLIFIÉ SANS GRAPHIQUE -->
<?php if ($isCaissier === true): ?>
<!-- Section des totaux caisse -->
<div class="container-fluid row">
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_caisse, 0, '.', ' '); ?> Ar</h2>
<p>Totale CAISSE</p>
</div>
<div class="icon">
<i class="fa fa-credit-card"></i>
</div>
</div>
</div>
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_mvola_caisse, 0, '.', ' '); ?> Ar</h2>
<p>Totale MVOLA</p>
</div>
<div class="icon">
<i class="fa fa-mobile-alt"></i>
</div>
</div>
</div>
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_espece_caisse, 0, '.', ' '); ?> Ar</h2>
<p>Totale en espèce</p>
</div>
<div class="icon">
<i class="fa fa-usd"></i>
</div>
</div>
</div>
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_vb_caisse, 0, '.', ' '); ?> Ar</h2>
<p>Totale en banque</p>
</div>
<div class="icon">
<i class="fa fa-credit-card-alt"></i>
</div>
</div>
</div>
</div>
<!-- Détail Orders vs Avances -->
<div class="container-fluid row" style="margin-top: 10px; margin-bottom: 20px;">
<div class="col-lg-12">
<div class="box box-success treasury-summary">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-calculator"></i> Résumé de Trésorerie
</h3>
</div>
<div class="box-body">
<!-- Calcul Principal : Brut - Sorties = Net -->
<div class="row text-center">
<!-- Total Brut Encaissé -->
<div class="col-sm-3 col-xs-12">
<div class="amount-block brut">
<span class="amount-label" style="color: #388e3c;">💰 Total Brut</span>
<div class="amount-header" style="color: #2e7d32;">
<?php echo number_format($total_brut, 0, '.', ' '); ?> Ar
</div>
<span class="amount-sublabel">Orders + Avances</span>
</div>
</div>
<!-- Opérateur Moins -->
<div class="col-sm-1 col-xs-12">
<div class="math-operator">−</div>
</div>
<!-- Décaissements Payés -->
<div class="col-sm-3 col-xs-12">
<div class="amount-block sorties">
<span class="amount-label" style="color: #c62828;">💸 Décaissements</span>
<div class="amount-header" style="color: #d32f2f;">
<?php echo number_format($total_sorties, 0, '.', ' '); ?> Ar
</div>
<span class="amount-sublabel">Espèce + MVOLA + Virement</span>
</div>
</div>
<!-- Opérateur Égal -->
<div class="col-sm-1 col-xs-12">
<div class="math-operator">=</div>
</div>
<!-- Solde Net Disponible -->
<div class="col-sm-4 col-xs-12">
<div class="amount-block net">
<span class="amount-label" style="color: #1565c0;">✅ Solde Net</span>
<div class="amount-header" style="color: #1976d2; font-size: 36px;">
<?php echo number_format($total_caisse, 0, '.', ' '); ?> Ar
</div>
<span class="amount-sublabel">Disponible en caisse</span>
</div>
</div>
</div>
<!-- Séparateur Stylisé -->
<hr class="custom-divider">
<!-- Détail par Mode de Paiement -->
<div class="row text-center">
<!-- Espèce -->
<div class="col-sm-4 col-xs-12" style="margin-bottom: 15px;">
<div class="payment-detail-block espece">
<div class="payment-icon espece">
<i class="fa fa-money"></i>
</div>
<div class="payment-amount">
<?php echo number_format($total_espece_caisse, 0, '.', ' '); ?> Ar
</div>
<div class="payment-label">💵 Espèce Disponible</div>
</div>
</div>
<!-- MVOLA -->
<div class="col-sm-4 col-xs-12" style="margin-bottom: 15px;">
<div class="payment-detail-block mvola">
<div class="payment-icon mvola">
<i class="fa fa-mobile"></i>
</div>
<div class="payment-amount">
<?php echo number_format($total_mvola_caisse, 0, '.', ' '); ?> Ar
</div>
<div class="payment-label">📱 MVOLA Disponible</div>
</div>
</div>
<!-- Banque -->
<div class="col-sm-4 col-xs-12" style="margin-bottom: 15px;">
<div class="payment-detail-block banque">
<div class="payment-icon banque">
<i class="fa fa-bank"></i>
</div>
<div class="payment-amount">
<?php echo number_format($total_vb_caisse, 0, '.', ' '); ?> Ar
</div>
<div class="payment-label">🏦 Banque Disponible</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Détail des avances par mode de paiement -->
<div class="container-fluid row" style="margin-top: 10px; margin-bottom: 20px;">
<div class="col-lg-12">
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title"><i class="fa fa-info-circle"></i> Détail des Avances par Mode de Paiement</h3>
</div>
<div class="box-body">
<div class="row">
<div class="col-sm-4">
<div class="description-block">
<h5 class="description-header"><?php echo number_format($total_avances_mvola, 0, '.', ' '); ?> Ar</h5>
<span class="description-text">MVOLA</span>
</div>
</div>
<div class="col-sm-4">
<div class="description-block">
<h5 class="description-header"><?php echo number_format($total_avances_espece, 0, '.', ' '); ?> Ar</h5>
<span class="description-text">ESPÈCE</span>
</div>
</div>
<div class="col-sm-4">
<div class="description-block">
<h5 class="description-header"><?php echo number_format($total_avances_virement, 0, '.', ' '); ?> Ar</h5>
<span class="description-text">BANQUE</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Section Rapport de Performance -->
<section class="content-header">
<h1>📊 Mes Performances de Vente</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-home"></i> Accueil</a></li>
<li class="active">Rapports</li>
</ol>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card shadow-sm border-0">
<div class="card-body">
<div class="row mt-4">
<div class="col-md-12 col-lg-12">
<div class="card shadow-sm border-0">
<div class="card-header bg-white text-primary font-weight-bold">
<h3 class="card-title m-0">
<i class="fa fa-list"></i> Liste de mes ventes validées
</h3>
</div>
<div class="card-body">
<!-- Filtres -->
<div class="row g-3 align-items-center mb-4" style="margin: 5px 0 5px 5px;">
<div class="col-md-3">
<label for="startDateCaissier" class="form-label">Date de début</label>
<input type="date" id="startDateCaissier" class="form-control">
</div>
<div class="col-md-3">
<label for="endDateCaissier" class="form-label">Date de fin</label>
<input type="date" id="endDateCaissier" class="form-control">
</div>
<div class="col-md-3 d-flex align-items-end">
<br>
<button id="filteredBtnCaissier" class="btn btn-primary w-100">
<i class="fa fa-filter"></i> Filtrer
</button>
<button id="ExportBTNCaissier" class="btn btn-success w-100" style="margin-left: 5px;">
<i class="fa fa-file-excel-o"></i> Exporter
</button>
</div>
</div>
<!-- Dans la section caissière, assurez-vous que le tableau a la bonne structure -->
<table id="caissierperf" class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Caissier</th>
<th>Moto vendue</th>
<th>Date de vente</th>
<th>Prix de vente</th>
</tr>
</thead>
<tbody>
<!-- Les données seront chargées automatiquement par DataTables -->
</tbody>
<tfoot>
<tr>
<th colspan="3" style="text-align:right; font-weight: bold;">Total :</th>
<th style="font-weight: bold;"></th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ✅ SCRIPT POUR LE TABLEAU CAISSIER UNIQUEMENT -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
(function() {
var caissierTable;
$(document).ready(function () {
// console.log('🔍 Initialisation du tableau caissier...');
// Configuration DataTable pour caissier
caissierTable = $('#caissierperf').DataTable({
'ajax': {
'url': '<?= base_url('reports/detail/fetchCaissierPerformances') ?>',
'data': function(d) {
// ✅ AJOUT : Envoyer les dates au serveur
d.startDate = $('#startDateCaissier').val();
d.endDate = $('#endDateCaissier').val();
},
'dataSrc': function(json) {
console.log('📊 Données reçues:', json);
return json.data;
},
'error': function(xhr, error, thrown) {
console.error('❌ Erreur AJAX:', error, thrown);
console.error('Réponse:', xhr.responseText);
}
},
'columns': [
{ 'data': 0 }, // Caissier
{ 'data': 1 }, // Moto vendue
{ 'data': 2 }, // Date
{ 'data': 3 } // Prix
],
'order': [[2, 'desc']],
'pageLength': 10,
'lengthMenu': [[5, 10, 25, 50, -1], [5, 10, 25, 50, "Tout"]],
'language': {
'processing': "Traitement en cours...",
'search': "Rechercher&nbsp;:",
'lengthMenu': "Afficher _MENU_ éléments",
'info': "Affichage de l'élément _START_ à _END_ sur _TOTAL_ éléments",
'infoEmpty': "Affichage de l'élément 0 à 0 sur 0 élément",
'infoFiltered': "(filtré de _MAX_ éléments au total)",
'loadingRecords': "Chargement en cours...",
'zeroRecords': "Aucune vente enregistrée",
'emptyTable': "Aucune donnée disponible",
'paginate': {
'first': "Premier",
'previous': "Précédent",
'next': "Suivant",
'last': "Dernier"
}
},
'footerCallback': function (row, data, start, end, display) {
const api = this.api();
const parseNumber = function (i) {
return typeof i === 'string'
? parseFloat(i.replace(/[^\d.-]/g, ''))
: typeof i === 'number' ? i : 0;
};
const totalPrixVente = api
.column(3, { page: 'current' })
.data()
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
const totalFormate = totalPrixVente.toLocaleString('fr-FR');
$(api.column(3).footer()).html('<strong>' + totalFormate + ' Ar</strong>');
}
});
// ✅ CORRECTION : Filtrage par dates
$('#filteredBtnCaissier').on('click', function () {
const startDate = $('#startDateCaissier').val();
const endDate = $('#endDateCaissier').val();
// console.log('🔍 Filtrage:', startDate, endDate);
// Recharger les données avec les nouveaux paramètres
caissierTable.ajax.reload();
});
// Export Excel
$('#ExportBTNCaissier').on('click', function () {
const table = document.getElementById('caissierperf');
const wb = XLSX.utils.table_to_book(table, { sheet: "Performances Caissier" });
const today = new Date().toISOString().split('T')[0];
const fileName = 'performances_caissier_' + today + '.xlsx';
XLSX.writeFile(wb, fileName);
});
});
})();
</script>
<?php endif; ?>
<!-- securite -->
<!-- Dashboard pour Sécurité -->
<!-- Dashboard pour Sécurité -->
<?php if ($isSecurite === true): ?>
<!-- Styles spécifiques pour Sécurité -->
<style>
<style>
.content { margin-top: 0 !important; padding-top: 0 !important; }
</style>
</style>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<!-- small box -->
<div class="small-box bg-aqua">
<div class="inner">
<h3><?php echo $total_products ?></h3>
<p>Total Produits</p>
</div>
<div class="icon">
<i class="ion ion-bag"></i>
</div>
<a href="<?php echo base_url('products/') ?>" class="small-box-footer">
Plus d'information <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
<!-- ./col -->
</div>
<!-- /.row -->
<!-- Section informative pour la sécurité -->
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">
<i class="fa fa-shield"></i> Informations Sécurité
</h3>
</div>
<div class="box-body">
<p>
<strong>Bienvenue sur votre tableau de bord sécurité.</strong>
</p>
<p>
Vous avez accès à la consultation du nombre total de produits en stock.
Pour plus de détails, cliquez sur "Plus d'information" dans la carte ci-dessus.
</p>
</div>
</div>
</div>
</div>
</section>
<?php endif; ?>
<!-- mecanicien -->
<?php if ($isMecanicien === true): ?>
<section class="content-header">
<h1>Rapport de performance d'un mécanicien</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-home"></i> Accueil</a></li>
<li class="active" onclick="window.history.back()" style="cursor: pointer;">Rapports</li>
</ol>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card shadow-sm border-0">
<div class="card-body">
<!-- Product Details -->
<div class="row mt-4">
<div class="col-md-12 col-lg-12">
<div class="card shadow-sm border-0">
<div class="card-body">
<div class="row g-3 align-items-center mb-4" style="margin: 5px 0 5px 5px;">
<div class="col-md-4 d-flex align-items-end">
<br>
<button id="filterBtnMec" class="btn btn-primary" style="margin-right: 5px;">
<i class="fa fa-filter"></i> Filtrer
</button>
<button id="resetFilterMec" class="btn btn-warning" style="margin-right: 5px;">
<i class="fa fa-refresh"></i> Aujourd'hui
</button>
<button id="exportBtnMec" class="btn btn-success">
<i class="fa fa-file-excel-o"></i> Exporter
</button>
</div>
</div>
<table id="mecanicienperf" class="table table-hover table-striped">
<thead>
<tr>
<th >Motos</th>
<th >Désignation</th>
<th >Numéro de série</th>
<th >Début de la réparation</th>
<th >Fin de la réparation</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
var manageTable;
$(document).ready(function () {
manageTable = $('#mecanicienperf').DataTable({
'ajax': 'mecanicien/fetchMecanicienPerformances',
'order': [],
'pageLength': 5,
'lengthMenu': [
[5, 10, 25, 50, -1],
[5, 10, 25, 50, "Tout"]
],
columnDefs: [
{
targets: "_all", // ou un index de colonne, ou un tableau d’index
className: "text-left" // ou "dt-left" si tu utilises les classes par défaut de DataTables
}
],
"footerCallback": function (row, data, start, end, display) {
const api = this.api();
const parseNumber = (i) => typeof i === 'string'
? parseFloat(i.replace(/[^\d.-]/g, ''))
: typeof i === 'number'
? i
: 0;
const total = api
.column(2, { page: 'current' })
.data()
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
$(api.column(2).footer()).html(total.toLocaleString('fr-FR'));
}
});
// Filtrage par dates
$('#filteredB1').on('click', function () {
const startDate = $('#startDate').val();
const endDate = $('#endDate').val();
manageTable.ajax.url('mecanicien/fetchMecanicienPerformances').load(function () {
const filteredData = [];
manageTable.rows().every(function () {
const data = this.data();
const repairDate = data[2].split(' ')[0]; // Début réparation
const isValid =
(!startDate && !endDate) ||
(startDate && endDate && repairDate >= startDate && repairDate <= endDate) ||
(startDate && !endDate && repairDate >= startDate) ||
(!startDate && endDate && repairDate <= endDate);
if (isValid) {
filteredData.push(data);
}
});
manageTable.clear().rows.add(filteredData).draw();
});
});
// Export en Excel
$('#ExportBTN1').on('click', function () {
const table = document.getElementById('mecanicienperf');
const wb = XLSX.utils.table_to_book(table, { sheet: "Feuille1" });
XLSX.writeFile(wb, 'export-performance-mecanicien.xlsx');
});
});
</script>
<?php endif; ?>
<!-- Small boxes (Stat box) -->
<?php if ($is_admin == true): ?>
<div class="row">
<div class="col-lg-2 col-xs-4">
<!-- small box -->
<div class="small-box bg-aqua">
<div class="inner">
<h3><?php echo $total_products ?></h3>
<p>Produit</p>
</div>
<div class="icon">
<i class="ion ion-bag"></i>
</div>
<a href="<?php echo base_url('products/') ?>" class="small-box-footer">Plus d'information<i class="fa fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-xs-4">
<!-- small box -->
<div class="small-box bg-green">
<div class="inner">
<h3><?php echo $total_paid_orders ?></h3>
<p>Commande payée</p>
</div>
<div class="icon">
<i class="ion ion-stats-bars"></i>
</div>
<a href="<?php echo base_url('orders/') ?>" class="small-box-footer">Plus d'information <i class="fa fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-xs-4">
<!-- small box -->
<div class="small-box bg-yellow">
<div class="inner">
<h3><?php echo $total_users; ?></h3>
<p>Utilisateur</p>
</div>
<div class="icon">
<i class="ion ion-android-people"></i>
</div>
<a href="<?php echo base_url('users/') ?>" class="small-box-footer">Plus d'information <i class="fa fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-xs-4">
<!-- small box -->
<div class="small-box bg-red">
<div class="inner">
<h3><?php echo $total_stores ?></h3>
<p>Point de vente</p>
</div>
<div class="icon">
<i class="ion ion-android-home"></i>
</div>
<a href="<?php echo base_url('stores/') ?>" class="small-box-footer">Plus d'information <i class="fa fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-4 col-xs-4">
<!-- small box -->
<div class="small-box bg-primary">
<div class="inner" style="color:white;">
<h3><?php echo count($count_id) ?></h3>
<p>Statistique des Commercials</p>
</div>
<div class="icon">
<i class="ion-stats-bars"></i>
</div>
<a href="<?php echo base_url('statistic/') ?>" class="small-box-footer">Plus d'information <i class="fa fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- End of row -->
</div>
<div class="row">
<!-- total en caisse -->
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total, 0, '.', ' '); ?>Ar</h2>
<p>Totale FLUX</p>
</div>
<div class="icon">
<i class="fa fa-credit-card"></i>
</div>
</div>
</div>
<!-- total mvola -->
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_mvola, 0, '.', ' '); ?>Ar</h2>
<p>Totale MVOLA</p>
</div>
<div class="icon">
<i class="fa fa-mobile-alt"></i>
</div>
</div>
</div>
<!-- Total en espece -->
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_espece, 0, '.', ' '); ?>Ar</h2>
<p>Totale en espece</p>
</div>
<div class="icon">
<i class="fa fa fa-usd"></i>
</div>
</div>
</div>
<!-- Total en virement bancaire -->
<div class="col-lg-3 col-xs-6">
<div class="small-box" style="background-color: #A9A9A9;">
<div class="inner">
<h2><?php echo number_format($total_virement_bancaire, 0, '.', ' '); ?>Ar</h2>
<p>Totale en banque</p>
</div>
<div class="icon">
<i class="fa fa-credit-card-alt"></i>
</div>
</div>
</div>
</div>
<!-- /.row -->
<div class="row" style="padding: 15px;">
<div class="col-lg-6 col-xs-12" style="background-color: white; box-shadow: inset 1px 1px 3px #00000052; padding: 20px; text-align: center;">
<div class="box-header">
<h3 class="box-title">Statistique des ventes par magasin</h3>
</div>
<div class="box-body" style="display: flex; justify-content: center; align-items: center; height: 300px;">
<canvas id="storeChart" style="max-width: 100%; height: 280px;"></canvas>
</div>
</div>
<div class="col-lg-6 col-xs-12" style="background-color: white; box-shadow: inset 1px 1px 3px #00000052; padding: 20px; text-align: center;">
<div>
<div class="box-header">
<h3 class="box-title">Liste des marques les plus vendues</h3>
</div>
<div class="box-body" style="display: flex; justify-content: center; align-items: center; height: 300px;">
<canvas id="MotosChart" style="max-width: 100%; height: 280px;"></canvas>
</div>
</div>
</div>
</div>
<!-- Section Rapports des performances -->
<section class="content-header">
<h1>📊 Rapports des performances</h1>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<!-- CARD COMMERCIAL -->
<!-- CARD COMMERCIAL -->
<div class="card shadow-sm border-0 mb-4">
<div class="card-body">
<div class="row mt-4">
<div class="col-md-12 col-lg-12">
<div class="card shadow-sm border-0">
<div class="card-header bg-white text-primary font-weight-bold">
<h3 class="card-title m-0">
<i class="fa fa-users"></i> Performances des commerciaux
</h3>
</div>
<div class="card-body">
<!-- Filtres Commercial -->
<div class="row g-3 align-items-center mb-4" style="margin:5px;">
<div class="col-md-3">
<label for="startDateComm" class="form-label">Date de début</label>
<input type="date" id="startDateComm" class="form-control">
</div>
<div class="col-md-3">
<label for="endDateComm" class="form-label">Date de fin</label>
<input type="date" id="endDateComm" class="form-control">
</div>
<div class="col-md-3">
<label for="pventeComm" class="form-label">Points de ventes</label>
<select id="pventeComm" 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-3 d-flex align-items-end">
<button id="filterBtnComm" class="btn btn-primary w-100">
<i class="fa fa-filter"></i> Filtrer
</button>
<button id="resetFilterComm" class="btn btn-warning w-100" style="margin-left:5px;">
<i class="fa fa-refresh"></i> Aujourd'hui
</button>
<button id="exportBtnComm" class="btn btn-success w-100" style="margin-left:5px;">
<i class="fa fa-file-excel-o"></i> Exporter
</button>
</div>
</div>
<!-- TABLE -->
<table id="commperformance" class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Nom et prénom</th>
<th>Email</th>
<th>Motos vendue</th>
<th>Date de vente</th>
<th>Prix d'achat</th>
<th>Prix de vente</th>
<th>Point de ventes</th>
<th>Bénéfices</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="5" class="text-end fw-bold">Total :</th>
<th class="fw-bold"></th>
<th></th>
<th class="fw-bold"></th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- CARD MÉCANICIEN -->
<div class="card shadow-sm border-0">
<div class="card-body">
<div class="row mt-4">
<div class="col-md-12 col-lg-12">
<div class="card shadow-sm border-0">
<div class="card-header bg-white text-primary font-weight-bold">
<h3 class="card-title m-0">
<i class="fa fa-wrench"></i> Performances des Mécaniciens
</h3>
</div>
<div class="card-body">
<!-- Filtres Mécanicien - AVEC IDs UNIQUES -->
<div class="row g-3 align-items-center mb-4" style="margin: 5px 0 5px 5px;">
<div class="col-md-3">
<label for="startDateMec" class="form-label">Date de début</label>
<input type="date" id="startDateMec" class="form-control">
</div>
<div class="col-md-3">
<label for="endDateMec" class="form-label">Date de fin</label>
<input type="date" id="endDateMec" class="form-control">
</div>
<?php
$session = session();
$users = $session->get('user');
if ($users["group_name"] === "Direction" || $users["group_name"] === "SuperAdmin" || $users["group_name"] === "DAF"):
?>
<div class="col-md-3">
<label for="pventeMec" class="form-label">Points de ventes</label>
<select id="pventeMec" class="form-control">
<option value="TOUS">TOUS</option>
<?php foreach ($stores as $value): ?>
<option value="<?= $value['name']; ?>"><?= $value['name']; ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<div class="col-md-3 d-flex align-items-end">
<br>
<button id="filterBtnMec" class="btn btn-primary w-100">
<i class="fa fa-filter"></i> Filtrer
</button>
<button id="exportBtnMec" class="btn btn-success w-100" style="margin-left: 5px;">
<i class="fa fa-file-excel-o"></i> Exporter
</button>
</div>
</div>
<table id="mecperformance" class="table table-hover table-striped table-bordered">
<thead>
<tr>
<th>Mécaniciens</th>
<th>Motos</th>
<th>Désignation</th>
<th>Numéro de série</th>
<th>Début de la réparation</th>
<th>Fin de la réparation</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
var commTable, mecTable;
// ==================== MODIFICATIONS POUR FILTRAGE AUTOMATIQUE ====================
$(document).ready(function () {
// Fonction pour obtenir la date d'aujourd'hui au format YYYY-MM-DD
function getTodayDate() {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// Initialiser les champs de date avec aujourd'hui par défaut
const todayDate = getTodayDate();
$('#startDateComm').val(todayDate);
$('#endDateComm').val(todayDate);
$('#startDateMec').val(todayDate);
$('#endDateMec').val(todayDate);
// Configuration langue française
$.extend(true, $.fn.dataTable.defaults, {
language: {
sProcessing: "Traitement en cours...",
sSearch: "Rechercher&nbsp;:",
sLengthMenu: "Afficher _MENU_ &eacute;l&eacute;ments",
sInfo: "Affichage de l'&eacute;lement _START_ &agrave; _END_ sur _TOTAL_ &eacute;l&eacute;ments",
sInfoEmpty: "Affichage de l'&eacute;lement 0 &agrave; 0 sur 0 &eacute;l&eacute;ment",
sInfoFiltered: "(filtr&eacute; de _MAX_ &eacute;l&eacute;ments au total)",
sLoadingRecords: "Chargement en cours...",
sZeroRecords: "Aucune vente aujourd'hui",
sEmptyTable: "Aucune donn&eacute;e disponible",
oPaginate: {
sFirst: "Premier",
sPrevious: "Pr&eacute;c&eacute;dent",
sNext: "Suivant",
sLast: "Dernier"
}
}
});
// ==================== TABLE COMMERCIAL ====================
if ($('#commperformance').length > 0) {
commTable = $('#commperformance').DataTable({
'ajax': {
'url': '<?= base_url('reports/detail/fetchPerformances') ?>',
'type': 'GET',
'data': function(d) {
// ✅ Envoyer les dates (aujourd'hui par défaut)
d.startDate = $('#startDateComm').val();
d.endDate = $('#endDateComm').val();
d.pvente = $('#pventeComm').val();
}
},
'order': [],
'pageLength': 10,
'lengthMenu': [[5, 10, 25, 50, -1], [5, 10, 25, 50, "Tout"]],
"columnDefs": [{
"targets": 3,
"searchable": false
}],
"footerCallback": function (row, data, start, end, display) {
const api = this.api();
const parseNumber = function (i) {
return typeof i === 'string' ?
parseFloat(i.replace(/[^\d.-]/g, '')) :
typeof i === 'number' ? i : 0;
};
const totalPrixVente = api
.column(5, { page: 'current' })
.data()
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
const totalBenefices = api
.column(7, { page: 'current' })
.data()
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
$(api.column(5).footer()).html('<strong>' + totalPrixVente.toLocaleString('fr-FR') + ' Ar</strong>');
$(api.column(7).footer()).html('<strong>' + totalBenefices.toLocaleString('fr-FR') + ' Ar</strong>');
}
});
// ✅ BOUTON FILTRAGE COMMERCIAL
$('#filterBtnComm').on('click', function () {
('🔍 Filtrage Commercial:', {
startDate: $('#startDateComm').val(),
endDate: $('#endDateComm').val(),
pvente: $('#pventeComm').val()
});
commTable.ajax.reload();
});
// ✅ Bouton pour réinitialiser à aujourd'hui
$('#resetFilterComm').on('click', function() {
$('#startDateComm').val(todayDate);
$('#endDateComm').val(todayDate);
$('#pventeComm').val('TOUS');
commTable.ajax.reload();
});
// ✅ BOUTON EXPORT COMMERCIAL
$('#exportBtnComm').on('click', function () {
const table = document.getElementById('commperformance');
const wb = XLSX.utils.table_to_book(table, { sheet: "Performance Commercial" });
const startDate = $('#startDateComm').val();
const endDate = $('#endDateComm').val();
const fileName = `performances_commercial_${startDate}_${endDate}.xlsx`;
XLSX.writeFile(wb, fileName);
});
}
// ==================== TABLE MÉCANICIEN ====================
if ($('#mecperformance').length > 0) {
mecTable = $('#mecperformance').DataTable({
'ajax': {
'url': '<?= base_url('mecanicien/fetchMecanicienPerformances') ?>',
'type': 'GET',
'data': function(d) {
// ✅ Envoyer les dates (aujourd'hui par défaut)
d.startDate = $('#startDateMec').val();
d.endDate = $('#endDateMec').val();
d.pvente = $('#pventeMec').val();
}
},
'order': [],
'pageLength': 10,
'lengthMenu': [[5, 10, 25, 50, -1], [5, 10, 25, 50, "Tout"]],
columnDefs: [{
targets: "_all",
className: "text-left"
}]
});
// ✅ BOUTON FILTRAGE MÉCANICIEN
$('#filterBtnMec').on('click', function () {
('🔍 Filtrage Mécanicien:', {
startDate: $('#startDateMec').val(),
endDate: $('#endDateMec').val(),
pvente: $('#pventeMec').val()
});
mecTable.ajax.reload();
});
// ✅ Bouton pour réinitialiser à aujourd'hui
$('#resetFilterMec').on('click', function() {
$('#startDateMec').val(todayDate);
$('#endDateMec').val(todayDate);
$('#pventeMec').val('TOUS');
mecTable.ajax.reload();
});
// ✅ BOUTON EXPORT MÉCANICIEN
$('#exportBtnMec').on('click', function () {
const table = document.getElementById('mecperformance');
const wb = XLSX.utils.table_to_book(table, { sheet: "Performance Mécanicien" });
const startDate = $('#startDateMec').val();
const endDate = $('#endDateMec').val();
const fileName = `performances_mecanicien_${startDate}_${endDate}.xlsx`;
XLSX.writeFile(wb, fileName);
});
}
});
</script>
<?php endif; ?>
<?php if ($isCommercial === true || $isChef === true) : ?>
<!-- <div class="content-wrapper"> -->
<!-- <h5>Votre statistique de vente</h5> -->
<!-- performance content wraper: <div class="content-wrapper"> -->
<!-- <section class="content-header">
<h1> Rapports des performances</h1> -->
<!-- <ol class="breadcrumb">
<li><a href="#"><i class="fa fa-home"></i> Accueil</a></li>
<li class="active" onclick="window.history.back()" style="cursor: pointer;"> Rapports</li>
</ol> -->
<!-- </section> -->
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card shadow-sm border-0">
<div class="card-body">
<!-- Product Details -->
<div class="row mt-4">
<div class="col-md-12 col-lg-12">
<div class="card shadow-sm border-0">
<div class="card-body">
<div class="row g-3 align-items-center mb-4" style="margin: 5px 0 5px 5px;">
<div class="col-md-3">
<label for="startDate" class="form-label">Date de début</label>
<input type="date" id="startDate" class="form-control">
</div>
<div class="col-md-3">
<label for="endDate" class="form-label">Date de fin</label>
<input type="date" id="endDate" class="form-control">
</div>
<div class="col-md-3 d-flex align-items-end">
<br>
<button id="filteredB1" class="btn btn-primary w-100">Filtrer
🔍</button>
<button id="ExportBTN1" class="btn btn-success w-100">Exporter
📤</button>
</div>
</div>
<table id="commperformance" class="table table-hover table-striped">
<thead>
<tr>
<th>Nom et prénom</th>
<th>Motos vendues</th>
<th>Date de vente</th>
<th>Prix de vente</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="3" style="text-align:right">Total:</th>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<div style="width: 80%; margin: auto;">
<canvas id="salesChart"></canvas>
</div>
<!-- /.content -->
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
var manageTable;
$(document).ready(function () {
// Initialize the datatable
manageTable = $('#commperformance').DataTable({
'ajax': 'reports/detail/fetchPerformances',
'order': [],
'pageLength': 5,
'lengthMenu': [
[5, 10, 25, 50, -1],
[5, 10, 25, 50, "All"]
],
"columnDefs": [{
"targets": 3, // Ensure date column is not searchable (we handle it manually)
"searchable": true
}],
"footerCallback": function (row, data, start, end, display) {
const api = this.api();
// Helper function to parse string to float
const parseNumber = function (i) {
return typeof i === 'string' ?
parseFloat(i.replace(/[^\d.-]/g, '')) : // remove currency symbols, commas
typeof i === 'number' ?
i : 0;
};
// Calculate total for Prix de vente (column 5)
const totalPrixVente = api
.column(3, { page: 'current' })
.data()
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
const totalPrixVenteFormate = totalPrixVente.toLocaleString('fr-FR');
// Update footer
$(api.column(3).footer()).html(totalPrixVenteFormate);
}
});
$('#filteredB1').on('click', function () {
const startDate = $('#startDate').val();
const endDate = $('#endDate').val();
const pvente = $('#pvente').val();
// Get all original data (you may need to fetch from server or already loaded)
manageTable.ajax.url('reports/detail/fetchPerformances').load(function () {
const filteredData = [];
manageTable.rows().every(function () {
const data = this.data();
const saleDate = data[2].split(' ')[0];
// Filter logic
const dateMatch = (!startDate && !endDate) ||
(startDate && endDate && saleDate >= startDate && saleDate <= endDate) ||
(startDate && !endDate && saleDate >= startDate) ||
(!startDate && endDate && saleDate <= endDate);
if (dateMatch) {
filteredData.push(data);
}
});
// Clear and reload table with filtered data
manageTable.clear().rows.add(filteredData).draw();
});
});
});
document.getElementById('ExportBTN1').addEventListener('click', function () {
// Select your table
var table = document.getElementById('commperformance');
// Convert it to a workbook
var wb = XLSX.utils.table_to_book(table, {
sheet: "Feuille1"
});
// Export it
XLSX.writeFile(wb, 'export-commercial-performance.xlsx');
});
</script>
<!-- </div> -->
<?php endif; ?>
</section>
<!-- /.content-wrapper -->
</div>
<!-- js chart -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript">
window.onload = function() {
const ctx = document.getElementById("salesChart")?.getContext("2d");
if (!ctx) {
console.error("Canvas element not found!");
return;
}
const userData = <?= $isCommercial == true ? $user_order : '' ?>;
if (!Array.isArray(userData) || userData.length === 0) {
console.error("User data is empty or invalid", userData);
return;
}
const currentYear = new Date().getFullYear();
// Filter and sort data by date
const filteredData = userData
.filter(sale => new Date(sale.date_time).getFullYear() === currentYear)
.sort((a, b) => new Date(a.date_time) - new Date(b.date_time)); // Sort by date
if (filteredData.length === 0) {
console.warn("No data available for the current year.");
return;
}
let labels = filteredData.map(sale => sale.date_time);
let salesAmounts = filteredData.map(sale => parseFloat(sale.net_amount));
new Chart(ctx, {
type: "line",
data: {
labels: labels,
datasets: [{
label: "Montant (Net)",
data: salesAmounts,
backgroundColor: "rgba(54, 162, 235, 0.5)",
borderColor: "rgba(54, 162, 235, 1)",
borderWidth: 2,
fill: false,
tension: 0.3
}]
},
options: {
responsive: true,
scales: {
x: {
title: {
display: true,
text: "Date & Heure"
}
},
y: {
beginAtZero: true,
title: {
display: true,
text: "Montant (Ar)"
}
}
}
}
});
};
</script>
<!-- piechart for order per store -->
<script>
$(document).ready(function() {
$("#dashboardMainMenu").addClass('active');
var ctx = document.getElementById('storeChart').getContext('2d');
var paymentChart = new Chart(ctx, {
type: 'pie',
data: {
labels: <?= $labelStore ?>,
datasets: [{
label: 'Pourcentage de Transactions',
data: <?= $totalPerStore ?>,
backgroundColor: ['#3498db', '#2ecc71', '#B88A2F'],
borderColor: ['#2980b9', '#27ae60', '#f39c12'],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
label: function(tooltipItem) {
return tooltipItem.raw.toFixed(2) + '%';
}
}
},
legend: {
position: 'bottom',
labels: {
generateLabels: function(chart) {
return chart.data.labels.map(function(label, i) {
return {
text: `${label} (${chart.data.datasets[0].data[i].toFixed(2)}%)`,
fillStyle: chart.data.datasets[0].backgroundColor[i]
};
});
}
}
}
}
}
});
// document.addEventListener("DOMContentLoaded", function() {
let orders = <?= $marques_total ?>; // Orders from PHP
let brandNames = <?= $marques ?>; // All brands from PHP
// Step 1: Count occurrences of each brand
let brandCount = {};
orders.forEach(order => {
let brand = order.name;
brandCount[brand] = (brandCount[brand] || 0) + 1;
});
// console.log(brandCount);
// Step 2: Convert to array and sort by count (descending)
let sortedBrands = Object.entries(brandCount)
.sort((a, b) => b[1] - a[1]) // Sort by count descending
.slice(0, 5); // Keep only top 5
// Step 3: Prepare data for the chart
let labels = sortedBrands.map(item => item[0]); // Brand names
let data = sortedBrands.map(item => item[1]); // Order counts
// console.log(labels);
// Step 4: Create the Pie Chart
let ctx2 = document.getElementById('MotosChart').getContext('2d');
new Chart(ctx2, {
type: 'pie',
data: {
labels: labels,
datasets: [{
label: 'Top 5 Marques',
data: data,
backgroundColor: [
'#FF6384', '#36A2EB', '#FFCE56', '#4CAF50', '#8E44AD'
],
hoverOffset: 4
}]
}
});
// });
});
</script>