Initial commit

This commit is contained in:
Porawit Dongwang
2026-09-16 23:20:08 +07:00
commit 0041668dbb
32577 changed files with 3687927 additions and 0 deletions
@@ -0,0 +1,48 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/logger.php';
require_once '../includes/notifier.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$id = $_POST['id'] ?? '';
if (empty($id)) {
jsonResponse(false, 'ไม่พบข้อมูลที่ต้องการลบ');
}
try {
// ตรวจสอบว่ามีการจองผูกอยู่หรือไม่
$stmt = $pdo->prepare("SELECT id FROM schedules WHERE driver_id = ? LIMIT 1");
$stmt->execute([$id]);
if ($stmt->fetch()) {
jsonResponse(false, 'ไม่สามารถลบได้ เนื่องจากพนักงานขับรถคนนี้มีคิวการจองอยู่ในระบบ');
}
$stmt = $pdo->prepare("SELECT first_name, last_name FROM drivers WHERE id = ?");
$stmt->execute([$id]);
$driverInfo = $stmt->fetch();
$driverName = $driverInfo ? trim($driverInfo['first_name'] . ' ' . $driverInfo['last_name']) : $id;
$stmt = $pdo->prepare("DELETE FROM drivers WHERE id = ?");
$stmt->execute([$id]);
if ($stmt->rowCount() > 0) {
logActivity("Delete Driver ({$driverName})", 'drivers', $id);
notifyEvent('driver', "👤 แจ้งเตือนพนักงานขับรถ\nลบข้อมูลพนักงานออกจากระบบ: {$driverName}");
jsonResponse(true, 'ลบข้อมูลสำเร็จ');
} else {
jsonResponse(false, 'ไม่พบข้อมูลในฐานข้อมูล');
}
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,47 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
// รับข้อมูลแบบ JSON หรือ Form Data
$data = json_decode(file_get_contents("php://input"), true) ?: $_POST;
$doc_id = $data['id'] ?? '';
if (empty($doc_id)) {
jsonResponse(false, 'Document ID is required');
}
try {
// ดึงข้อมูลไฟล์เพื่อเอา path ไปลบไฟล์จริง
$stmt = $pdo->prepare("SELECT file_path FROM driver_documents WHERE id = ?");
$stmt->execute([$doc_id]);
$doc = $stmt->fetch();
if ($doc) {
$filePath = '../' . $doc['file_path'];
// ลบข้อมูลจากฐานข้อมูล
$deleteStmt = $pdo->prepare("DELETE FROM driver_documents WHERE id = ?");
$deleteStmt->execute([$doc_id]);
// ลบไฟล์จริงออกจากเซิร์ฟเวอร์
if (file_exists($filePath)) {
unlink($filePath);
}
jsonResponse(true, 'ลบไฟล์สำเร็จ');
} else {
jsonResponse(false, 'ไม่พบเอกสารที่ต้องการลบ');
}
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,25 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
$driver_id = $_GET['driver_id'] ?? '';
if (empty($driver_id)) {
jsonResponse(false, 'Driver ID is required');
}
try {
$stmt = $pdo->prepare("SELECT * FROM driver_documents WHERE driver_id = ? ORDER BY created_at DESC");
$stmt->execute([$driver_id]);
$docs = $stmt->fetchAll();
jsonResponse(true, 'Success', $docs);
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,81 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$driver_id = $_POST['driver_id'] ?? '';
if (empty($driver_id)) {
jsonResponse(false, 'Driver ID is required');
}
// ตรวจสอบว่ามีไฟล์ส่งมาหรือไม่
if (!isset($_FILES['document']) || $_FILES['document']['error'] === UPLOAD_ERR_NO_FILE) {
jsonResponse(false, 'กรุณาเลือกไฟล์เอกสาร (PDF)');
}
$file = $_FILES['document'];
// ตรวจสอบ Error ของไฟล์
if ($file['error'] !== UPLOAD_ERR_OK) {
jsonResponse(false, 'เกิดข้อผิดพลาดในการอัปโหลดไฟล์: ' . $file['error']);
}
// ตรวจสอบประเภทไฟล์ (ต้องเป็น PDF เท่านั้น)
$fileType = mime_content_type($file['tmp_name']);
$allowedTypes = ['application/pdf'];
if (!in_array($fileType, $allowedTypes)) {
jsonResponse(false, 'อนุญาตให้อัปโหลดเฉพาะไฟล์ PDF เท่านั้น');
}
// ตรวจสอบขนาดไฟล์ (เช่น ไม่เกิน 5MB)
$maxSize = 5 * 1024 * 1024;
if ($file['size'] > $maxSize) {
jsonResponse(false, 'ขนาดไฟล์ต้องไม่เกิน 5MB');
}
// สร้างโฟลเดอร์สำหรับเก็บไฟล์ถ้ายังไม่มี
$uploadDir = '../uploads/driver_docs/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
// สร้างชื่อไฟล์ใหม่เพื่อป้องกันชื่อซ้ำ และปัญหาภาษาไทย
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$newFileName = 'drv_' . $driver_id . '_' . time() . '_' . uniqid() . '.' . $extension;
$destination = $uploadDir . $newFileName;
$dbPath = 'uploads/driver_docs/' . $newFileName;
// ย้ายไฟล์ไปยังโฟลเดอร์ปลายทาง
if (move_uploaded_file($file['tmp_name'], $destination)) {
try {
// บันทึกข้อมูลลงฐานข้อมูล
$stmt = $pdo->prepare("INSERT INTO driver_documents (driver_id, original_name, file_name, file_path) VALUES (?, ?, ?, ?)");
$stmt->execute([
$driver_id,
$file['name'],
$newFileName,
$dbPath
]);
jsonResponse(true, 'อัปโหลดไฟล์สำเร็จ');
} catch (PDOException $e) {
// หากบันทึกฐานข้อมูลลบเหลว ให้ลบไฟล์ที่อัปโหลดไปแล้วด้วย
if (file_exists($destination)) {
unlink($destination);
}
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
} else {
jsonResponse(false, 'ไม่สามารถบันทึกไฟล์ได้ กรุณาลองใหม่อีกครั้ง');
}
?>
@@ -0,0 +1,67 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/logger.php';
require_once '../includes/notifier.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$id = $_POST['id'] ?? '';
$first_name = trim($_POST['first_name'] ?? '');
$last_name = trim($_POST['last_name'] ?? '');
$phone = trim($_POST['phone'] ?? '');
$status = $_POST['status'] ?? 'available';
// New HR fields
$hr_cid = trim($_POST['hr_cid'] ?? '');
$sex = trim($_POST['sex'] ?? '');
$position = trim($_POST['position'] ?? '');
$department = trim($_POST['department'] ?? '');
$person_type = trim($_POST['person_type'] ?? '');
$license_type = trim($_POST['license_type'] ?? '');
$license_expiry_date = trim($_POST['license_expiry_date'] ?? '');
if (empty($license_expiry_date)) {
$license_expiry_date = null;
}
if (empty($first_name) || empty($last_name)) {
jsonResponse(false, 'กรุณากรอกชื่อและนามสกุล');
}
// Generate random avatar if empty
$avatar = 'https://ui-avatars.com/api/?name=' . urlencode($first_name . ' ' . $last_name) . '&background=random';
try {
if (empty($id)) {
// สร้างใหม่
$stmt = $pdo->prepare("INSERT INTO drivers (first_name, last_name, phone, status, avatar, hr_cid, sex, position, department, person_type, license_type, license_expiry_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$first_name, $last_name, $phone, $status, $avatar, $hr_cid, $sex, $position, $department, $person_type, $license_type, $license_expiry_date]);
$newId = $pdo->lastInsertId();
logActivity("Create Driver ({$first_name} {$last_name})", 'drivers', $newId);
notifyEvent('driver', "👤 แจ้งเตือนพนักงานขับรถ\nมีพนักงานใหม่เพิ่มเข้าระบบ: {$first_name} {$last_name}");
jsonResponse(true, 'เพิ่มพนักงานใหม่สำเร็จ');
} else {
// แก้ไข
$stmt = $pdo->prepare("UPDATE drivers SET first_name=?, last_name=?, phone=?, status=?, avatar=?, hr_cid=?, sex=?, position=?, department=?, person_type=?, license_type=?, license_expiry_date=? WHERE id=?");
$stmt->execute([$first_name, $last_name, $phone, $status, $avatar, $hr_cid, $sex, $position, $department, $person_type, $license_type, $license_expiry_date, $id]);
logActivity("Update Driver ({$first_name} {$last_name})", 'drivers', $id);
notifyEvent('driver', "👤 แจ้งเตือนพนักงานขับรถ\nแก้ไขข้อมูลพนักงาน: {$first_name} {$last_name}");
jsonResponse(true, 'แก้ไขข้อมูลพนักงานสำเร็จ');
}
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,33 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$id = $_POST['id'] ?? '';
$status = $_POST['status'] ?? '';
if (empty($id) || empty($status)) {
jsonResponse(false, 'ข้อมูลไม่ครบถ้วน');
}
try {
$stmt = $pdo->prepare("UPDATE drivers SET status = ? WHERE id = ?");
$stmt->execute([$status, $id]);
if ($stmt->rowCount() > 0) {
jsonResponse(true, 'อัปเดตสถานะสำเร็จ');
} else {
jsonResponse(false, 'ไม่พบพนักงานในระบบ หรือสถานะเหมือนเดิม');
}
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,36 @@
<?php
session_start();
require_once '../includes/db_hr.php';
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
exit;
}
if (!$pdo_hr) {
http_response_code(500);
exit;
}
$cid = $_GET['cid'] ?? '';
if (empty($cid)) {
http_response_code(400);
exit;
}
try {
$stmt = $pdo_hr->prepare("SELECT HR_IMAGE FROM hr_person WHERE HR_CID = ?");
$stmt->execute([$cid]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result && !empty($result['HR_IMAGE'])) {
// Output image
header("Content-Type: image/jpeg");
echo $result['HR_IMAGE'];
} else {
http_response_code(404);
}
} catch (PDOException $e) {
http_response_code(500);
}
?>
@@ -0,0 +1,82 @@
<?php
session_start();
require_once '../includes/db_hr.php'; // โหลดการเชื่อมต่อ DB ตัวที่ 2
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if (!$pdo_hr) {
jsonResponse(false, 'ไม่สามารถเชื่อมต่อฐานข้อมูล hosoffice_2566 ได้ กรุณาตั้งค่าใน includes/db_hr.php');
}
$keyword = $_GET['q'] ?? '';
if (empty($keyword) || mb_strlen($keyword, 'UTF-8') < 2) {
jsonResponse(true, 'Success', []); // คืนค่าว่างถ้าคำค้นหาสั้นไป
}
try {
$sql = "SELECT a.HR_CID, a.HR_FNAME, a.HR_LNAME, a.HR_STARTWORK_DATE, a.HR_PHONE, a.SEX,
(a.HR_IMAGE IS NOT NULL AND LENGTH(a.HR_IMAGE) > 0) as HAS_IMAGE,
e.HR_PREFIX_NAME, b.HR_DEPARTMENT_SUB_SUB_NAME,
c.HR_LEVEL_NAME, d.HR_PERSON_TYPE_NAME, f.HR_POSITION_NAME
FROM hr_person a
LEFT OUTER JOIN hr_department_sub_sub b on a.HR_DEPARTMENT_SUB_SUB_ID = b.HR_DEPARTMENT_SUB_SUB_ID
LEFT OUTER JOIN hr_level c ON a.HR_LEVEL_ID = c.HR_LEVEL_ID
LEFT OUTER JOIN hr_person_type d ON a.HR_PERSON_TYPE_ID = d.HR_PERSON_TYPE_ID
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position f ON a.HR_POSITION_ID=f.HR_POSITION_ID
WHERE (a.HR_FNAME LIKE ? OR a.HR_LNAME LIKE ? OR a.HR_CID LIKE ?) AND a.HR_STATUS_ID='01'
LIMIT 15";
$stmt = $pdo_hr->prepare($sql);
$searchTerm = "%$keyword%";
$stmt->execute([$searchTerm, $searchTerm, $searchTerm]);
$raw_results = $stmt->fetchAll(PDO::FETCH_ASSOC);
$results = [];
foreach ($raw_results as $person) {
$prefix = $person['HR_PREFIX_NAME'] ?? '';
$fname = $person['HR_FNAME'] ?? '';
$lname = $person['HR_LNAME'] ?? '';
$fullName = trim($prefix . $fname . ' ' . $lname);
$department = $person['HR_DEPARTMENT_SUB_SUB_NAME'] ?? 'ไม่ระบุ';
$position = trim(($person['HR_POSITION_NAME'] ?? '') . ' ' . ($person['HR_LEVEL_NAME'] ?? ''));
$person_type = $person['HR_PERSON_TYPE_NAME'] ?? 'ไม่ระบุ';
$work_duration = 'ไม่ระบุวันที่เริ่มงาน';
if (!empty($person['HR_STARTWORK_DATE'])) {
try {
$startDate = new DateTime($person['HR_STARTWORK_DATE']);
$currentDate = new DateTime();
if ($startDate <= $currentDate) {
$interval = $currentDate->diff($startDate);
$work_duration = $interval->format('%y ปี %m เดือน %d วัน');
}
} catch (Exception $e) { }
}
$results[] = [
'prefix' => $prefix,
'fname' => $fname,
'lname' => $lname,
'full_name' => $fullName,
'department' => $department,
'position' => $position,
'person_type' => $person_type,
'work_duration' => $work_duration,
'phone' => $person['HR_PHONE'] ?? '',
'sex' => $person['SEX'] ?? '',
'has_image' => (bool)$person['HAS_IMAGE'],
'cid' => $person['HR_CID']
];
}
jsonResponse(true, 'Success', $results);
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,35 @@
<?php
require_once '../includes/auth.php';
require_once '../includes/db.php';
header('Content-Type: application/json; charset=utf-8');
$vehicle_id = isset($_GET['vehicle_id']) ? intval($_GET['vehicle_id']) : 0;
if ($vehicle_id === 0) {
echo json_encode(['success' => false, 'message' => 'Invalid vehicle ID']);
exit;
}
try {
$stmt = $pdo->prepare("
SELECT vi.*, d.first_name, d.last_name
FROM vehicle_inspections vi
LEFT JOIN drivers d ON vi.inspector_cid COLLATE utf8mb4_unicode_ci = d.hr_cid COLLATE utf8mb4_unicode_ci
WHERE vi.vehicle_id = ?
ORDER BY vi.inspection_date DESC, vi.inspection_time DESC
LIMIT 50
");
$stmt->execute([$vehicle_id]);
$history = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Decode JSON items for each record
foreach ($history as &$record) {
$record['items'] = json_decode($record['items_json'], true);
unset($record['items_json']);
}
echo json_encode(['success' => true, 'data' => $history]);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
}
@@ -0,0 +1,60 @@
<?php
require_once '../includes/auth.php';
require_once '../includes/db.php';
header('Content-Type: application/json; charset=utf-8');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['success' => false, 'message' => 'Invalid request method']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) {
echo json_encode(['success' => false, 'message' => 'No data provided']);
exit;
}
try {
// Add vehicle_status column to history if it doesn't exist
try {
$pdo->exec("ALTER TABLE vehicle_inspections ADD COLUMN vehicle_status VARCHAR(50) NULL");
} catch (PDOException $e) {}
$pdo->beginTransaction();
// 1. Save Inspection History
$stmt = $pdo->prepare("
INSERT INTO vehicle_inspections
(vehicle_id, inspector_cid, inspection_date, inspection_time, mileage, fuel_level, other_items, items_json, vehicle_status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$data['vehicle_id'],
$data['inspector_cid'],
$data['inspection_date'],
$data['inspection_time'],
$data['mileage'],
$data['fuel_level'],
$data['other_items'] ?? '',
json_encode($data['items'], JSON_UNESCAPED_UNICODE),
$data['vehicle_status'] ?? 'available'
]);
// 2. Update Vehicle Status
if (!empty($data['vehicle_status'])) {
$updateStmt = $pdo->prepare("UPDATE vehicles SET status = ? WHERE id = ?");
$updateStmt->execute([$data['vehicle_status'], $data['vehicle_id']]);
}
$pdo->commit();
echo json_encode(['success' => true, 'message' => 'บันทึกข้อมูลและอัปเดตสถานะรถเรียบร้อยแล้ว']);
} catch (PDOException $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
}
@@ -0,0 +1,37 @@
<?php
require_once '../includes/auth.php';
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
// Check if user is admin
if (!isAdmin()) {
sendJson(403, ['error' => 'Permission denied. Admins only.']);
}
$method = $_SERVER['REQUEST_METHOD'];
function sendJson($statusCode, $data) {
http_response_code($statusCode);
header('Content-Type: application/json');
echo json_encode($data);
exit();
}
if ($method === 'GET') {
try {
$stmt = $pdo->query("
SELECT al.id, al.user_id, al.action, al.table_name, al.record_id, al.ip_address, al.created_at, u.full_name as user_name
FROM activity_logs al
LEFT JOIN users u ON al.user_id = u.id
ORDER BY al.created_at DESC
LIMIT 1000
");
$logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
sendJson(200, ['logs' => $logs]);
} catch (PDOException $e) {
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
} else {
sendJson(405, ['error' => 'Method Not Allowed']);
}
?>
@@ -0,0 +1,38 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/notifier.php';
require_once '../includes/logger.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$id = $_POST['id'] ?? null;
if (!$id) {
jsonResponse(false, 'Missing maintenance record ID');
}
try {
$stmt = $pdo->prepare("SELECT v.license_plate FROM maintenance_records m JOIN vehicles v ON m.vehicle_id = v.id WHERE m.id = ?");
$stmt->execute([$id]);
$veh = $stmt->fetch();
$plate = $veh ? $veh['license_plate'] : "ID {$id}";
$stmt = $pdo->prepare("DELETE FROM maintenance_records WHERE id = ?");
$stmt->execute([$id]);
logActivity("Delete Maintenance Record", 'maintenance_records', $id);
notifyEvent('maintenance', "🛠 แจ้งเตือนซ่อมบำรุง\nลบข้อมูลประวัติการซ่อม ทะเบียน: {$plate}");
jsonResponse(true, 'ลบประวัติการซ่อมสำเร็จ');
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,42 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$doc_id = $_POST['id'] ?? null;
if (!$doc_id) {
jsonResponse(false, 'Missing doc id');
}
try {
$stmt = $pdo->prepare("SELECT file_path FROM maintenance_documents WHERE id = ?");
$stmt->execute([$doc_id]);
$doc = $stmt->fetch(PDO::FETCH_ASSOC);
if ($doc) {
// Delete physical file
$physical_path = '../' . $doc['file_path'];
if (file_exists($physical_path)) {
unlink($physical_path);
}
// Delete DB record
$stmtDelete = $pdo->prepare("DELETE FROM maintenance_documents WHERE id = ?");
$stmtDelete->execute([$doc_id]);
jsonResponse(true, 'ลบเอกสารสำเร็จ');
} else {
jsonResponse(false, 'ไม่พบเอกสารที่ต้องการลบ');
}
} catch (PDOException $e) {
jsonResponse(false, 'DB Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,21 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
$maintenance_record_id = $_GET['maintenance_record_id'] ?? null;
if (!$maintenance_record_id) jsonResponse(false, 'Missing maintenance_record_id');
try {
$stmt = $pdo->prepare("SELECT * FROM maintenance_documents WHERE maintenance_record_id = ? ORDER BY id DESC");
$stmt->execute([$maintenance_record_id]);
$docs = $stmt->fetchAll(PDO::FETCH_ASSOC);
jsonResponse(true, 'Success', $docs);
} catch (PDOException $e) {
jsonResponse(false, 'DB Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,80 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$maintenance_record_id = $_POST['maintenance_record_id'] ?? null;
if (!$maintenance_record_id) {
jsonResponse(false, 'Missing maintenance_record_id');
}
if (!isset($_FILES['documents']) || empty($_FILES['documents']['name'][0])) {
jsonResponse(false, 'No files uploaded');
}
$uploadDir = '../uploads/maintenance/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$successFiles = [];
$errors = [];
foreach ($_FILES['documents']['tmp_name'] as $key => $tmp_name) {
if ($_FILES['documents']['error'][$key] === UPLOAD_ERR_OK) {
$original_name = basename($_FILES['documents']['name'][$key]);
$file_size = $_FILES['documents']['size'][$key];
$file_type = mime_content_type($tmp_name);
// Validate PDF
$ext = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
if ($ext !== 'pdf' || $file_type !== 'application/pdf') {
$errors[] = "$original_name ไม่ใช่ไฟล์ PDF";
continue;
}
// Max 10MB
if ($file_size > 10 * 1024 * 1024) {
$errors[] = "$original_name ขนาดเกิน 10MB";
continue;
}
// Generate unique filename
$new_filename = uniqid('maint_') . '_' . time() . '.pdf';
$dest_path = $uploadDir . $new_filename;
if (move_uploaded_file($tmp_name, $dest_path)) {
// Save to DB
try {
$stmt = $pdo->prepare("INSERT INTO maintenance_documents (maintenance_record_id, original_name, file_name, file_path) VALUES (?, ?, ?, ?)");
$relative_path = 'uploads/maintenance/' . $new_filename;
$stmt->execute([$maintenance_record_id, $original_name, $new_filename, $relative_path]);
$successFiles[] = $original_name;
} catch (PDOException $e) {
unlink($dest_path);
$errors[] = "DB Error for $original_name: " . $e->getMessage();
}
} else {
$errors[] = "ไม่สามารถบันทึกไฟล์ $original_name ได้";
}
}
}
if (count($successFiles) > 0) {
$msg = "อัปโหลดสำเร็จ " . count($successFiles) . " ไฟล์";
if (count($errors) > 0) {
$msg .= " (ไม่สำเร็จ " . count($errors) . " ไฟล์)";
}
jsonResponse(true, $msg);
} else {
jsonResponse(false, 'อัปโหลดไม่สำเร็จ: ' . implode(', ', $errors));
}
?>
@@ -0,0 +1,32 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
$vehicle_id = $_GET['vehicle_id'] ?? null;
if (!$vehicle_id) {
jsonResponse(false, 'Missing vehicle_id');
}
try {
$stmt = $pdo->prepare("SELECT * FROM maintenance_records WHERE vehicle_id = ? ORDER BY repair_date DESC, id DESC");
$stmt->execute([$vehicle_id]);
$records = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Fetch documents for each record
foreach ($records as &$record) {
$docStmt = $pdo->prepare("SELECT * FROM maintenance_documents WHERE maintenance_record_id = ? ORDER BY id ASC");
$docStmt->execute([$record['id']]);
$record['documents'] = $docStmt->fetchAll(PDO::FETCH_ASSOC);
}
jsonResponse(true, 'Success', $records);
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,72 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/notifier.php';
require_once '../includes/logger.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$vehicle_id = $_POST['vehicle_id'] ?? null;
$repair_date = $_POST['repair_date'] ?? null;
$description = trim($_POST['description'] ?? '');
$mileage = empty($_POST['mileage']) ? null : (int)$_POST['mileage'];
$cost = empty($_POST['cost']) ? null : (float)$_POST['cost'];
$garage = trim($_POST['garage'] ?? '');
if (!$vehicle_id || !$repair_date || empty($description)) {
jsonResponse(false, 'กรุณากรอกข้อมูลที่จำเป็นให้ครบถ้วน (วันที่ และ รายละเอียด)');
}
try {
$stmt = $pdo->prepare("INSERT INTO maintenance_records (vehicle_id, repair_date, description, mileage, cost, garage) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$vehicle_id, $repair_date, $description, $mileage, $cost, $garage]);
$maintenance_record_id = $pdo->lastInsertId();
// Handle file uploads if any
$upload_msg = '';
if (isset($_FILES['documents']) && !empty($_FILES['documents']['name'][0])) {
$uploadDir = '../uploads/maintenance/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
$successFiles = 0;
foreach ($_FILES['documents']['tmp_name'] as $key => $tmp_name) {
if ($_FILES['documents']['error'][$key] === UPLOAD_ERR_OK) {
$original_name = basename($_FILES['documents']['name'][$key]);
$file_size = $_FILES['documents']['size'][$key];
$file_type = mime_content_type($tmp_name);
$ext = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
if ($ext === 'pdf' && $file_type === 'application/pdf' && $file_size <= 10 * 1024 * 1024) {
$new_filename = uniqid('maint_') . '_' . time() . '.pdf';
$dest_path = $uploadDir . $new_filename;
if (move_uploaded_file($tmp_name, $dest_path)) {
$docStmt = $pdo->prepare("INSERT INTO maintenance_documents (maintenance_record_id, original_name, file_name, file_path) VALUES (?, ?, ?, ?)");
$docStmt->execute([$maintenance_record_id, $original_name, $new_filename, 'uploads/maintenance/' . $new_filename]);
$successFiles++;
}
}
}
}
if ($successFiles > 0) $upload_msg = " (และแนบเอกสาร $successFiles ไฟล์)";
}
// Fetch vehicle plate for notification
$vehStmt = $pdo->prepare("SELECT license_plate FROM vehicles WHERE id = ?");
$vehStmt->execute([$vehicle_id]);
$veh = $vehStmt->fetch();
$plate = $veh ? $veh['license_plate'] : "ID {$vehicle_id}";
notifyEvent('maintenance', "🛠 แจ้งเตือนซ่อมบำรุง\nมีการบันทึกประวัติการซ่อมรถ ทะเบียน: {$plate}\nรายละเอียด: {$description}");
jsonResponse(true, 'บันทึกประวัติการซ่อมสำเร็จ' . $upload_msg);
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,77 @@
<?php
require_once '../includes/db_intranet.php';
header('Content-Type: application/json');
if (!$intranet_pdo) {
echo json_encode([]);
exit;
}
$start = $_GET['start'] ?? '';
$end = $_GET['end'] ?? '';
try {
$sql = "SELECT * FROM booking_car";
$params = [];
if ($start && $end) {
$sql .= " WHERE booking_car_request_date_start >= ? AND booking_car_request_date_start <= ?";
$params = [
date('Y-m-d', strtotime($start)),
date('Y-m-d', strtotime($end))
];
}
$stmt = $intranet_pdo->prepare($sql);
$stmt->execute($params);
$bookings = $stmt->fetchAll();
$events = [];
foreach ($bookings as $b) {
$statusText = trim($b['booking_car_request_status'] ?? '');
$area = trim($b['booking_car_request_area'] ?? '');
$color = '#3b82f6'; // blue-500 (ในสมุย)
if ($area === 'นอกเกาะสมุย') {
$color = '#f97316'; // orange-500 (นอกสมุย)
}
$startTime = !empty($b['booking_car_request_time_start']) ? $b['booking_car_request_time_start'] : '00:00:00';
$endTime = !empty($b['booking_car_request_time_end']) ? $b['booking_car_request_time_end'] : '23:59:59';
$startDate = $b['booking_car_request_date_start'];
$endDate = !empty($b['booking_car_request_date_end']) ? $b['booking_car_request_date_end'] : $startDate;
$currentDate = $startDate;
while (strtotime($currentDate) <= strtotime($endDate)) {
$events[] = [
'id' => $b['booking_car_id'] . '_' . $currentDate,
'title' => $title,
'start' => $currentDate . 'T' . $startTime,
'end' => $currentDate . 'T' . $endTime,
'backgroundColor' => 'transparent',
'borderColor' => 'transparent',
'extendedProps' => [
'iconColor' => $color,
'name' => $b['booking_car_request_name'],
'phone' => $b['booking_car_request_phone'],
'purpose' => $b['booking_car_request_title'],
'type' => $b['booking_car_request_type'],
'status' => $statusText,
'station' => $b['booking_car_request_station'],
'desc' => $b['booking_car_request_description'],
'link' => $b['booking_car_request_link_view'],
'date' => date('d/m/', strtotime($currentDate)) . (date('Y', strtotime($currentDate)) + 543) . ($startTime != '00:00:00' ? ' ' . date('H:i', strtotime($startTime)) : '')
]
];
$currentDate = date('Y-m-d', strtotime($currentDate . ' +1 day'));
}
}
echo json_encode($events);
} catch (PDOException $e) {
echo json_encode([]);
}
?>
@@ -0,0 +1,121 @@
<?php
require_once '../includes/auth.php';
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/logger.php';
require_once '../includes/notifier.php';
function sendJson($statusCode, $data) {
http_response_code($statusCode);
header('Content-Type: application/json');
echo json_encode($data);
exit();
}
// Check if user is admin
if (!isAdmin()) {
sendJson(403, ['error' => 'Permission denied. Admins only.']);
}
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'GET') {
try {
// Auto-create table if not exists
try {
$pdo->query("SELECT 1 FROM settings LIMIT 1");
} catch (PDOException $e) {
$pdo->exec("
CREATE TABLE IF NOT EXISTS settings (
setting_key VARCHAR(50) PRIMARY KEY,
setting_value TEXT NULL,
description VARCHAR(255) NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
");
$defaultSettings = [
['line_notify_token', '', 'LINE Notify Token สำหรับส่งการแจ้งเตือน'],
['telegram_bot_token', '', 'Telegram Bot Token ที่ได้จาก BotFather'],
['telegram_chat_id', '', 'Telegram Chat ID หรือ Group ID ที่ต้องการให้บอทส่งข้อความ'],
['notify_events', '["vehicle","driver","schedule","maintenance"]', 'เหตุการณ์ที่ต้องการให้แจ้งเตือน (JSON array)']
];
$stmt = $pdo->prepare("INSERT IGNORE INTO settings (setting_key, setting_value, description) VALUES (?, ?, ?)");
foreach ($defaultSettings as $setting) {
$stmt->execute($setting);
}
}
$stmt = $pdo->query("SELECT setting_key, setting_value FROM settings");
$settingsData = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
sendJson(200, ['settings' => $settingsData]);
} catch (PDOException $e) {
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
} elseif ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
$action = $data['action'] ?? '';
if ($action === 'save') {
$settings = $data['settings'] ?? [];
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE settings SET setting_value = ? WHERE setting_key = ?");
foreach ($settings as $key => $value) {
// Ensure the setting key exists to avoid SQL errors if someone injects keys
$checkStmt = $pdo->prepare("SELECT setting_key FROM settings WHERE setting_key = ?");
$checkStmt->execute([$key]);
if ($checkStmt->fetch()) {
$stmt->execute([$value, $key]);
} else {
$insertStmt = $pdo->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (?, ?)");
$insertStmt->execute([$key, $value]);
}
}
$pdo->commit();
logActivity("Updated Notification Settings", 'settings', null);
sendJson(200, ['success' => true]);
} catch (PDOException $e) {
$pdo->rollBack();
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
}
elseif ($action === 'test_line') {
$token = $data['token'] ?? '';
if (empty($token)) {
sendJson(400, ['error' => 'LINE Notify Token is required']);
}
$message = "✅ ทดสอบระบบแจ้งเตือนผ่าน LINE Notify\nจากระบบจัดการข้อมูลยานพาหนะ";
$result = sendLineNotify($token, $message);
if ($result === true) {
sendJson(200, ['success' => true]);
} else {
sendJson(400, ['error' => 'เกิดข้อผิดพลาดในการส่ง LINE Notify: ' . $result]);
}
}
elseif ($action === 'test_telegram') {
$token = $data['token'] ?? '';
$chat_id = $data['chat_id'] ?? '';
if (empty($token) || empty($chat_id)) {
sendJson(400, ['error' => 'Telegram Bot Token and Chat ID are required']);
}
$message = "✅ ทดสอบระบบแจ้งเตือนผ่าน Telegram\nจากระบบจัดการข้อมูลยานพาหนะ";
$result = sendTelegramMessage($token, $chat_id, $message);
if ($result === true) {
sendJson(200, ['success' => true]);
} else {
sendJson(400, ['error' => 'เกิดข้อผิดพลาดในการส่ง Telegram: ' . $result]);
}
}
else {
sendJson(400, ['error' => 'Invalid action']);
}
} else {
sendJson(405, ['error' => 'Method Not Allowed']);
}
@@ -0,0 +1,167 @@
<?php
require_once '../includes/auth.php';
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/logger.php';
// Check if user is admin
if (!isAdmin()) {
sendJson(403, ['error' => 'Permission denied. Admins only.']);
}
$method = $_SERVER['REQUEST_METHOD'];
// Function to send JSON response
function sendJson($statusCode, $data) {
http_response_code($statusCode);
header('Content-Type: application/json');
echo json_encode($data);
exit();
}
// Function to validate password strength
function validatePassword($password) {
if (strlen($password) < 6) return false;
return true;
}
switch ($method) {
case 'GET':
// Read (List)
try {
$stmt = $pdo->query("SELECT id, username, id_card, full_name, role, created_at FROM users ORDER BY created_at DESC");
$users = $stmt->fetchAll();
sendJson(200, ['users' => $users]);
} catch (PDOException $e) {
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
break;
case 'POST':
// Create
$data = json_decode(file_get_contents('php://input'), true);
$id_card = trim($data['id_card'] ?? '');
$full_name = trim($data['full_name'] ?? '');
$role = trim($data['role'] ?? 'user');
$password = $data['password'] ?? '';
if (empty($id_card) || empty($full_name) || empty($password)) {
sendJson(400, ['error' => 'Missing required fields']);
}
if (strlen($id_card) !== 13) {
sendJson(400, ['error' => 'ID card must be 13 digits']);
}
if (!validatePassword($password)) {
sendJson(400, ['error' => 'รหัสผ่านต้องมีความยาวไม่น้อยกว่า 6 ตัวอักษร']);
}
try {
// Check if id_card already exists
$stmt = $pdo->prepare("SELECT id FROM users WHERE id_card = ?");
$stmt->execute([$id_card]);
if ($stmt->fetch()) {
sendJson(400, ['error' => 'ID card already exists']);
}
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$username = $id_card; // Use id_card as username fallback if username is NOT NULL
$stmt = $pdo->prepare("INSERT INTO users (username, id_card, password, full_name, role) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$username, $id_card, $hashedPassword, $full_name, $role]);
$newUserId = $pdo->lastInsertId();
logActivity("Create User ({$id_card})", 'users', $newUserId);
sendJson(201, ['message' => 'User created successfully', 'id' => $newUserId]);
} catch (PDOException $e) {
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
break;
case 'PUT':
// Update
$data = json_decode(file_get_contents('php://input'), true);
$id = $data['id'] ?? null;
if (!$id) {
sendJson(400, ['error' => 'User ID is required']);
}
$id_card = trim($data['id_card'] ?? '');
$full_name = trim($data['full_name'] ?? '');
$role = trim($data['role'] ?? 'user');
$password = $data['password'] ?? '';
if (empty($id_card) || empty($full_name)) {
sendJson(400, ['error' => 'Missing required fields']);
}
if (strlen($id_card) !== 13) {
sendJson(400, ['error' => 'ID card must be 13 digits']);
}
try {
// Check if id_card is taken by someone else
$stmt = $pdo->prepare("SELECT id FROM users WHERE id_card = ? AND id != ?");
$stmt->execute([$id_card, $id]);
if ($stmt->fetch()) {
sendJson(400, ['error' => 'ID card is already in use by another user']);
}
if (!empty($password)) {
if (!validatePassword($password)) {
sendJson(400, ['error' => 'รหัสผ่านต้องมีความยาวไม่น้อยกว่า 6 ตัวอักษร']);
}
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET id_card = ?, full_name = ?, role = ?, password = ? WHERE id = ?");
$stmt->execute([$id_card, $full_name, $role, $hashedPassword, $id]);
} else {
$stmt = $pdo->prepare("UPDATE users SET id_card = ?, full_name = ?, role = ? WHERE id = ?");
$stmt->execute([$id_card, $full_name, $role, $id]);
}
logActivity("Update User ({$id_card})", 'users', $id);
sendJson(200, ['message' => 'User updated successfully']);
} catch (PDOException $e) {
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
break;
case 'DELETE':
// Delete
$id = $_GET['id'] ?? null;
if (!$id) {
sendJson(400, ['error' => 'User ID is required']);
}
// Prevent deleting oneself
if ($id == $_SESSION['user_id']) {
sendJson(400, ['error' => 'Cannot delete your own account']);
}
try {
// ดึงชื่อก่อนลบ
$stmtName = $pdo->prepare("SELECT id_card FROM users WHERE id = ?");
$stmtName->execute([$id]);
$delUser = $stmtName->fetch();
$delIdCard = $delUser ? $delUser['id_card'] : $id;
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$id]);
logActivity("Delete User ({$delIdCard})", 'users', $id);
sendJson(200, ['message' => 'User deleted successfully']);
} catch (PDOException $e) {
sendJson(500, ['error' => 'Database error: ' . $e->getMessage()]);
}
break;
default:
sendJson(405, ['error' => 'Method Not Allowed']);
}
@@ -0,0 +1,56 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/logger.php';
require_once '../includes/notifier.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$id = $_POST['id'] ?? '';
if (empty($id)) {
jsonResponse(false, 'ไม่พบข้อมูลที่ต้องการลบ');
}
try {
// ตรวจสอบว่ามีการจองผูกอยู่หรือไม่
$stmt = $pdo->prepare("SELECT id FROM schedules WHERE vehicle_id = ? LIMIT 1");
$stmt->execute([$id]);
if ($stmt->fetch()) {
jsonResponse(false, 'ไม่สามารถลบได้ เนื่องจากรถคันนี้มีการจองอยู่ในระบบ');
}
// ตรวจสอบสถานะจำหน่าย
$stmt = $pdo->prepare("SELECT status FROM vehicles WHERE id = ?");
$stmt->execute([$id]);
$vehicle = $stmt->fetch();
if ($vehicle && $vehicle['status'] === 'disposed') {
jsonResponse(false, 'ไม่สามารถลบได้ เนื่องจากรถคันนี้อยู่ในสถานะจำหน่ายแล้ว');
}
$stmt = $pdo->prepare("SELECT license_plate FROM vehicles WHERE id = ?");
$stmt->execute([$id]);
$vehicleInfo = $stmt->fetch();
$license_plate = $vehicleInfo ? $vehicleInfo['license_plate'] : $id;
$stmt = $pdo->prepare("DELETE FROM vehicles WHERE id = ?");
$stmt->execute([$id]);
if ($stmt->rowCount() > 0) {
logActivity("Delete Vehicle ({$license_plate})", 'vehicles', $id);
notifyEvent('vehicle', "🚗 แจ้งเตือนยานพาหนะ\nลบข้อมูลรถออกจากระบบ: {$license_plate}");
jsonResponse(true, 'ลบข้อมูลสำเร็จ');
} else {
jsonResponse(false, 'ไม่พบข้อมูลในฐานข้อมูล');
}
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,42 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$doc_id = $_POST['id'] ?? null;
if (!$doc_id) {
jsonResponse(false, 'Missing doc id');
}
try {
$stmt = $pdo->prepare("SELECT file_path FROM vehicle_documents WHERE id = ?");
$stmt->execute([$doc_id]);
$doc = $stmt->fetch(PDO::FETCH_ASSOC);
if ($doc) {
// Delete physical file
$physical_path = '../' . $doc['file_path'];
if (file_exists($physical_path)) {
unlink($physical_path);
}
// Delete DB record
$stmtDelete = $pdo->prepare("DELETE FROM vehicle_documents WHERE id = ?");
$stmtDelete->execute([$doc_id]);
jsonResponse(true, 'ลบเอกสารสำเร็จ');
} else {
jsonResponse(false, 'ไม่พบเอกสารที่ต้องการลบ');
}
} catch (PDOException $e) {
jsonResponse(false, 'DB Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,21 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
$vehicle_id = $_GET['vehicle_id'] ?? null;
if (!$vehicle_id) jsonResponse(false, 'Missing vehicle_id');
try {
$stmt = $pdo->prepare("SELECT * FROM vehicle_documents WHERE vehicle_id = ? ORDER BY id DESC");
$stmt->execute([$vehicle_id]);
$docs = $stmt->fetchAll(PDO::FETCH_ASSOC);
jsonResponse(true, 'Success', $docs);
} catch (PDOException $e) {
jsonResponse(false, 'DB Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,81 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$vehicle_id = $_POST['vehicle_id'] ?? null;
if (!$vehicle_id) {
jsonResponse(false, 'Missing vehicle_id');
}
if (!isset($_FILES['documents']) || empty($_FILES['documents']['name'][0])) {
jsonResponse(false, 'No files uploaded');
}
$uploadDir = '../uploads/vehicles/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
$successFiles = [];
$errors = [];
foreach ($_FILES['documents']['tmp_name'] as $key => $tmp_name) {
if ($_FILES['documents']['error'][$key] === UPLOAD_ERR_OK) {
$original_name = basename($_FILES['documents']['name'][$key]);
$file_size = $_FILES['documents']['size'][$key];
$file_type = mime_content_type($tmp_name);
// Validate PDF
$ext = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
if ($ext !== 'pdf' || $file_type !== 'application/pdf') {
$errors[] = "$original_name ไม่ใช่ไฟล์ PDF";
continue;
}
// Max 10MB
if ($file_size > 10 * 1024 * 1024) {
$errors[] = "$original_name ขนาดเกิน 10MB";
continue;
}
// Generate unique filename
$new_filename = uniqid('veh_') . '_' . time() . '.pdf';
$dest_path = $uploadDir . $new_filename;
if (move_uploaded_file($tmp_name, $dest_path)) {
// Save to DB
try {
$stmt = $pdo->prepare("INSERT INTO vehicle_documents (vehicle_id, original_name, file_name, file_path) VALUES (?, ?, ?, ?)");
$relative_path = 'uploads/vehicles/' . $new_filename;
$stmt->execute([$vehicle_id, $original_name, $new_filename, $relative_path]);
$successFiles[] = $original_name;
} catch (PDOException $e) {
// Remove file if DB insert fails
unlink($dest_path);
$errors[] = "DB Error for $original_name: " . $e->getMessage();
}
} else {
$errors[] = "ไม่สามารถบันทึกไฟล์ $original_name ได้";
}
}
}
if (count($successFiles) > 0) {
$msg = "อัปโหลดสำเร็จ " . count($successFiles) . " ไฟล์";
if (count($errors) > 0) {
$msg .= " (ไม่สำเร็จ " . count($errors) . " ไฟล์)";
}
jsonResponse(true, $msg);
} else {
jsonResponse(false, 'อัปโหลดไม่สำเร็จ: ' . implode(', ', $errors));
}
?>
@@ -0,0 +1,128 @@
<?php
session_start();
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
require_once '../includes/logger.php';
require_once '../includes/notifier.php';
// เช็คสิทธิ์ (อย่างน้อยต้องล็อกอิน)
if (!isset($_SESSION['user_id'])) {
jsonResponse(false, 'Unauthorized', [], 401);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonResponse(false, 'Invalid request method');
}
$id = $_POST['id'] ?? '';
$license_plate = trim($_POST['license_plate'] ?? '');
$type = trim($_POST['type'] ?? '');
$brand = trim($_POST['brand'] ?? '');
$model = trim($_POST['model'] ?? '');
$status = $_POST['status'] ?? 'available';
$tax_expiry = empty($_POST['tax_expiry']) ? null : $_POST['tax_expiry'];
// New fields
$chassis_number = trim($_POST['chassis_number'] ?? '');
$engine_number = trim($_POST['engine_number'] ?? '');
$engine_cc = empty($_POST['engine_cc']) ? null : (int)$_POST['engine_cc'];
$fuel_capacity = trim($_POST['fuel_capacity'] ?? '');
$fuel_type = trim($_POST['fuel_type'] ?? '');
$color = trim($_POST['color'] ?? '#FFFFFF');
$asset_number = trim($_POST['asset_number'] ?? '');
$vehicle_style = trim($_POST['vehicle_style'] ?? '');
$model_year = trim($_POST['model_year'] ?? '');
if (empty($license_plate) || empty($type)) {
jsonResponse(false, 'กรุณากรอกข้อมูลที่จำเป็นให้ครบถ้วน');
}
// สร้างคอลัมน์ image_path อัตโนมัติหากยังไม่มี
try {
$pdo->exec("ALTER TABLE vehicles ADD COLUMN image_path VARCHAR(255) NULL");
} catch (PDOException $e) {
// Column might already exist
}
// อัปเดต ENUM สำหรับ status ให้รองรับ disposed
try {
$pdo->exec("ALTER TABLE vehicles MODIFY COLUMN status ENUM('available', 'in_use', 'maintenance', 'disposed') DEFAULT 'available'");
} catch (PDOException $e) {
// ENUM might already be updated
}
// อัปโหลดรูปภาพใหม่
$image_path = null;
$upload_dir = '../uploads/vehicles/';
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
if (isset($_FILES['image']) && $_FILES['image']['error'] == UPLOAD_ERR_OK) {
$file_ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
$allowed_ext = ['jpg', 'jpeg', 'png', 'webp'];
if (in_array($file_ext, $allowed_ext)) {
// ลบรูปเก่าถ้ามีการอัปโหลดใหม่ (กรณีแก้ไข)
if (!empty($id)) {
$stmt = $pdo->prepare("SELECT image_path FROM vehicles WHERE id = ?");
$stmt->execute([$id]);
$old_vehicle = $stmt->fetch();
if ($old_vehicle && !empty($old_vehicle['image_path'])) {
$old_path = '../' . $old_vehicle['image_path'];
if (file_exists($old_path)) unlink($old_path);
}
}
$new_filename = 'veh_' . time() . '_' . rand(1000, 9999) . '.' . $file_ext;
$dest = $upload_dir . $new_filename;
if (move_uploaded_file($_FILES['image']['tmp_name'], $dest)) {
$image_path = 'uploads/vehicles/' . $new_filename;
}
}
}
try {
if (empty($id)) {
// สร้างใหม่
// เช็คทะเบียนซ้ำ
$stmt = $pdo->prepare("SELECT id FROM vehicles WHERE license_plate = ?");
$stmt->execute([$license_plate]);
if ($stmt->fetch()) {
jsonResponse(false, 'ทะเบียนรถนี้มีในระบบแล้ว');
}
$stmt = $pdo->prepare("INSERT INTO vehicles (license_plate, type, brand, model, status, tax_expiry, chassis_number, engine_number, engine_cc, fuel_capacity, fuel_type, color, asset_number, vehicle_style, model_year, image_path) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$license_plate, $type, $brand, $model, $status, $tax_expiry, $chassis_number, $engine_number, $engine_cc, $fuel_capacity, $fuel_type, $color, $asset_number, $vehicle_style, $model_year, $image_path]);
$newId = $pdo->lastInsertId();
logActivity("Create Vehicle ({$license_plate})", 'vehicles', $newId);
notifyEvent('vehicle', "🚗 แจ้งเตือนยานพาหนะ\nมีรถใหม่เพิ่มเข้าระบบ ทะเบียน: {$license_plate} ({$brand} {$model})");
jsonResponse(true, 'เพิ่มรถใหม่สำเร็จ');
} else {
// แก้ไข
$stmt = $pdo->prepare("SELECT id FROM vehicles WHERE license_plate = ? AND id != ?");
$stmt->execute([$license_plate, $id]);
if ($stmt->fetch()) {
jsonResponse(false, 'ทะเบียนรถนี้มีในระบบแล้ว (ซ้ำกับคันอื่น)');
}
if ($image_path) {
$stmt = $pdo->prepare("UPDATE vehicles SET license_plate=?, type=?, brand=?, model=?, status=?, tax_expiry=?, chassis_number=?, engine_number=?, engine_cc=?, fuel_capacity=?, fuel_type=?, color=?, asset_number=?, vehicle_style=?, model_year=?, image_path=? WHERE id=?");
$stmt->execute([$license_plate, $type, $brand, $model, $status, $tax_expiry, $chassis_number, $engine_number, $engine_cc, $fuel_capacity, $fuel_type, $color, $asset_number, $vehicle_style, $model_year, $image_path, $id]);
} else {
$stmt = $pdo->prepare("UPDATE vehicles SET license_plate=?, type=?, brand=?, model=?, status=?, tax_expiry=?, chassis_number=?, engine_number=?, engine_cc=?, fuel_capacity=?, fuel_type=?, color=?, asset_number=?, vehicle_style=?, model_year=? WHERE id=?");
$stmt->execute([$license_plate, $type, $brand, $model, $status, $tax_expiry, $chassis_number, $engine_number, $engine_cc, $fuel_capacity, $fuel_type, $color, $asset_number, $vehicle_style, $model_year, $id]);
}
logActivity("Update Vehicle ({$license_plate})", 'vehicles', $id);
notifyEvent('vehicle', "🚗 แจ้งเตือนยานพาหนะ\nมีการอัปเดตข้อมูลรถ ทะเบียน: {$license_plate}");
jsonResponse(true, 'แก้ไขข้อมูลรถสำเร็จ');
}
} catch (PDOException $e) {
jsonResponse(false, 'Database Error: ' . $e->getMessage());
}
?>
@@ -0,0 +1,20 @@
<?php
require_once '../includes/db.php';
require_once '../includes/api_helper.php';
try {
// Fetch unique brands
$stmtBrands = $pdo->query("SELECT DISTINCT brand FROM vehicles WHERE brand IS NOT NULL AND brand != '' ORDER BY brand");
$brands = $stmtBrands->fetchAll(PDO::FETCH_COLUMN);
// Fetch unique models
$stmtModels = $pdo->query("SELECT DISTINCT model FROM vehicles WHERE model IS NOT NULL AND model != '' ORDER BY model");
$models = $stmtModels->fetchAll(PDO::FETCH_COLUMN);
echo jsonResponse(true, 'Suggestions loaded', [
'brands' => $brands,
'models' => $models
]);
} catch (PDOException $e) {
echo jsonResponse(false, 'Database error: ' . $e->getMessage());
}