fix: undefined variables and wrong column name in add_pend.php, scanner improvements

This commit is contained in:
2026-01-21 22:36:25 +08:00
parent 334d24b6b8
commit ed732162e0
5 changed files with 104 additions and 44 deletions

View File

@@ -19,7 +19,7 @@ $mimeType = mime_content_type($imagePath);
// Construct Prompt based on Type
if ($type === 'kk') {
$promptText = "Extract strictly from this Indonesian Family Card (Kartu Keluarga). Return ONLY a raw JSON object with these keys: 'no_kk' (16 digits), 'kepala_keluarga' (Name), 'alamat', 'rt', 'rw', 'desa', 'kecamatan', 'kabupaten', 'provinsi', 'kode_pos', 'anggota': [ { 'nik': '...', 'nama': '...', 'hubungan': '...' } ] (Array of all family members found in the table. 'hubungan' examples: KEPALA KELUARGA, ISTRI, ANAK, FAMILI LAIN). Value must be string. If not found, use empty string.";
$promptText = "Extract strictly from this Indonesian Family Card (Kartu Keluarga). Return ONLY a raw JSON object with these keys: 'no_kk' (16 digits), 'kepala_keluarga' (Name), 'alamat', 'rt', 'rw', 'desa', 'kecamatan', 'kabupaten', 'provinsi', 'kode_pos', 'anggota': [ { 'nik': '...', 'nama': '...', 'hubungan': '...', 'tempat_lh': '...', 'tgl_lh': 'YYYY-MM-DD', 'jekel': 'LK/PR', 'agama': '...', 'kawin': '...', 'pekerjaan': '...', 'kewarganegaraan': 'WNI/WNA' } ] (Array of all family members found in the table. 'hubungan' examples: KEPALA KELUARGA, ISTRI, ANAK, FAMILI LAIN). Value must be string. If not found, use empty string.";
} else {
// Default to KTP
$promptText = "Extract data from this Indonesian KTP. Return ONLY a raw JSON object with keys: 'nik' (16 digits), 'nama' (Name), 'tempat_lh' (Place of Birth), 'tgl_lh' (YYYY-MM-DD), 'je_kel' (LK/PR), 'alamat' (Street only), 'rt', 'rw', 'desa' (Kel/Desa), 'kecamatan', 'kabupaten' (or Kota), 'provinsi', 'agama', 'status' (Sudah/Belum/Cerai Hidup/Cerai Mati), 'pekerjaan', 'kewarganegaraan' (WNI/WNA). Clean up text. If field is unclear, return empty string.";
@@ -74,6 +74,7 @@ if (!isset($result['candidates'][0]['content']['parts'][0]['text'])) {
// Parse AI Response
$rawText = $result['candidates'][0]['content']['parts'][0]['text'];
file_put_contents('../../debug_ai.txt', "AI Response:\n" . $rawText . "\n-------------------\n", FILE_APPEND);
// Remove Markdown Code Blocks if any (```json ... ```)
$cleanJson = preg_replace('/^```json\s*|\s*```$/', '', trim($rawText));

View File

@@ -166,18 +166,7 @@ window.addEventListener('load', function() {
<tr><td>Kabupaten</td><td>${d.kabupaten || '-'}</td></tr>
<tr><td>Provinsi</td><td>${d.provinsi || '-'}</td></tr>
</table>
<hr>
<strong>Ditemukan ${d.anggota ? d.anggota.length : 0} Anggota:</strong>
<div style="max-height: 150px; overflow-y: auto; background: #f8f9fa; border: 1px solid #ddd; padding: 5px;">
${d.anggota && d.anggota.length > 0 ?
'<ul style="padding-left: 20px; margin-bottom: 0;">' +
d.anggota.map(m => `<li><b>${m.nama}</b><br><small>${m.nik} (${m.hubungan})</small></li>`).join('') +
'</ul>'
: '<i class="text-muted">Tidak ada anggota terdeteksi</i>'}
</div>
<p class="mb-0 text-muted mt-2">Gunakan data ini?</p>
<p class="mb-0 text-muted">Gunakan data ini?</p>
</div>
`,
icon: 'question',
@@ -190,8 +179,8 @@ window.addEventListener('load', function() {
if(d.anggota) document.getElementById('anggota_json').value = JSON.stringify(d.anggota);
if(d.kepala_keluarga) document.getElementsByName('kepala')[0].value = d.kepala_keluarga;
if(d.desa) document.getElementsByName('desa')[0].value = d.desa;
if(d.rt) document.getElementsByName('rt')[0].value = d.rt;
if(d.rw) document.getElementsByName('rw')[0].value = d.rw;
document.getElementsByName('rt')[0].value = d.rt || '000';
document.getElementsByName('rw')[0].value = d.rw || '000';
if(d.kecamatan) document.getElementsByName('kec')[0].value = d.kecamatan;
if(d.kabupaten) document.getElementsByName('kab')[0].value = d.kabupaten;
if(d.provinsi) document.getElementsByName('prov')[0].value = d.provinsi;
@@ -273,10 +262,11 @@ window.addEventListener('load', function() {
$query_simpan = mysqli_query($koneksi, $sql_simpan);
// Process Auto-Linking Members
$linked_count = 0;
$failed_count = 0;
if ($query_simpan && !empty($_POST['anggota_json'])) {
file_put_contents('debug_log.txt', "----------------------------------------\n", FILE_APPEND);
file_put_contents('debug_log.txt', "Saving KK ID: " . mysqli_insert_id($koneksi) . "\n", FILE_APPEND);
file_put_contents('debug_log.txt', "Raw JSON: " . $_POST['anggota_json'] . "\n", FILE_APPEND);
$id_kk_baru = mysqli_insert_id($koneksi);
$anggota_list = json_decode($_POST['anggota_json'], true);
@@ -285,33 +275,66 @@ window.addEventListener('load', function() {
$nik_mem = mysqli_real_escape_string($koneksi, $mem['nik']);
$hub_mem = mysqli_real_escape_string($koneksi, $mem['hubungan']);
file_put_contents('debug_log.txt', "Processing NIK: $nik_mem\n", FILE_APPEND);
// Search Resident by NIK
$sql_cek_pend = "SELECT id_pend FROM tb_pdd WHERE nik='$nik_mem'";
$q_cek_pend = mysqli_query($koneksi, $sql_cek_pend);
if ($row_pend = mysqli_fetch_assoc($q_cek_pend)) {
$id_pend_found = $row_pend['id_pend'];
file_put_contents('debug_log.txt', "Found Existing ID: $id_pend_found. Linking...\n", FILE_APPEND);
// Insert into tb_anggota
$sql_add_ang = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES ('$id_kk_baru', '$id_pend_found', '$hub_mem')";
mysqli_query($koneksi, $sql_add_ang);
$linked_count++;
if (!mysqli_query($koneksi, $sql_add_ang)) {
file_put_contents('debug_log.txt', "Link Error: " . mysqli_error($koneksi) . "\n", FILE_APPEND);
} else {
file_put_contents('debug_log.txt', "Success Link ID $id_pend_found\n", FILE_APPEND);
}
} else {
$failed_count++;
// Create New Resident if not found
file_put_contents('debug_log.txt', "NIK Not Found. Creating New.\n", FILE_APPEND);
$nama_mem = mysqli_real_escape_string($koneksi, $mem['nama']);
$tempat_lh = mysqli_real_escape_string($koneksi, $mem['tempat_lh'] ?? '-');
$tgl_lh = mysqli_real_escape_string($koneksi, $mem['tgl_lh'] ?? '0000-00-00');
$jekel = mysqli_real_escape_string($koneksi, $mem['jekel'] ?? 'LK');
$agama = mysqli_real_escape_string($koneksi, $mem['agama'] ?? 'Islam');
$kawin = mysqli_real_escape_string($koneksi, $mem['kawin'] ?? 'Belum Kawin');
$pekerjaan = mysqli_real_escape_string($koneksi, $mem['pekerjaan'] ?? 'Pelajar/Mahasiswa');
$kewarganegaraan = mysqli_real_escape_string($koneksi, $mem['kewarganegaraan'] ?? 'WNI');
$sql_new_pend = "INSERT INTO tb_pdd (
nik, nama, tempat_lh, tgl_lh, jekel,
desa, rt, rw, agama, kawin, pekerjaan, status, kwn
) VALUES (
'$nik_mem', '$nama_mem', '$tempat_lh', '$tgl_lh', '$jekel',
'$desa', '$rt', '$rw', '$agama', '$kawin', '$pekerjaan', 'Ada', '$kewarganegaraan'
)";
if (mysqli_query($koneksi, $sql_new_pend)) {
$id_pend_new = mysqli_insert_id($koneksi);
file_put_contents('debug_log.txt', "Created New ID: $id_pend_new. Linking...\n", FILE_APPEND);
// Link to KK
$sql_add_ang = "INSERT INTO tb_anggota (id_kk, id_pend, hubungan) VALUES ('$id_kk_baru', '$id_pend_new', '$hub_mem')";
mysqli_query($koneksi, $sql_add_ang);
} else {
file_put_contents('debug_log.txt', "Error Creating Resident: " . mysqli_error($koneksi) . "\n", FILE_APPEND);
}
}
}
} else {
file_put_contents('debug_log.txt', "JSON Decode Failed or Not Array\n", FILE_APPEND);
}
}
mysqli_close($koneksi);
if ($query_simpan) {
$msg_add = "";
if($linked_count > 0 || $failed_count > 0) {
$msg_add = "<br>Anggota Terhubung: <b>$linked_count</b><br>Tidak Ditemukan: <b>$failed_count</b>";
}
echo "<script>
Swal.fire({title: 'Tambah Data Berhasil',html: 'Data KK disimpan.$msg_add',icon: 'success',confirmButtonText: 'OK'
Swal.fire({title: 'Tambah Data Berhasil',text: '',icon: 'success',confirmButtonText: 'OK'
}).then((result) => {if (result.value){
window.location = 'index.php?page=data-kartu';
}

View File

@@ -208,8 +208,8 @@ window.addEventListener('load', function() {
if(d.no_kk) document.getElementsByName('no_kk')[0].value = d.no_kk;
if(d.kepala_keluarga) document.getElementsByName('kepala')[0].value = d.kepala_keluarga;
if(d.desa) document.getElementsByName('desa')[0].value = d.desa;
if(d.rt) document.getElementsByName('rt')[0].value = d.rt;
if(d.rw) document.getElementsByName('rw')[0].value = d.rw;
document.getElementsByName('rt')[0].value = d.rt || '000';
document.getElementsByName('rw')[0].value = d.rw || '000';
if(d.kecamatan) document.getElementsByName('kec')[0].value = d.kecamatan;
if(d.kabupaten) document.getElementsByName('kab')[0].value = d.kabupaten;
if(d.provinsi) document.getElementsByName('prov')[0].value = d.provinsi;

View File

@@ -334,13 +334,46 @@ window.addEventListener('load', function() {
$nik = $_POST['nik'];
$cek_nik = mysqli_query($koneksi, "SELECT * FROM tb_pdd WHERE nik='$nik'");
if(mysqli_num_rows($cek_nik) > 0){
echo "<script>
Swal.fire({title: 'Gagal',text: 'NIK sudah terdaftar dalam sistem!',icon: 'error',confirmButtonText: 'OK'
}).then((result) => {if (result.value){
window.location = 'index.php?page=add-pend';
}
})</script>";
return;
// AUTO-LINKING: Instead of blocking, we UPDATE the existing record with Scan Data
// Sanitize input first before UPDATE
$nama = mysqli_real_escape_string($koneksi, $_POST['nama']);
$tempat_lh = mysqli_real_escape_string($koneksi, $_POST['tempat_lh']);
$tgl_lh = mysqli_real_escape_string($koneksi, $_POST['tgl_lh']);
$jekel = mysqli_real_escape_string($koneksi, $_POST['jekel']);
$desa = mysqli_real_escape_string($koneksi, $_POST['desa']);
$rt = mysqli_real_escape_string($koneksi, $_POST['rt']);
$rw = mysqli_real_escape_string($koneksi, $_POST['rw']);
$agama = mysqli_real_escape_string($koneksi, $_POST['agama']);
$kawin = mysqli_real_escape_string($koneksi, $_POST['kawin']);
$pekerjaan = mysqli_real_escape_string($koneksi, $_POST['pekerjaan']);
$kewarganegaraan = mysqli_real_escape_string($koneksi, $_POST['kewarganegaraan']);
$sql_update = "UPDATE tb_pdd SET
nama='$nama',
tempat_lh='$tempat_lh',
tgl_lh='$tgl_lh',
jekel='$jekel',
desa='$desa',
rt='$rt',
rw='$rw',
agama='$agama',
kawin='$kawin',
pekerjaan='$pekerjaan',
kewarganegaraan='$kewarganegaraan',
foto_ktp='$nama_file'
WHERE nik='$nik'";
$query_update = mysqli_query($koneksi, $sql_update);
if ($query_update) {
echo "<script>
Swal.fire({title: 'Data Diperbarui',text: 'NIK sudah ada, data penduduk telah diperbarui dengan hasil scan KTP.',icon: 'success',confirmButtonText: 'OK'
}).then((result) => {if (result.value){
window.location = 'index.php?page=data-pend';
}
})</script>";
return;
}
}
// Sanitize Input to prevent SQL Injection & Syntax Errors

View File

@@ -11,12 +11,13 @@
</div>
<div class="modal-body text-center bg-dark p-0" style="position: relative; overflow: hidden; height: 80vh;">
<!-- Container for Canvases -->
<div id="scanner-container" style="position: relative; margin: auto; display: inline-block;">
<canvas id="canvas-image" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
<canvas id="canvas-overlay" style="position: absolute; left: 0; top: 0; z-index: 2; cursor: crosshair;"></canvas>
<!-- Container for Canvases -->
<div id="scanner-container" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 10px rgba(0,0,0,0.5);">
<canvas id="canvas-image" style="position: absolute; left: 0; top: 0; z-index: 10;"></canvas>
<canvas id="canvas-overlay" style="position: absolute; left: 0; top: 0; z-index: 20; cursor: crosshair;"></canvas>
</div>
<div id="scanner-loading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); color: white; display: none;">
<i class="fas fa-spinner fa-spin fa-3x"></i><br>Detecting Document...
<div id="scanner-loading" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); color: white; display: none; z-index: 50; text-align: center;">
<i class="fas fa-spinner fa-spin fa-3x"></i><br><span style="margin-top: 10px; display: block;">Sedang menganalisa...</span>
</div>
</div>
<div class="modal-footer justify-content-between">
@@ -57,7 +58,6 @@ window.addEventListener('load', function() {
const LINE_COLOR = '#00ff00';
const LINE_WIDTH = 3;
// --- Public Function to Open Scanner ---
// --- Public Function to Open Scanner ---
window.openScanner = function(file) {
if (!file) return;
@@ -76,7 +76,10 @@ window.addEventListener('load', function() {
function checkReady() {
if (imgLoaded && modalShown) {
initScanner();
// Defer execution to allow UI (spinner) to render first
setTimeout(function() {
initScanner();
}, 100);
}
}
@@ -116,7 +119,7 @@ window.addEventListener('load', function() {
canvasOverlay.height = h;
// Resize container
$('#scanner-container').css({ width: w, height: h, marginTop: '10px' });
$('#scanner-container').css({ width: w, height: h });
// Draw Image
ctxImg.drawImage(originalImg, 0, 0, w, h);