verifyRole('viewCom'); $storesModel = new Stores(); $data['page_title'] = $this->pageTitle; $data['stores'] = $storesModel->getActiveStore(); return $this->render_template('historique/index', $data); } /** * Récupérer les données pour DataTables */ public function fetchHistoriqueData() { $historiqueModel = new Historique(); // Récupération des paramètres envoyés par DataTables $draw = intval($this->request->getGet('draw')); $start = intval($this->request->getGet('start')); $length = intval($this->request->getGet('length')); // Filtres personnalisés $filters = [ 'action' => $this->request->getGet('action'), 'store_name' => $this->request->getGet('store_name'), 'product_name'=> $this->request->getGet('product'), 'sku' => $this->request->getGet('sku'), 'date_from' => $this->request->getGet('date_from'), 'date_to' => $this->request->getGet('date_to') ]; // 1️⃣ Nombre total de lignes (sans filtre) $recordsTotal = $historiqueModel->countAll(); // 2️⃣ Récupération des données filtrées $allDataFiltered = $historiqueModel->getHistoriqueWithFilters($filters); $recordsFiltered = count($allDataFiltered); // 3️⃣ Pagination $dataPaginated = array_slice($allDataFiltered, $start, $length); // 4️⃣ Formatage pour DataTables $data = []; foreach ($dataPaginated as $row) { $data[] = [ date('d/m/Y H:i:s', strtotime($row['created_at'])), $row['product_name'] ?? 'N/A', $row['sku'] ?? 'N/A', $row['store_name'] ?? 'N/A', $this->getActionBadge($row['action']), $row['description'] ?? '' ]; } // 5️⃣ Retour JSON return $this->response->setJSON([ 'draw' => $draw, 'recordsTotal' => $recordsTotal, 'recordsFiltered' => $recordsFiltered, 'data' => $data ]); } /** * Historique spécifique d'un produit */ public function product($productId) { $this->verifyRole('viewCom'); $historiqueModel = new Historique(); $productsModel = new Products(); $product = $productsModel->find($productId); if (!$product) { session()->setFlashdata('error', 'Produit introuvable'); return redirect()->to('/historique'); } $data['page_title'] = 'Historique - ' . $product['name']; $data['product'] = $product; $data['historique'] = $historiqueModel->getHistoriqueByProduct($productId); return $this->render_template('historique/product', $data); } /** * Enregistrer un mouvement d'entrée */ public function entrer() { if (!$this->request->isAJAX()) { return $this->response->setStatusCode(404); } $data = $this->request->getJSON(true); if (!isset($data['product_id']) || !isset($data['store_id'])) { return $this->response->setJSON([ 'success' => false, 'message' => 'Paramètres manquants.' ]); } $productsModel = new Products(); $storesModel = new Stores(); $historiqueModel = new Historique(); $product = $productsModel->find($data['product_id']); $store = $storesModel->find($data['store_id']); if (!$product || !$store) { return $this->response->setJSON([ 'success' => false, 'message' => 'Produit ou magasin introuvable.' ]); } // Mettre à jour le produit $updateData = [ 'store_id' => $data['store_id'], 'availability' => 1 ]; if ($productsModel->update($data['product_id'], $updateData)) { // Enregistrer dans l'historique $description = "Produit ajouté au magasin " . $store['name'] . " depuis TOUS"; $historiqueModel->logMovement( 'products', 'ENTRER', $product['id'], $product['name'], $product['sku'], $store['name'], $description ); return $this->response->setJSON(['success' => true]); } return $this->response->setJSON([ 'success' => false, 'message' => 'Erreur lors de la mise à jour.' ]); } /** * Enregistrer un mouvement de sortie */ public function sortie() { if (!$this->request->isAJAX()) { return $this->response->setStatusCode(404); } $data = $this->request->getJSON(true); if (!isset($data['product_id'])) { return $this->response->setJSON([ 'success' => false, 'message' => 'ID produit manquant.' ]); } $productsModel = new Products(); $storesModel = new Stores(); $historiqueModel = new Historique(); $product = $productsModel->find($data['product_id']); if (!$product) { return $this->response->setJSON([ 'success' => false, 'message' => 'Produit introuvable.' ]); } $currentStore = $storesModel->find($product['store_id']); $currentStoreName = $currentStore ? $currentStore['name'] : 'TOUS'; // Mettre à jour le produit (retirer du magasin) $updateData = [ 'store_id' => 0, // TOUS 'availability' => 0 // Non disponible ]; if ($productsModel->update($data['product_id'], $updateData)) { // Enregistrer dans l'historique $description = "Produit retiré du magasin " . $currentStoreName . " vers TOUS"; $historiqueModel->logMovement( 'products', 'SORTIE', $product['id'], $product['name'], $product['sku'], 'TOUS', $description ); return $this->response->setJSON(['success' => true]); } return $this->response->setJSON([ 'success' => false, 'message' => 'Erreur lors de la mise à jour.' ]); } /** * Exporter l'historique */ public function export() { $this->verifyRole('viewCom'); $historiqueModel = new Historique(); $filters = [ 'action' => $this->request->getGet('action'), 'store_name' => $this->request->getGet('store_name'), // Utilise le nom du magasin 'product_name' => $this->request->getGet('product'), 'sku' => $this->request->getGet('sku'), 'date_from' => $this->request->getGet('date_from'), 'date_to' => $this->request->getGet('date_to') ]; $csvData = $historiqueModel->exportHistorique($filters); $filename = 'historique_' . date('Y-m-d_H-i-s') . '.csv'; return $this->response ->setHeader('Content-Type', 'text/csv') ->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"') ->setBody($csvData); } /** * Nettoyer l'historique ancien */ public function clean() { $this->verifyRole('updateCom'); $days = $this->request->getPost('days') ?? 365; $historiqueModel = new Historique(); $deleted = $historiqueModel->cleanOldHistory($days); if ($deleted) { session()->setFlashdata('success', "Historique nettoyé ($deleted entrées supprimées)"); } else { session()->setFlashdata('info', 'Aucune entrée à supprimer'); } return redirect()->to('/historique'); } /** * Obtenir le badge HTML pour une action */ private function getActionBadge($action) { $badges = [ 'CREATE' => 'Création', 'UPDATE' => 'Modification', 'DELETE' => 'Suppression', 'ASSIGN_STORE' => 'Assignation', 'ENTRER' => 'Entrée', 'SORTIE' => 'Sortie', 'IMPORT' => ' Import' ]; return $badges[$action] ?? '' . $action . ''; } /** * API pour obtenir les statistiques */ public function getStats() { if (!$this->request->isAJAX()) { return $this->response->setStatusCode(404); } $historiqueModel = new Historique(); $stats = $historiqueModel->getHistoriqueStats(); return $this->response->setJSON($stats); } }