## Recouvrement - Liste triée par date décroissante - Pop-up de confirmation anti-doublons - Affichage avec permission "Voir" seule ## Mise à jour produit - Correction erreur "Column count doesn't match" (triggers MySQL corrigés) - Formulaire corrigé (action, catégorie, champs null) - Catégorie et date d'arrivage correctement préremplis - Historique affiche le nom de l'utilisateur qui modifie ## Espace commercial - Colonne "Disponibilité" ajoutée avec statut "En attente de livraison" - Bouton panier caché pour les motos commandées - Surbrillance jaune pour les motos en attente ## Notifications - Caissière reçoit les notifications via notifCommande - notifSortieCaisse réservé à Direction/Admin ## Avances - Colonne "N° Série" ajoutée dans toutes les listes - Compteurs sur les boutons Incomplètes/Complètes ## Facture / BL - Total, Remise, Total à payer affichés - "Ariary" ne se répète plus - Prix individuel par moto - Impression automatique : 1 produit = Facture, 2+ = BL - Remise multiple : colonne product changée en TEXT ## Rapports - Filtre par date dans le rapport stock - Filtre par commercial et mécanicien dans les performances - Correction rapport stock (GROUP BY marque) - Liens absolus (correction erreur 404) ## Sidebar - Marge en haut supprimée (production) - Padding en bas ajouté pour scroll complet Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
287 lines
15 KiB
PHP
287 lines
15 KiB
PHP
<style>
|
|
.card {
|
|
border-radius: 12px;
|
|
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.table {
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
th {
|
|
text-align: center;
|
|
background-color: #343a40 !important;
|
|
color: white;
|
|
}
|
|
|
|
tbody tr:hover {
|
|
background-color: rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.btn-primary {
|
|
border-radius: 8px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.bg-primary {
|
|
background-color: #007bff !important;
|
|
}
|
|
|
|
.bg-success {
|
|
background-color: #28a745 !important;
|
|
}
|
|
|
|
.bg-warning {
|
|
background-color: #ffc107 !important;
|
|
}
|
|
</style>
|
|
|
|
<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-header bg-primary text-white">
|
|
<h3 class="card-title m-0"> Gérer les Performances</h3>
|
|
</div>
|
|
|
|
<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-header bg-success text-white">
|
|
<h3 class="card-title m-0"> performances des commercials</h3>
|
|
</div>
|
|
<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-2">
|
|
<label for="pvente" class="form-label">Points de ventes</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="commercialFilter" class="form-label">Commercial</label>
|
|
<select id="commercialFilter" class="form-control">
|
|
<option value="TOUS">TOUS</option>
|
|
<?php foreach ($commerciaux as $com): ?>
|
|
<option value="<?= $com['id']; ?>"><?= $com['firstname'] . ' ' . $com['lastname']; ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2 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>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énefices</th>
|
|
</tr>
|
|
</thead>
|
|
<tfoot>
|
|
<tr>
|
|
<th colspan="5" style="text-align:right">Total:</th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<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-header bg-success text-white">
|
|
<h3 class="card-title m-0">📈 performances des Mécanicien</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3 align-items-center mb-4" style="margin: 5px 0 5px 5px;">
|
|
<div class="col-md-2">
|
|
<label for="startDate2" class="form-label">Date de début</label>
|
|
<input type="date" id="startDate2" class="form-control">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="endDate2" class="form-label">Date de fin</label>
|
|
<input type="date" id="endDate2" class="form-control">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label for="pvente2" class="form-label">Points de ventes</label>
|
|
<select id="pvente2" 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="mecanicienFilter" class="form-label">Mécanicien</label>
|
|
<select id="mecanicienFilter" class="form-control">
|
|
<option value="TOUS">TOUS</option>
|
|
<?php foreach ($mecaniciens as $mec): ?>
|
|
<option value="<?= $mec['id']; ?>"><?= $mec['firstname'] . ' ' . $mec['lastname']; ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2 d-flex align-items-end">
|
|
<br>
|
|
<button id="filteredB2" class="btn btn-primary w-100">Filtrer</button>
|
|
<button id="ExportBTN2" class="btn btn-success w-100">Exporter</button>
|
|
</div>
|
|
</div>
|
|
<table id="mecperformance" class="table table-hover table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Mécanicien</th>
|
|
<th>Image</th>
|
|
<th>Moto réparée</th>
|
|
<th>N° Série</th>
|
|
<th>Point de vente</th>
|
|
<th>Date début</th>
|
|
<th>Date fin</th>
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
|
<script>
|
|
var manageTable;
|
|
|
|
$(document).ready(function () {
|
|
$("#reportNav").addClass('active');
|
|
|
|
// Initialize the datatable
|
|
|
|
var baseUrl = '<?= base_url() ?>';
|
|
|
|
manageTable = $('#commperformance').DataTable({
|
|
'ajax': baseUrl + '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": false
|
|
}],
|
|
"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(5, { page: 'current' })
|
|
.data()
|
|
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
|
|
|
|
// Calculate total for Bénefices (column 7)
|
|
const totalBenefices = api
|
|
.column(7, { page: 'current' })
|
|
.data()
|
|
.reduce((a, b) => parseNumber(a) + parseNumber(b), 0);
|
|
|
|
// Update footer
|
|
$(api.column(5).footer()).html(totalPrixVente.toFixed(2));
|
|
$(api.column(7).footer()).html(totalBenefices.toFixed(2));
|
|
}
|
|
});
|
|
|
|
// Filtre commercial - côté serveur
|
|
$('#filteredB1').on('click', function () {
|
|
var startDate = $('#startDate').val();
|
|
var endDate = $('#endDate').val();
|
|
var pvente = $('#pvente').val();
|
|
var commercial = $('#commercialFilter').val();
|
|
|
|
var url = baseUrl + 'reports/detail/fetchPerformances?startDate=' + startDate + '&endDate=' + endDate + '&pvente=' + pvente + '&commercial=' + commercial;
|
|
manageTable.ajax.url(url).load();
|
|
});
|
|
|
|
// DataTable mécanicien
|
|
var mecTable = $('#mecperformance').DataTable({
|
|
'ajax': baseUrl + 'mecanicien/fetchMecanicienPerformances',
|
|
'order': [],
|
|
'pageLength': 10
|
|
});
|
|
|
|
// Filtre mécanicien - côté serveur
|
|
$('#filteredB2').on('click', function () {
|
|
var startDate = $('#startDate2').val();
|
|
var endDate = $('#endDate2').val();
|
|
var mecanic = $('#mecanicienFilter').val();
|
|
|
|
var url = baseUrl + 'mecanicien/fetchMecanicienPerformances?startDate=' + startDate + '&endDate=' + endDate + '&mecanic_id=' + (mecanic === 'TOUS' ? '' : mecanic);
|
|
mecTable.ajax.url(url).load();
|
|
});
|
|
});
|
|
|
|
// Export commercial
|
|
document.getElementById('ExportBTN1').addEventListener('click', function () {
|
|
var wb = XLSX.utils.table_to_book(document.getElementById('commperformance'), { sheet: "Commercial" });
|
|
XLSX.writeFile(wb, 'export-commercial-performance.xlsx');
|
|
});
|
|
|
|
// Export mécanicien
|
|
document.getElementById('ExportBTN2').addEventListener('click', function () {
|
|
var wb = XLSX.utils.table_to_book(document.getElementById('mecperformance'), { sheet: "Mecanicien" });
|
|
XLSX.writeFile(wb, 'export-mecanicien-performance.xlsx');
|
|
});
|
|
</script>
|