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
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 :",
|
|
'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 :",
|
|
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: "Aucune vente aujourd'hui",
|
|
sEmptyTable: "Aucune donnée disponible",
|
|
oPaginate: {
|
|
sFirst: "Premier",
|
|
sPrevious: "Précé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>
|