correction garage
Deploy HouseHub / deploy (push) Successful in 1s

This commit is contained in:
2026-05-14 22:15:55 +02:00
parent f62f724046
commit b2a3e34bbe
5 changed files with 519 additions and 17 deletions
+165 -1
View File
@@ -17,6 +17,24 @@ require_once dirname(__DIR__, 2) . '/includes/db.php';
$UPLOAD_DIR = '/uploads/garage/';
if (!is_dir($UPLOAD_DIR)) { @mkdir($UPLOAD_DIR, 0755, true); }
$pdo->exec("
CREATE TABLE IF NOT EXISTS pf_garage_documents (
id INT AUTO_INCREMENT PRIMARY KEY,
vehicle_id INT NOT NULL,
maintenance_id INT DEFAULT NULL,
label VARCHAR(255) DEFAULT NULL,
filename VARCHAR(255) NOT NULL,
original_name VARCHAR(255) DEFAULT NULL,
mime VARCHAR(120) DEFAULT NULL,
size INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_gd_vehicle (vehicle_id),
KEY idx_gd_maint (maintenance_id),
FOREIGN KEY (vehicle_id) REFERENCES pf_vehicles(id) ON DELETE CASCADE,
FOREIGN KEY (maintenance_id) REFERENCES pf_maintenances(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
");
$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? '';
@@ -38,6 +56,37 @@ function handleUpload(string $field, string $dir): ?string {
return null;
}
function handleGarageDocumentUpload(string $field, string $dir): ?array {
if (!isset($_FILES[$field]) || $_FILES[$field]['error'] !== UPLOAD_ERR_OK) {
return null;
}
if ($_FILES[$field]['size'] > 12 * 1024 * 1024) {
gErr('Fichier trop volumineux (max 12 Mo).', 400);
}
$ext = strtolower(pathinfo($_FILES[$field]['name'], PATHINFO_EXTENSION));
$allowed = ['pdf','jpg','jpeg','png','gif','webp','doc','docx','xls','xlsx','odt','txt'];
if (!in_array($ext, $allowed, true)) {
gErr('Format non autorisé.', 400);
}
$fname = 'd_' . uniqid('', true) . '.' . $ext;
if (!move_uploaded_file($_FILES[$field]['tmp_name'], $dir . $fname)) {
return null;
}
$mimeMap = [
'pdf' => 'application/pdf', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp',
'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xls' => 'application/vnd.ms-excel', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'odt' => 'application/vnd.oasis.opendocument.text', 'txt' => 'text/plain',
];
return [
'filename' => $fname,
'original_name' => $_FILES[$field]['name'],
'mime' => $mimeMap[$ext] ?? 'application/octet-stream',
'size' => (int) $_FILES[$field]['size'],
];
}
// ─── Vehicles ─────────────────────────────────────────────────────────────────
if ($action === 'vehicles') {
if ($method === 'GET') {
@@ -47,6 +96,12 @@ if ($action === 'vehicles') {
$vehicle = $v->fetch(); if (!$vehicle) gErr('Véhicule introuvable', 404);
$s = $pdo->prepare("SELECT COUNT(*) as cnt, COALESCE(SUM(cost),0) as total FROM pf_maintenances WHERE vehicle_id = ?"); $s->execute([$id]); $vehicle['stats'] = $s->fetch();
$p = $pdo->prepare("SELECT COUNT(*) as cnt, COALESCE(SUM(price*quantity),0) as total FROM pf_parts WHERE vehicle_id = ?"); $p->execute([$id]); $vehicle['parts_stats'] = $p->fetch();
$dc = $pdo->prepare("SELECT COUNT(*) FROM pf_garage_documents WHERE vehicle_id = ? AND maintenance_id IS NULL");
$dc->execute([$id]);
$vehicle['vehicle_docs_count'] = (int) $dc->fetchColumn();
$dm = $pdo->prepare("SELECT COUNT(*) FROM pf_garage_documents WHERE vehicle_id = ? AND maintenance_id IS NOT NULL");
$dm->execute([$id]);
$vehicle['maint_docs_count'] = (int) $dm->fetchColumn();
gOk($vehicle);
}
$stmt = $pdo->query("SELECT v.*, (SELECT COUNT(*) FROM pf_maintenances m WHERE m.vehicle_id = v.id) as maintenance_count, (SELECT COALESCE(SUM(cost),0) FROM pf_maintenances m WHERE m.vehicle_id = v.id) as total_cost, (SELECT date FROM pf_maintenances m WHERE m.vehicle_id = v.id ORDER BY date DESC LIMIT 1) as last_maintenance FROM pf_vehicles v ORDER BY v.created_at DESC");
@@ -76,11 +131,110 @@ if ($action === 'vehicles') {
}
if ($method === 'DELETE') {
$id = $_GET['id'] ?? null; if (!$id) gErr('ID manquant');
$docs = $pdo->prepare('SELECT filename FROM pf_garage_documents WHERE vehicle_id = ?');
$docs->execute([$id]);
foreach ($docs->fetchAll(PDO::FETCH_COLUMN) as $fn) {
if ($fn) {
@unlink($UPLOAD_DIR . basename($fn));
}
}
$v = $pdo->prepare("SELECT photo FROM pf_vehicles WHERE id=?"); $v->execute([$id]); $row = $v->fetch(); if ($row['photo']) @unlink($UPLOAD_DIR . $row['photo']);
$pdo->prepare("DELETE FROM pf_vehicles WHERE id = ?")->execute([$id]); gOk(['deleted' => true]);
}
}
// ─── Documents (véhicule / entretien — factures, PDF, etc.) ───────────────────
if ($action === 'garage_documents') {
if ($method === 'GET') {
$vid = $_GET['vehicle_id'] ?? null;
$mid = $_GET['maintenance_id'] ?? null;
$vehicleOnly = ($_GET['vehicle_only'] ?? '') === '1';
if ($mid) {
$stmt = $pdo->prepare("SELECT d.*, v.name as vehicle_name FROM pf_garage_documents d JOIN pf_vehicles v ON v.id = d.vehicle_id WHERE d.maintenance_id = ? ORDER BY d.created_at DESC");
$stmt->execute([$mid]);
gOk($stmt->fetchAll());
}
if (!$vid) {
gErr('vehicle_id ou maintenance_id requis');
}
if ($vehicleOnly) {
$stmt = $pdo->prepare("SELECT * FROM pf_garage_documents WHERE vehicle_id = ? AND maintenance_id IS NULL ORDER BY created_at DESC");
$stmt->execute([$vid]);
} else {
$stmt = $pdo->prepare("SELECT * FROM pf_garage_documents WHERE vehicle_id = ? ORDER BY created_at DESC");
$stmt->execute([$vid]);
}
gOk($stmt->fetchAll());
}
if ($method === 'POST') {
$d = $_POST;
$vid = (int) ($d['vehicle_id'] ?? 0);
if ($vid < 1) {
gErr('vehicle_id manquant');
}
$mid = isset($d['maintenance_id']) && $d['maintenance_id'] !== '' ? (int) $d['maintenance_id'] : null;
if ($mid) {
$chk = $pdo->prepare("SELECT id FROM pf_maintenances WHERE id = ? AND vehicle_id = ?");
$chk->execute([$mid, $vid]);
if (!$chk->fetch()) {
gErr('Entretien invalide pour ce véhicule');
}
}
$up = handleGarageDocumentUpload('file', $UPLOAD_DIR);
if (!$up) {
gErr('Upload échoué ou fichier manquant');
}
$label = trim($d['label'] ?? '');
$pdo->prepare("INSERT INTO pf_garage_documents (vehicle_id, maintenance_id, label, filename, original_name, mime, size) VALUES (?,?,?,?,?,?,?)")
->execute([$vid, $mid, $label ?: null, $up['filename'], $up['original_name'], $up['mime'], $up['size']]);
gOk(['id' => (int) $pdo->lastInsertId()]);
}
if ($method === 'DELETE') {
$id = (int) ($_GET['id'] ?? 0);
if ($id < 1) {
gErr('ID manquant');
}
$r = $pdo->prepare("SELECT filename FROM pf_garage_documents WHERE id = ?");
$r->execute([$id]);
$row = $r->fetch();
if (!$row) {
gErr('Document introuvable', 404);
}
if (!empty($row['filename'])) {
@unlink($UPLOAD_DIR . $row['filename']);
}
$pdo->prepare("DELETE FROM pf_garage_documents WHERE id = ?")->execute([$id]);
gOk(['deleted' => true]);
}
}
if ($action === 'garage_document') {
$id = (int) ($_GET['id'] ?? 0);
if ($id < 1) {
gErr('ID manquant');
}
$stmt = $pdo->prepare('SELECT * FROM pf_garage_documents WHERE id = ?');
$stmt->execute([$id]);
$doc = $stmt->fetch();
if (!$doc || empty($doc['filename'])) {
http_response_code(404);
exit;
}
$f = basename($doc['filename']);
$path = $UPLOAD_DIR . $f;
if (!preg_match('/^d_[a-zA-Z0-9._-]+$/', $f) || !is_file($path)) {
http_response_code(404);
exit;
}
$mime = $doc['mime'] ?: 'application/octet-stream';
header('Content-Type: ' . $mime);
$disp = $doc['original_name'] ?: $f;
header('Content-Disposition: inline; filename="' . rawurlencode($disp) . '"');
header('Cache-Control: private, max-age=3600');
readfile($path);
exit;
}
// ─── Maintenances ─────────────────────────────────────────────────────────────
if ($action === 'maintenances') {
$vid = $_GET['vehicle_id'] ?? null;
@@ -89,10 +243,13 @@ if ($action === 'maintenances') {
if ($id) {
$stmt = $pdo->prepare("SELECT m.*, v.name as vehicle_name, v.license_plate, v.current_km FROM pf_maintenances m JOIN pf_vehicles v ON v.id = m.vehicle_id WHERE m.id = ?");
$stmt->execute([$id]); $m = $stmt->fetch(); if (!$m) gErr('Entretien introuvable', 404);
$dc = $pdo->prepare("SELECT COUNT(*) FROM pf_garage_documents WHERE maintenance_id = ?");
$dc->execute([$id]);
$m['documents_count'] = (int) $dc->fetchColumn();
gOk($m);
}
if ($vid) {
$stmt = $pdo->prepare("SELECT m.*, GROUP_CONCAT(p.name SEPARATOR ', ') as parts_names, COUNT(p.id) as parts_count, COALESCE(SUM(p.price*p.quantity),0) as parts_cost FROM pf_maintenances m LEFT JOIN pf_parts p ON p.maintenance_id = m.id WHERE m.vehicle_id = ? GROUP BY m.id ORDER BY m.date DESC, m.created_at DESC");
$stmt = $pdo->prepare("SELECT m.*, GROUP_CONCAT(p.name SEPARATOR ', ') as parts_names, COUNT(p.id) as parts_count, COALESCE(SUM(p.price*p.quantity),0) as parts_cost, (SELECT COUNT(*) FROM pf_garage_documents d WHERE d.maintenance_id = m.id) as documents_count FROM pf_maintenances m LEFT JOIN pf_parts p ON p.maintenance_id = m.id WHERE m.vehicle_id = ? GROUP BY m.id ORDER BY m.date DESC, m.created_at DESC");
$stmt->execute([$vid]); gOk($stmt->fetchAll());
}
$stmt = $pdo->query("SELECT m.*, v.name as vehicle_name, v.license_plate, v.current_km FROM pf_maintenances m JOIN pf_vehicles v ON v.id = m.vehicle_id WHERE m.next_date IS NOT NULL OR m.next_km IS NOT NULL ORDER BY m.next_date ASC");
@@ -126,6 +283,13 @@ if ($action === 'maintenances') {
}
if ($method === 'DELETE') {
$id = $_GET['id'] ?? null; if (!$id) gErr('ID manquant');
$docs = $pdo->prepare('SELECT filename FROM pf_garage_documents WHERE maintenance_id = ?');
$docs->execute([$id]);
foreach ($docs->fetchAll(PDO::FETCH_COLUMN) as $fn) {
if ($fn) {
@unlink($UPLOAD_DIR . basename($fn));
}
}
$pdo->prepare("DELETE FROM pf_maintenances WHERE id = ?")->execute([$id]); gOk(['deleted' => true]);
}
}