feat : penambahan rumah ibadah
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
const db = require('../config/database');
|
||||
|
||||
// Mengambil data status bantuan warga berdasarkan pencarian NIK dari halaman publik
|
||||
// Mengambil data status bantuan warga beserta lokasi pangkalan ibadah
|
||||
const cek_status_nik = (req, res) => {
|
||||
const nik_warga = req.params.nik;
|
||||
|
||||
@@ -9,12 +9,20 @@ const cek_status_nik = (req, res) => {
|
||||
return res.status(400).json({ error: 'Format NIK tidak valid.' });
|
||||
}
|
||||
|
||||
const kueri_pencarian = `SELECT nik, nama_kk, status_validasi, lat, lng FROM MUSTAHIK WHERE nik = ?`;
|
||||
// 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 = ?
|
||||
`;
|
||||
|
||||
// Baris kompleks: Penggunaan parameter '?' (parameterized query) memastikan bahwa mesin SQLite menganggap variabel 'nik_warga' murni sebagai nilai data, bukan sebagai perintah yang bisa dieksekusi, sehingga secara absolut mencegah serangan SQL Injection.
|
||||
db.get(kueri_pencarian, [nik_warga], (error_sistem, baris_data) => {
|
||||
if (error_sistem) {
|
||||
console.error('Sistem gagal membaca tabel:', error_sistem.message);
|
||||
console.error('Sistem gagal membaca tabel gabungan:', error_sistem.message);
|
||||
return res.status(500).json({ error: 'Terjadi kegagalan server internal.' });
|
||||
}
|
||||
|
||||
@@ -26,7 +34,7 @@ const cek_status_nik = (req, res) => {
|
||||
});
|
||||
};
|
||||
|
||||
// Mengontrol alur penerimaan data survei lapangan secara transaksional
|
||||
// Mengontrol alur penerimaan data survei lapangan beserta penentuan pangkalan bantuan
|
||||
const submit_survey_data = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
@@ -35,12 +43,13 @@ const submit_survey_data = async (req, res) => {
|
||||
no_kk,
|
||||
jumlah_tanggungan,
|
||||
lat,
|
||||
lng,
|
||||
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 || !indikator_bps) {
|
||||
if (!nik || !nama_kk || !lat || !lng || !agama || !indikator_bps) {
|
||||
return res.status(400).json({ error: 'Payload data survei tidak lengkap dari klien.' });
|
||||
}
|
||||
|
||||
@@ -48,65 +57,79 @@ const submit_survey_data = async (req, res) => {
|
||||
db.serialize(() => {
|
||||
db.run('BEGIN TRANSACTION');
|
||||
|
||||
// 1. Menyimpan data identitas ke tabel MUSTAHIK
|
||||
const kueri_mustahik = `INSERT INTO MUSTAHIK (nik, nama_kk, no_kk, jumlah_tanggungan, lat, lng) VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
// 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.run(kueri_mustahik, [nik, nama_kk, no_kk, jumlah_tanggungan, lat, lng], function(error_mustahik) {
|
||||
// Baris kompleks: Jika terjadi kegagalan pada tahap pertama ini, perintah ROLLBACK membatalkan status transaksi secara keseluruhan, mencegah adanya data terisolasi di memori.
|
||||
if (error_mustahik) {
|
||||
db.get(kueri_cari_pangkalan, [agama], (error_cari, baris_pangkalan) => {
|
||||
if (error_cari) {
|
||||
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.' });
|
||||
console.error('Gagal mencocokkan rumah ibadah:', error_cari.message);
|
||||
return res.status(500).json({ error: 'Gagal memproses penentuan lokasi bantuan.' });
|
||||
}
|
||||
|
||||
// Mengekstrak ID yang otomatis digenerate (Auto Increment) untuk digunakan sebagai Foreign Key
|
||||
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
const id_pangkalan_terpilih = baris_pangkalan ? baris_pangkalan.id : null;
|
||||
|
||||
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) {
|
||||
// 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 INDIKATOR_BPS:', error_indikator.message);
|
||||
return res.status(500).json({ error: 'Gagal merekam indikator ekonomi BPS.' });
|
||||
console.error('Gagal menyimpan DML MUSTAHIK:', error_mustahik.message);
|
||||
return res.status(500).json({ error: 'Gagal menyimpan data identitas warga, NIK mungkin sudah terdaftar.' });
|
||||
}
|
||||
|
||||
// Secara permanen menerapkan semua kueri yang tertunda ke dalam file SQLite
|
||||
db.run('COMMIT');
|
||||
res.status(201).json({
|
||||
message: 'Data survei kriteria BPS berhasil disubmit',
|
||||
id_mustahik: id_mustahik_baru
|
||||
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
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -120,10 +143,6 @@ const submit_survey_data = async (req, res) => {
|
||||
|
||||
// Menarik agregasi data statistik untuk ditampilkan di halaman publik
|
||||
const ambil_statistik_publik = (req, res) => {
|
||||
/* Baris kompleks: Kueri ini menggunakan fungsi agregasi COUNT dikombinasikan dengan ekspresi
|
||||
kondisional CASE WHEN. Pendekatan ini sangat optimal karena mesin SQLite hanya perlu
|
||||
memindai tabel MUSTAHIK satu kali untuk mendapatkan dua nilai hitungan yang berbeda,
|
||||
sehingga menghemat alokasi memori dan waktu eksekusi server backend. */
|
||||
const kueri_statistik = `
|
||||
SELECT
|
||||
COUNT(CASE WHEN status_validasi = 'Verified' THEN 1 END) AS terverifikasi,
|
||||
@@ -140,9 +159,8 @@ const ambil_statistik_publik = (req, res) => {
|
||||
});
|
||||
};
|
||||
|
||||
// Mengekspor semua fungsi agar dapat diakses oleh file router
|
||||
module.exports = {
|
||||
cek_status_nik,
|
||||
submit_survey_data,
|
||||
ambil_statistik_publik
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user