/** * ระบบนัดหมายออนไลน์ (Appointment Booking System Backend) * ผู้พัฒนา: Antigravity AI */ /** * ฟังก์ชัน doGet สำหรับแสดงผลหน้าเว็บ HTML Form (กรณีใช้งานผ่าน Web App URL ของ Apps Script) */ function doGet(e) { return HtmlService.createHtmlOutputFromFile('index') .setTitle('ระบบนัดหมายออนไลน์ - Booking System') .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL) .addMetaTag('viewport', 'width=device-width, initial-scale=1'); } /** * ฟังก์ชัน doPost สำหรับรองรับการส่งข้อมูลแบบ API จากภายนอก (เช่น หน้าเว็บ HTML ที่รันจากเครื่อง Local) */ function doPost(e) { var response = { status: "fail", message: "คำขอไม่ถูกต้อง" }; try { var params = {}; // ตรวจสอบวิธีการส่งข้อมูล (แบบ Form Parameters หรือ JSON Body) if (e.postData && e.postData.contents) { try { params = JSON.parse(e.postData.contents); } catch (parseErr) { // หากไม่ใช่ JSON ให้พยายาม parse แบบ Form urlencoded params = e.parameter; } } else { params = e.parameter; } var name = params.name; var topic = params.topic; var date = params.date; var time = params.time; if (!name || !topic || !date || !time) { return ContentService.createTextOutput(JSON.stringify({ status: "fail", message: "กรุณากรอกข้อมูลให้ครบถ้วน" })).setMimeType(ContentService.MimeType.JSON); } var result = bookAppointment(name, topic, date, time); response = result; } catch (err) { response = { status: "error", message: "เกิดข้อผิดพลาดทางระบบ: " + err.toString() }; } // รองรับ CORS สำหรับการเรียกใช้งานจากภายนอก return ContentService.createTextOutput(JSON.stringify(response)) .setMimeType(ContentService.MimeType.JSON); } /** * ฟังก์ชันจองการนัดหมาย * ตรวจสอบความถูกต้อง เช็คเวลาซ้ำ บันทึกลง Google Sheet และบันทึกไปยัง Google Calendar * * @param {string} name ชื่อผู้จอง * @param {string} topic หัวข้อการนัดหมาย * @param {string} dateStr วันที่ที่เลือก (YYYY-MM-DD) * @param {string} timeStr เวลาที่เลือก (HH:MM) * @return {object} ผลการทำงาน { status: "success"|"fail"|"error", message: string } */ function bookAppointment(name, topic, dateStr, timeStr) { try { // 1. ตรวจสอบความถูกต้องและแปลงประเภทข้อมูล if (!name || !topic || !dateStr || !timeStr) { return { status: "fail", message: "ข้อมูลไม่ครบถ้วน" }; } // สร้าง Date object สำหรับเวลาเริ่มต้น var startDateTime = new Date(dateStr + 'T' + timeStr + ':00'); if (isNaN(startDateTime.getTime())) { return { status: "fail", message: "รูปแบบวันที่หรือเวลาไม่ถูกต้อง" }; } // กำหนดเวลาสิ้นสุดโดยนับไปอีก 30 นาที var endDateTime = new Date(startDateTime.getTime() + 30 * 60 * 1000); // ตรวจสอบไม่ให้จองเวลาย้อนหลัง var now = new Date(); if (startDateTime < now) { return { status: "fail", message: "ไม่สามารถจองเวลานัดหมายในอดีตได้" }; } // 2. ตรวจสอบเวลาซ้ำ (Overlap Checking) ใน Google Sheet var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // สร้างหัวตารางกรณีเปิดใช้งานครั้งแรกและชีตว่างเปล่า if (sheet.getLastRow() === 0) { sheet.appendRow(["วันเวลาที่ทำรายการ", "ชื่อผู้นัดหมาย", "หัวข้อการนัดหมาย", "เวลาเริ่มต้น", "เวลาสิ้นสุด", "Google Calendar Event ID"]); // ตกแต่งหัวตารางเล็กน้อย sheet.getRange(1, 1, 1, 6).setFontWeight("bold").setBackground("#6366f1").setFontColor("#ffffff"); } var data = sheet.getDataRange().getValues(); var hasOverlap = false; // วนลูปตรวจสอบทุกแถว (เริ่มที่แถว index 1 ข้าม Header) for (var i = 1; i < data.length; i++) { var row = data[i]; var exStart = new Date(row[3]); // คอลัมน์ D: เวลาเริ่มต้น var exEnd = new Date(row[4]); // คอลัมน์ E: เวลาสิ้นสุด if (!isNaN(exStart.getTime()) && !isNaN(exEnd.getTime())) { // ตรวจสอบการทับซ้อนของช่วงเวลา (Interval Overlap) // สูตรการทับซ้อน: (StartA < EndB) && (StartB < EndA) if (startDateTime < exEnd && exStart < endDateTime) { hasOverlap = true; break; } } } if (hasOverlap) { return { status: "fail", message: "ช่วงเวลาดังกล่าว (" + formatDateTimeString(startDateTime) + " - " + formatTimeString(endDateTime) + ") มีผู้จองไว้แล้ว กรุณาเลือกช่วงเวลาอื่น" }; } // 3. สร้างกิจกรรมบน Google Calendar var calendar = CalendarApp.getDefaultCalendar(); if (!calendar) { return { status: "error", message: "ไม่พบ Google Calendar เริ่มต้นในบัญชีนี้" }; } var eventTitle = "นัดหมาย: " + topic; var eventDescription = "ผู้จอง: " + name + "\nรายละเอียด: " + topic + "\nสร้างผ่านระบบจองนัดหมายอัตโนมัติ"; var event = calendar.createEvent(eventTitle, startDateTime, endDateTime, { description: eventDescription, location: "Online (Google Meet)" }); var eventId = event.getId(); // 4. บันทึกข้อมูลลง Google Sheet sheet.appendRow([ new Date(), // วันเวลาที่ทำรายการ name, // ชื่อผู้จอง topic, // หัวข้อการนัดหมาย startDateTime, // เวลาเริ่มต้น endDateTime, // เวลาสิ้นสุด eventId // Calendar Event ID ]); return { status: "success", message: "จองนัดหมายสำเร็จ! บันทึกในคิวและปฏิทินเรียบร้อยแล้ว (" + formatDateTimeString(startDateTime) + " - " + formatTimeString(endDateTime) + ")" }; } catch (err) { return { status: "error", message: "เกิดข้อผิดพลาดในการตรวจสอบหรือบันทึกข้อมูล: " + err.toString() }; } } /** * ฟังก์ชันช่วยแปลงรูปแบบ วันที่-เวลา ให้แสดงผลสวยงาม (ภาษาไทย) */ function formatDateTimeString(date) { var options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: false }; return date.toLocaleString('th-TH', options) + ' น.'; } /** * ฟังก์ชันช่วยแปลงรูปแบบ เวลา ให้แสดงผลสวยงาม (ภาษาไทย) */ function formatTimeString(date) { var options = { hour: '2-digit', minute: '2-digit', hour12: false }; return date.toLocaleString('th-TH', options) + ' น.'; }