Files
2026-06-11 02:38:02 +00:00

166 lines
7.2 KiB
JavaScript

const db = require('../config/database');
// Mengambil data status bantuan warga beserta lokasi pangkalan ibadah
const cek_status_nik = (req, res) => {
const nik_warga = req.params.nik;
// Praktik keamanan: Memastikan input NIK murni berupa 16 digit angka untuk mencegah manipulasi query
if (!/^\d{16}$/.test(nik_warga)) {
return res.status(400).json({ error: 'Format NIK tidak valid.' });
}
// Baris kompleks: Operasi LEFT JOIN menghubungkan tabel MUSTAHIK dengan RUMAH_IBADAH berdasarkan Foreign Key id_rumah_ibadah untuk menarik koordinat pangkalan distribusi secara simultan dalam satu siklus I/O.
const kueri_pencarian = `
SELECT m.nik, m.nama_kk, m.status_validasi, m.lat, m.lng, m.agama,
r.nama_tempat AS rumah_ibadah_nama,
r.lat AS rumah_ibadah_lat,
r.lng AS rumah_ibadah_lng
FROM MUSTAHIK m
LEFT JOIN RUMAH_IBADAH r ON m.id_rumah_ibadah = r.id
WHERE m.nik = ?
`;
db.get(kueri_pencarian, [nik_warga], (error_sistem, baris_data) => {
if (error_sistem) {
console.error('Sistem gagal membaca tabel gabungan:', error_sistem.message);
return res.status(500).json({ error: 'Terjadi kegagalan server internal.' });
}
if (!baris_data) {
return res.status(404).json({ error: 'Data tidak ditemukan.' });
}
res.status(200).json(baris_data);
});
};
// Mengontrol alur penerimaan data survei lapangan beserta penentuan pangkalan bantuan
const submit_survey_data = async (req, res) => {
try {
const {
nik,
nama_kk,
no_kk,
jumlah_tanggungan,
lat,
lng,
agama,
indikator_bps
} = req.body;
// Praktik keamanan: Validasi input dasar untuk mencegah insersi data kosong (null pointer exception)
if (!nik || !nama_kk || !lat || !lng || !agama || !indikator_bps) {
return res.status(400).json({ error: 'Payload data survei tidak lengkap dari klien.' });
}
// Memulai transaksi basis data untuk menjaga integritas penyimpanan parsial
db.serialize(() => {
db.run('BEGIN TRANSACTION');
// Baris kompleks: Memanfaatkan db.serialize untuk memastikan kueri SELECT pencarian pangkalan ibadah selesai dieksekusi sebelum beralih ke perintah INSERT transaksional berikutnya guna menghindari balapan data (race condition).
const kueri_cari_pangkalan = `SELECT id FROM RUMAH_IBADAH WHERE agama = ? LIMIT 1`;
db.get(kueri_cari_pangkalan, [agama], (error_cari, baris_pangkalan) => {
if (error_cari) {
db.run('ROLLBACK');
console.error('Gagal mencocokkan rumah ibadah:', error_cari.message);
return res.status(500).json({ error: 'Gagal memproses penentuan lokasi bantuan.' });
}
const id_pangkalan_terpilih = baris_pangkalan ? baris_pangkalan.id : null;
// 1. Menyimpan data identitas dan relasi pangkalan ke tabel MUSTAHIK
const kueri_mustahik = `
INSERT INTO MUSTAHIK (nik, nama_kk, no_kk, jumlah_tanggungan, lat, lng, agama, id_rumah_ibadah)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(kueri_mustahik, [nik, nama_kk, no_kk, jumlah_tanggungan, lat, lng, agama, id_pangkalan_terpilih], function(error_mustahik) {
if (error_mustahik) {
db.run('ROLLBACK');
console.error('Gagal menyimpan DML MUSTAHIK:', error_mustahik.message);
return res.status(500).json({ error: 'Gagal menyimpan data identitas warga, NIK mungkin sudah terdaftar.' });
}
const id_mustahik_baru = this.lastID;
const {
luas_lantai_per_kapita,
material_lantai,
material_dinding,
fasilitas_sanitasi,
sumber_air_minum,
sumber_penerangan,
pekerjaan_utama,
pendapatan_bulanan,
frekuensi_makan,
kepemilikan_aset
} = indikator_bps;
// 2. Menyimpan 10 parameter kondisi ke tabel INDIKATOR_BPS
const kueri_indikator = `
INSERT INTO INDIKATOR_BPS (
id_mustahik, luas_lantai_per_kapita, material_lantai, material_dinding,
fasilitas_sanitasi, sumber_air_minum, sumber_penerangan,
pekerjaan_utama, pendapatan_bulanan, frekuensi_makan, kepemilikan_aset
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(kueri_indikator, [
id_mustahik_baru,
luas_lantai_per_kapita,
material_lantai,
material_dinding,
fasilitas_sanitasi,
sumber_air_minum,
sumber_penerangan,
pekerjaan_utama,
pendapatan_bulanan,
frekuensi_makan,
kepemilikan_aset
], function(error_indikator) {
if (error_indikator) {
db.run('ROLLBACK');
console.error('Gagal menyimpan DML INDIKATOR_BPS:', error_indikator.message);
return res.status(500).json({ error: 'Gagal merekam indikator ekonomi BPS.' });
}
// Secara permanen menerapkan semua kueri yang tertunda ke dalam file SQLite
db.run('COMMIT');
res.status(201).json({
message: 'Data survei kriteria BPS dan pangkalan bantuan berhasil disimpan.',
id_mustahik: id_mustahik_baru
});
});
});
});
});
} catch (error_sistem) {
console.error('Kesalahan eksekusi sistem:', error_sistem);
res.status(500).json({ error: 'Kegagalan pemrosesan internal server.' });
}
};
// Menarik agregasi data statistik untuk ditampilkan di halaman publik
const ambil_statistik_publik = (req, res) => {
const kueri_statistik = `
SELECT
COUNT(CASE WHEN status_validasi = 'Verified' THEN 1 END) AS terverifikasi,
COUNT(CASE WHEN status_validasi = 'Pending' THEN 1 END) AS diproses
FROM MUSTAHIK
`;
db.get(kueri_statistik, [], (error_sql, baris_data) => {
if (error_sql) {
console.error('Gagal menarik agregasi statistik:', error_sql.message);
return res.status(500).json({ error: 'Gagal memuat statistik.' });
}
res.status(200).json(baris_data);
});
};
module.exports = {
cek_status_nik,
submit_survey_data,
ambil_statistik_publik
};