From 0a6c8ec05d01ecd78248640389fa90f73e8c793b Mon Sep 17 00:00:00 2001 From: Erwann PHILIPPE Date: Wed, 16 Sep 2026 11:11:08 +0200 Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation=20de=20l'api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .htaccess | 19 ++ config.php | 43 +++ index.php | 635 ++++++++++++++++++++++++++++++++++++++++++++ voituresapi (1).sql | 188 +++++++++++++ 4 files changed, 885 insertions(+) create mode 100644 .htaccess create mode 100644 config.php create mode 100644 index.php create mode 100644 voituresapi (1).sql diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..a6f197c --- /dev/null +++ b/.htaccess @@ -0,0 +1,19 @@ +# Activation de la réécriture d'URL pour rediriger vers index.php + + RewriteEngine On + RewriteBase /voitureAPI/ + + # Ne pas réécrire si le fichier ou dossier existe déjà + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + + # Rediriger toutes les autres requêtes vers index.php + RewriteRule ^(.*)$ index.php [QSA,L] + + +# En-têtes CORS globaux + + Header set Access-Control-Allow-Origin "*" + Header set Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" + Header set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" + diff --git a/config.php b/config.php new file mode 100644 index 0000000..3259066 --- /dev/null +++ b/config.php @@ -0,0 +1,43 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + ]; + + try { + $pdo = new PDO($dsn, DB_USER, DB_PASS, $options); + } catch (PDOException $e) { + http_response_code(500); + header('Content-Type: application/json; charset=UTF-8'); + echo json_encode([ + 'success' => false, + 'error' => 'Erreur de connexion à la base de données: ' . $e->getMessage() + ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + exit; + } + } + + return $pdo; +} diff --git a/index.php b/index.php new file mode 100644 index 0000000..52ab652 --- /dev/null +++ b/index.php @@ -0,0 +1,635 @@ + true, + 'message' => 'API Voitures opérationnelle', + 'database' => DB_NAME, + 'endpoints' => [ + 'Voitures' => [ + 'GET /cars' => 'Liste toutes les voitures', + 'GET /cars/{id}' => 'Détails d\'une voiture', + 'GET /cars/{id}/etat' => 'État complet (voiture, dernier km, entretiens, notes)', + 'POST /cars' => 'Créer une voiture (marque, modele, annee, dateAchat, VIN)', + 'PUT /cars/{id}' => 'Modifier les paramètres d\'une voiture', + 'DELETE /cars/{id}' => 'Supprimer une voiture (et ses données associées)' + ], + 'Kilométrage' => [ + 'GET /cars/{id}/kilometrage' => 'Historique des relevés kilométriques', + 'POST /cars/{id}/kilometrage' => 'Ajouter un relevé kilométrique (valeur, date_releve)', + 'DELETE /kilometrage/{id}' => 'Supprimer un relevé kilométrique' + ], + 'Entretiens (Maintenance)' => [ + 'GET /cars/{id}/maintenance' => 'Historique des entretiens d\'une voiture', + 'POST /cars/{id}/maintenance' => 'Ajouter un entretien (type_entretien, date_evenement, kilometrage, description, prix)', + 'PUT /maintenance/{id}' => 'Modifier un entretien', + 'DELETE /maintenance/{id}' => 'Supprimer un entretien' + ], + 'Notes' => [ + 'GET /cars/{id}/notes' => 'Notes associées à une voiture', + 'POST /cars/{id}/notes' => 'Ajouter une note (titre, contenu)', + 'PUT /notes/{id}' => 'Modifier une note', + 'DELETE /notes/{id}' => 'Supprimer une note' + ] + ] + ]); + } + + $resource = strtolower($segments[0]); + + // ========================================================================= + // RESSOURCE: CARS (/cars ...) + // ========================================================================= + if ($resource === 'cars' || $resource === 'voitures') { + $carId = isset($segments[1]) && is_numeric($segments[1]) ? (int)$segments[1] : null; + $subResource = $segments[2] ?? null; + + // --- SOUS-RESSOURCES DE CARS --- + + // 1. /cars/{id}/etat (État complet via la procédure sp_getEtatVoiture) + if ($carId && $subResource === 'etat' && $method === 'GET') { + try { + $stmt = $db->prepare('CALL sp_getEtatVoiture(:id)'); + $stmt->execute([':id' => $carId]); + + $car = $stmt->fetch(); + if (!$car) { + sendJson(404, ['success' => false, 'error' => "Voiture #{$carId} introuvable"]); + } + + $maintenances = []; + if ($stmt->nextRowset()) { + $maintenances = $stmt->fetchAll(); + } + + $notes = []; + if ($stmt->nextRowset()) { + $notes = $stmt->fetchAll(); + } + $stmt->closeCursor(); + + sendJson(200, [ + 'success' => true, + 'data' => [ + 'voiture' => $car, + 'maintenances' => $maintenances, + 'notes' => $notes + ] + ]); + } catch (Exception $e) { + // Fallback si la procédure stockée a un souci + $stmtCar = $db->prepare(' + SELECT c.*, + (SELECT valeur FROM kilometrage WHERE car_id = c.id ORDER BY date_releve DESC, id DESC LIMIT 1) AS dernier_km + FROM cars c WHERE c.id = ? + '); + $stmtCar->execute([$carId]); + $car = $stmtCar->fetch(); + if (!$car) { + sendJson(404, ['success' => false, 'error' => "Voiture #{$carId} introuvable"]); + } + + $stmtMaint = $db->prepare('SELECT * FROM maintenance_logs WHERE car_id = ? ORDER BY date_evenement DESC'); + $stmtMaint->execute([$carId]); + + $stmtNotes = $db->prepare('SELECT * FROM notes WHERE car_id = ? ORDER BY date_creation DESC'); + $stmtNotes->execute([$carId]); + + sendJson(200, [ + 'success' => true, + 'data' => [ + 'voiture' => $car, + 'maintenances' => $stmtMaint->fetchAll(), + 'notes' => $stmtNotes->fetchAll() + ] + ]); + } + } + + // 2. /cars/{id}/kilometrage + if ($carId && $subResource === 'kilometrage') { + if ($method === 'GET') { + $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 50; + try { + $stmt = $db->prepare('CALL sp_getKilometrages(:id, :limit)'); + $stmt->execute([':id' => $carId, ':limit' => $limit]); + $data = $stmt->fetchAll(); + $stmt->closeCursor(); + } catch (Exception $e) { + $stmt = $db->prepare('SELECT * FROM kilometrage WHERE car_id = ? ORDER BY date_releve DESC, id DESC LIMIT ?'); + $stmt->bindValue(1, $carId, PDO::PARAM_INT); + $stmt->bindValue(2, $limit, PDO::PARAM_INT); + $stmt->execute(); + $data = $stmt->fetchAll(); + } + sendJson(200, ['success' => true, 'data' => $data]); + } + + if ($method === 'POST') { + $body = getBody(); + if (!isset($body['valeur'])) { + sendJson(400, ['success' => false, 'error' => 'Le champ valeur (kilométrage) est obligatoire']); + } + $dateReleve = $body['date_releve'] ?? date('Y-m-d'); + $valeur = (int)$body['valeur']; + + $stmt = $db->prepare('INSERT INTO kilometrage (car_id, date_releve, valeur) VALUES (?, ?, ?)'); + $stmt->execute([$carId, $dateReleve, $valeur]); + $newId = (int)$db->lastInsertId(); + + sendJson(201, [ + 'success' => true, + 'message' => 'Relevé kilométrique enregistré', + 'data' => [ + 'id' => $newId, + 'car_id' => $carId, + 'date_releve' => $dateReleve, + 'valeur' => $valeur + ] + ]); + } + + sendJson(405, ['success' => false, 'error' => 'Méthode non autorisée pour cette sous-ressource']); + } + + // 3. /cars/{id}/maintenance + if ($carId && ($subResource === 'maintenance' || $subResource === 'entretiens')) { + if ($method === 'GET') { + $stmt = $db->prepare('SELECT * FROM maintenance_logs WHERE car_id = ? ORDER BY date_evenement DESC'); + $stmt->execute([$carId]); + sendJson(200, ['success' => true, 'data' => $stmt->fetchAll()]); + } + + if ($method === 'POST') { + $body = getBody(); + if (empty($body['type_entretien']) || empty($body['date_evenement']) || !isset($body['kilometrage'])) { + sendJson(400, [ + 'success' => false, + 'error' => 'Les champs type_entretien, date_evenement et kilometrage sont obligatoires' + ]); + } + + $stmt = $db->prepare(' + INSERT INTO maintenance_logs (car_id, type_entretien, date_evenement, kilometrage, description, prix) + VALUES (?, ?, ?, ?, ?, ?) + '); + $stmt->execute([ + $carId, + trim((string)$body['type_entretien']), + (string)$body['date_evenement'], + (int)$body['kilometrage'], + isset($body['description']) ? trim((string)$body['description']) : null, + isset($body['prix']) ? (float)$body['prix'] : null + ]); + + $newId = (int)$db->lastInsertId(); + $stmtGet = $db->prepare('SELECT * FROM maintenance_logs WHERE id = ?'); + $stmtGet->execute([$newId]); + + sendJson(201, [ + 'success' => true, + 'message' => 'Entretien enregistré avec succès', + 'data' => $stmtGet->fetch() + ]); + } + + sendJson(405, ['success' => false, 'error' => 'Méthode non autorisée pour cette sous-ressource']); + } + + // 4. /cars/{id}/notes + if ($carId && $subResource === 'notes') { + if ($method === 'GET') { + $stmt = $db->prepare('SELECT * FROM notes WHERE car_id = ? ORDER BY date_creation DESC'); + $stmt->execute([$carId]); + sendJson(200, ['success' => true, 'data' => $stmt->fetchAll()]); + } + + if ($method === 'POST') { + $body = getBody(); + if (empty($body['contenu'])) { + sendJson(400, ['success' => false, 'error' => 'Le champ contenu est obligatoire']); + } + + $titre = isset($body['titre']) ? trim((string)$body['titre']) : null; + $contenu = trim((string)$body['contenu']); + + $stmt = $db->prepare('INSERT INTO notes (car_id, titre, contenu) VALUES (?, ?, ?)'); + $stmt->execute([$carId, $titre, $contenu]); + + $newId = (int)$db->lastInsertId(); + $stmtGet = $db->prepare('SELECT * FROM notes WHERE id = ?'); + $stmtGet->execute([$newId]); + + sendJson(201, [ + 'success' => true, + 'message' => 'Note enregistrée avec succès', + 'data' => $stmtGet->fetch() + ]); + } + + sendJson(405, ['success' => false, 'error' => 'Méthode non autorisée pour cette sous-ressource']); + } + + // --- OPÉRATIONS PRINCIPALES SUR LES VOITURES (/cars ou /cars/{id}) --- + + // GET /cars : Liste toutes les voitures + if ($carId === null && $method === 'GET') { + $sql = 'SELECT c.*, + (SELECT valeur FROM kilometrage WHERE car_id = c.id ORDER BY date_releve DESC, id DESC LIMIT 1) AS dernier_km + FROM cars c + ORDER BY c.id ASC'; + $stmt = $db->query($sql); + sendJson(200, ['success' => true, 'data' => $stmt->fetchAll()]); + } + + // GET /cars/{id} : Consulter une voiture + if ($carId !== null && $subResource === null && $method === 'GET') { + $stmt = $db->prepare(' + SELECT c.*, + (SELECT valeur FROM kilometrage WHERE car_id = c.id ORDER BY date_releve DESC, id DESC LIMIT 1) AS dernier_km + FROM cars c + WHERE c.id = ? + '); + $stmt->execute([$carId]); + $car = $stmt->fetch(); + if (!$car) { + sendJson(404, ['success' => false, 'error' => "Voiture #{$carId} introuvable"]); + } + sendJson(200, ['success' => true, 'data' => $car]); + } + + // POST /cars : Créer une voiture + if ($carId === null && $method === 'POST') { + $body = getBody(); + + // Validation des champs obligatoires + $required = ['marque', 'modele', 'annee', 'dateAchat']; + foreach ($required as $field) { + if (empty($body[$field])) { + sendJson(400, ['success' => false, 'error' => "Le champ '$field' est obligatoire"]); + } + } + + $marque = trim((string)$body['marque']); + $modele = trim((string)$body['modele']); + $annee = (int)$body['annee']; + $dateAchat = (string)$body['dateAchat']; + $vin = !empty($body['VIN']) ? trim((string)$body['VIN']) : null; + + // Utilisation de la procédure stockée sp_insertVoiture + try { + $stmt = $db->prepare('CALL sp_insertVoiture(:marque, :modele, :annee, :dateAchat, :vin)'); + $stmt->execute([ + ':marque' => $marque, + ':modele' => $modele, + ':annee' => $annee, + ':dateAchat' => $dateAchat, + ':vin' => $vin + ]); + $res = $stmt->fetch(); + $stmt->closeCursor(); + $newId = isset($res['new_id']) ? (int)$res['new_id'] : (int)$db->lastInsertId(); + } catch (Exception $e) { + // Fallback direct INSERT si la procédure a une incompatibilité + $stmt = $db->prepare('INSERT INTO cars (marque, modele, annee, dateAchat, VIN) VALUES (?, ?, ?, ?, ?)'); + $stmt->execute([$marque, $modele, $annee, $dateAchat, $vin]); + $newId = (int)$db->lastInsertId(); + } + + // Si un kilométrage initial est fourni + if (!empty($body['kilometrage_initial'])) { + $kmStmt = $db->prepare('INSERT INTO kilometrage (car_id, date_releve, valeur) VALUES (?, ?, ?)'); + $kmStmt->execute([$newId, $dateAchat, (int)$body['kilometrage_initial']]); + } + + // Récupère l'enregistrement créé + $stmtGet = $db->prepare(' + SELECT c.*, + (SELECT valeur FROM kilometrage WHERE car_id = c.id ORDER BY date_releve DESC, id DESC LIMIT 1) AS dernier_km + FROM cars c + WHERE c.id = ? + '); + $stmtGet->execute([$newId]); + + sendJson(201, [ + 'success' => true, + 'message' => 'Voiture créée avec succès', + 'data' => $stmtGet->fetch() + ]); + } + + // PUT / PATCH /cars/{id} : Mettre à jour les paramètres d'une voiture + if ($carId !== null && $subResource === null && ($method === 'PUT' || $method === 'PATCH')) { + // Vérifier si la voiture existe + $check = $db->prepare('SELECT id FROM cars WHERE id = ?'); + $check->execute([$carId]); + if (!$check->fetch()) { + sendJson(404, ['success' => false, 'error' => "Voiture #{$carId} introuvable"]); + } + + $body = getBody(); + $allowedFields = ['marque', 'modele', 'annee', 'dateAchat', 'VIN']; + $updates = []; + $params = []; + + foreach ($allowedFields as $field) { + if (array_key_exists($field, $body)) { + $updates[] = "`$field` = ?"; + $params[] = $body[$field]; + } + } + + if (empty($updates)) { + sendJson(400, ['success' => false, 'error' => 'Aucun paramètre valide à mettre à jour']); + } + + $params[] = $carId; + $sql = 'UPDATE cars SET ' . implode(', ', $updates) . ' WHERE id = ?'; + $stmt = $db->prepare($sql); + $stmt->execute($params); + + // Récupère la voiture mise à jour + $stmtGet = $db->prepare(' + SELECT c.*, + (SELECT valeur FROM kilometrage WHERE car_id = c.id ORDER BY date_releve DESC, id DESC LIMIT 1) AS dernier_km + FROM cars c + WHERE c.id = ? + '); + $stmtGet->execute([$carId]); + + sendJson(200, [ + 'success' => true, + 'message' => 'Paramètres de la voiture mis à jour avec succès', + 'data' => $stmtGet->fetch() + ]); + } + + // DELETE /cars/{id} : Supprimer une voiture + if ($carId !== null && $subResource === null && $method === 'DELETE') { + // Vérifier existence + $check = $db->prepare('SELECT id FROM cars WHERE id = ?'); + $check->execute([$carId]); + if (!$check->fetch()) { + sendJson(404, ['success' => false, 'error' => "Voiture #{$carId} introuvable"]); + } + + // Exécution de la procédure stockée sp_deleteVoiture + try { + $stmt = $db->prepare('CALL sp_deleteVoiture(:id)'); + $stmt->execute([':id' => $carId]); + $stmt->closeCursor(); + } catch (Exception $e) { + $stmt = $db->prepare('DELETE FROM cars WHERE id = ?'); + $stmt->execute([$carId]); + } + + sendJson(200, [ + 'success' => true, + 'message' => "Voiture #{$carId} ainsi que toutes ses données associées ont été supprimées avec succès" + ]); + } + + sendJson(405, ['success' => false, 'error' => "Méthode HTTP non autorisée pour cette URL"]); + } + + // ========================================================================= + // RESSOURCE: KILOMETRAGE DIRECT (/kilometrage/{id}) + // ========================================================================= + if ($resource === 'kilometrage') { + $kmId = isset($segments[1]) && is_numeric($segments[1]) ? (int)$segments[1] : null; + + if ($kmId && $method === 'DELETE') { + $stmt = $db->prepare('DELETE FROM kilometrage WHERE id = ?'); + $stmt->execute([$kmId]); + if ($stmt->rowCount() === 0) { + sendJson(404, ['success' => false, 'error' => "Relevé kilométrique #{$kmId} introuvable"]); + } + sendJson(200, ['success' => true, 'message' => "Relevé kilométrique #{$kmId} supprimé"]); + } + + sendJson(405, ['success' => false, 'error' => "Méthode non autorisée sur /kilometrage"]); + } + + // ========================================================================= + // RESSOURCE: MAINTENANCE DIRECT (/maintenance/{id}) + // ========================================================================= + if ($resource === 'maintenance' || $resource === 'entretiens') { + $maintId = isset($segments[1]) && is_numeric($segments[1]) ? (int)$segments[1] : null; + + if (!$maintId) { + sendJson(400, ['success' => false, 'error' => 'Identifiant d\'entretien requis']); + } + + if ($method === 'GET') { + $stmt = $db->prepare('SELECT * FROM maintenance_logs WHERE id = ?'); + $stmt->execute([$maintId]); + $item = $stmt->fetch(); + if (!$item) { + sendJson(404, ['success' => false, 'error' => "Entretien #{$maintId} introuvable"]); + } + sendJson(200, ['success' => true, 'data' => $item]); + } + + if ($method === 'PUT' || $method === 'PATCH') { + $body = getBody(); + $allowed = ['type_entretien', 'date_evenement', 'kilometrage', 'description', 'prix']; + $updates = []; + $params = []; + + foreach ($allowed as $f) { + if (array_key_exists($f, $body)) { + $updates[] = "`$f` = ?"; + $params[] = $body[$f]; + } + } + + if (empty($updates)) { + sendJson(400, ['success' => false, 'error' => 'Aucun paramètre à modifier']); + } + + $params[] = $maintId; + $stmt = $db->prepare('UPDATE maintenance_logs SET ' . implode(', ', $updates) . ' WHERE id = ?'); + $stmt->execute($params); + + $stmtGet = $db->prepare('SELECT * FROM maintenance_logs WHERE id = ?'); + $stmtGet->execute([$maintId]); + sendJson(200, [ + 'success' => true, + 'message' => 'Entretien mis à jour avec succès', + 'data' => $stmtGet->fetch() + ]); + } + + if ($method === 'DELETE') { + $stmt = $db->prepare('DELETE FROM maintenance_logs WHERE id = ?'); + $stmt->execute([$maintId]); + if ($stmt->rowCount() === 0) { + sendJson(404, ['success' => false, 'error' => "Entretien #{$maintId} introuvable"]); + } + sendJson(200, ['success' => true, 'message' => "Entretien #{$maintId} supprimé avec succès"]); + } + + sendJson(405, ['success' => false, 'error' => "Méthode non autorisée sur /maintenance/{id}"]); + } + + // ========================================================================= + // RESSOURCE: NOTES DIRECT (/notes/{id}) + // ========================================================================= + if ($resource === 'notes') { + $noteId = isset($segments[1]) && is_numeric($segments[1]) ? (int)$segments[1] : null; + + if (!$noteId) { + sendJson(400, ['success' => false, 'error' => 'Identifiant de note requis']); + } + + if ($method === 'GET') { + $stmt = $db->prepare('SELECT * FROM notes WHERE id = ?'); + $stmt->execute([$noteId]); + $item = $stmt->fetch(); + if (!$item) { + sendJson(404, ['success' => false, 'error' => "Note #{$noteId} introuvable"]); + } + sendJson(200, ['success' => true, 'data' => $item]); + } + + if ($method === 'PUT' || $method === 'PATCH') { + $body = getBody(); + $allowed = ['titre', 'contenu']; + $updates = []; + $params = []; + + foreach ($allowed as $f) { + if (array_key_exists($f, $body)) { + $updates[] = "`$f` = ?"; + $params[] = $body[$f]; + } + } + + if (empty($updates)) { + sendJson(400, ['success' => false, 'error' => 'Aucun paramètre à modifier']); + } + + $params[] = $noteId; + $stmt = $db->prepare('UPDATE notes SET ' . implode(', ', $updates) . ' WHERE id = ?'); + $stmt->execute($params); + + $stmtGet = $db->prepare('SELECT * FROM notes WHERE id = ?'); + $stmtGet->execute([$noteId]); + sendJson(200, [ + 'success' => true, + 'message' => 'Note mise à jour avec succès', + 'data' => $stmtGet->fetch() + ]); + } + + if ($method === 'DELETE') { + $stmt = $db->prepare('DELETE FROM notes WHERE id = ?'); + $stmt->execute([$noteId]); + if ($stmt->rowCount() === 0) { + sendJson(404, ['success' => false, 'error' => "Note #{$noteId} introuvable"]); + } + sendJson(200, ['success' => true, 'message' => "Note #{$noteId} supprimée avec succès"]); + } + + sendJson(405, ['success' => false, 'error' => "Méthode non autorisée sur /notes/{id}"]); + } + + // Ressource inconnue + sendJson(404, [ + 'success' => false, + 'error' => "Ressource '/$resource' non reconnue. Consultez la racine '/' pour la documentation des routes." + ]); + +} catch (PDOException $e) { + sendJson(500, [ + 'success' => false, + 'error' => 'Erreur SQL: ' . $e->getMessage() + ]); +} catch (Throwable $e) { + sendJson(500, [ + 'success' => false, + 'error' => 'Erreur serveur: ' . $e->getMessage() + ]); +} diff --git a/voituresapi (1).sql b/voituresapi (1).sql new file mode 100644 index 0000000..891545f --- /dev/null +++ b/voituresapi (1).sql @@ -0,0 +1,188 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.3 +-- https://www.phpmyadmin.net/ +-- +-- Hôte : 127.0.0.1:3306 +-- Généré le : mer. 16 sep. 2026 à 08:43 +-- Version du serveur : 8.4.7 +-- Version de PHP : 8.3.28 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Base de données : `voituresapi` +-- + +DELIMITER $$ +-- +-- Procédures +-- +DROP PROCEDURE IF EXISTS `sp_deleteVoiture`$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_deleteVoiture` (IN `p_id` INT) BEGIN + DELETE FROM cars WHERE id = p_id; + SELECT ROW_COUNT() AS affected; +END$$ + +DROP PROCEDURE IF EXISTS `sp_getEtatVoiture`$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_getEtatVoiture` (IN `p_id` INT) BEGIN + SELECT c.*, + (SELECT valeur FROM kilometrage WHERE car_id = c.id ORDER BY date_releve DESC, id DESC LIMIT 1) AS dernier_km + FROM cars c + WHERE c.id = p_id; + + SELECT * FROM maintenance_logs WHERE car_id = p_id ORDER BY date_evenement DESC; + + SELECT * FROM notes WHERE car_id = p_id ORDER BY date_creation DESC; +END$$ + +DROP PROCEDURE IF EXISTS `sp_getKilometrages`$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_getKilometrages` (IN `p_id` INT, IN `p_limit` INT) BEGIN + SELECT id, car_id, valeur, date_releve + FROM kilometrage + WHERE car_id = p_id + ORDER BY date_releve DESC, id DESC + LIMIT p_limit; +END$$ + +DROP PROCEDURE IF EXISTS `sp_insertVoiture`$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_insertVoiture` (IN `p_marque` VARCHAR(255), IN `p_modele` VARCHAR(255), IN `p_annee` INT, IN `p_dateAchat` DATE, IN `p_VIN` VARCHAR(255)) BEGIN + INSERT INTO cars (marque, modele, annee, dateAchat, VIN) + VALUES (p_marque, p_modele, p_annee, p_dateAchat, p_VIN); + SELECT LAST_INSERT_ID() AS new_id; +END$$ + +DELIMITER ; + +-- -------------------------------------------------------- + +-- +-- Structure de la table `cars` +-- + +DROP TABLE IF EXISTS `cars`; +CREATE TABLE IF NOT EXISTS `cars` ( + `id` int NOT NULL AUTO_INCREMENT, + `marque` varchar(50) NOT NULL, + `modele` varchar(50) NOT NULL, + `annee` int NOT NULL, + `dateAchat` date NOT NULL, + `VIN` varchar(17) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- Déchargement des données de la table `cars` +-- + +INSERT INTO `cars` (`id`, `marque`, `modele`, `annee`, `dateAchat`, `VIN`) VALUES +(1, 'Peugeot', '207', 2009, '2025-05-20', 'VF3WA8HZCXXXXXXXX'), +(2, 'Peugeot', '208', 2010, '2025-05-20', 'VF3WA8HZCXXXXXXXX'); + +-- -------------------------------------------------------- + +-- +-- Structure de la table `kilometrage` +-- + +DROP TABLE IF EXISTS `kilometrage`; +CREATE TABLE IF NOT EXISTS `kilometrage` ( + `car_id` int NOT NULL, + `date_releve` date NOT NULL, + `valeur` int NOT NULL, + KEY `fk_km_car_id` (`car_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- Déchargement des données de la table `kilometrage` +-- + +INSERT INTO `kilometrage` (`car_id`, `date_releve`, `valeur`) VALUES +(1, '2026-04-20', 133000), +(1, '2026-04-20', 133200); + +-- -------------------------------------------------------- + +-- +-- Structure de la table `maintenance_logs` +-- + +DROP TABLE IF EXISTS `maintenance_logs`; +CREATE TABLE IF NOT EXISTS `maintenance_logs` ( + `id` int NOT NULL AUTO_INCREMENT, + `car_id` int NOT NULL, + `type_entretien` varchar(100) NOT NULL, + `date_evenement` date NOT NULL, + `kilometrage` int NOT NULL, + `description` text, + `prix` decimal(10,2) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `fk_car_id` (`car_id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- Déchargement des données de la table `maintenance_logs` +-- + +INSERT INTO `maintenance_logs` (`id`, `car_id`, `type_entretien`, `date_evenement`, `kilometrage`, `description`, `prix`) VALUES +(1, 1, 'Vidange', '2023-10-15', 145000, 'Huile 5W40 + Filtre à huile', 85.00), +(2, 1, 'Pneus', '2024-02-01', 152000, 'Changement pneus avant Michelin', 160.00); + +-- -------------------------------------------------------- + +-- +-- Structure de la table `notes` +-- + +DROP TABLE IF EXISTS `notes`; +CREATE TABLE IF NOT EXISTS `notes` ( + `id` int NOT NULL AUTO_INCREMENT, + `car_id` int NOT NULL, + `titre` varchar(100) DEFAULT NULL, + `contenu` text NOT NULL, + `date_creation` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `fk_notes_car_id` (`car_id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- +-- Déchargement des données de la table `notes` +-- + +INSERT INTO `notes` (`id`, `car_id`, `titre`, `contenu`, `date_creation`) VALUES +(2, 1, 'Clé', 'Ne pas oublier de faire revenir légèrement la clé vers la gauche une fois démarrée', '2026-04-20 14:58:46'), +(3, 1, 'Batterie', 'Recharger la batterie', '2026-04-20 15:03:01'); + +-- +-- Contraintes pour les tables déchargées +-- + +-- +-- Contraintes pour la table `kilometrage` +-- +ALTER TABLE `kilometrage` + ADD CONSTRAINT `fk_km_car_id` FOREIGN KEY (`car_id`) REFERENCES `cars` (`id`) ON DELETE CASCADE; + +-- +-- Contraintes pour la table `maintenance_logs` +-- +ALTER TABLE `maintenance_logs` + ADD CONSTRAINT `fk_car_id` FOREIGN KEY (`car_id`) REFERENCES `cars` (`id`) ON DELETE CASCADE; + +-- +-- Contraintes pour la table `notes` +-- +ALTER TABLE `notes` + ADD CONSTRAINT `fk_notes_car_id` FOREIGN KEY (`car_id`) REFERENCES `cars` (`id`) ON DELETE CASCADE; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;