Files
2026-06-11 18:14:21 +07:00

18 KiB
Raw Permalink Blame History

Codebase Navigation — WebGIS Poverty Mapping

Quick reference for navigating the project. Updated: 2026-06-03.


Directory Tree at a Glance

WebgisPovertyMapping/
├── index.php                   ← Main app shell (auth-aware)
├── index.html                  ← Redirect/legacy entry from older prototype
├── dashboard.php               ← Authenticated admin/operator shell
├── papan-kebutuhan.php         ← Public needs board page
├── config.php                  ← All app constants (DB, session, map center)
├── koneksi.php                 ← DB connection + Haversine + calc_proximity()
├── setup_database.sql          ← Full schema (idempotent, run to init DB)
│
├── auth/
│   ├── helper.php              ← RBAC core: is_logged_in(), require_auth(), has_role()
│   ├── login.php               ← Login page
│   └── change_password.php     ← Forced password-change page
│
├── pages/
│   ├── map.php                 ← Dashboard wrapper embedding index.php?embedded=1
│   ├── penduduk.php            ← Operator/admin penduduk management
│   ├── kebutuhan.php           ← Operator/admin kebutuhan workflow
│   ├── status-bantuan.php      ← Operator/admin aid status workflow
│   ├── ibadah.php              ← Admin rumah ibadah management
│   ├── users.php               ← Admin user management
│   ├── import.php              ← Admin CSV import
│   ├── laporan.php             ← Admin export/report page
│   └── analisis.php            ← Admin analytics/recalculation page
│
├── modules/                    ← Frontend JS modules (loaded by index.php)
│   ├── ibadah.js               ← Rumah Ibadah layer: markers, circles, CRUD
│   ├── penduduk.js             ← Penduduk layer: proximity coloring, CRUD, filters
│   ├── stats.js                ← Dashboard modal: cards + chart + rekap table
│   ├── heatmap.js              ← Heatmap overlay (leaflet.heat, weighted by jiwa)
│   └── kebutuhan.js            ← Kebutuhan bantuan popup/actions
│
├── css/
│   └── admin.css               ← Shared dashboard/page styling
│
├── includes/
│   ├── page-start.php          ← Authenticated page shell start
│   └── page-end.php            ← Authenticated page shell end
│
├── api/
│   ├── auth/                   ← login.php · logout.php · change_password.php
│   ├── users/                  ← ambil · simpan · update · reset_password · toggle_active
│   ├── ibadah/                 ← ambil · simpan · update · hapus · update_posisi · update_kontak · update_radius · recalculate
│   ├── penduduk/               ← ambil · simpan · verifikasi · hapus · nonaktifkan · update_posisi · update_status · riwayat · arsip
│   ├── stats/                  ← ambil.php (aggregations)
│   ├── kebutuhan/              ← ambil · simpan · update_status
│   ├── papan/                  ← public board + donor contact endpoints
│   ├── import/                 ← csv.php · template.php
│   └── export/                 ← csv.php · pdf.php
│
├── tests/
│   ├── test_db.php                         ← Schema smoke test
│   ├── test_auth_helper.php                ← Auth helper unit tests
│   ├── test_ibadah.php                     ← Ibadah column + radius tests
│   ├── test_penduduk.php                   ← Penduduk columns + NIK index tests
│   ├── test_kebutuhan.php                  ← Kebutuhan schema/query smoke tests
│   ├── test_proximity.php                  ← Haversine + tie-breaking unit tests
│   ├── test_verifikasi_binding.php         ← Verification endpoint bind order guard
│   ├── test_update_posisi_scope.php        ← Penduduk move scope guard
│   ├── test_operator_scope_endpoints.php   ← Operator endpoint scope checks
│   ├── test_public_verification_filters.php← Public verification filters
│   ├── test_frontend_module_loader.php     ← Module loader cache-busting guard
│   ├── test_frontend_reliability_guards.php ← Loader/heatmap/recalc guard checks
│   ├── test_no_legacy_poi.php              ← Legacy POI removal guard
│   ├── test_viewer_public_filters.php      ← Viewer public-data leakage guard
│   ├── test_operator_scope_strict.php      ← Strict operator ibadah scope guard
│   ├── test_penduduk_binding_types.php     ← Penduduk/import bind type guard
│   ├── test_csrf_enforcement.php           ← CSRF helper/endpoint/frontend wiring guard
│   ├── test_session_cookie_security.php    ← Session cookie security guard
│   ├── test_operator_ibadah_highlight.php  ← Operator assigned-ibadah highlight guard
│   └── test_viewer_account_ui_hidden.php   ← Viewer account creation UI guard
│
├── Tugas/                      ← Assignment docs (SRS, use-case diagram)
└── docs/
    ├── codebase-navigation.md  ← This file
    └── superpowers/
        ├── specs/              ← PRD and design specs
        └── plans/              ← Phase implementation plans

Essential Files — Start Here

File Why You Need It
config.php All configurable constants — DB credentials, map center (CENTER_LAT/LNG), SESSION_TIMEOUT, MAX_LOGIN_ATTEMPTS
koneksi.php DB connection + the two core functions: haversine_distance() and calc_proximity() — the heart of the proximity engine
setup_database.sql Authoritative schema — run this to initialize or reset the DB
auth/helper.php RBAC foundation used by every endpoint: require_auth(), has_role(), is_logged_in(), session timeout logic
index.php Main SPA shell — role detection, toolbar rendering, all modals, map init, utility functions (showToast, showDeleteConfirm, etc.)
File Purpose
codebase-audit-report.md End-to-end business process, backend/frontend wiring, data lifecycle, current logic concerns, fix priorities, and development suggestions.
business-process-sop.md SOP proses bisnis aktif untuk administrator, operator, publik, donatur, verifikasi, proximity, dan catatan audit.
deployment-docker.md Docker/Coolify deployment, reverse proxy routing, database container, and troubleshooting.
deployment-xampp.md Legacy XAMPP setup if the app must run without Docker.
superpowers/README.md Index PRD, implementation plans, and the latest superpowers audit refresh.
superpowers/plans/2026-06-03-codebase-audit-refresh.md Latest codebase audit snapshot after hardening.
../README.md Setup, stack, default account, roles, features, and test commands.
../setup_database.sql Authoritative database schema and default admin seed.

Database Tables

Core v1.0 Tables

rumah_ibadah — Worship places with service radius

Key Columns Notes
id, nama, jenis (ENUM 6 types), lat/lng Core identity
radius_m INT DEFAULT 500 Validated 1005000
deleted_at TIMESTAMP NULL Soft delete — WHERE deleted_at IS NULL for all queries

penduduk_miskin — Poor residents (core data)

Key Columns Notes
id, nama_kk, nik VARCHAR(16) UNIQUE NIK nullable but unique
lat/lng, ibadah_id FK, jarak_m, is_blank_spot Proximity results — computed by calc_proximity()
kategori ENUM 3 levels, status_bantuan ENUM 3 states Classification + aid tracking
status_verifikasi ENUM('Pending','Terverifikasi','Ditolak') Public visibility gate
is_active TINYINT(1) 0 = deceased/relocated (archived)
deleted_at TIMESTAMP NULL Admin error correction (soft delete)

is_active=0 vs deleted_at IS NOT NULL: Both hide the record from all active queries. is_active=0 = real person, archived. deleted_at = data entry error, logically cancelled.

users — System accounts

Key Columns Notes
role ENUM('administrator','operator','viewer') RBAC basis
ibadah_id FK Operator's assigned worship place
must_change_password TINYINT(1) Forces redirect to change_password.php on login
login_attempts, locked_until Brute-force protection state

riwayat_bantuan — Aid status audit log (append-only)

Key Columns Notes
penduduk_id, operator_id FK Who changed what
status_lama, status_baru, catatan Change record
No deleted_at Intentionally — immutable audit trail

kebutuhan — Assistance needs per resident

Key Columns Notes
penduduk_id, kategori, deskripsi, status Need details and fulfillment state
created_by, updated_by Operator/admin audit references

riwayat_kebutuhan — Kebutuhan status audit log (append-only)

Key Columns Notes
kebutuhan_id, operator_id FK Which need changed and who changed it
status_lama, status_baru, catatan Status transition record
created_at Append-only timestamp for audit chronology

kontak_donatur — Public donor contact submissions

Key Columns Notes
nama, kontak, kategori_minat, pesan Public contact form data
is_read Admin dashboard notification state

API Endpoint Map

Public (no auth required)

Endpoint Method Purpose
api/ibadah/ambil.php GET All active ibadah + KK/jiwa counts
api/penduduk/ambil.php GET Active penduduk — PII masked for non-auth
api/stats/ambil.php GET Aggregate stats; rekap_ibadah only for admin
api/papan/ambil.php GET Public verified kebutuhan board aggregation
api/papan/kontak_donatur.php POST Public donor contact submission

Operator+ (operator or admin)

Endpoint Method Purpose
api/penduduk/simpan.php POST Add penduduk (auto-calls calc_proximity)
api/penduduk/update_posisi.php POST Move marker (recalcs proximity)
api/penduduk/update_status.php POST Change aid status + write audit log
api/penduduk/riwayat.php GET Aid history for a penduduk (scoped to own ibadah for operators)
api/kebutuhan/ambil.php GET List kebutuhan for a scoped penduduk
api/kebutuhan/simpan.php POST Add kebutuhan for a scoped penduduk
api/kebutuhan/update_status.php POST Update kebutuhan status + write audit log

Admin only

Endpoint Method Purpose
api/ibadah/simpan.php POST Create ibadah
api/ibadah/update.php POST Update ibadah master data from admin page
api/ibadah/hapus.php POST Soft-delete ibadah (warns if operators linked)
api/ibadah/update_posisi.php POST Move ibadah → triggers full recalc
api/ibadah/update_radius.php POST Change radius → triggers full recalc
api/ibadah/update_kontak.php POST Update contact only
api/ibadah/recalculate.php POST Bulk recalculate all proximity
api/penduduk/verifikasi.php POST Approve/reject pending penduduk records
api/penduduk/hapus.php POST Soft-delete penduduk (data entry error)
api/penduduk/nonaktifkan.php POST Set is_active=0 (deceased/relocated)
api/penduduk/arsip.php GET List inactive/deleted warga for audit (up to 200 rows)
api/papan/donatur.php GET/POST GET lists donor contacts; POST marks unread entries as read with CSRF
api/users/ambil.php GET List all accounts
api/users/simpan.php POST Create account (must_change_password=1 forced)
api/users/update.php POST Edit nama/role/ibadah_id
api/users/reset_password.php POST Generate temp password + must_change=1
api/users/toggle_active.php POST Enable/disable account (cannot self-deactivate)
api/import/csv.php POST CSV import (mode=preview or mode=import)
api/import/template.php GET Download CSV template
api/export/csv.php GET Export warga binaan as CSV (no NIK)
api/export/pdf.php GET Print-ready HTML report (no NIK)

Frontend Module Map

modules/ibadah.js

  • Entry: window.initIbadah() — called by index.php on load
  • Shared state: window._ibadahList[] — read by penduduk.js for client-side proximity preview
  • Key functions:
    • addToMap(data) — creates draggable marker + radius circle
    • buildInfoPopup(data) — admin: editable kontak/radius/export links; viewer: read-only
    • _ibadahHapus(id) — two-step: operator-warning check → confirm → soft-delete
    • _recalcAll() — calls recalculate.php, disables all CRUD buttons during operation
    • window._ibadahToggleLayer(bool) / _setBufferVisible(bool) — layer controls

modules/penduduk.js

  • Entry: window.initPenduduk() — called by index.php on load
  • Shared state: window._pendudukList[] — read by stats.js and heatmap.js
  • Key functions:
    • buildInfoPopup(data, ibadah) — proximity section + NIK (auth only) + status buttons (operator) + riwayat
    • findNearestIbadah(lat, lng) — client-side Haversine mirror of PHP calc_proximity()
    • applyFilters() — AND-logic filter across 4 dimensions + search
    • window._pendudukRecalcAll() — client-side repaint after ibadah change (no server call)
    • _updateBlankSpotCounter() / _filterBlankSpot() — blank spot counter + click-to-filter

modules/stats.js

  • Entry: window._showDashboard() — opens modal
  • window._statsUpdate() — re-fetches and re-renders (only if modal visible)
  • Destroys and recreates Chart.js instance on each update to avoid memory leaks

modules/heatmap.js

  • Entry: window._toggleHeatmap(bool) — creates/destroys heatmap layer
  • Intensity = 0.2 + 0.8 * (jumlah_jiwa / maxJiwa) — proportional to household size
  • window._heatmapSetKategori(k) — filter heatmap by category

modules/kebutuhan.js

  • Entry: loaded for authenticated users through window.MAP_MODULES
  • Builds kebutuhan controls inside penduduk popups
  • Calls api/kebutuhan/ambil.php, api/kebutuhan/simpan.php, and api/kebutuhan/update_status.php

Core Algorithm: Proximity Engine

Location: koneksi.phpcalc_proximity($conn, $lat, $lng)

Logic:

  1. Query all rumah_ibadah WHERE deleted_at IS NULL ORDER BY id ASC
  2. For each, compute Haversine distance
  3. Track two candidates: best_in_radius (nearest within radius) and best_overall (nearest regardless)
  4. Winner = best_in_radius if exists; else best_overall (blank spot)
  5. Tie-breaking: ORDER BY id ASC + strict < comparison → lowest id wins on equal distance

Triggers:

  • api/penduduk/simpan.php — on each new penduduk
  • api/penduduk/update_posisi.php — when penduduk moved
  • api/ibadah/update_posisi.php — after ibadah position change (loops ALL penduduk)
  • api/ibadah/update_radius.php — after radius change (loops ALL penduduk)
  • api/ibadah/hapus.php — after soft-delete (loops ALL penduduk)
  • api/ibadah/recalculate.php — manual bulk trigger (admin "Hitung Ulang Semua")
  • api/import/csv.php — per-row during import

Client-side mirror: modules/penduduk.jsfindNearestIbadah() for instant visual feedback during drag/radius resize (no server call).


RBAC Quick Reference

viewer (0)       → public/fallback read-only map, aggregated stats, PII masked
operator (1)     → + add/move penduduk, update aid status (own ibadah only)
administrator (2) → + everything: CRUD ibadah, manage users, import/export, recalculate

Operators are created by administrators in pages/users.php and must be linked to one rumah_ibadah. The shared admin shell renders navigation by role: administrators see dashboard/master/import/export/user management, while operators see map, penduduk, kebutuhan, and status bantuan only. Unauthenticated visitors are treated as viewer, so the admin user-management UI does not offer viewer for new accounts. The backend role remains for fallback RBAC and existing read-only accounts.

Session flow:

  1. Unauthenticated → index.php renders as viewer (no redirect)
  2. Login → api/auth/login.php → session set → if must_change_password=1, redirect to auth/change_password.php
  3. Every page/API: auth/helper.php:is_logged_in() validates session + renews last_activity
  4. Idle 2hr → session expired → treated as viewer on next request

Legacy Status

The obsolete road/polyline, parcel/polygon, and business-location prototype features have been removed from the active app.

Active core:

  • rumah_ibadah
  • penduduk_miskin
  • users
  • kebutuhan
  • riwayat_bantuan
  • riwayat_kebutuhan
  • kontak_donatur

Running Tests

Tests are intended to run from CLI/local PHP. Browser access to /tests/ is blocked by .htaccess for deployment safety.

Run selected static/smoke tests from the project root:

& 'C:\Program Files\Xampp\php\php.exe' tests\run_all.php

Some database smoke tests load ../config.php or ../koneksi.php and should be run from the tests directory after importing setup_database.sql.


Configuration Quick-Start

Edit config.php to set:

define('CENTER_LAT', -0.0557);   // Map center latitude
define('CENTER_LNG', 109.3487);  // Map center longitude  
define('ZOOM_LEVEL', 15);        // Initial zoom
define('DB_HOST', 'localhost');
define('DB_PORT', 3307);         // Local configured MySQL port
define('DB_NAME', 'db_webgis');

Default admin credentials (must change on first login): admin / Admin1234