// Google Apps Script สำหรับบันทึกเวลาเข้า-ออกงานและส่งอีเมล
// ตั้งค่าเริ่มต้น
const CONFIG = {
spreadsheetId: 'YOUR_SPREADSHEET_ID', // ID ของ Google Sheets สำหรับเก็บข้อมูล
sheetName: 'AttendanceRecords', // ชื่อชีตสำหรับเก็บข้อมูล
folderId: 'YOUR_FOLDER_ID', // ID ของ Google Drive Folder สำหรับเก็บรูปภาพ
adminEmail: 'admin@company.com', // อีเมลแอดมิน
emailSubject: 'ยืนยันการบันทึกเวลาเข้า-ออกงาน',
dateFormat: 'dd/MM/yyyy',
timeFormat: 'HH:mm'
};
// ฟังก์ชันหลักสำหรับรับข้อมูลจากฟอร์ม
function doPost(e) {
try {
// รับข้อมูลจากฟอร์ม
const formData = e.parameter;
const fileBlob = e.postData.contents ? Utilities.newBlob(JSON.parse(e.postData.contents).file) : null;
// ตรวจสอบข้อมูลที่จำเป็น
if (!formData.employeeName || !formData.employeeEmail || !formData.workDate) {
return createResponse(false, 'ข้อมูลไม่ครบถ้วน');
}
// อัพโหลดไฟล์รูปภาพ (ถ้ามี)
let imageUrl = '';
if (fileBlob) {
imageUrl = uploadImageToDrive(fileBlob, formData.employeeId, formData.workDate);
}
// บันทึกข้อมูลลง Google Sheets
const recordId = saveToSpreadsheet(formData, imageUrl);
// ส่งอีเมลยืนยัน
sendConfirmationEmail(formData, imageUrl, recordId);
// ส่งอีเมลแจ้งเตือนไปยังแอดมิน
sendAdminNotification(formData, imageUrl, recordId);
return createResponse(true, 'บันทึกข้อมูลสำเร็จและส่งอีเมลแล้ว', { recordId: recordId });
} catch (error) {
console.error('Error in doPost:', error);
return createResponse(false, 'เกิดข้อผิดพลาด: ' + error.toString());
}
}
// ฟังก์ชันสำหรับอัพโหลดรูปภาพไปยัง Google Drive
function uploadImageToDrive(fileBlob, employeeId, workDate) {
try {
// สร้างโฟลเดอร์ถ้ายังไม่มี
const folder = DriveApp.getFolderById(CONFIG.folderId);
// สร้างชื่อไฟล์
const fileName = `fingerprint_${employeeId}_${workDate}_${new Date().getTime()}.jpg`;
// อัพโหลดไฟล์
const file = folder.createFile(fileBlob);
file.setName(fileName);
// ตั้งค่าให้ทุกคนที่ลิงก์สามารถดูได้
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
return file.getUrl();
} catch (error) {
console.error('Error uploading image:', error);
throw new Error('ไม่สามารถอัพโหลดรูปภาพได้: ' + error.toString());
}
}
// ฟังก์ชันสำหรับบันทึกข้อมูลลง Google Sheets
function saveToSpreadsheet(formData, imageUrl) {
try {
// เปิด Spreadsheet
const ss = SpreadsheetApp.openById(CONFIG.spreadsheetId);
let sheet = ss.getSheetByName(CONFIG.sheetName);
// ถ้ายังไม่มีชีต ให้สร้างใหม่
if (!sheet) {
sheet = ss.insertSheet(CONFIG.sheetName);
// สร้างหัวคอลัมน์
const headers = [
'รหัสบันทึก', 'วันที่บันทึก', 'เวลาบันทึก', 'ชื่อ-นามสกุล', 'รหัสพนักงาน',
'อีเมล', 'วันที่ทำงาน', 'เวลาเข้า', 'เวลาออก', 'หมายเหตุ',
'URL รูปภาพ', 'สถานะอีเมล', 'วันที่ส่งอีเมล'
];
sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
sheet.getRange(1, 1, 1, headers.length).setFontWeight('bold');
}
// สร้างรหัสบันทึก
const recordId = 'ATT' + new Date().getTime();
const timestamp = new Date();
// เตรียมข้อมูลสำหรับบันทึก
const rowData = [
recordId,
Utilities.formatDate(timestamp, 'Asia/Bangkok', CONFIG.dateFormat),
Utilities.formatDate(timestamp, 'Asia/Bangkok', CONFIG.timeFormat),
formData.employeeName,
formData.employeeId,
formData.employeeEmail,
formData.workDate,
formData.clockIn,
formData.clockOut,
formData.remarks || '',
imageUrl,
'รอส่ง',
''
];
// บันทึกลงแถวสุดท้าย
const lastRow = sheet.getLastRow() + 1;
sheet.getRange(lastRow, 1, 1, rowData.length).setValues([rowData]);
return recordId;
} catch (error) {
console.error('Error saving to spreadsheet:', error);
throw new Error('ไม่สามารถบันทึกข้อมูลได้: ' + error.toString());
}
}
// ฟังก์ชันสำหรับส่งอีเมลยืนยันไปยังพนักงาน
function sendConfirmationEmail(formData, imageUrl, recordId) {
try {
// สร้างเนื้อหาอีเมล
const emailBody = `
<html>
<body style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #333;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 10px;">
<h2 style="color: #1a73e8; border-bottom: 2px solid #1a73e8; padding-bottom: 10px;">
ยืนยันการบันทึกเวลาเข้า-ออกงาน
</h2>
<p>เรียนคุณ <strong>${formData.employeeName}</strong></p>
<p>ระบบได้รับข้อมูลการบันทึกเวลาทำงานของคุณเรียบร้อยแล้ว</p>
<div style="background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin: 15px 0;">
<h3 style="color: #5f6368; margin-top: 0;">รายละเอียดการบันทึกเวลา</h3>
<table style="width: 100%;">
<tr>
<td style="width: 40%; padding: 5px 0;"><strong>รหัสบันทึก:</strong></td>
<td style="padding: 5px 0;">${recordId}</td>
</tr>
<tr>
<td style="padding: 5px 0;"><strong>วันที่ทำงาน:</strong></td>
<td style="padding: 5px 0;">${formatDateThai(formData.workDate)}</td>
</tr>
<tr>
<td style="padding: 5px 0;"><strong>เวลาเข้า:</strong></td>
<td style="padding: 5px 0;">${formData.clockIn}</td>
</tr>
<tr>
<td style="padding: 5px 0;"><strong>เวลาออก:</strong></td>
<td style="padding: 5px 0;">${formData.clockOut}</td>
</tr>
<tr>
<td style="padding: 5px 0;"><strong>หมายเหตุ:</strong></td>
<td style="padding: 5px 0;">${formData.remarks || '-'}</td>
</tr>
</table>
</div>
${imageUrl ? `<p><strong>ลิงก์รูปภาพการสแกนนิ้ว:</strong> <a href="${imageUrl}" target="_blank">${imageUrl}</a></p>` : ''}
<p>ข้อมูลนี้จะถูกบันทึกไว้ในระบบจนถึงวันที่ 31 มีนาคม 2569</p>
<div style="background-color: #e8f0fe; padding: 15px; border-radius: 5px; margin-top: 20px;">
<p style="margin: 0; font-size: 14px;">
<strong>หมายเหตุ:</strong> หากพบข้อผิดพลาดในข้อมูล กรุณาติดต่อฝ่ายทรัพยากรบุคคลภายใน 3 วันทำการ
</p>
</div>
<hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">
<p style="font-size: 12px; color: #666;">
อีเมลนี้ถูกส่งอัตโนมัติจากระบบบันทึกเวลาเข้า-ออกงาน<br>
กรุณาอย่าตอบกลับอีเมลนี้
</p>
</div>
</body>
</html>
`;
// ส่งอีเมล
MailApp.sendEmail({
to: formData.employeeEmail,
subject: `${CONFIG.emailSubject} (รหัส: ${recordId})`,
htmlBody: emailBody,
name: 'ระบบบันทึกเวลาทำงาน'
});
// อัพเดทสถานะใน Google Sheets
updateEmailStatus(recordId, 'ส่งแล้ว');
console.log('ส่งอีเมลยืนยันไปยัง:', formData.employeeEmail);
} catch (error) {
console.error('Error sending confirmation email:', error);
updateEmailStatus(recordId, 'ส่งไม่สำเร็จ');
throw new Error('ไม่สามารถส่งอีเมลได้: ' + error.toString());
}
}
// ฟังก์ชันสำหรับส่งอีเมลแจ้งเตือนไปยังแอดมิน
function sendAdminNotification(formData, imageUrl, recordId) {
try {
const adminEmailBody = `
<html>
<body>
<h3>แจ้งเตือน: มีการบันทึกเวลาเข้า-ออกงานใหม่</h3>
<p><strong>รหัสบันทึก:</strong> ${recordId}</p>
<p><strong>พนักงาน:</strong> ${formData.employeeName} (${formData.employeeId})</p>
<p><strong>วันที่ทำงาน:</strong> ${formatDateThai(formData.workDate)}</p>
<p><strong>เวลา:</strong> ${formData.clockIn} - ${formData.clockOut}</p>
<p><strong>อีเมลพนักงาน:</strong> ${formData.employeeEmail}</p>
<p><strong>หมายเหตุ:</strong> ${formData.remarks || '-'}</p>
${imageUrl ? `<p><strong>รูปภาพ:</strong> <a href="${imageUrl}" target="_blank">ดูรูปภาพ</a></p>` : ''}
<p>ข้อมูลนี้ถูกบันทึกเมื่อ: ${Utilities.formatDate(new Date(), 'Asia/Bangkok', 'dd/MM/yyyy HH:mm')}</p>
</body>
</html>
`;
MailApp.sendEmail({
to: CONFIG.adminEmail,
subject: `แจ้งเตือน: บันทึกเวลาใหม่จาก ${formData.employeeName}`,
htmlBody: adminEmailBody
});
} catch (error) {
console.error('Error sending admin notification:', error);
}
}
// ฟังก์ชันสำหรับอัพเดทสถานะอีเมลใน Google Sheets
function updateEmailStatus(recordId, status) {
try {
const ss = SpreadsheetApp.openById(CONFIG.spreadsheetId);
const sheet = ss.getSheetByName(CONFIG.sheetName);
if (!sheet) return;
// ค้นหารหัสบันทึก
const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) {
if (data[i][0] === recordId) {
// อัพเดทสถานะอีเมลและวันที่ส่ง
sheet.getRange(i + 1, 12).setValue(status);
sheet.getRange(i + 1, 13).setValue(Utilities.formatDate(new Date(), 'Asia/Bangkok', 'dd/MM/yyyy HH:mm'));
break;
}
}
} catch (error) {
console.error('Error updating email status:', error);
}
}
// ฟังก์ชันสำหรับแปลงวันที่เป็นรูปแบบไทย
function formatDateThai(dateString) {
const date = new Date(dateString);
const thaiMonths = [
'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน',
'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'
];
const day = date.getDate();
const month = thaiMonths[date.getMonth()];
const year = date.getFullYear() + 543; // แปลงเป็นพ.ศ.
return `${day} ${month} ${year}`;
}
// ฟังก์ชันสำหรับสร้าง response
function createResponse(success, message, data = {}) {
const response = {
success: success,
message: message,
...data
};
return ContentService
.createTextOutput(JSON.stringify(response))
.setMimeType(ContentService.MimeType.JSON);
}
// ฟังก์ชันสำหรับตั้งค่าเริ่มต้น (เรียกใช้งานครั้งแรก)
function setup() {
// สร้าง Spreadsheet ใหม่ถ้ายังไม่มี
if (!CONFIG.spreadsheetId || CONFIG.spreadsheetId === 'YOUR_SPREADSHEET_ID') {
const ss = SpreadsheetApp.create('บันทึกเวลาเข้า-ออกงาน');
const sheet = ss.getSheetByName('Sheet1');
sheet.setName(CONFIG.sheetName);
console.log('สร้าง Spreadsheet ใหม่แล้ว ID:', ss.getId());
console.log('URL:', ss.getUrl());
}
// สร้างโฟลเดอร์ใน Google Drive ถ้ายังไม่มี
if (!CONFIG.folderId || CONFIG.folderId === 'YOUR_FOLDER_ID') {
const folder = DriveApp.createFolder('รูปภาพสแกนนิ้วมือ');
console.log('สร้างโฟลเดอร์ใหม่แล้ว ID:', folder.getId());
}
console.log('ตั้งค่าระบบเรียบร้อยแล้ว');
}
// ฟังก์ชันสำหรับสร้าง Web App
function doGet() {
const html = HtmlService.createHtmlOutputFromFile('index')
.setTitle('แบบฟอร์มบันทึกเวลาเข้า-ออกงาน')
.setFaviconUrl('https://[Log in to view URL]');
return html;
}
// ฟังก์ชันสำหรับทดสอบระบบ
function testSystem() {
const testData = {
employeeName: 'ทดสอบระบบ',
employeeId: 'TEST001',
employeeEmail: Session.getActiveUser().getEmail(),
workDate: '2029-01-07',
clockIn: '08:30',
clockOut: '17:00',
remarks: 'ทดสอบระบบ'
};
const recordId = saveToSpreadsheet(testData, 'https://[Log in to view URL]');
console.log('บันทึกข้อมูลทดสอบสำเร็จ รหัส:', recordId);
sendConfirmationEmail(testData, 'https://[Log in to view URL]', recordId);
console.log('ส่งอีเมลทดสอบแล้ว');
}
To embed this project on your website, copy the following code and paste it into your website's HTML: