motorbike/app/Views/reports/stockDetail.php
andrymodeste 38d37a0987 feat: modifications et corrections du 03-04-2026
- Bouton impression conditionnel : 2 boutons (Facture + BL) si 1 produit, 1 bouton (BL) si plusieurs produits
- Ajout filtres (date, point de vente, utilisateur) sur la page Rapports principale
- Ajout filtres (date, point de vente) sur la page Rapports/Stock pour les 3 tableaux
- Remplacement affichage "UGS" par "N° SERIE" dans toutes les pages
- Mise en page facture avec remise : titre FACTURE repositionné, tableau plus compact
- Correction remise commandes multi-produits : total_price recevait un tableau au lieu d'un nombre
- SuperAdmin voit toutes les remises (tous statuts) au lieu de seulement "En attente"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 08:49:40 +02:00

367 lines
16 KiB
PHP

<!-- Custom Styling -->
<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 Stocks</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 Produits vendus et en stock</h3>
</div>
<div class="card-body">
<!-- Filter Bar -->
<div class="row g-3 align-items-center mb-3" style="margin: 5px 0;">
<div class="col-md-2">
<label for="startDateStock" class="form-label fw-bold">Date de début</label>
<input type="date" id="startDateStock" class="form-control">
</div>
<div class="col-md-2">
<label for="endDateStock" class="form-label fw-bold">Date de fin</label>
<input type="date" id="endDateStock" class="form-control">
</div>
<div class="col-md-3">
<label for="storeFilter" class="form-label fw-bold">Points de ventes</label>
<select id="storeFilter" class="form-control">
<option value="TOUS">TOUS</option>
<?php foreach ($stores as $value) { ?>
<option value="<?= $value['id'] ?>"><?= $value['name'] ?></option>
<?php } ?>
</select>
</div>
<div class="col-md-2 d-flex align-items-end">
<br>
<button id="filterBtn" class="btn btn-primary w-100">Filtrer</button>
</div>
</div>
<!-- Chart Section -->
<div class="row justify-content-center my-4">
<div class="col-md-12">
<canvas id="stockChart" style="min-height: 400px;"></canvas>
</div>
</div>
<!-- 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-white text-primary font-weight-bold">
<h3 class="card-title m-0">🛒 Détails des produits vendus</h3>
</div>
<div class="card-body">
<table id="venteTable" class="table table-hover table-striped">
<thead>
<tr>
<th>Numéro de série</th>
<th>Date de vente</th>
<th>Point de vente</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
<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">📦 Détails des produits en stock</h3>
</div>
<div class="card-body">
<table id="stockTable" class="table table-hover table-striped">
<thead>
<tr>
<th>Marques</th>
<th>Nombre des produits</th>
<th>Point de vente</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
<div class="col-md-12 col-lg-12">
<div class="card shadow-sm border-0 rounded-3">
<div
class="card-header bg-white text-primary font-weight-bold">
<h3 class="card-title m-0">📦 Exportation des produits vendus</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-3">
<label for="exportStoreFilter" class="form-label">Point de vente</label>
<select id="exportStoreFilter" class="form-control">
<option value="TOUS">TOUS</option>
<?php foreach ($stores as $value) { ?>
<option value="<?= $value['id'] ?>"><?= $value['name'] ?></option>
<?php } ?>
</select>
</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="export1"
class="table table-hover table-striped table-bordered">
<thead class="table-primary">
<tr>
<th>Numéro de série</th>
<th>Quantité</th>
<th>Prix</th>
<th>Date de vente</th>
<th>Point de vente</th>
</tr>
</thead>
<tbody>
<!-- DataTables will populate this -->
</tbody>
</table>
</div>
</div>
</div>
</div> <!-- End row -->
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
var manageTable;
var manageTable2;
var manageTable3;
$(document).ready(function () {
$("#reportNav").addClass('active');
// initialize the datatable
manageTable = $('#venteTable').DataTable({
'ajax': 'fetchData/' + 0,
'order': [],
'pageLength': 5, // Set default rows per page
'lengthMenu': [
[5, 10, 25, 50, -1],
[5, 10, 25, 50, "All"]
] // Allow users to select different page sizes
});
manageTable2 = $('#stockTable').DataTable({
'ajax': 'fetchDataStock/' + 0,
'order': [],
'pageLength': 5, // Set default rows per page
'lengthMenu': [
[5, 10, 25, 50, -1],
[5, 10, 25, 50, "All"]
] // Allow users to select different page sizes
});
manageTable3 = $('#export1').DataTable({
ajax: {
url: 'fetchDataStock2/' + 0,
dataSrc: 'data'
},
order: [],
pageLength: 5,
lengthMenu: [
[5, 10, 25, 50, -1],
[5, 10, 25, 50, "All"]
]
});
const storeSelect = document.getElementById('storeFilter');
storeSelect.addEventListener('change', function () {
let filterValue = storeSelect.value === "TOUS" ? "0" : storeSelect.value;
let startDate = $('#startDateStock').val();
let endDate = $('#endDateStock').val();
let params = '?startDate=' + startDate + '&endDate=' + endDate;
manageTable.ajax.url('fetchData/' + filterValue + params).load();
manageTable2.ajax.url('fetchDataStock/' + filterValue + params).load();
});
let productsSold = <?= $ventes ?>;
let productsInStock = <?= $stock ?>;
function applyFilter(storeId) {
let filteredSoldProducts = productsSold;
let filteredStockProducts = productsInStock;
// If a specific store is selected, filter the data
if (storeId && storeId !== "TOUS") {
filteredSoldProducts = productsSold.filter(sale => sale.store_id === storeId);
filteredStockProducts = productsInStock.filter(product => product.store_id === storeId);
}
updateChart(filteredStockProducts, filteredSoldProducts);
}
// Trigger the filter on button click
$('#filterBtn').click(function () {
let storeId = $('#storeFilter').val();
let filterValue = storeId === "TOUS" ? "0" : storeId;
let startDate = $('#startDateStock').val();
let endDate = $('#endDateStock').val();
let params = '?startDate=' + startDate + '&endDate=' + endDate;
manageTable.ajax.url('fetchData/' + filterValue + params).load();
manageTable2.ajax.url('fetchDataStock/' + filterValue + params).load();
manageTable3.ajax.url('fetchDataStock2/' + filterValue + params).load();
applyFilter(storeId);
});
// Apply default filter on page load (TOUS)
applyFilter("TOUS");
});
$('#filteredB1').on('click', function () {
let storeId = $('#exportStoreFilter').val();
let filterValue = storeId === "TOUS" ? "0" : storeId;
let startDate = $('#startDate').val();
let endDate = $('#endDate').val();
let params = '?startDate=' + startDate + '&endDate=' + endDate;
manageTable3.ajax.url('fetchDataStock2/' + filterValue + params).load();
});
// Function to update the chart
function updateChart(filteredStockProducts, filteredSoldProducts) {
const stockData = {};
const soldData = {};
// Aggregate stock quantities
filteredStockProducts.forEach(product => {
stockData[product.name] = (stockData[product.name] || 0) + parseInt(product.qty);
});
// Aggregate sold quantities
filteredSoldProducts.forEach(sale => {
soldData[sale.Pname] = (soldData[sale.Pname] || 0) + 1;
});
// Extract labels and data
const labels = [...new Set([...Object.keys(stockData), ...Object.keys(soldData)])];
const stockValues = labels.map(label => stockData[label] || 0);
const soldValues = labels.map(label => soldData[label] || 0);
// Update Chart.js instance
stockChart.data.labels = labels;
stockChart.data.datasets[0].data = stockValues;
stockChart.data.datasets[1].data = soldValues;
stockChart.update();
}
// Initialize Line Chart
const ctx = document.getElementById("stockChart").getContext("2d");
const stockChart = new Chart(ctx, {
type: "line", // Changed to line chart
data: {
labels: [],
datasets: [{
label: "Quantité en stock",
data: [],
borderColor: "rgba(0, 0, 255, 0.5)",
backgroundColor: "rgba(0, 0, 255, 0.2)",
fill: true
},
{
label: "Quantité vendue",
data: [],
borderColor: "rgba(255, 0, 0, 0.5)",
backgroundColor: "rgba(255, 0, 0, 0.2)",
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
document.getElementById('ExportBTN1').addEventListener('click', function () {
// Select your table
var table = document.getElementById('export1');
// Convert it to a workbook
var wb = XLSX.utils.table_to_book(table, {
sheet: "Feuille1"
});
// Export it
XLSX.writeFile(wb, 'export-produits.xlsx');
});
</script>