var requestData = JSON.parse(e.postData.contents);
var action = requestData.action;
var payload = requestData.payload;
function doPost(e) {
var lock = LockService.getScriptLock(https://script.google.com/macros/s/AKfycbx7Ui76UkYkpcQZlbRsPq083C1uv5RBOhlylzxN1d1f9_uGa1QT_tpCVdyiKgZCEzSl/exec);
plase {
lock.waitLock(10000);/**
* TPK DESA PUSUK LESTARI - BACKEND APPS SCRIPT
* Web App Endpoint & Database Controller
*/
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('index')
.setTitle('TPK DESA PUSUK LESTARI - Sistem Informasi Pendampingan Keluarga')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.addMetaTag('viewport', 'width=device-width, initial-scale=1.0');
}
var response = {};
switch(action) {
case 'setupDatabase':
response = setupDatabase();
break;
case 'login':
response = processLogin(payload);
break;
case 'getData':
response = fetchAllData();
break;
case 'saveSasaran':
response = saveSasaranData(payload);
break;
case 'addKunjungan':
response = recordKunjungan(payload);
break;
case 'backupDatabase':
response = createSpreadsheetBackup();
break;
default:
response = { status: 'error', message: 'Aksi tidak dikenali' };
}
return ContentService.createTextOutput(JSON.stringify(response))
.setMimeType(ContentService.MimeType.JSON);
} catch (err) {
return ContentService.createTextOutput(JSON.stringify({ status: 'error', message: err.message }))
.setMimeType(ContentService.MimeType.JSON);
} finally {
lock.releaseLock();
}
}
/**
* Inisialisasi Otomatis Google Sheets Database
*/
function setupDatabase() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetsToCreate = [
{ name: 'CONFIG', headers: ['KEY', 'VALUE'] },
{ name: 'USERS', headers: ['ID', 'USERNAME', 'PASSWORD', 'ROLE', 'NAMA'] },
{ name: 'MASTER_DUSUN', headers: ['ID', 'NAMA_DUSUN'] },
{ name: 'MASTER_TPK', headers: ['ID', 'NAMA_TPK', 'KETUA'] },
{ name: 'BADUTA', headers: ['ID', 'NIK', 'NAMA', 'JK', 'TGL_LAHIR', 'WALI', 'HP', 'DUSUN', 'BB', 'TB', 'GIZI', 'KEMBANG', 'STATUS', 'TPK', 'KET'] },
{ name: 'BUMIL', headers: ['ID', 'NIK', 'NAMA', 'TGL_LAHIR', 'SUAMI', 'HP', 'DUSUN', 'USIA_HAMIL', 'HPL', 'LILA', 'HB', 'KEK', 'ANEMIA', 'RISIKO', 'STATUS', 'TPK', 'KET'] },
{ name: 'NIPAS', headers: ['ID', 'NIK', 'NAMA', 'TGL_LAHIR', 'TGL_SALIN', 'SUAMI', 'HP', 'DUSUN', 'ASI', 'KB', 'BAHAYA', 'STATUS', 'TPK', 'KET'] },
{ name: 'CATIN', headers: ['ID', 'NIK', 'NAMA', 'JK', 'TGL_LAHIR', 'PASANGAN', 'HP', 'DUSUN', 'TGL_NIKAH', 'HB', 'LILA', 'KESIAPAN', 'STATUS', 'TPK', 'KET'] },
{ name: 'KUNJUNGAN', headers: ['ID', 'TARGET_ID', 'TGL', 'KUNJUNGAN_KE', 'HASIL', 'TINDAK_LANJUT', 'TPK'] },
{ name: 'AUDIT_LOG', headers: ['TIMESTAMP', 'USER', 'AKSI', 'TARGET', 'ID_DATA', 'KETERANGAN'] }
];
sheetsToCreate.forEach(function(item) {
var sheet = ss.getSheetByName(item.name);
if (!sheet) {
sheet = ss.insertSheet(item.name);
sheet.getRange(1, 1, 1, item.headers.length).setValues([item.headers])
.setFontWeight('bold')
.setBackground('#1F4E78')
.setFontColor('#FFFFFF');
sheet.setFrozenRows(1);
}
});
// Default User Admin
var userSheet = ss.getSheetByName('USERS');
if (userSheet.getLastRow() === 1) {
userSheet.appendRow(['USR-001', 'admin', '123', 'ADMIN', 'Administrator TPK']);
}
return { status: 'success', message: 'Database TPK Desa Pusuk Lestari Berhasil Disiapkan!' };
}
function processLogin(payload) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('USERS');
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
var username = String(data[i][1]);
var password = String(data[i][2]);
if (username === payload.username && password === payload.password) {
logAudit(payload.username, 'LOGIN', 'USERS', data[i][0], 'Login sukses');
return {
status: 'success',
user: { username: data[i][1], role: data[i][3], nama: data[i][4] }
};
}
}
return { status: 'error', message: 'Username atau Password salah!' };
}
function fetchAllData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
return {
status: 'success',
baduta: getSheetDataValues(ss, 'BADUTA'),
bumil: getSheetDataValues(ss, 'BUMIL'),
nipas: getSheetDataValues(ss, 'NIPAS'),
catin: getSheetDataValues(ss, 'CATIN'),
kunjungan: getSheetDataValues(ss, 'KUNJUNGAN')
};
}
function getSheetDataValues(ss, sheetName) {
var sheet = ss.getSheetByName(sheetName);
if (!sheet) return [];
var rows = sheet.getDataRange().getValues();
if (rows.length <= 1) return [];
var headers = rows[0];
var results = [];
for (var i = 1; i < rows.length; i++) {
var row = rows[i];
var obj = {};
for (var j = 0; j < headers.length; j++) {
obj[headers[j].toLowerCase()] = row[j];
}
results.push(obj);
}
return results;
}
function logAudit(user, aksi, target, idData, ket) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('AUDIT_LOG');
if (sheet) {
var now = Utilities.formatDate(new Date(), 'Asia/Makassar', 'dd/MM/yyyy HH:mm:ss');
sheet.appendRow([now, user, aksi, target, idData, ket]);
}
}
function createSpreadsheetBackup() {
var file = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId());
var folderName = "TPK_Pusuk_Lestari_Backups";
var folders = DriveApp.getFoldersByName(folderName);
var targetFolder;
if (folders.hasNext()) {
targetFolder = folders.next();
} else {
targetFolder = DriveApp.createFolder(folderName);
}
var backupName = "BACKUP_TPK_PUSUK_LESTARI_" + Utilities.formatDate(new Date(), 'Asia/Makassar', 'yyyyMMdd_HHmmss');
file.makeCopy(backupName, targetFolder);
return { status: 'success', message: 'Backup database berhasil disimpan di Google Drive folder ' + folderName };
}
/* PLACEHOLDER: FUNGSI CRUD BARU */