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,73 @@
<?php
// File: actions/process_login.php
// สำคัญ: ต้องไม่มีช่องว่าง, ตัวอักษร, หรือ BOM ก่อน <?php นี้
session_start();
if (isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true) {
header("location: ../dashboard.php");
exit;
}
require_once '../includes/db_hosoffice.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user = trim($_POST['username'] ?? '');
$pass = trim($_POST['password'] ?? '');
if (empty($user) || empty($pass)) {
$_SESSION['login_error'] = "กรุณากรอก Username และ Password";
header("location: ../index.php");
exit;
}
$pass_md5 = MD5($pass);
$sql = "SELECT HR_CID, HR_PASSWORD, HR_STATUS_ID, HR_PREFIX_NAME, HR_FNAME, HR_LNAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
WHERE a.HR_USERNAME = :user LIMIT 1";
try {
$stmt = $pdo_hos->prepare($sql);
$stmt->execute(['user' => $user]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) {
$_SESSION['login_error'] = "ไม่พบบัญชีผู้ใช้นี้";
header("location: ../index.php");
exit;
}
if (strtolower($row['HR_PASSWORD']) !== strtolower($pass_md5)) {
$_SESSION['login_error'] = "รหัสผ่านไม่ถูกต้อง";
header("location: ../index.php");
exit;
}
if ($row['HR_STATUS_ID'] !== '01') {
$_SESSION['login_error'] = "บัญชีผู้ใช้นี้ถูกปิดการใช้งานไปแล้ว";
header("location: ../index.php");
exit;
}
unset($_SESSION['login_error']);
$_SESSION['loggedin'] = true;
$_SESSION['fullname'] = $row['HR_PREFIX_NAME'] . $row['HR_FNAME'] . " " . $row['HR_LNAME'];
$_SESSION['cid'] = $row['HR_CID'];
//$_SESSION['dep_id'] = $row['HR_DEPARTMENT_SUB_SUB_ID'];
//$_SESSION['department'] = $row['HR_DEPARTMENT_SUB_SUB_NAME'];
header("location: ../dashboard.php");
exit;
} catch (PDOException $e) {
$_SESSION['login_error'] = "เกิดข้อผิดพลาดของระบบ: " . $e->getMessage();
header("location: ../index.php");
exit;
}
} else {
header("location: ../index.php");
exit;
}
// สำคัญ: ต้องไม่มีช่องว่าง หรือบรรทัดว่างหลังโค้ด PHP นี้
@@ -0,0 +1,117 @@
<!doctype html>
<html lang="th">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>แบบประเมินระเบียบปฏิบัติในการรักษาความมั่นคงปลอดภัยระบบเทคโนโลยีสารสนเทศ</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Sarabun:wght@400;500;600;700&display=swap');
:root { --ink:#1a2938; --muted:#66788a; --line:#dce5ec; --soft:#f6f9fb; --accent:#007f8b; --accent-dark:#005d68; --navy:#12344d; --gold:#f3ba4b; --shadow:0 18px 55px rgba(22,52,77,.13); }
* { box-sizing:border-box; }
body { margin:0; background:linear-gradient(135deg,#e9f4f5 0%,#f5f8fb 48%,#e7edf5 100%); color:var(--ink); font-family:Sarabun,"TH Sarabun New",Tahoma,sans-serif; font-size:16px; line-height:1.55; }
.sheet { width:min(210mm,calc(100% - 32px)); min-height:297mm; margin:28px auto; padding:0 16mm 20mm; overflow:hidden; background:#fff; border:1px solid rgba(18,52,77,.08); border-radius:18px; box-shadow:var(--shadow); }
h1,h2,p { margin:0; }
h1 { position:relative; margin:0 -16mm; padding:18mm 18mm 5px; color:#fff; font-size:25px; line-height:1.35; text-align:center; font-weight:700; letter-spacing:.1px; background:radial-gradient(circle at 83% 20%,rgba(255,255,255,.19) 0 3px,transparent 4px),radial-gradient(circle at 87% 26%,rgba(255,255,255,.12) 0 12px,transparent 13px),linear-gradient(120deg,var(--navy),#075e70 70%,#008c8d); }
.subtitle { margin:0 -16mm; padding:2px 18mm 15mm; color:#d9fbfa; font-size:18px; text-align:center; font-weight:500; background:linear-gradient(120deg,var(--navy),#075e70 70%,#008c8d); }
.intro { margin-top:26px; padding:15px 18px; color:#385066; text-align:justify; text-indent:28px; background:#f0f8f8; border-left:4px solid var(--accent); border-radius:0 10px 10px 0; }
.section-title { display:flex; align-items:center; gap:10px; margin-top:30px; color:var(--navy); font-size:18px; font-weight:700; letter-spacing:.05px; }
.section-title::before { content:""; display:inline-block; width:9px; height:28px; flex:none; border-radius:8px; background:linear-gradient(180deg,#12a5a2,var(--accent-dark)); box-shadow:0 3px 8px rgba(0,127,139,.22); }
.details { display:grid; grid-template-columns:1.2fr 1fr 1.15fr; gap:14px; margin-top:13px; padding:17px; background:var(--soft); border:1px solid #e8eef3; border-radius:12px; }
label { display:block; font-weight:600; color:#344b60; }
input[type="text"], input[type="number"], textarea { width:100%; margin-top:3px; padding:8px 9px; color:var(--ink); font:inherit; background:#fff; border:1px solid #cfdae2; border-radius:7px; outline:none; transition:border-color .18s,box-shadow .18s; }
input[type="text"]:focus, input[type="number"]:focus, textarea:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(0,127,139,.13); }
.use-options { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:11px; margin:13px 0 0; }
.option { display:flex; align-items:center; gap:10px; min-height:52px; padding:10px 14px; cursor:pointer; color:#385066; font-weight:500; background:#fff; border:1px solid #d8e3ea; border-radius:10px; box-shadow:0 2px 4px rgba(25,57,79,.03); transition:transform .18s,border-color .18s,box-shadow .18s; }
.option:hover { transform:translateY(-1px); border-color:#8cc2c5; box-shadow:0 7px 18px rgba(21,77,92,.1); }
input[type="radio"] { width:18px; height:18px; flex:none; accent-color:var(--accent); cursor:pointer; }
.table-wrap { margin-top:13px; overflow-x:auto; border:1px solid #dce6ec; border-radius:12px; box-shadow:0 4px 16px rgba(18,52,77,.06); }
table { width:100%; min-width:730px; table-layout:fixed; border-collapse:separate; border-spacing:0; background:#fff; }
th,td { padding:9px 7px; border-right:1px solid var(--line); border-bottom:1px solid var(--line); vertical-align:middle; }
th:last-child,td:last-child { border-right:0; }
tbody tr:last-child td { border-bottom:0; }
th { color:#fff; text-align:center; font-weight:600; line-height:1.3; background:linear-gradient(180deg,#24526b,#173e55); }
thead tr+tr th { color:#ecfbfb; font-size:14px; background:#1c455e; }
tbody tr:nth-child(even) td { background:#f8fafc; }
tbody tr:hover td { background:#f0faf9; }
.rules th:first-child { width:61%; }
.rules th:not(:first-child) { width:6.5%; }
.rules td:first-child { padding:12px 14px; text-align:left; vertical-align:top; color:#324b60; }
.choice { padding:3px; text-align:center; }
.choice label { display:flex; justify-content:center; align-items:center; min-height:37px; }
.choice label:has(input:checked) { background:#d9f2ef; border-radius:6px; }
.sla th:first-child { width:40%; }
.sla th:nth-child(2) { width:12%; }
.sla th:nth-child(n+3):nth-child(-n+7) { width:7%; }
.sla th:last-child { width:13%; }
.sla td { text-align:center; }
.sla td:first-child { padding-left:14px; text-align:left; color:#324b60; }
.sla textarea { min-height:51px; margin:0; resize:vertical; border-color:transparent; background:transparent; }
.sla textarea:focus { border-color:var(--accent); background:#fff; }
.note { margin-top:9px; padding:10px 13px; color:#556b7c; font-size:15px; background:#fff8e9; border:1px solid #f5e2b2; border-radius:8px; }
.actions { display:flex; justify-content:flex-end; gap:10px; margin-top:26px; padding-top:20px; border-top:1px solid #e4ebf0; }
button { padding:10px 20px; color:#fff; font:inherit; font-weight:600; cursor:pointer; border:0; border-radius:8px; background:linear-gradient(135deg,#008f91,var(--accent-dark)); box-shadow:0 6px 13px rgba(0,93,104,.2); transition:transform .18s,box-shadow .18s; }
button:hover { transform:translateY(-1px); box-shadow:0 9px 18px rgba(0,93,104,.27); }
button:focus-visible { outline:3px solid rgba(243,186,75,.75); outline-offset:2px; }
button[type="reset"] { color:#4c6172; background:#fff; border:1px solid #cddae2; box-shadow:none; }
@media print { body { background:#fff; } .sheet { width:100%; min-height:0; margin:0; padding:0 12mm 12mm; border:0; border-radius:0; box-shadow:none; } h1,.subtitle { margin:0 -12mm; } .actions { display:none; } }
@media (max-width:650px) { .sheet { width:100%; margin:0; padding:0 16px 30px; border:0; border-radius:0; } h1 { margin:0 -16px; padding:40px 20px 8px; font-size:20px; } .subtitle { margin:0 -16px; padding:3px 20px 32px; font-size:16px; } .details,.use-options { grid-template-columns:1fr; } .section-title { margin-top:25px; font-size:17px; } .actions { justify-content:stretch; } button { flex:1; padding:11px 10px; } }
</style>
</head>
<body>
<main class="sheet">
<form id="assessment">
<h1>แบบประเมินระเบียบปฏิบัติในการรักษาความมั่นคงปลอดภัยระบบเทคโนโลยีสารสนเทศ</h1>
<p class="subtitle">โรงพยาบาลเกาะสมุย พ.ศ.2569</p>
<p class="intro"><strong>คำอธิบาย</strong> แบบประเมินมี 4 ส่วน กรุณาตอบตามความเป็นจริงเพื่อกลุ่มงานสุขภาพดิจิทัลจะนำผลการประเมินไปวิเคราะห์เพื่อจัดการความั่นคงปลอดภัยระบบเทคโนโลยีสารสนเทศของโรงพยาบาลเกาะสมุย ให้เกิดประโยชน์สูงสุด</p>
<h2 class="section-title">ส่วนที่ 1 ข้อมูลผู้รับการประเมิน</h2>
<div class="details">
<label>ชื่อ-สกุล <input type="text" name="name" aria-label="ชื่อ-สกุล"></label>
<label>ตำแหน่ง <input type="text" name="position" aria-label="ตำแหน่ง"></label>
<label>หน่วยงาน <input type="text" name="department" aria-label="หน่วยงาน"></label>
</div>
<h2 class="section-title">ส่วนที่ 2 ท่านใช้คอมพิวเตอร์ในการปฏิบัติงานหรือไม่</h2>
<div class="use-options">
<label class="option"><input type="radio" name="computer_use" value="ใช้คอมพิวเตอร์ในการปฏิบัติงาน" required> 1.ใช้คอมพิวเตอร์ในการปฏิบัติงาน</label>
<label class="option"><input type="radio" name="computer_use" value="ไม่ได้ใช้คอมพิวเตอร์ในการปฏิบัติงาน"> 2.ไม่ได้ใช้คอมพิวเตอร์ในการปฏิบัติงาน</label>
</div>
<h2 class="section-title">ส่วนที่ 3 การประเมินการรับรู้ ความเข้าใจ และการปฏิบัติตามระเบียบในการรักษาความมั่นคงปลอดภัยระบบเทคโนโลยีสารสนเทศของโรงพยาบาลเกาะสมุย</h2>
<div class="table-wrap">
<table class="rules">
<thead><tr><th rowspan="2">ระเบียบ</th><th colspan="2">การรับรู้</th><th colspan="2">ความเข้าใจ</th><th colspan="2">การปฏิบัติ</th></tr><tr><th>รู้</th><th>ไม่รู้</th><th>เข้าใจ</th><th>ไม่เข้าใจ</th><th>ปฏิบัติได้</th><th>ปฏิบัติไม่ได้</th></tr></thead>
<tbody id="rules-body"></tbody>
</table>
</div>
<h2 class="section-title">ส่วนที่4 แบบประเมินข้อตกลงการให้บริการ Service Level Agreement (SLA) พ.ศ.2569</h2>
<p class="note"><strong>คำอธิบาย</strong> ส่วนนี้สำหรับเจ้าหน้าที่โรงพยาบาลเกาะสมุยที่ใช้คอมพิวเตอร์ในการปฏิบัติงาน หากท่านไม่ได้ใช้คอมพิวเตอร์ในการปฏิบัติงานไม่ต้องตอบส่วนนี้</p>
<div class="table-wrap">
<table class="sla">
<thead><tr><th rowspan="2">บริการ</th><th rowspan="2">เวลามาตรฐาน<br>(นาที)</th><th colspan="5">ระดับความพึงพอใจ</th><th rowspan="2">ระยะเวลาที่คาดหวัง<br>(นาที)<br>โปรดแสดงความคิดเห็น</th></tr><tr><th>5<br>มากที่สุด</th><th>4<br>มาก</th><th>3<br>ปานกลาง</th><th>2<br>น้อย</th><th>1<br>น้อยมาก</th></tr></thead>
<tbody id="sla-body"></tbody>
</table>
</div>
<div class="actions"><button type="reset">ล้างคำตอบ</button><button type="submit">ส่งแบบประเมิน</button></div>
</form>
</main>
<script>
const rules = [
'ผู้ใช้งานต้องดูแลรักษา ป้องกันความเสียหายที่อาจจะเกิดขึ้นกับเครื่องคอมพิวเตอร์อุปกรณ์ต่อพ่วง เช่น ไม่วางอาหารหรือเครื่องดื่มบริเวรณเครื่องเคอมพิวเตอร์ห้ามเคลื่อนย้าย ติดตั้งเพิ่มเติมหรือกระทำการใดๆโดยไม่ได้รับอนุญาตจากผู้ดูแลระบบ',
'ห้ามผู้ใช้งานดาวน์โหลด อัพเดท ติดตั้งโปรแกรมใด นอกเหนือจากที่ผู้ดูแลระบบอนุญาต',
'ห้ามผู้ใช้งานเปิดโปรแกรมเพื่อความบันเทิงส่วนบุคคล เช่น การดูหนัง เล่นเกมส์ในระหว่างปฏิบัติงาน',
'หากเจ้าหน้าที่โรงพยาบาลเกาะสมุยจำเป็นต้องการส่งข้อมูลผู้ป่วยปรึกษาเพื่อการรักษาทางสื่อสังคมออนไลน์ เช่น Facebook , Line, Website หรือโปรแกรมอื่นๆ ที่เชื่อมต่อกับอินเทอร์เน็ต ต้องขออนุญาตผู้ป่วยเป็นลายลักษณ์อักษรโดยส่งตรงไปยังบุคคลที่ต้องการปรึกษาเท่านั้น เมื่อเสร็จสิ้นการปรึกษาให้ทำการลบข้อมูล ชื่อ-นามสกุล เลขประจำตัวผู้ป่วย ข้อมูลการเจ็บป่วย รูปภาพ ผลการตรวจต่างๆ รวมถึงคลิปวิดีโอการดูแลรักษาของผู้ป่วยทุกอย่างออกจากสื่อสังคมออนไลน์ทุกครั้ง',
'ผู้ใช้งานต้องรักษาชื่อผู้ใช้ (Username) และ รหัสผ่าน (Password) เป็นความลับ ห้ามใช้ร่วมกับผู้อื่น',
'เจ้าหน้าที่โรงพยาบาลเกาะสมุยต้องเก็บรักษาความลับข้อมูลผู้ป่วย ต้องไม่เปิดเผยหรือส่งต่อข้อมูล ชื่อ-นามสกุล เลขประจำตัวผู้ป่วย ข้อมูลการเจ็บป่วย รูปภาพ ผลการตรวจต่างๆ รวมถึงคลิปวิดีโอการดูแลรักษาผู้ป่วยในทุกช่องทาง',
'ห้ามผู้ใช้งานเข้าถึงข้อมูลผู้ป่วยที่ไม่ได้อยู่ในความรับผิดชอบ โดยไม่ขออนุญาตจากแพทย์หรือผู้รับผิดชอบโดยตรง',
'เจ้าหน้าที่โรงพยาบาลเกาะสมุยต้องยอมรับและถือปฏิบัติตามกฎระเบียบที่กำหนดขึ้น และปฏิบัติตาม พรบ.คอมพิวเตอร์ พ.ศ.2560 อย่างเคร่งครัดจะอ้างว่าไม่ทราบไม่ได้ กรณีฝ่าฝืนระเบียบปฏิบัติฯนี้ ครั้งที่1แจ้งหัวหน้าตักเตือน/ครั้งที่2 แจ้งหัวหน้ากลุ่มงานตักเตือน/ครั้งที่3เขียนรายงานให้ผู้บริหาร'
];
const services = [['การให้คำปรึกษา ( help desk)',5],['แก้ไขปัญหาเครื่องคอมพิวเตอร์ขัดข้อง',30],['แก้ไขปัญหาเครื่องพิมพ์ขัดข้อง',15],['แก้ไขปัญหาเครื่องสำรองไฟขัดข้อง',15],['แก้ไขปัญหาอุปกรณ์ต่อพ่วงขัดข้อง',15],['แก้ไขปัญหาระบบเครือข่ายขัดข้อง',30],['แก้ไขปัญหาการใช้งานโปรแกรม HOSxP',15],['แก้ไขปัญหาการใช้งานโปรแกรมอื่นๆ',30],['ขอข้อมูลสารสนเทศ',420]];
document.querySelector('#rules-body').innerHTML = rules.map((r,i) => `<tr><td>${i+1}.${r}</td>${['knowledge','understanding','practice'].map(group => ['yes','no'].map((value,j) => `<td class="choice"><label><input aria-label="ข้อ ${i+1} ${group} ${value}" type="radio" name="rule_${i}_${group}" value="${j ? 'no' : 'yes'}"></label></td>`).join('')).join('')}</tr>`).join('');
document.querySelector('#sla-body').innerHTML = services.map(([service,minutes],i) => `<tr><td>${i+1}.${service}</td><td>${minutes}</td>${[5,4,3,2,1].map(score => `<td class="choice"><label><input aria-label="${service} ระดับ ${score}" type="radio" name="satisfaction_${i}" value="${score}"></label></td>`).join('')}<td><textarea name="comment_${i}" aria-label="ระยะเวลาที่คาดหวังและความคิดเห็น: ${service}"></textarea></td></tr>`).join('');
document.querySelector('#assessment').addEventListener('submit', event => { event.preventDefault(); alert('บันทึกแบบประเมินเรียบร้อยแล้ว'); });
</script>
</body>
</html>
@@ -0,0 +1,36 @@
<?php
session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header("location: ../index.php");
exit;
}
require_once '../includes/db_assessment.php';
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['id'])) {
$id = $_POST['id'];
// Get info for logging
$stmt = $pdo_assess->prepare("SELECT fullname, assess_year FROM it_assessments WHERE id = ?");
$stmt->execute([$id]);
$assessment = $stmt->fetch();
if ($assessment) {
// Delete
$del_stmt = $pdo_assess->prepare("DELETE FROM it_assessments WHERE id = ?");
$del_stmt->execute([$id]);
// Log the action
$admin_cid = $_SESSION['cid'];
$admin_name = $_SESSION['fullname'] ?? 'Admin';
$action_detail = "ลบข้อมูลประเมินของ: " . $assessment['fullname'] . " (ปี " . $assessment['assess_year'] . ")";
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'DELETE_ASSESSMENT', $action_detail);
$_SESSION['success_msg'] = "ลบข้อมูลแบบประเมินเรียบร้อยแล้ว";
}
}
// Redirect back to summary, retaining the year filter if possible
$year = $_POST['filter_year'] ?? '';
header("Location: ../summary.php" . ($year ? "?year=$year" : ""));
exit;
@@ -0,0 +1,67 @@
<?php
session_start(); ob_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
ob_clean(); header("Content-Type: application/json; charset=utf-8"); echo json_encode(["data" => []]);
exit;
}
require_once '../includes/db_assessment.php';
require_once '../includes/db_hosoffice.php';
$filter_year = $_GET['year'] ?? (date('Y')+543);
$rules = $pdo_assess->query("SELECT id FROM it_rules ORDER BY order_no ASC")->fetchAll(PDO::FETCH_ASSOC);
$slas = $pdo_assess->query("SELECT id FROM it_slas ORDER BY order_no ASC")->fetchAll(PDO::FETCH_ASSOC);
$assessments = [];
try {
$stmt = $pdo_assess->prepare("SELECT * FROM it_assessments WHERE assess_year = :year ORDER BY created_at DESC");
$stmt->execute(['year' => $filter_year]);
$assessments = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) { }
$data = [];
$no = 1;
foreach ($assessments as $row) {
$rules_data = json_decode($row['rules_data'], true) ?: [];
$sla_data = json_decode($row['sla_data'], true) ?: [];
$rowData = [];
$rowData[] = '<div class="text-center">'.$no++.'</div>';
$rowData[] = '<div class="text-center">'.htmlspecialchars($row['assess_year']).'</div>';
$rowData[] = htmlspecialchars($row['fullname']);
$rowData[] = htmlspecialchars($row['position']);
$rowData[] = htmlspecialchars($row['department']);
if($row['computer_use'] == '1'){
$rowData[] = '<div class="text-center"><span class="badge bg-success">ใช้</span></div>';
} else {
$rowData[] = '<div class="text-center"><span class="badge bg-secondary">ไม่ใช้</span></div>';
}
foreach($rules as $r){
$r_id = $r['id'];
$k = $rules_data[$r_id]['k'] ?? '-';
$u = $rules_data[$r_id]['u'] ?? '-';
$p = $rules_data[$r_id]['p'] ?? '-';
$rowData[] = '<div class="text-center">'.($k == 'yes' ? '✔️' : ($k == 'no' ? '❌' : '-')).'</div>';
$rowData[] = '<div class="text-center">'.($u == 'yes' ? '✔️' : ($u == 'no' ? '❌' : '-')).'</div>';
$rowData[] = '<div class="text-center">'.($p == 'yes' ? '✔️' : ($p == 'no' ? '❌' : '-')).'</div>';
}
foreach($slas as $s){
$s_id = $s['id'];
$score = $sla_data[$s_id]['score'] ?? '-';
$comment = $sla_data[$s_id]['comment'] ?? '-';
$rowData[] = '<div class="text-center">'.htmlspecialchars($score).'</div>';
$rowData[] = htmlspecialchars($comment);
}
$rowData[] = '<div class="text-center">'.date('d/m/Y H:i', strtotime($row['created_at'])).'</div>';
$deleteForm = '<div class="text-center"><form method="POST" action="actions/delete_assessment.php" onsubmit="return confirm(\'ยืนยันการลบข้อมูลประเมินของ '.htmlspecialchars($row['fullname']).' ใช่หรือไม่?\');"><input type="hidden" name="id" value="'.$row['id'].'"><input type="hidden" name="filter_year" value="'.htmlspecialchars($filter_year).'"><button type="submit" class="btn btn-sm btn-danger py-0 px-2" title="ลบข้อมูล">ลบ</button></form></div>';
$rowData[] = $deleteForm;
$data[] = $rowData;
}
ob_clean(); header("Content-Type: application/json; charset=utf-8"); echo json_encode(["data" => $data]);
@@ -0,0 +1,57 @@
<?php
session_start(); ob_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
ob_clean(); header("Content-Type: application/json; charset=utf-8"); echo json_encode(["data" => [], "count" => 0]);
exit;
}
require_once '../includes/db_assessment.php';
require_once '../includes/db_hosoffice.php';
$filter_year = $_GET['year'] ?? (date('Y')+543);
$assessments = [];
try {
$stmt = $pdo_assess->prepare("SELECT hr_cid FROM it_assessments WHERE assess_year = :year");
$stmt->execute(['year' => $filter_year]);
$completed_cids = $stmt->fetchAll(PDO::FETCH_COLUMN);
} catch (Exception $e) {
$completed_cids = [];
}
$data = [];
try {
$sql = "SELECT a.HR_CID, e.HR_PREFIX_NAME, a.HR_FNAME, a.HR_LNAME,
p.HR_POSITION_NAME,
COALESCE(d.HR_DEPARTMENT_SUB_SUB_NAME, d2.HR_DEPARTMENT_SUB_NAME, '-') as DEPARTMENT_NAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position p ON a.HR_POSITION_ID=p.HR_POSITION_ID
LEFT OUTER JOIN hr_department_sub d2 ON a.HR_DEPARTMENT_SUB_ID=d2.HR_DEPARTMENT_SUB_ID
LEFT OUTER JOIN hr_department_sub_sub d ON a.HR_DEPARTMENT_SUB_SUB_ID=d.HR_DEPARTMENT_SUB_SUB_ID
WHERE a.HR_STATUS_ID = '01'";
if (count($completed_cids) > 0) {
$in_marks = str_repeat('?,', count($completed_cids) - 1) . '?';
$sql .= " AND a.HR_CID NOT IN ($in_marks)";
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->prepare($sql);
$stmt_un->execute($completed_cids);
} else {
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->query($sql);
}
$unassessed_users = $stmt_un->fetchAll(PDO::FETCH_ASSOC);
$no = 1;
foreach($unassessed_users as $u) {
$fullname = trim(($u['HR_PREFIX_NAME'] ?? '') . $u['HR_FNAME'] . ' ' . $u['HR_LNAME']);
$data[] = [
'<div class="text-center">'.$no++.'</div>',
htmlspecialchars($fullname),
htmlspecialchars($u['HR_POSITION_NAME'] ?? '-'),
htmlspecialchars($u['DEPARTMENT_NAME'] ?? '-')
];
}
} catch (Exception $e) { }
ob_clean(); header("Content-Type: application/json; charset=utf-8"); echo json_encode(["data" => $data, "count" => count($data)]);
@@ -0,0 +1,6 @@
<?php
session_start();
$_SESSION = array();
session_destroy();
header("location: ../index.php");
exit;
@@ -0,0 +1,80 @@
<?php
session_start();
if (isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true) {
header("location: ../form.php");
exit;
}
require_once '../includes/db_hosoffice.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user = trim($_POST['username'] ?? '');
$pass = trim($_POST['password'] ?? '');
if (empty($user) || empty($pass)) {
$_SESSION['login_error'] = "กรุณากรอก Username และ Password";
header("location: ../index.php");
exit;
}
$pass_md5 = MD5($pass);
$sql = "SELECT a.HR_CID, a.HR_PASSWORD, a.HR_STATUS_ID, e.HR_PREFIX_NAME, a.HR_FNAME, a.HR_LNAME,
p.HR_POSITION_NAME, d.HR_DEPARTMENT_SUB_SUB_NAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position p ON a.HR_POSITION_ID=p.HR_POSITION_ID
LEFT OUTER JOIN hr_department_sub_sub d ON a.HR_DEPARTMENT_SUB_SUB_ID=d.HR_DEPARTMENT_SUB_SUB_ID
WHERE a.HR_USERNAME = :user LIMIT 1";
try {
$stmt = $pdo_hos->prepare($sql);
$stmt->execute(['user' => $user]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) {
$_SESSION['login_error'] = "ไม่พบบัญชีผู้ใช้นี้";
header("location: ../index.php");
exit;
}
if (strtolower($row['HR_PASSWORD']) !== strtolower($pass_md5)) {
$_SESSION['login_error'] = "รหัสผ่านไม่ถูกต้อง";
header("location: ../index.php");
exit;
}
if ($row['HR_STATUS_ID'] !== '01') {
$_SESSION['login_error'] = "บัญชีผู้ใช้นี้ถูกปิดการใช้งานไปแล้ว";
header("location: ../index.php");
exit;
}
unset($_SESSION['login_error']);
$_SESSION['loggedin'] = true;
$_SESSION['fullname'] = $row['HR_PREFIX_NAME'] . $row['HR_FNAME'] . " " . $row['HR_LNAME'];
$_SESSION['cid'] = $row['HR_CID'];
$_SESSION['position'] = $row['HR_POSITION_NAME'] ?? '';
$_SESSION['department'] = $row['HR_DEPARTMENT_SUB_SUB_NAME'] ?? '';
// Include db_assessment.php to get $super_admins
require_once '../includes/db_assessment.php';
$_SESSION['is_admin'] = in_array($row['HR_CID'], $super_admins);
// Admin check (optional, if you want admins to go to summary.php instead of form.php)
// For now, redirect everyone to the form.
header("location: ../form.php");
exit;
} catch (PDOException $e) {
$_SESSION['login_error'] = "เกิดข้อผิดพลาดของระบบฐานข้อมูล";
// log error securely $e->getMessage()
header("location: ../index.php");
exit;
}
} else {
header("location: ../index.php");
exit;
}
@@ -0,0 +1,76 @@
<?php
session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true) {
header("location: ../index.php");
exit;
}
require_once '../includes/db_assessment.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$cid = $_SESSION['cid'];
$assess_year = $_POST['assess_year'];
$fullname = $_POST['fullname'] ?? '';
$position = $_POST['position'] ?? '';
$department = $_POST['department'] ?? '';
$computer_use = $_POST['computer_use'] ?? '2';
$rules_json = null;
$sla_json = null;
if ($computer_use == '1') {
$rules_data = [];
$sla_data = [];
foreach ($_POST as $key => $val) {
// Check for rules: r_{id}_k, r_{id}_u, r_{id}_p
if (preg_match('/^r_(\d+)_(k|u|p)$/', $key, $matches)) {
$id = $matches[1];
$type = $matches[2];
$rules_data[$id][$type] = $val;
}
// Check for sla: sla_{id}_score, sla_{id}_comment
elseif (preg_match('/^sla_(\d+)_(score|comment)$/', $key, $matches)) {
$id = $matches[1];
$type = $matches[2];
$sla_data[$id][$type] = $val;
}
}
$rules_json = json_encode($rules_data, JSON_UNESCAPED_UNICODE);
$sla_json = json_encode($sla_data, JSON_UNESCAPED_UNICODE);
}
$sql = "INSERT INTO it_assessments (assess_year, hr_cid, fullname, position, department, computer_use, rules_data, sla_data)
VALUES (:assess_year, :hr_cid, :fullname, :position, :department, :computer_use, :rules_data, :sla_data)";
$params = [
':assess_year' => $assess_year,
':hr_cid' => $cid,
':fullname' => $fullname,
':position' => $position,
':department' => $department,
':computer_use' => $computer_use,
':rules_data' => $rules_json,
':sla_data' => $sla_json
];
try {
$stmt = $pdo_assess->prepare($sql);
$stmt->execute($params);
$_SESSION['success_msg'] = "บันทึกข้อมูลเรียบร้อยแล้ว";
} catch (PDOException $e) {
if ($e->errorInfo[1] == 1062) {
$_SESSION['error_msg'] = "ท่านได้ทำแบบประเมินสำหรับปีนี้ไปแล้ว";
} else {
$_SESSION['error_msg'] = "เกิดข้อผิดพลาดในการบันทึกข้อมูล: " . $e->getMessage();
}
}
header("location: ../form.php");
exit;
} else {
header("location: ../form.php");
exit;
}
@@ -0,0 +1,57 @@
<?php
//session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
echo json_encode(["data" => [], "count" => 0]);
exit;
}
require_once '../includes/db_assessment.php';
require_once '../includes/db_hosoffice.php';
$filter_year = $_GET['year'] ?? (date('Y')+543);
$assessments = [];
try {
$stmt = $pdo_assess->prepare("SELECT hr_cid FROM it_assessments WHERE assess_year = :year");
$stmt->execute(['year' => $filter_year]);
$completed_cids = $stmt->fetchAll(PDO::FETCH_COLUMN);
} catch (Exception $e) {
$completed_cids = [];
}
$data = [];
try {
$sql = "SELECT a.HR_CID, e.HR_PREFIX_NAME, a.HR_FNAME, a.HR_LNAME,
p.HR_POSITION_NAME,
COALESCE(d.HR_DEPARTMENT_SUB_SUB_NAME, d2.HR_DEPARTMENT_SUB_NAME, '-') as DEPARTMENT_NAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position p ON a.HR_POSITION_ID=p.HR_POSITION_ID
LEFT OUTER JOIN hr_department_sub d2 ON a.HR_DEPARTMENT_SUB_ID=d2.HR_DEPARTMENT_SUB_ID
LEFT OUTER JOIN hr_department_sub_sub d ON a.HR_DEPARTMENT_SUB_SUB_ID=d.HR_DEPARTMENT_SUB_SUB_ID
WHERE a.HR_STATUS_ID = '01'";
if (count($completed_cids) > 0) {
$in_marks = str_repeat('?,', count($completed_cids) - 1) . '?';
$sql .= " AND a.HR_CID NOT IN ($in_marks)";
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->prepare($sql);
$stmt_un->execute($completed_cids);
} else {
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->query($sql);
}
$unassessed_users = $stmt_un->fetchAll(PDO::FETCH_ASSOC);
$no = 1;
foreach($unassessed_users as $u) {
$fullname = trim(($u['HR_PREFIX_NAME'] ?? '') . $u['HR_FNAME'] . ' ' . $u['HR_LNAME']);
$data[] = [
'<div class="text-center">'.$no++.'</div>',
htmlspecialchars($fullname),
htmlspecialchars($u['HR_POSITION_NAME'] ?? '-'),
htmlspecialchars($u['DEPARTMENT_NAME'] ?? '-')
];
}
} catch (Exception $e) { }
echo json_encode(["data" => $data, "count" => count($data)]);
@@ -0,0 +1,447 @@
<?php
session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header("location: index.php");
exit;
}
require_once 'includes/db_assessment.php';
// Handle Post Requests
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$action = $_POST['action'] ?? '';
$admin_cid = $_SESSION['cid'];
$admin_name = $_SESSION['fullname'] ?? 'Admin';
if ($action == 'add_year') {
$year = trim($_POST['year_text']);
try {
$stmt = $pdo_assess->prepare("INSERT INTO it_years (year_text, is_active) VALUES (?, 0)");
$stmt->execute([$year]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'ADD_YEAR', "เพิ่มปีประเมินใหม่: $year");
$_SESSION['success_msg'] = "เพิ่มปีประเมินเรียบร้อยแล้ว";
} catch (PDOException $e) {
$_SESSION['error_msg'] = "มีปีนี้ในระบบแล้ว หรือเกิดข้อผิดพลาด";
}
}
elseif ($action == 'set_active_year') {
$id = $_POST['id'];
$ystmt = $pdo_assess->prepare("SELECT year_text FROM it_years WHERE id = ?");
$ystmt->execute([$id]);
$yr = $ystmt->fetchColumn();
$pdo_assess->query("UPDATE it_years SET is_active = 0");
$stmt = $pdo_assess->prepare("UPDATE it_years SET is_active = 1 WHERE id = ?");
$stmt->execute([$id]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'SET_ACTIVE_YEAR', "เปิดรับประเมินสำหรับปี: $yr");
$_SESSION['success_msg'] = "เปิดใช้งานปีที่เลือกเรียบร้อยแล้ว (สามารถเปิดได้เพียง 1 รายการเท่านั้น)";
}
elseif ($action == 'add_rule' || $action == 'edit_rule') {
$content = $_POST['content'];
$order = $_POST['order_no'];
$active = isset($_POST['is_active']) ? 1 : 0;
if ($action == 'add_rule') {
$stmt = $pdo_assess->prepare("INSERT INTO it_rules (content, order_no, is_active) VALUES (?, ?, ?)");
$stmt->execute([$content, $order, $active]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'ADD_RULE', "เพิ่มระเบียบปฏิบัติ: " . mb_substr($content, 0, 50) . "...");
} else {
$id = $_POST['id'];
$stmt = $pdo_assess->prepare("UPDATE it_rules SET content=?, order_no=?, is_active=? WHERE id=?");
$stmt->execute([$content, $order, $active, $id]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'EDIT_RULE', "แก้ไขระเบียบปฏิบัติ ID $id: " . mb_substr($content, 0, 50) . "...");
}
$_SESSION['success_msg'] = "บันทึกข้อมูลระเบียบปฏิบัติเรียบร้อยแล้ว";
}
elseif ($action == 'delete_rule') {
$id = $_POST['id'];
$stmt = $pdo_assess->prepare("SELECT content FROM it_rules WHERE id=?");
$stmt->execute([$id]);
$r_content = $stmt->fetchColumn();
$stmt = $pdo_assess->prepare("DELETE FROM it_rules WHERE id=?");
$stmt->execute([$id]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'DELETE_RULE', "ลบระเบียบปฏิบัติ: " . mb_substr($r_content, 0, 50) . "...");
$_SESSION['success_msg'] = "ลบข้อมูลระเบียบปฏิบัติเรียบร้อยแล้ว";
}
elseif ($action == 'add_sla' || $action == 'edit_sla') {
$name = $_POST['service_name'];
$time = $_POST['standard_time'];
$order = $_POST['order_no'];
$active = isset($_POST['is_active']) ? 1 : 0;
if ($action == 'add_sla') {
$stmt = $pdo_assess->prepare("INSERT INTO it_slas (service_name, standard_time, order_no, is_active) VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $time, $order, $active]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'ADD_SLA', "เพิ่ม SLA: $name ($time นาที)");
} else {
$id = $_POST['id'];
$stmt = $pdo_assess->prepare("UPDATE it_slas SET service_name=?, standard_time=?, order_no=?, is_active=? WHERE id=?");
$stmt->execute([$name, $time, $order, $active, $id]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'EDIT_SLA', "แก้ไข SLA ID $id: $name ($time นาที)");
}
$_SESSION['success_msg'] = "บันทึกข้อมูลบริการ SLA เรียบร้อยแล้ว";
}
elseif ($action == 'delete_sla') {
$id = $_POST['id'];
$stmt = $pdo_assess->prepare("SELECT service_name FROM it_slas WHERE id=?");
$stmt->execute([$id]);
$s_name = $stmt->fetchColumn();
$stmt = $pdo_assess->prepare("DELETE FROM it_slas WHERE id=?");
$stmt->execute([$id]);
logAdminAction($pdo_assess, $admin_cid, $admin_name, 'DELETE_SLA', "ลบ SLA: $s_name");
$_SESSION['success_msg'] = "ลบข้อมูลบริการ SLA เรียบร้อยแล้ว";
}
header("Location: admin_settings.php");
exit;
}
// Fetch Data
$it_years = $pdo_assess->query("SELECT * FROM it_years ORDER BY year_text DESC")->fetchAll();
$counts_stmt = $pdo_assess->query("SELECT assess_year, COUNT(id) as total_assessments FROM it_assessments GROUP BY assess_year");
$counts_map = [];
foreach ($counts_stmt->fetchAll() as $c) {
$counts_map[$c['assess_year']] = $c['total_assessments'];
}
$rules = $pdo_assess->query("SELECT * FROM it_rules ORDER BY order_no ASC")->fetchAll();
$slas = $pdo_assess->query("SELECT * FROM it_slas ORDER BY order_no ASC")->fetchAll();
$logs = $pdo_assess->query("SELECT * FROM it_logs ORDER BY created_at DESC LIMIT 50")->fetchAll();
?>
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>ตั้งค่าระบบประเมิน (Super Admin)</title>
<!-- Favicon -->
<link rel="icon" type="image/png" href="assets/images/logo.png">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
body { font-family: 'Sarabun', sans-serif; background-color: #f8f9fa; }
.navbar-custom { background: linear-gradient(135deg, #12344d, #1a2938); }
.card { border: none; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); margin-bottom: 2rem; }
.card-header { background: #fff; border-bottom: 1px solid #eee; border-radius: 15px 15px 0 0 !important; font-weight: bold; color: #007f8b;}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark navbar-custom mb-4">
<div class="container-fluid px-4">
<a class="navbar-brand fw-bold d-flex align-items-center" href="admin_settings.php">
<img src="assets/images/logo.png" alt="Logo" width="40" height="40" class="d-inline-block align-text-top me-2 bg-white rounded-circle">
<span>ระบบประเมิน - ตั้งค่า</span>
</a>
<div class="d-flex">
<a href="summary.php" class="btn btn-outline-light btn-sm rounded-pill px-3 me-2">ไปหน้าสรุปผล</a>
<a href="actions/logout.php" class="btn btn-danger btn-sm rounded-pill px-3">ออกจากระบบ</a>
</div>
</div>
</nav>
<div class="container">
<!-- 1. ตั้งค่าปี -->
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>1. ตั้งค่าปีที่เปิดให้ประเมิน (เปิดได้เพียง 1 รายการ)</span>
<form method="POST" class="d-flex m-0">
<input type="hidden" name="action" value="add_year">
<input type="text" name="year_text" class="form-control form-control-sm me-2" placeholder="ระบุปี เช่น 2570" required pattern="[0-9]{4}">
<button type="submit" class="btn btn-sm btn-success text-nowrap">+ เพิ่มปี</button>
</form>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-striped m-0">
<thead class="table-light">
<tr>
<th>ปีประเมิน</th>
<th class="text-center">จำนวนผู้ทำประเมิน</th>
<th class="text-center">สถานะปัจจุบัน</th>
<th class="text-center">จัดการ</th>
</tr>
</thead>
<tbody>
<?php foreach($it_years as $y):
$count = $counts_map[$y['year_text']] ?? 0;
?>
<tr>
<td class="fw-bold">ปี <?php echo htmlspecialchars($y['year_text']); ?></td>
<td class="text-center"><span class="badge bg-secondary"><?php echo $count; ?> รายการ</span></td>
<td class="text-center">
<?php if($y['is_active']): ?>
<span class="badge bg-primary px-3 py-2">กำลังเปิดรับประเมิน</span>
<?php else: ?>
<span class="badge bg-light text-muted border px-3 py-2">ปิด</span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if(!$y['is_active']): ?>
<form method="POST" class="m-0" onsubmit="return confirm('ต้องการเปิดให้ปี <?php echo $y['year_text']; ?> เป็นปีปัจจุบันที่ใช้ทำประเมินใช่หรือไม่? (ปีอื่นๆ จะถูกปิดอัตโนมัติ)');">
<input type="hidden" name="action" value="set_active_year">
<input type="hidden" name="id" value="<?php echo $y['id']; ?>">
<button type="submit" class="btn btn-sm btn-outline-primary">เปิดใช้งานปีนี้</button>
</form>
<?php else: ?>
<button class="btn btn-sm btn-primary disabled">ใช้งานอยู่</button>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php if(empty($it_years)): ?>
<tr><td colspan="4" class="text-center text-muted">ยังไม่ได้เพิ่มปีประเมิน กรุณาเพิ่มปีด้านบน</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- 2. จัดการระเบียบปฏิบัติ -->
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>2. ส่วนที่ 3 - การประเมินการรับรู้ (ระเบียบปฏิบัติ)</span>
<button class="btn btn-sm btn-success" onclick="openRuleModal()">+ เพิ่มรายการใหม่</button>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-striped m-0">
<thead class="table-light"><tr><th>ลำดับ</th><th>ระเบียบปฏิบัติ</th><th>สถานะ</th><th>จัดการ</th></tr></thead>
<tbody>
<?php foreach($rules as $r): ?>
<tr>
<td class="text-center"><?php echo $r['order_no']; ?></td>
<td><?php echo htmlspecialchars($r['content']); ?></td>
<td><?php echo $r['is_active'] ? '<span class="badge bg-success">เปิดใช้</span>' : '<span class="badge bg-secondary">ปิด</span>'; ?></td>
<td style="white-space:nowrap;">
<button class="btn btn-sm btn-warning" onclick='editRule(<?php echo json_encode($r); ?>)'>แก้ไข</button>
<form method="POST" class="d-inline" onsubmit="return confirm('ยืนยันการลบ?');">
<input type="hidden" name="action" value="delete_rule">
<input type="hidden" name="id" value="<?php echo $r['id']; ?>">
<button type="submit" class="btn btn-sm btn-danger">ลบ</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- 3. จัดการ SLA -->
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>3. ส่วนที่ 4 - ข้อตกลงการให้บริการ (SLA)</span>
<button class="btn btn-sm btn-success" onclick="openSlaModal()">+ เพิ่มรายการใหม่</button>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-striped m-0">
<thead class="table-light"><tr><th>ลำดับ</th><th>ชื่อบริการ</th><th>เวลามาตรฐาน (นาที)</th><th>สถานะ</th><th>จัดการ</th></tr></thead>
<tbody>
<?php foreach($slas as $s): ?>
<tr>
<td class="text-center"><?php echo $s['order_no']; ?></td>
<td><?php echo htmlspecialchars($s['service_name']); ?></td>
<td class="text-center"><?php echo $s['standard_time']; ?></td>
<td><?php echo $s['is_active'] ? '<span class="badge bg-success">เปิดใช้</span>' : '<span class="badge bg-secondary">ปิด</span>'; ?></td>
<td style="white-space:nowrap;">
<button class="btn btn-sm btn-warning" onclick='editSla(<?php echo json_encode($s); ?>)'>แก้ไข</button>
<form method="POST" class="d-inline" onsubmit="return confirm('ยืนยันการลบ?');">
<input type="hidden" name="action" value="delete_sla">
<input type="hidden" name="id" value="<?php echo $s['id']; ?>">
<button type="submit" class="btn btn-sm btn-danger">ลบ</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- 4. ประวัติการปรับปรุงระบบ (Logs) -->
<div class="card">
<div class="card-header bg-dark text-white" style="border-radius: 15px 15px 0 0 !important;">
<i class="bi bi-clock-history"></i> ประวัติการดำเนินการ (System Logs) - 50 รายการล่าสุด
</div>
<div class="card-body p-0">
<div class="table-responsive" style="max-height: 400px; overflow-y: auto;">
<table class="table table-sm table-striped m-0" style="font-size: 0.9rem;">
<thead class="table-light sticky-top">
<tr>
<th>วัน-เวลา</th>
<th>ผู้ดำเนินการ</th>
<th>ประเภท</th>
<th>รายละเอียด</th>
</tr>
</thead>
<tbody>
<?php foreach($logs as $log): ?>
<tr>
<td><?php echo date('d/m/Y H:i', strtotime($log['created_at'])); ?></td>
<td><?php echo htmlspecialchars($log['admin_name']); ?></td>
<td><span class="badge bg-secondary"><?php echo htmlspecialchars($log['action_type']); ?></span></td>
<td><?php echo htmlspecialchars($log['action_detail']); ?></td>
</tr>
<?php endforeach; ?>
<?php if(empty($logs)): ?>
<tr><td colspan="4" class="text-center text-muted py-3">ยังไม่มีประวัติการดำเนินการ</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Rule Modal -->
<div class="modal fade" id="ruleModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title" id="ruleModalTitle">เพิ่ม/แก้ไข ระเบียบปฏิบัติ</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" name="action" id="ruleAction" value="add_rule">
<input type="hidden" name="id" id="ruleId" value="">
<div class="mb-3">
<label class="form-label">ลำดับ</label>
<input type="number" class="form-control" name="order_no" id="ruleOrder" required value="0">
</div>
<div class="mb-3">
<label class="form-label">เนื้อหาระเบียบปฏิบัติ</label>
<textarea class="form-control" name="content" id="ruleContent" rows="4" required></textarea>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="is_active" id="ruleActive" value="1" checked>
<label class="form-check-label">เปิดใช้งาน</label>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">บันทึกข้อมูล</button>
</div>
</form>
</div>
</div>
</div>
<!-- SLA Modal -->
<div class="modal fade" id="slaModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST">
<div class="modal-header">
<h5 class="modal-title" id="slaModalTitle">เพิ่ม/แก้ไข SLA</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" name="action" id="slaAction" value="add_sla">
<input type="hidden" name="id" id="slaId" value="">
<div class="mb-3">
<label class="form-label">ลำดับ</label>
<input type="number" class="form-control" name="order_no" id="slaOrder" required value="0">
</div>
<div class="mb-3">
<label class="form-label">ชื่อบริการ</label>
<input type="text" class="form-control" name="service_name" id="slaName" required>
</div>
<div class="mb-3">
<label class="form-label">เวลามาตรฐาน (นาที)</label>
<input type="number" class="form-control" name="standard_time" id="slaTime" required>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="is_active" id="slaActive" value="1" checked>
<label class="form-check-label">เปิดใช้งาน</label>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">บันทึกข้อมูล</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
const ruleModal = new bootstrap.Modal(document.getElementById('ruleModal'));
const slaModal = new bootstrap.Modal(document.getElementById('slaModal'));
function openRuleModal() {
document.getElementById('ruleAction').value = 'add_rule';
document.getElementById('ruleId').value = '';
document.getElementById('ruleContent').value = '';
document.getElementById('ruleOrder').value = '0';
document.getElementById('ruleActive').checked = true;
document.getElementById('ruleModalTitle').innerText = 'เพิ่มระเบียบปฏิบัติ';
ruleModal.show();
}
function editRule(r) {
document.getElementById('ruleAction').value = 'edit_rule';
document.getElementById('ruleId').value = r.id;
document.getElementById('ruleContent').value = r.content;
document.getElementById('ruleOrder').value = r.order_no;
document.getElementById('ruleActive').checked = (r.is_active == 1);
document.getElementById('ruleModalTitle').innerText = 'แก้ไขระเบียบปฏิบัติ';
ruleModal.show();
}
function openSlaModal() {
document.getElementById('slaAction').value = 'add_sla';
document.getElementById('slaId').value = '';
document.getElementById('slaName').value = '';
document.getElementById('slaTime').value = '';
document.getElementById('slaOrder').value = '0';
document.getElementById('slaActive').checked = true;
document.getElementById('slaModalTitle').innerText = 'เพิ่มบริการ SLA';
slaModal.show();
}
function editSla(s) {
document.getElementById('slaAction').value = 'edit_sla';
document.getElementById('slaId').value = s.id;
document.getElementById('slaName').value = s.service_name;
document.getElementById('slaTime').value = s.standard_time;
document.getElementById('slaOrder').value = s.order_no;
document.getElementById('slaActive').checked = (s.is_active == 1);
document.getElementById('slaModalTitle').innerText = 'แก้ไขบริการ SLA';
slaModal.show();
}
<?php if(isset($_SESSION['success_msg'])): ?>
Swal.fire({
icon: 'success',
title: 'สำเร็จ!',
text: '<?php echo $_SESSION['success_msg']; ?>',
timer: 2000,
showConfirmButton: false
});
<?php unset($_SESSION['success_msg']); ?>
<?php endif; ?>
</script>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

@@ -0,0 +1,429 @@
<?php
session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true) {
header("location: index.php");
exit;
}
require_once 'includes/db_assessment.php';
$cid = $_SESSION['cid'];
// ดึงปีปัจจุบันจากตาราง it_years
$stmt = $pdo_assess->query("SELECT year_text FROM it_years WHERE is_active = 1 LIMIT 1");
$current_year = $stmt->fetchColumn();
if (!$current_year) {
echo "<!DOCTYPE html><html lang='th'><head><meta charset='UTF-8'><title>ระบบประเมิน</title><link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'></head><body class='bg-light d-flex align-items-center justify-content-center vh-100'><div class='text-center'><h3>ขณะนี้ยังไม่มีการเปิดรับทำแบบประเมินประจำปี</h3><a href='actions/logout.php' class='btn btn-secondary mt-3'>ออกจากระบบ</a></div></body></html>";
exit;
}
// ตรวจสอบว่าเคยทำประเมินในปีนี้หรือยัง
$has_assessed = false;
$assessed_date = null;
try {
$stmt = $pdo_assess->prepare("SELECT created_at FROM it_assessments WHERE hr_cid = :cid AND assess_year = :year LIMIT 1");
$stmt->execute(['cid' => $cid, 'year' => $current_year]);
$result = $stmt->fetch();
if ($result) {
$has_assessed = true;
$assessed_date = date('d/m/Y H:i', strtotime($result['created_at']));
}
} catch (PDOException $e) {
}
?>
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>แบบประเมิน - หน่วยงานสุขภาพดิจิทัล</title>
<!-- Favicon -->
<link rel="icon" type="image/png" href="assets/images/logo.png">
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
body {
font-family: 'Sarabun', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
color: #333;
min-height: 100vh;
}
.navbar-custom {
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.form-container {
background: #ffffff;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
padding: 3rem;
margin-top: 2rem;
margin-bottom: 3rem;
border: 1px solid rgba(255, 255, 255, 0.4);
}
.header-title {
background: linear-gradient(135deg, #008f91, #005d68);
color: white;
padding: 2rem;
border-radius: 15px;
text-align: center;
margin-bottom: 2rem;
box-shadow: 0 8px 20px rgba(0, 143, 145, 0.2);
}
.section-title {
color: #007f8b;
font-weight: 700;
border-left: 5px solid #007f8b;
padding-left: 15px;
margin-top: 2.5rem;
margin-bottom: 1.5rem;
}
.table-custom th {
background: #12344d;
color: white;
text-align: center;
vertical-align: middle;
}
.table-custom td {
vertical-align: middle;
}
.table-custom tbody tr:hover {
background-color: #f0faf9;
}
.radio-custom input[type="radio"] {
width: 20px;
height: 20px;
accent-color: #007f8b;
}
.btn-submit {
background: linear-gradient(135deg, #008f91, #005d68);
color: white;
border: none;
padding: 12px 30px;
font-size: 1.1rem;
border-radius: 50px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-submit:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 143, 145, 0.3);
color: white;
}
.card-done {
background: white;
border-radius: 15px;
padding: 3rem;
text-align: center;
margin-top: 5rem;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
}
.card-done h3 {
color: #28a745;
font-weight: 700;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-custom sticky-top">
<div class="container">
<a class="navbar-brand fw-bold text-dark d-flex align-items-center" href="#">
<img src="assets/images/logo.png" alt="Logo" width="40" height="40" class="d-inline-block align-text-top me-2">
<span>IT Assessment System</span>
</a>
<div class="d-flex align-items-center">
<span class="me-3 fw-bold text-muted">ยินดีต้อนรับ, <?php echo htmlspecialchars($_SESSION['fullname']); ?></span>
<a href="actions/logout.php" class="btn btn-outline-danger btn-sm rounded-pill px-3">ออกจากระบบ</a>
<?php if(isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<a href="summary.php" class="btn btn-outline-primary btn-sm rounded-pill px-3 ms-2">หน้าสรุปผล (Admin)</a>
<?php endif; ?>
</div>
</div>
</nav>
<div class="container">
<?php if ($has_assessed): ?>
<div class="card-done">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" fill="currentColor" class="bi bi-check-circle-fill text-success mb-3" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" />
</svg>
<h3>ท่านได้ทำแบบประเมินประจำปี <?php echo $current_year; ?> เรียบร้อยแล้ว</h3>
<p class="text-muted fs-5 mt-3">ทำรายการเมื่อวันที่: <strong><?php echo $assessed_date; ?></strong></p>
<p class="text-muted">ขอขอบคุณที่ให้ความร่วมมือในการทำแบบประเมินของหน่วยงานสุขภาพดิจิทัล</p>
</div>
<?php else: ?>
<div class="form-container">
<div class="header-title">
<h2 class="fw-bold mb-2">แบบประเมินระเบียบปฏิบัติในการรักษาความมั่นคงปลอดภัย<br>ระบบเทคโนโลยีสารสนเทศ</h2>
<h5 class="mb-0">โรงพยาบาลเกาะสมุย ประจำปี <?php echo $current_year; ?></h5>
</div>
<div class="alert alert-info border-0 bg-info bg-opacity-10 text-dark">
<strong>คำอธิบาย:</strong> แบบประเมินมี 4 ส่วน กรุณาตอบตามความเป็นจริงเพื่อกลุ่มงานสุขภาพดิจิทัลจะนำผลการประเมินไปวิเคราะห์เพื่อจัดการความมั่นคงปลอดภัยระบบเทคโนโลยีสารสนเทศของโรงพยาบาลเกาะสมุย ให้เกิดประโยชน์สูงสุด
</div>
<form id="assessmentForm" action="actions/save_assessment.php" method="POST">
<input type="hidden" name="assess_year" value="<?php echo $current_year; ?>">
<h4 class="section-title">ส่วนที่ 1 ข้อมูลผู้รับการประเมิน</h4>
<div class="row g-3">
<div class="col-md-4">
<label class="form-label fw-bold">ชื่อ-สกุล</label>
<input type="text" class="form-control" name="fullname" value="<?php echo htmlspecialchars($_SESSION['fullname']); ?>" readonly>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">ตำแหน่ง</label>
<input type="text" class="form-control bg-light" name="position" value="<?php echo htmlspecialchars($_SESSION['position'] ?? ''); ?>" readonly>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">หน่วยงาน</label>
<input type="text" class="form-control bg-light" name="department" value="<?php echo htmlspecialchars($_SESSION['department'] ?? ''); ?>" readonly>
</div>
</div>
<h4 class="section-title">ส่วนที่ 2 การใช้งานคอมพิวเตอร์</h4>
<div class="card border-0 shadow-sm mb-4">
<div class="card-body">
<div class="form-check mb-2">
<input class="form-check-input" type="radio" name="computer_use" id="use_yes" value="1" required>
<label class="form-check-label fw-bold" for="use_yes">
1. ใช้คอมพิวเตอร์ในการปฏิบัติงาน
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="computer_use" id="use_no" value="2">
<label class="form-check-label fw-bold" for="use_no">
2. ไม่ได้ใช้คอมพิวเตอร์ในการปฏิบัติงาน
</label>
</div>
</div>
</div>
<h4 class="section-title">ส่วนที่ 3 การประเมินการรับรู้ ความเข้าใจ และการปฏิบัติ</h4>
<div class="table-responsive rounded shadow-sm border border-1 mb-4">
<table class="table table-bordered table-custom mb-0">
<thead>
<tr>
<th rowspan="2" class="align-middle" style="width: 50%;">ระเบียบปฏิบัติ</th>
<th colspan="2">การรับรู้</th>
<th colspan="2">ความเข้าใจ</th>
<th colspan="2">การปฏิบัติ</th>
</tr>
<tr style="background:#173e55;">
<th>รู้</th>
<th>ไม่รู้</th>
<th>เข้าใจ</th>
<th>ไม่เข้าใจ</th>
<th>ได้</th>
<th>ไม่ได้</th>
</tr>
</thead>
<tbody>
<?php
$rules = $pdo_assess->query("SELECT * FROM it_rules WHERE is_active = 1 ORDER BY order_no ASC")->fetchAll();
$n = 1;
foreach ($rules as $rule):
$r_id = $rule['id'];
?>
<tr>
<td><?php echo $n . ". " . htmlspecialchars($rule['content']); ?></td>
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_k" value="yes" required></td>
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_k" value="no"></td>
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_u" value="yes" required></td>
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_u" value="no"></td>
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_p" value="yes" required></td>
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_p" value="no"></td>
</tr>
<?php
$n++;
endforeach; ?>
</tbody>
</table>
</div>
<div id="extended_sections">
<h4 class="section-title">ส่วนที่ 4 แบบประเมินข้อตกลงการให้บริการ (SLA)</h4>
<div class="alert alert-warning border-0 text-dark" style="background:#fff8e9;">
<strong>หมายเหตุ:</strong> ส่วนนี้สำหรับเจ้าหน้าที่ที่ใช้คอมพิวเตอร์ในการปฏิบัติงานเท่านั้น
</div>
<div class="table-responsive rounded shadow-sm border border-1 mb-5">
<table class="table table-bordered table-custom mb-0">
<thead>
<tr>
<th rowspan="2" class="align-middle">บริการ</th>
<th rowspan="2" class="align-middle">เวลามาตรฐาน<br>(นาที)</th>
<th colspan="5">ระดับความพึงพอใจ</th>
<th rowspan="2" class="align-middle">ข้อเสนอแนะ / เวลาที่คาดหวัง</th>
</tr>
<tr style="background:#173e55;">
<th>5<br><small>มากที่สุด</small></th>
<th>4<br><small>มาก</small></th>
<th>3<br><small>ปานกลาง</small></th>
<th>2<br><small>น้อย</small></th>
<th>1<br><small>น้อยมาก</small></th>
</tr>
</thead>
<tbody>
<?php
$slas = $pdo_assess->query("SELECT * FROM it_slas WHERE is_active = 1 ORDER BY order_no ASC")->fetchAll();
$n = 1;
foreach ($slas as $sla):
$s_id = $sla['id'];
?>
<tr>
<td><?php echo $n . ". " . htmlspecialchars($sla['service_name']); ?></td>
<td class="text-center"><?php echo $sla['standard_time']; ?></td>
<?php for ($score = 5; $score >= 1; $score--): ?>
<td class="text-center radio-custom"><input type="radio" name="sla_<?php echo $s_id; ?>_score" value="<?php echo $score; ?>" required></td>
<?php endfor; ?>
<td><input type="text" class="form-control form-control-sm" name="sla_<?php echo $s_id; ?>_comment" placeholder="ความคิดเห็น..."></td>
</tr>
<?php
$n++;
endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="text-center mt-4">
<button type="submit" class="btn btn-submit px-5" id="btnSubmit">บันทึกแบบประเมิน</button>
</div>
</form>
</div>
<?php endif; ?>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const useYes = document.getElementById("use_yes");
const useNo = document.getElementById("use_no");
const extendedSections = document.getElementById("extended_sections");
function toggleSections() {
if (useNo && useNo.checked) {
extendedSections.style.display = "none";
// ยกเลิก required ชั่วคราว
const reqInputs = extendedSections.querySelectorAll('input[required]');
reqInputs.forEach(input => {
input.dataset.required = 'true';
input.removeAttribute('required');
// Clear validation highlights
let row = input.closest('tr');
if (row) row.classList.remove('table-danger');
input.classList.remove('is-invalid');
});
} else {
extendedSections.style.display = "block";
const reqInputs = extendedSections.querySelectorAll('input[data-required="true"]');
reqInputs.forEach(input => {
input.setAttribute('required', 'required');
});
}
}
if (useYes && useNo) {
useYes.addEventListener("change", toggleSections);
useNo.addEventListener("change", toggleSections);
}
// Highlight invalid fields when native HTML5 validation fails
const allInputs = document.querySelectorAll('#assessmentForm input');
allInputs.forEach(input => {
input.addEventListener('invalid', function() {
let row = this.closest('tr');
if (row) {
row.classList.add('table-danger');
} else {
this.classList.add('is-invalid');
}
});
input.addEventListener('change', function() {
let row = this.closest('tr');
if (row) {
// Because radios in the same row might have different names (like Rule K, U, P),
// we shouldn't necessarily remove table-danger if other groups in the same row are still invalid.
// However, a simple approach is to check if the form is valid.
// Actually, checking if the specific required radios are filled is tricky.
// For a better UX, we can just remove table-danger and let them submit again to re-check.
row.classList.remove('table-danger');
} else {
this.classList.remove('is-invalid');
}
});
});
const form = document.getElementById("assessmentForm");
if (form) {
form.addEventListener("submit", function(e) {
e.preventDefault();
// Double check if form is valid (it should be if submit fires, due to HTML5, but just in case)
if (!form.checkValidity()) {
return;
}
Swal.fire({
title: 'ยืนยันการส่งแบบประเมิน?',
text: "โปรดตรวจสอบข้อมูลให้ถูกต้องก่อนกดยืนยัน",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#008f91',
cancelButtonColor: '#d33',
confirmButtonText: 'ยืนยันส่งข้อมูล',
cancelButtonText: 'ยกเลิก'
}).then((result) => {
if (result.isConfirmed) {
form.submit();
}
});
});
}
});
<?php if (isset($_SESSION['success_msg'])): ?>
Swal.fire({
icon: 'success',
title: 'สำเร็จ!',
text: '<?php echo $_SESSION['success_msg']; ?>',
confirmButtonColor: '#008f91'
});
<?php unset($_SESSION['success_msg']); ?>
<?php endif; ?>
<?php if (isset($_SESSION['error_msg'])): ?>
Swal.fire({
icon: 'error',
title: 'เกิดข้อผิดพลาด',
text: '<?php echo $_SESSION['error_msg']; ?>',
confirmButtonColor: '#d33'
});
<?php unset($_SESSION['error_msg']); ?>
<?php endif; ?>
</script>
</body>
</html>
@@ -0,0 +1,38 @@
<?php
// File: includes/db_assessment.php
// สำหรับเชื่อมต่อฐานข้อมูลของระบบแบบประเมิน (Local/ระบบนี้)
$host = 'localhost'; // แก้ไขเป็น Host ของระบบแบบประเมิน
$db = 'it_assessment'; // แก้ไขเป็นชื่อฐานข้อมูลของระบบนี้
$user = 'root'; // แก้ไขเป็น Username ของคุณ
$pass = '@Samui@10742'; // แก้ไขเป็น Password ของคุณ
$charset = 'utf8mb4';
// เลขบัตรประชาชนของ Super Admin ที่เข้าจัดการระบบได้
$super_admins = [
'1840400002613',
'3840400171314',
'3800500016451'
];
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo_assess = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// ฟังก์ชันบันทึกประวัติการปรับปรุง
function logAdminAction($pdo, $admin_cid, $admin_name, $action_type, $action_detail) {
try {
$stmt = $pdo->prepare("INSERT INTO it_logs (admin_cid, admin_name, action_type, action_detail) VALUES (?, ?, ?, ?)");
$stmt->execute([$admin_cid, $admin_name, $action_type, $action_detail]);
} catch (PDOException $e) {
// เงียบไว้ถ้าบันทึก log ไม่ได้
}
}
@@ -0,0 +1,20 @@
<?php
// File: includes/db_hosoffice.php
$host = '10.0.250.115'; // แก้ไขเป็น Host ของคุณ
$db = 'hosoffice_2566'; // แก้ไขเป็นชื่อฐานข้อมูลของคุณ
$user = 'hosoffice'; // แก้ไขเป็น Username ของคุณ
$pass = 'hosoffice10742'; // แก้ไขเป็น Password ของคุณ
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo_hos = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
@@ -0,0 +1,109 @@
<?php
session_start();
if (isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true) {
header("location: form.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>เข้าสู่ระบบ - แบบประเมินประจำปี หน่วยงานสุขภาพดิจิทัล</title>
<!-- Favicon -->
<link rel="icon" type="image/png" href="assets/images/logo.png">
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Google Fonts: Sarabun -->
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
body {
font-family: 'Sarabun', sans-serif;
background: linear-gradient(135deg, #e9f4f5 0%, #f5f8fb 48%, #e7edf5 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.login-card {
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.5);
box-shadow: 0 18px 55px rgba(22, 52, 77, 0.13);
padding: 2.5rem;
width: 100%;
max-width: 400px;
}
.login-card h2 {
font-weight: 700;
color: #12344d;
margin-bottom: 1.5rem;
text-align: center;
}
.form-control {
border-radius: 10px;
padding: 0.75rem 1rem;
border: 1px solid #dce5ec;
}
.form-control:focus {
box-shadow: 0 0 0 3px rgba(0, 127, 139, 0.13);
border-color: #007f8b;
}
.btn-primary {
background: linear-gradient(135deg, #008f91, #005d68);
border: none;
border-radius: 10px;
padding: 0.75rem;
font-weight: 600;
width: 100%;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 9px 18px rgba(0, 93, 104, 0.27);
}
</style>
</head>
<body>
<div class="login-card">
<div class="text-center mb-3">
<img src="assets/images/logo.png" alt="Logo" width="80" class="img-fluid">
</div>
<h2>เข้าสู่ระบบ</h2>
<p class="text-center text-muted mb-4">ระบบแบบประเมินสุขภาพดิจิทัล ประจำปี</p>
<form action="actions/process_login.php" method="POST">
<div class="mb-3">
<label for="username" class="form-label text-muted fw-bold">ชื่อผู้ใช้งาน (Username)</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-4">
<label for="password" class="form-label text-muted fw-bold">รหัสผ่าน (Password)</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">เข้าสู่ระบบ</button>
</form>
</div>
<?php
if (isset($_SESSION['login_error'])) {
$error = $_SESSION['login_error'];
echo "<script>
Swal.fire({
icon: 'error',
title: 'เข้าสู่ระบบล้มเหลว',
text: '$error',
confirmButtonColor: '#007f8b'
});
</script>";
unset($_SESSION['login_error']);
}
?>
</body>
</html>
@@ -0,0 +1,427 @@
<?php
session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header("location: index.php");
exit;
}
require_once 'includes/db_assessment.php';
require_once 'includes/db_hosoffice.php';
$year = $_GET['year'] ?? (date('Y') + 543);
// 1. Get total HR users
$total_users = 0;
try {
$stmt = $pdo_hos->query("SELECT COUNT(*) FROM hr_person WHERE HR_STATUS_ID='01'");
$total_users = (int)$stmt->fetchColumn();
} catch (Exception $e) { }
// 2. Get total assessed
$stmt = $pdo_assess->prepare("SELECT COUNT(*) FROM it_assessments WHERE assess_year = ?");
$stmt->execute([$year]);
$total_assessed = (int)$stmt->fetchColumn();
$percent_assessed = $total_users > 0 ? round(($total_assessed / $total_users) * 100, 2) : 0;
// 3. Get rules
$rules = $pdo_assess->query("SELECT * FROM it_rules ORDER BY order_no ASC")->fetchAll();
// 4. Aggregate answers
$stmt = $pdo_assess->prepare("SELECT rules_data FROM it_assessments WHERE assess_year = ?");
$stmt->execute([$year]);
$assessments = $stmt->fetchAll(PDO::FETCH_COLUMN);
// Initialize counters
$stats = [];
foreach ($rules as $r) {
$r_id = $r['id'];
$stats[$r_id] = [
'k_yes' => 0, 'k_no' => 0,
'u_yes' => 0, 'u_no' => 0,
'p_yes' => 0, 'p_no' => 0,
];
}
foreach ($assessments as $json_data) {
$data = json_decode($json_data, true);
if (is_array($data)) {
foreach ($rules as $r) {
$r_id = $r['id'];
if (isset($data[$r_id])) {
if ($data[$r_id]['k'] == 'yes') $stats[$r_id]['k_yes']++;
elseif ($data[$r_id]['k'] == 'no') $stats[$r_id]['k_no']++;
if ($data[$r_id]['u'] == 'yes') $stats[$r_id]['u_yes']++;
elseif ($data[$r_id]['u'] == 'no') $stats[$r_id]['u_no']++;
if ($data[$r_id]['p'] == 'yes') $stats[$r_id]['p_yes']++;
elseif ($data[$r_id]['p'] == 'no') $stats[$r_id]['p_no']++;
}
}
}
}
// 5. AI Summary Calculation
$max_k_yes = -1; $id_k_yes = ''; $max_k_no = -1; $id_k_no = '';
$max_u_yes = -1; $id_u_yes = ''; $max_u_no = -1; $id_u_no = '';
$max_p_yes = -1; $id_p_yes = ''; $max_p_no = -1; $id_p_no = '';
$rule_mapping = [];
$n = 1;
foreach ($rules as $r) {
$rule_mapping[$r['id']] = $n;
$n++;
}
foreach ($stats as $id => $s) {
if ($s['k_yes'] > $max_k_yes) { $max_k_yes = $s['k_yes']; $id_k_yes = $id; }
if ($s['k_no'] > $max_k_no) { $max_k_no = $s['k_no']; $id_k_no = $id; }
if ($s['u_yes'] > $max_u_yes) { $max_u_yes = $s['u_yes']; $id_u_yes = $id; }
if ($s['u_no'] > $max_u_no) { $max_u_no = $s['u_no']; $id_u_no = $id; }
if ($s['p_yes'] > $max_p_yes) { $max_p_yes = $s['p_yes']; $id_p_yes = $id; }
if ($s['p_no'] > $max_p_no) { $max_p_no = $s['p_no']; $id_p_no = $id; }
}
$rule_k_best = $rule_mapping[$id_k_yes] ?? '-';
$rule_k_worst = $rule_mapping[$id_k_no] ?? '-';
$rule_u_best = $rule_mapping[$id_u_yes] ?? '-';
$rule_u_worst = $rule_mapping[$id_u_no] ?? '-';
$rule_p_best = $rule_mapping[$id_p_yes] ?? '-';
$rule_p_worst = $rule_mapping[$id_p_no] ?? '-';
?>
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>รายงานการประเมิน ปี <?php echo htmlspecialchars($year); ?></title>
<!-- Favicon -->
<link rel="icon" type="image/png" href="assets/images/logo.png">
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* TH Sarabun PSK Equivalent settings */
@page { size: A4; margin: 2.5cm 2cm 2cm 2.5cm; } /* บน 2.5, ขวา 2, ล่าง 2, ซ้าย 2.5 */
body {
font-family: 'Sarabun', sans-serif;
font-size: 10pt; /* ลดขนาดเป็น 10pt ตามที่ต้องการ */
color: #000;
background: #fff;
margin: 0;
padding: 0;
line-height: 1.3;
}
.page { page-break-after: always; min-height: 297mm; position: relative; }
.page:last-child { page-break-after: avoid; }
.header-title {
text-align: center;
font-weight: bold;
margin-bottom: 25px;
font-size: 12pt;
line-height: 1.5;
}
.sub-header {
margin-bottom: 15px;
text-align: center;
font-size: 10pt;
}
/* Table Styling */
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
font-size: 10pt;
}
th, td {
border: 1px solid #000;
padding: 6px 8px;
vertical-align: middle;
}
th {
text-align: center;
font-weight: bold;
background-color: #f9f9f9;
-webkit-print-color-adjust: exact;
}
.text-center { text-align: center; }
.text-left { text-align: left; }
.section-title {
font-weight: bold;
margin-top: 25px;
margin-bottom: 15px;
font-size: 11pt;
text-decoration: underline;
}
/* Stats List Styling */
.stats-list { margin-bottom: 25px; padding-left: 10px; }
.stats-list-item { display: flex; margin-bottom: 8px; font-size: 10pt; }
.stats-list-item .col-1 { width: 70px; font-weight: bold; }
.stats-list-item .col-2 { width: 200px; }
/* Lined Box (เส้นประสำหรับเขียน) */
.lined-box {
margin-bottom: 25px;
width: 100%;
}
.lined-box .line {
border-bottom: 1px dashed #ccc;
min-height: 32px;
line-height: 32px;
outline: none;
padding-left: 5px;
font-size: 10pt;
white-space: nowrap;
overflow: hidden;
}
.lined-box .line:focus {
background-color: #fdfdfd;
border-bottom: 1px dashed #008f91;
}
/* Print Rules */
@media print {
body { margin: 0; -webkit-print-color-adjust: exact; }
.no-print { display: none !important; }
.page { min-height: auto; margin: 0; box-shadow: none; border: none; }
th { background-color: transparent; }
.lined-box .line { border-bottom: 1px dashed #aaa; } /* พิมพ์แล้วเห็นเส้นจางๆ */
}
/* Screen preview styling (shadows like a paper) */
@media screen {
body { background: #e0e5ec; padding: 20px; display: flex; flex-direction: column; align-items: center; }
.page {
background: white;
width: 210mm; /* A4 Width */
padding: 2.5cm 2cm 2cm 2.5cm;
margin-bottom: 20px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
border-radius: 2px;
box-sizing: border-box;
}
}
.btn-print {
position: fixed; top: 20px; right: 20px; padding: 12px 24px; background: linear-gradient(135deg, #008f91, #005d68);
color: #fff; text-decoration: none; border-radius: 50px; font-family: 'Sarabun', sans-serif;
font-size: 14pt; font-weight: bold; box-shadow: 0 4px 10px rgba(0,0,0,0.15); border: none; cursor: pointer;
z-index: 1000; transition: transform 0.2s;
}
.btn-print:hover { transform: translateY(-2px); }
</style>
</head>
<body>
<button onclick="window.print()" class="btn-print no-print">🖨️ พิมพ์รายงาน</button>
<!-- Page 1: ตารางสรุป -->
<div class="page">
<div class="header-title">
รายงานการประเมินระเบียบปฏิบัติด้านความมั่นคงปลอดภัยของระบบเทคโนโลยีสารสนเทศ<br>
ของโรงพยาบาลเกาะสมุย ประจำปี <?php echo htmlspecialchars($year); ?>
</div>
<table>
<thead>
<tr>
<th rowspan="2" style="width: 50%; vertical-align: middle;">ระเบียบปฏิบัติด้านความมั่นคงปลอดภัยของระบบเทคโนโลยีสารสนเทศ<br>ของโรงพยาบาลเกาะสมุย</th>
<th colspan="2">การรับรู้</th>
<th colspan="2">ความเข้าใจ</th>
<th colspan="2">การปฏิบัติ</th>
</tr>
<tr>
<th>รับรู้</th>
<th>ร้อยละ</th>
<th>เข้าใจ</th>
<th>ร้อยละ</th>
<th>ปฏิบัติ<br>ได้</th>
<th>ร้อยละ</th>
</tr>
</thead>
<tbody>
<?php
$n = 1;
foreach ($rules as $r):
$id = $r['id'];
$s = $stats[$id];
// Calculate %
$total_k = $s['k_yes'] + $s['k_no'];
$pct_k = $total_k > 0 ? number_format(($s['k_yes'] / $total_k) * 100, 2) : '0.00';
$total_u = $s['u_yes'] + $s['u_no'];
$pct_u = $total_u > 0 ? number_format(($s['u_yes'] / $total_u) * 100, 2) : '0.00';
$total_p = $s['p_yes'] + $s['p_no'];
$pct_p = $total_p > 0 ? number_format(($s['p_yes'] / $total_p) * 100, 2) : '0.00';
?>
<tr>
<td><?php echo $n . "." . htmlspecialchars($r['content']); ?></td>
<td class="text-center"><?php echo $s['k_yes']; ?></td>
<td class="text-center"><?php echo $pct_k; ?></td>
<td class="text-center"><?php echo $s['u_yes']; ?></td>
<td class="text-center"><?php echo $pct_u; ?></td>
<td class="text-center"><?php echo $s['p_yes']; ?></td>
<td class="text-center"><?php echo $pct_p; ?></td>
</tr>
<?php $n++; endforeach; ?>
</tbody>
</table>
</div>
<!-- Page 2: การรับรู้ระเบียบ -->
<div class="page">
<div class="header-title">
รายงานการประเมินความรับรู้ระเบียบปฏิบัติด้านความมั่นคงปลอดภัยของระบบเทคโนโลยีสารสนเทศ<br>
ของโรงพยาบาลเกาะสมุย ครั้งที่ ประจำปี <?php echo htmlspecialchars($year); ?>
</div>
<div class="sub-header">
จำนวนผู้ใช้งานระบบทั้งสิ้น <?php echo $total_users; ?> คน ดำเนินการประเมิน <?php echo $total_assessed; ?> คน คิดเป็นร้อยละ <?php echo $percent_assessed; ?>
</div>
<div class="section-title">การรับรู้ระเบียบ</div>
<div class="stats-list">
<?php
$n = 1;
foreach ($rules as $r):
$id = $r['id'];
$s = $stats[$id];
$total_k = $s['k_yes'] + $s['k_no'];
$pct_k = $total_k > 0 ? number_format(($s['k_yes'] / $total_k) * 100, 2) : '0.00';
?>
<div class="stats-list-item">
<div class="col-1">ข้อที่ <?php echo $n; ?></div>
<div class="col-2">รู้ <?php echo $s['k_yes']; ?> คน ไม่รู้ <?php echo $s['k_no']; ?> คน</div>
<div>การรับรู้คิดเป็นร้อยละ <?php echo $pct_k; ?></div>
</div>
<?php $n++; endforeach; ?>
</div>
<div class="section-title">สรุปผลการประเมิน</div>
<div class="lined-box">
<div class="line" contenteditable="true">ระเบียบข้อที่รับรู้มากที่สุดคือข้อที่ <?php echo $rule_k_best; ?> ข้อที่ไม่รับรู้มากที่สุดคือข้อที่ <?php echo $rule_k_worst; ?></div>
<div class="line" contenteditable="true">สาเหตุหลักอาจเกิดจากการขาดการประชาสัมพันธ์ระเบียบข้อ <?php echo $rule_k_worst; ?> อย่างทั่วถึง</div>
<div class="line" contenteditable="true">หรือพนักงานอาจยังไม่คุ้นเคยกับรายละเอียดเชิงลึกของระเบียบดังกล่าว</div>
<div class="line" contenteditable="true"></div>
</div>
<div class="section-title">เสนอแนะแนวทางแก้ไข</div>
<div class="lined-box">
<div class="line" contenteditable="true">ควรเพิ่มช่องทางการสื่อสารและประชาสัมพันธ์ระเบียบข้อ <?php echo $rule_k_worst; ?> ให้ชัดเจนยิ่งขึ้น</div>
<div class="line" contenteditable="true">ผ่านระบบอินทราเน็ต หรือการแจ้งเตือนในการประชุมประจำเดือนของแต่ละแผนก</div>
<div class="line" contenteditable="true"></div>
<div class="line" contenteditable="true"></div>
</div>
</div>
<!-- Page 3: ความเข้าใจระเบียบ -->
<div class="page">
<div class="header-title">
รายงานการประเมินความเข้าใจระเบียบปฏิบัติด้านความมั่นคงปลอดภัยของระบบเทคโนโลยีสารสนเทศ<br>
ของโรงพยาบาลเกาะสมุย ประจำปี <?php echo htmlspecialchars($year); ?>
</div>
<div class="sub-header">
จำนวนผู้ใช้งานระบบทั้งสิ้น <?php echo $total_users; ?> คน ดำเนินการประเมิน <?php echo $total_assessed; ?> คน คิดเป็นร้อยละ <?php echo $percent_assessed; ?>
</div>
<div class="section-title">ความเข้าใจระเบียบ</div>
<div class="stats-list">
<?php
$n = 1;
foreach ($rules as $r):
$id = $r['id'];
$s = $stats[$id];
$total_u = $s['u_yes'] + $s['u_no'];
$pct_u = $total_u > 0 ? number_format(($s['u_yes'] / $total_u) * 100, 2) : '0.00';
?>
<div class="stats-list-item">
<div class="col-1">ข้อที่ <?php echo $n; ?></div>
<div class="col-2" style="width: 220px;">เข้าใจ <?php echo $s['u_yes']; ?> คน ไม่เข้าใจ <?php echo $s['u_no']; ?> คน</div>
<div>ความเข้าใจคิดเป็นร้อยละ <?php echo $pct_u; ?></div>
</div>
<?php $n++; endforeach; ?>
</div>
<div class="section-title">สรุปผลการประเมิน</div>
<div class="lined-box">
<div class="line" contenteditable="true">ระเบียบข้อที่เข้าใจมากที่สุดคือข้อที่ <?php echo $rule_u_best; ?> และข้อที่ไม่เข้าใจมากที่สุดคือข้อที่ <?php echo $rule_u_worst; ?></div>
<div class="line" contenteditable="true">สาเหตุหลักอาจเกิดจากเนื้อหาของระเบียบข้อ <?php echo $rule_u_worst; ?> มีความซับซ้อน หรือต้องอาศัยการตีความ</div>
<div class="line" contenteditable="true">ทำให้ผู้ใช้งานทั่วไปเกิดความสับสนได้ง่ายในทางปฏิบัติ</div>
<div class="line" contenteditable="true"></div>
</div>
<div class="section-title">เสนอแนะแนวทางแก้ไข</div>
<div class="lined-box">
<div class="line" contenteditable="true">ควรจัดทำคู่มือหรือสื่อการสอน (Infographic) ที่เข้าใจง่ายสำหรับระเบียบข้อ <?php echo $rule_u_worst; ?></div>
<div class="line" contenteditable="true">พร้อมยกตัวอย่างการใช้งานจริง เพื่อสร้างความเข้าใจที่ถูกต้องให้แก่เจ้าหน้าที่</div>
<div class="line" contenteditable="true"></div>
<div class="line" contenteditable="true"></div>
</div>
</div>
<!-- Page 4: การปฏิบัติตามระเบียบ -->
<div class="page">
<div class="header-title">
รายงานการประเมินการปฏิบัติตามระเบียบปฏิบัติด้านความมั่นคงปลอดภัยของระบบเทคโนโลยีสารสนเทศ<br>
ของโรงพยาบาลเกาะสมุย ประจำปี <?php echo htmlspecialchars($year); ?>
</div>
<div class="sub-header">
จำนวนผู้ใช้งานระบบทั้งสิ้น <?php echo $total_users; ?> คน ดำเนินการประเมิน <?php echo $total_assessed; ?> คน คิดเป็นร้อยละ <?php echo $percent_assessed; ?>
</div>
<div class="section-title">การปฏิบัติตามระเบียบ</div>
<div class="stats-list">
<?php
$n = 1;
foreach ($rules as $r):
$id = $r['id'];
$s = $stats[$id];
$total_p = $s['p_yes'] + $s['p_no'];
$pct_p = $total_p > 0 ? number_format(($s['p_yes'] / $total_p) * 100, 2) : '0.00';
?>
<div class="stats-list-item">
<div class="col-1">ข้อที่ <?php echo $n; ?></div>
<div class="col-2" style="width: 240px;">ปฏิบัติ <?php echo $s['p_yes']; ?> คน ไม่ปฏิบัติ <?php echo $s['p_no']; ?> คน</div>
<div>การปฏิบัติตามคิดเป็นร้อยละ <?php echo $pct_p; ?></div>
</div>
<?php $n++; endforeach; ?>
</div>
<div class="section-title">สรุปผลการประเมิน</div>
<div class="lined-box">
<div class="line" contenteditable="true">ระเบียบที่เจ้าหน้าที่ปฏิบัติตามมากที่สุดคือข้อที่ <?php echo $rule_p_best; ?> ส่วนข้อที่ละเมิดมากที่สุดคือข้อที่ <?php echo $rule_p_worst; ?></div>
<div class="line" contenteditable="true">สาเหตุของการละเมิดระเบียบข้อ <?php echo $rule_p_worst; ?> อาจเป็นเพราะข้อจำกัดในการทำงานจริง</div>
<div class="line" contenteditable="true">หรือความไม่สะดวกในการปฏิบัติตามขั้นตอนที่ระบบกำหนดไว้</div>
<div class="line" contenteditable="true"></div>
</div>
<div class="section-title">เสนอแนะแนวทางแก้ไข</div>
<div class="lined-box">
<div class="line" contenteditable="true">ควรสร้างความตระหนักถึงความเสี่ยงด้านความปลอดภัยหากละเมิดระเบียบข้อ <?php echo $rule_p_worst; ?></div>
<div class="line" contenteditable="true">และอาจพิจารณาทบทวนขั้นตอนการทำงานให้ยืดหยุ่น ควบคู่กับมาตรการกำกับดูแลที่เหมาะสม</div>
<div class="line" contenteditable="true"></div>
<div class="line" contenteditable="true"></div>
</div>
</div>
<!-- No-print warning text for users -->
<div class="no-print" style="margin: 20px; padding: 15px; background: #e9ecef; border-radius: 8px;">
💡 <strong>คำแนะนำ:</strong> คุณสามารถ <u>คลิกที่ข้อความสรุปผลเพื่อแก้ไข</u> ได้ก่อนกดปุ่มพิมพ์ (เนื้อหาที่แก้ไขจะไม่ถูกบันทึกในระบบ แต่จะปรากฏในเอกสารที่พิมพ์)
</div>
</body>
</html>
@@ -0,0 +1,75 @@
CREATE TABLE `it_years` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`year_text` varchar(4) NOT NULL,
`is_active` tinyint(1) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_year` (`year_text`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `it_years` (`year_text`, `is_active`) VALUES ('2569', 1);
CREATE TABLE `it_rules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` text NOT NULL,
`is_active` tinyint(1) DEFAULT 1,
`order_no` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `it_rules` (`content`, `is_active`, `order_no`) VALUES
('ผู้ใช้งานต้องดูแลรักษา ป้องกันความเสียหายที่อาจจะเกิดขึ้นกับเครื่องคอมพิวเตอร์อุปกรณ์ต่อพ่วง เช่น ไม่วางอาหารหรือเครื่องดื่มบริเวรณเครื่องเคอมพิวเตอร์ห้ามเคลื่อนย้าย ติดตั้งเพิ่มเติมหรือกระทำการใดๆโดยไม่ได้รับอนุญาตจากผู้ดูแลระบบ', 1, 1),
('ห้ามผู้ใช้งานดาวน์โหลด อัพเดท ติดตั้งโปรแกรมใด นอกเหนือจากที่ผู้ดูแลระบบอนุญาต', 1, 2),
('ห้ามผู้ใช้งานเปิดโปรแกรมเพื่อความบันเทิงส่วนบุคคล เช่น การดูหนัง เล่นเกมส์ในระหว่างปฏิบัติงาน', 1, 3),
('หากเจ้าหน้าที่โรงพยาบาลเกาะสมุยจำเป็นต้องการส่งข้อมูลผู้ป่วยปรึกษาเพื่อการรักษาทางสื่อสังคมออนไลน์ เช่น Facebook , Line, Website หรือโปรแกรมอื่นๆ ที่เชื่อมต่อกับอินเทอร์เน็ต ต้องขออนุญาตผู้ป่วยเป็นลายลักษณ์อักษรโดยส่งตรงไปยังบุคคลที่ต้องการปรึกษาเท่านั้น เมื่อเสร็จสิ้นการปรึกษาให้ทำการลบข้อมูล ชื่อ-นามสกุล เลขประจำตัวผู้ป่วย ข้อมูลการเจ็บป่วย รูปภาพ ผลการตรวจต่างๆ รวมถึงคลิปวิดีโอการดูแลรักษาของผู้ป่วยทุกอย่างออกจากสื่อสังคมออนไลน์ทุกครั้ง', 1, 4),
('ผู้ใช้งานต้องรักษาชื่อผู้ใช้ (Username) และ รหัสผ่าน (Password) เป็นความลับ ห้ามใช้ร่วมกับผู้อื่น', 1, 5),
('เจ้าหน้าที่โรงพยาบาลเกาะสมุยต้องเก็บรักษาความลับข้อมูลผู้ป่วย ต้องไม่เปิดเผยหรือส่งต่อข้อมูล ชื่อ-นามสกุล เลขประจำตัวผู้ป่วย ข้อมูลการเจ็บป่วย รูปภาพ ผลการตรวจต่างๆ รวมถึงคลิปวิดีโอการดูแลรักษาผู้ป่วยในทุกช่องทาง', 1, 6),
('ห้ามผู้ใช้งานเข้าถึงข้อมูลผู้ป่วยที่ไม่ได้อยู่ในความรับผิดชอบ โดยไม่ขออนุญาตจากแพทย์หรือผู้รับผิดชอบโดยตรง', 1, 7),
('เจ้าหน้าที่โรงพยาบาลเกาะสมุยต้องยอมรับและถือปฏิบัติตามกฎระเบียบที่กำหนดขึ้น และปฏิบัติตาม พรบ.คอมพิวเตอร์ พ.ศ.2560 อย่างเคร่งครัดจะอ้างว่าไม่ทราบไม่ได้ กรณีฝ่าฝืนระเบียบปฏิบัติฯนี้ ครั้งที่1แจ้งหัวหน้าตักเตือน/ครั้งที่2 แจ้งหัวหน้ากลุ่มงานตักเตือน/ครั้งที่3เขียนรายงานให้ผู้บริหาร', 1, 8);
CREATE TABLE `it_slas` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`service_name` varchar(255) NOT NULL,
`standard_time` int(11) NOT NULL COMMENT 'Minutes',
`is_active` tinyint(1) DEFAULT 1,
`order_no` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `it_slas` (`service_name`, `standard_time`, `is_active`, `order_no`) VALUES
('การให้คำปรึกษา (help desk)', 5, 1, 1),
('แก้ไขปัญหาเครื่องคอมพิวเตอร์ขัดข้อง', 30, 1, 2),
('แก้ไขปัญหาเครื่องพิมพ์ขัดข้อง', 15, 1, 3),
('แก้ไขปัญหาเครื่องสำรองไฟขัดข้อง', 15, 1, 4),
('แก้ไขปัญหาอุปกรณ์ต่อพ่วงขัดข้อง', 15, 1, 5),
('แก้ไขปัญหาระบบเครือข่ายขัดข้อง', 30, 1, 6),
('แก้ไขปัญหาการใช้งานโปรแกรม HOSxP', 15, 1, 7),
('แก้ไขปัญหาการใช้งานโปรแกรมอื่นๆ', 30, 1, 8),
('ขอข้อมูลสารสนเทศ', 420, 1, 9);
DROP TABLE IF EXISTS `it_assessments`;
CREATE TABLE `it_assessments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`assess_year` varchar(4) NOT NULL,
`hr_cid` varchar(13) NOT NULL,
`fullname` varchar(255) DEFAULT NULL,
`position` varchar(255) DEFAULT NULL,
`department` varchar(255) DEFAULT NULL,
`computer_use` enum('1','2') NOT NULL COMMENT '1=ใช้, 2=ไม่ใช้',
`rules_data` json DEFAULT NULL,
`sla_data` json DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_year_cid` (`assess_year`,`hr_cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `it_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_cid` varchar(13) NOT NULL,
`admin_name` varchar(255) DEFAULT NULL,
`action_type` varchar(50) NOT NULL,
`action_detail` text DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -0,0 +1,313 @@
<?php
session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header("location: index.php");
exit;
}
require_once 'includes/db_assessment.php';
// Fetch all available years for the filter
$years_stmt = $pdo_assess->query("SELECT year_text FROM it_years ORDER BY year_text DESC");
$years = $years_stmt->fetchAll(PDO::FETCH_COLUMN);
// Fetch counts by year
$counts_stmt = $pdo_assess->query("SELECT assess_year, COUNT(id) as total_assessments FROM it_assessments GROUP BY assess_year ORDER BY assess_year DESC");
$counts_by_year = $counts_stmt->fetchAll();
// Filter by selected year
$filter_year = $_GET['year'] ?? ($years[0] ?? (date('Y')+543));
// Fetch Rules and SLAs for Headers (Assuming we show all currently active ones, or all that exist)
$rules = $pdo_assess->query("SELECT id, content FROM it_rules ORDER BY order_no ASC")->fetchAll();
$slas = $pdo_assess->query("SELECT id, service_name FROM it_slas ORDER BY order_no ASC")->fetchAll();
?>
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>สรุปผลประเมินประจำปี - Admin</title>
<!-- Favicon -->
<link rel="icon" type="image/png" href="assets/images/logo.png">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- DataTables -->
<link href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/buttons/2.4.1/css/buttons.bootstrap5.min.css" rel="stylesheet">
<style>
body { font-family: 'Sarabun', sans-serif; background-color: #f8f9fa; }
.navbar-custom { background: linear-gradient(135deg, #12344d, #1a2938); }
.card { border: none; border-radius: 15px; box-shadow: 0 5px 20px rgba(0,0,0,0.05); }
table.dataTable thead th, table.dataTable thead td { text-align: center; vertical-align: middle; background-color: #f1f5f9; color: #334155; border-bottom: 2px solid #cbd5e1; font-size: 0.85rem; white-space: nowrap; }
table.dataTable tbody td { font-size: 0.9rem; vertical-align: middle; }
.table-responsive { overflow-x: auto; }
/* ปรับขนาดไอคอนเรียงลำดับ (Sort) ของ DataTables ให้เล็กและบางลง */
table.dataTable thead > tr > th.sorting::before,
table.dataTable thead > tr > th.sorting_asc::before,
table.dataTable thead > tr > th.sorting_desc::before,
table.dataTable thead > tr > th.sorting_asc_disabled::before,
table.dataTable thead > tr > th.sorting_desc_disabled::before {
right: 1.2em !important;
content: "▲" !important;
font-size: 0.55em !important;
bottom: 1em !important;
opacity: 0.2;
}
table.dataTable thead > tr > th.sorting::after,
table.dataTable thead > tr > th.sorting_asc::after,
table.dataTable thead > tr > th.sorting_desc::after,
table.dataTable thead > tr > th.sorting_asc_disabled::after,
table.dataTable thead > tr > th.sorting_desc_disabled::after {
right: 0.5em !important;
content: "▼" !important;
font-size: 0.55em !important;
bottom: 1em !important;
opacity: 0.2;
}
/* เน้นสีไอคอนเมื่อถูกเลือก (Active Sort) */
table.dataTable thead > tr > th.sorting_asc::before,
table.dataTable thead > tr > th.sorting_desc::after {
opacity: 1 !important;
color: #008f91;
}
/* เพิ่มระยะห่างข้อความกับไอคอน */
table.dataTable thead > tr > th {
padding-right: 25px !important;
}
/* ปุ่มส่งออก Excel สำหรับตารางรายชื่อผู้ที่ยังไม่ได้ทำประเมิน */
.btn-excel-unassessed {
background: linear-gradient(135deg, #107c41, #189853);
color: #ffffff !important;
border: none;
border-radius: 8px;
font-weight: 600;
padding: 8px 16px;
box-shadow: 0 4px 6px rgba(16, 124, 65, 0.2);
transition: all 0.3s ease;
}
.btn-excel-unassessed:hover {
background: linear-gradient(135deg, #0b5e31, #107c41);
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(16, 124, 65, 0.3);
}
.btn-excel-unassessed i {
margin-right: 5px;
font-size: 1.1em;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark navbar-custom mb-4">
<div class="container-fluid px-4">
<a class="navbar-brand fw-bold d-flex align-items-center" href="admin_settings.php">
<img src="assets/images/logo.png" alt="Logo" width="40" height="40" class="d-inline-block align-text-top me-2 bg-white rounded-circle">
<span>ระบบประเมินสุขภาพดิจิทัล (Admin)</span>
</a>
<div class="d-flex">
<span class="text-white me-3 mt-1">ผู้ดูแล: <?php echo htmlspecialchars($_SESSION['fullname']); ?></span>
<a href="admin_settings.php" class="btn btn-warning btn-sm rounded-pill px-3 me-2">ตั้งค่าระบบ</a>
<a href="form.php" class="btn btn-light btn-sm rounded-pill px-3 me-2">ไปหน้าฟอร์ม</a>
<a href="actions/logout.php" class="btn btn-outline-light btn-sm rounded-pill px-3">ออกจากระบบ</a>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="card p-4">
<!-- Summary Cards for Counts -->
<?php if(!empty($counts_by_year)): ?>
<div class="row mb-4">
<?php foreach($counts_by_year as $c): ?>
<div class="col-md-3 col-sm-6 mb-2">
<div class="card bg-light border-0 shadow-sm">
<div class="card-body text-center p-3">
<h6 class="text-muted mb-1">ปีประเมิน <?php echo htmlspecialchars($c['assess_year']); ?></h6>
<h3 class="text-primary mb-0 fw-bold"><?php echo number_format($c['total_assessments']); ?> <small class="text-muted fs-6">รายการ</small></h3>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="d-flex justify-content-between align-items-center mb-4 pb-3 border-bottom">
<h4 class="m-0 fw-bold text-dark"><i class="bi bi-file-earmark-bar-graph text-primary me-2"></i>สรุปผลประเมินประจำปี</h4>
<div class="d-flex gap-3 align-items-center">
<form method="GET" class="d-flex align-items-center bg-light px-3 py-2 rounded shadow-sm border border-1">
<label class="me-2 fw-bold text-muted mb-0">เลือกปีประเมิน:</label>
<select name="year" class="form-select form-select-sm" style="width: 120px;" onchange="this.form.submit()">
<?php foreach($years as $y): ?>
<option value="<?php echo htmlspecialchars($y); ?>" <?php if($y == $filter_year) echo 'selected'; ?>>
<?php echo htmlspecialchars($y); ?>
</option>
<?php endforeach; ?>
<?php if(empty($years)): ?>
<option value="">ไม่มีข้อมูล</option>
<?php endif; ?>
</select>
</form>
<a href="print_report.php?year=<?php echo urlencode($filter_year); ?>" target="_blank" class="btn btn-outline-secondary d-flex align-items-center shadow-sm">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="bi bi-printer me-2" viewBox="0 0 16 16">
<path d="M2.5 8a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1"/>
<path d="M5 1a2 2 0 0 0-2 2v2H2a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h1v1a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-1h1a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-1V3a2 2 0 0 0-2-2zM4 3a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2H4zm1 5a2 2 0 0 0-2 2v1H2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v-1a2 2 0 0 0-2-2zm7 2v3a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1"/>
</svg>
พิมพ์รายงานสรุป
</a>
</div>
</div>
<div class="table-responsive mt-2">
<table id="summaryTable" class="table table-hover table-bordered w-100 align-middle">
<thead>
<tr>
<th>ลำดับ</th>
<th>ปีประเมิน</th>
<th>ชื่อ-สกุล</th>
<th>ตำแหน่ง</th>
<th>หน่วยงาน</th>
<th>ใช้คอมพิวเตอร์</th>
<!-- Dynamic Rules -->
<?php
$n = 1;
foreach($rules as $r):
?>
<th title="<?php echo htmlspecialchars($r['content']); ?>">R<?php echo $n; ?>_รู้</th>
<th title="<?php echo htmlspecialchars($r['content']); ?>">R<?php echo $n; ?>_เข้าใจ</th>
<th title="<?php echo htmlspecialchars($r['content']); ?>">R<?php echo $n; ?>_ปฏิบัติ</th>
<?php
$n++;
endforeach;
?>
<!-- Dynamic SLA -->
<?php
$n = 1;
foreach($slas as $s):
?>
<th title="<?php echo htmlspecialchars($s['service_name']); ?>">SLA<?php echo $n; ?>_คะแนน</th>
<th title="<?php echo htmlspecialchars($s['service_name']); ?>">SLA<?php echo $n; ?>_เสนอแนะ</th>
<?php
$n++;
endforeach;
?>
<th>วันที่ทำประเมิน</th>
<th>จัดการ</th>
</tr>
</thead>
<tbody>
<!-- Data populated via AJAX -->
</tbody>
</table>
</div>
</div>
<!-- New Section for Unassessed Users -->
<div class="card p-4 mt-4 shadow-sm border-0 mb-5">
<div class="d-flex justify-content-between align-items-center mb-4 pb-3 border-bottom">
<h4 class="m-0 fw-bold text-dark">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="bi bi-person-x text-danger me-2" viewBox="0 0 16 16" style="vertical-align: text-bottom;">
<path d="M11 5a3 3 0 1 1-6 0 3 3 0 0 1 6 0M8 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4m.256 7a4.5 4.5 0 0 1-.229-1.004H3c.001-.246.154-.986.832-1.664C4.484 10.68 5.711 10 8 10q.39 0 .74.025c.226-.341.496-.65.804-.918Q8.844 9.002 8 9c-5 0-6 3-6 4s1 1 1 1z"/>
<path d="M12.5 16a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7m-.646-4.854.646.647.646-.647a.5.5 0 0 1 .708.708l-.647.646.647.646a.5.5 0 0 1-.708.708l-.646-.647-.646.647a.5.5 0 0 1-.708-.708l.647-.646-.647-.646a.5.5 0 0 1 .708-.708"/>
</svg>
รายชื่อผู้ที่ยังไม่ได้ทำการประเมิน (ปี <?php echo htmlspecialchars($filter_year); ?>)
</h4>
<span id="unassessed-count" class="badge bg-danger fs-6">กำลังโหลด...</span>
</div>
<div class="table-responsive mt-2">
<table id="unassessedTable" class="table table-hover table-bordered w-100 align-middle">
<thead>
<tr>
<th width="10%">ลำดับ</th>
<th width="30%">ชื่อ-สกุล</th>
<th width="30%">ตำแหน่ง</th>
<th width="30%">หน่วยงาน</th>
</tr>
</thead>
<tbody>
<!-- Data populated via AJAX -->
</tbody>
</table>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.1/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.1/js/buttons.bootstrap5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.1/js/buttons.html5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).ready(function() {
var year = "<?php echo urlencode($filter_year); ?>";
var summaryTable = $('#summaryTable').DataTable({
"pageLength": 10,
"language": { "url": "//cdn.datatables.net/plug-ins/1.13.6/i18n/th.json" },
"ajax": "actions/get_summary_data.php?year=" + year,
"dom": "<'row mb-3 align-items-center'<'col-md-5'l><'col-md-7 d-flex justify-content-end align-items-center gap-3'fB>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row mt-3 align-items-center'<'col-md-5'i><'col-md-7 text-end'p>>",
"buttons": [
{ extend: 'excelHtml5', text: '<i class="bi bi-file-earmark-excel"></i> ส่งออก Excel', className: 'btn btn-success shadow-sm', exportOptions: { columns: ':not(:last-child)' } }
],
"scrollX": true
});
var unassessedTable = $('#unassessedTable').DataTable({
"pageLength": 10,
"language": { "url": "//cdn.datatables.net/plug-ins/1.13.6/i18n/th.json" },
"ajax": {
"url": "actions/get_unassessed_data.php?year=" + year,
"dataSrc": function (json) {
// Update the badge count dynamically
$('#unassessed-count').text(json.count + " คน");
return json.data;
}
},
"dom": "<'row mb-3 align-items-center'<'col-md-5'l><'col-md-7 d-flex justify-content-end align-items-center gap-3'fB>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row mt-3 align-items-center'<'col-md-5'i><'col-md-7 text-end'p>>",
"buttons": [
{ extend: 'excelHtml5', text: '<i class="bi bi-file-earmark-excel"></i> ส่งออก Excel รายชื่อผู้ที่ยังไม่ประเมิน', className: 'btn-excel-unassessed' }
],
"scrollX": false
});
// Auto refresh data every 15 seconds silently
setInterval(function(){
summaryTable.ajax.reload(null, false); // false = keep current paging
unassessedTable.ajax.reload(null, false);
}, 15000);
});
<?php if(isset($_SESSION['success_msg'])): ?>
Swal.fire({
icon: 'success',
title: 'สำเร็จ!',
text: '<?php echo $_SESSION['success_msg']; ?>',
timer: 2000,
showConfirmButton: false
});
<?php unset($_SESSION['success_msg']); ?>
<?php endif; ?>
</script>
</body>
</html>
@@ -0,0 +1,8 @@
<?php
require_once 'includes/db_hosoffice.php';
try {
$stmt = $pdo_hos->query("SELECT COUNT(*) FROM hr_person WHERE HR_STATUS_ID='01'");
echo "Count: " . $stmt->fetchColumn();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
@@ -0,0 +1,32 @@
<?php
require_once 'includes/db_hosoffice.php';
$completed_cids = [];
$sql = "SELECT a.HR_CID, e.HR_PREFIX_NAME, a.HR_FNAME, a.HR_LNAME,
p.HR_POSITION_NAME,
COALESCE(d.HR_DEPARTMENT_SUB_SUB_NAME, d2.HR_DEPARTMENT_SUB_NAME, '-') as DEPARTMENT_NAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position p ON a.HR_POSITION_ID=p.HR_POSITION_ID
LEFT OUTER JOIN hr_department_sub d2 ON a.HR_DEPARTMENT_SUB_ID=d2.HR_DEPARTMENT_SUB_ID
LEFT OUTER JOIN hr_department_sub_sub d ON a.HR_DEPARTMENT_SUB_SUB_ID=d.HR_DEPARTMENT_SUB_SUB_ID
WHERE a.HR_STATUS_ID = '01' ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->query($sql);
$unassessed_users = $stmt_un->fetchAll(PDO::FETCH_ASSOC);
$data = [];
$no = 1;
foreach($unassessed_users as $u) {
$fullname = trim(($u['HR_PREFIX_NAME'] ?? '') . $u['HR_FNAME'] . ' ' . $u['HR_LNAME']);
$data[] = [
'<div class="text-center">'.$no++.'</div>',
htmlspecialchars($fullname),
htmlspecialchars($u['HR_POSITION_NAME'] ?? '-'),
htmlspecialchars($u['DEPARTMENT_NAME'] ?? '-')
];
}
$json = json_encode(["data" => $data, "count" => count($data)]);
if ($json === false) {
echo "JSON Encode Error: " . json_last_error_msg() . "\n";
} else {
echo "JSON OK, length: " . strlen($json) . "\n";
}
@@ -0,0 +1,23 @@
<?php
require_once 'includes/db_hosoffice.php';
$completed_cids = ['1800800154968', '1841600059334'];
$sql = "SELECT a.HR_CID, e.HR_PREFIX_NAME, a.HR_FNAME, a.HR_LNAME,
p.HR_POSITION_NAME,
COALESCE(d.HR_DEPARTMENT_SUB_SUB_NAME, d2.HR_DEPARTMENT_SUB_NAME, '-') as DEPARTMENT_NAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position p ON a.HR_POSITION_ID=p.HR_POSITION_ID
LEFT OUTER JOIN hr_department_sub d2 ON a.HR_DEPARTMENT_SUB_ID=d2.HR_DEPARTMENT_SUB_ID
LEFT OUTER JOIN hr_department_sub_sub d ON a.HR_DEPARTMENT_SUB_SUB_ID=d.HR_DEPARTMENT_SUB_SUB_ID
WHERE a.HR_STATUS_ID = '01'";
$in_marks = str_repeat('?,', count($completed_cids) - 1) . '?';
$sql .= " AND a.HR_CID NOT IN ($in_marks)";
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
try {
$stmt_un = $pdo_hos->prepare($sql);
$stmt_un->execute($completed_cids);
$res = $stmt_un->fetchAll(PDO::FETCH_ASSOC);
echo "Count: " . count($res) . "\n";
} catch(Exception $e) {
echo "ERROR: " . $e->getMessage() . "\n";
}
@@ -0,0 +1,57 @@
<?php
//session_start();
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true || !isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
echo json_encode(["data" => [], "count" => 0]);
exit;
}
require_once '../includes/db_assessment.php';
require_once '../includes/db_hosoffice.php';
$filter_year = $_GET['year'] ?? (date('Y')+543);
$assessments = [];
try {
$stmt = $pdo_assess->prepare("SELECT hr_cid FROM it_assessments WHERE assess_year = :year");
$stmt->execute(['year' => $filter_year]);
$completed_cids = $stmt->fetchAll(PDO::FETCH_COLUMN);
} catch (Exception $e) {
$completed_cids = [];
}
$data = [];
try {
$sql = "SELECT a.HR_CID, e.HR_PREFIX_NAME, a.HR_FNAME, a.HR_LNAME,
p.HR_POSITION_NAME,
COALESCE(d.HR_DEPARTMENT_SUB_SUB_NAME, d2.HR_DEPARTMENT_SUB_NAME, '-') as DEPARTMENT_NAME
FROM hr_person a
LEFT OUTER JOIN hr_prefix e ON a.HR_PREFIX_ID=e.HR_PREFIX_ID
LEFT OUTER JOIN hr_position p ON a.HR_POSITION_ID=p.HR_POSITION_ID
LEFT OUTER JOIN hr_department_sub d2 ON a.HR_DEPARTMENT_SUB_ID=d2.HR_DEPARTMENT_SUB_ID
LEFT OUTER JOIN hr_department_sub_sub d ON a.HR_DEPARTMENT_SUB_SUB_ID=d.HR_DEPARTMENT_SUB_SUB_ID
WHERE a.HR_STATUS_ID = '01'";
if (count($completed_cids) > 0) {
$in_marks = str_repeat('?,', count($completed_cids) - 1) . '?';
$sql .= " AND a.HR_CID NOT IN ($in_marks)";
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->prepare($sql);
$stmt_un->execute($completed_cids);
} else {
$sql .= " ORDER BY DEPARTMENT_NAME, a.HR_FNAME";
$stmt_un = $pdo_hos->query($sql);
}
$unassessed_users = $stmt_un->fetchAll(PDO::FETCH_ASSOC);
$no = 1;
foreach($unassessed_users as $u) {
$fullname = trim(($u['HR_PREFIX_NAME'] ?? '') . $u['HR_FNAME'] . ' ' . $u['HR_LNAME']);
$data[] = [
'<div class="text-center">'.$no++.'</div>',
htmlspecialchars($fullname),
htmlspecialchars($u['HR_POSITION_NAME'] ?? '-'),
htmlspecialchars($u['DEPARTMENT_NAME'] ?? '-')
];
}
} catch (Exception $e) { }
echo json_encode(["data" => $data, "count" => count($data)]);