18 KiB
Referensi Lengkap Aplikasi Panen Harga
Dokumen ini menjelaskan aplikasi Panen Harga, yaitu sistem prediksi harga cabai di Kabupaten Jember dengan visualisasi peta digital interaktif. Dokumen ini dapat digunakan sebagai referensi untuk menjelaskan tujuan aplikasi, arsitektur, fitur, alur data, teknologi, API, database, model LSTM, pengelolaan scraping, serta batasan sistem.
1. Identitas dan tujuan aplikasi
Nama aplikasi
Panen Harga
Tujuan
Aplikasi digunakan untuk:
- menampilkan harga cabai berdasarkan pasar di Kabupaten Jember;
- menampilkan lokasi pasar melalui peta digital;
- menghasilkan prediksi harga menggunakan model LSTM yang sudah dilatih;
- membantu pengguna membandingkan harga aktual dan hasil forecast;
- menyediakan panel admin untuk memperbarui data secara manual;
- menyediakan preprocessing terbatas untuk menangani gap data;
- mencatat riwayat scraping dan proses pengolahan data.
Aplikasi ini bukan marketplace dan tidak melakukan transaksi jual beli. Fokusnya adalah informasi harga, visualisasi lokasi, dan prediksi harga.
Komoditas
Sistem mendukung tiga komoditas:
| Slug API | Nama |
|---|---|
rawit |
Cabai Rawit |
merah |
Cabai Merah Besar |
keriting |
Cabai Merah Keriting |
Pasar
Pasar yang terdaftar:
- Pasar Tanjung
- Pasar Kreongan
- Pasar Tegal Besar
- Pasar Mangli
- Pasar Wirolegi
Ketersediaan model dapat berbeda untuk setiap komoditas. Saat ini model cabai merah keriting hanya tersedia untuk pasar yang memiliki artifact lengkap. Aplikasi tidak membuat prediksi palsu untuk pasar tanpa model atau data.
2. Teknologi dan tools
Backend
- Bahasa: Python 3.9
- Framework: Flask
- Server development: Werkzeug melalui
app.run - Database driver: PyMySQL
- Data processing: pandas dan NumPy
- Machine learning runtime: TensorFlow 2.10
- Preprocessing dan scaler: scikit-learn
- Pemuat scaler: joblib atau pickle
- HTTP scraping: requests
- Parsing tabel HTML: pandas dan lxml
- Pengujian: pytest
- CORS: flask-cors
Entry point backend adalah api/main.py. Aplikasi Flask dibuat
melalui application factory create_app().
Frontend
- Bahasa: JavaScript modern dengan JSX
- Framework: React 19
- Build tool: Vite
- Lint: Oxlint
- Peta: Leaflet dan React Leaflet
- Grafik: Recharts
- Ikon: Lucide React
- Styling: CSS biasa melalui
website/src/Public.css
Database
- Database: MySQL/MariaDB
- Pengelolaan lokal: phpMyAdmin, XAMPP, Laragon, atau WAMP
- Nama database default:
prediksicabe
Model dan artifact
Setiap kombinasi komoditas/pasar dapat memiliki:
model.h5: model LSTM yang sudah dilatih;scaler.pkl: scaler yang digunakan saat training;config.json: metadata model dan konfigurasi training.
API memuat artifact satu kali saat startup. API tidak menjalankan training ulang ketika aplikasi berjalan.
3. Struktur proyek
Struktur utama:
C:\PrediksiHargaCabe\
├── api\
│ ├── main.py
│ ├── requirements.txt
│ ├── restart_backend.ps1
│ ├── README.md
│ ├── app\
│ │ ├── __init__.py
│ │ ├── config.py
│ │ ├── errors.py
│ │ ├── api\
│ │ │ └── routes.py
│ │ ├── data\
│ │ │ ├── markets.json
│ │ │ └── repository.py
│ │ └── services\
│ │ ├── forecaster.py
│ │ ├── model_registry.py
│ │ ├── prediction_service.py
│ │ └── siskaperbapo_scraper.py
│ ├── models\
│ │ ├── rawit\
│ │ ├── merah\
│ │ └── keriting\
│ └── tests\
├── database\
│ └── panen_harga.sql
├── website\
│ ├── package.json
│ └── src\
│ ├── App.jsx
│ ├── Public.css
│ └── services\
│ └── api.js
├── RINGKASAN_FITUR.md
└── REFERENSI_APLIKASI.md
4. Arsitektur aplikasi
Pengguna
│
▼
React/Vite frontend :5173
│ HTTP/JSON + session cookie
▼
Flask REST API :8000
├── PredictionService
├── ModelRegistry
├── PriceRepository
└── SiskaperbapoScraper
│
├── Artifact model LSTM
└── MySQL prediksicabe
Frontend tidak mengakses database secara langsung. Semua data diambil melalui service layer pada website/src/services/api.js. Backend bertanggung jawab atas validasi, akses database, scraping, preprocessing, dan inference model.
5. Alur data utama
5.1 Data penelitian awal
Data CSV penelitian dapat dimasukkan satu kali ke MySQL menggunakan script import. Harga CSV dikonversi ke Rupiah penuh sebelum disimpan.
CSV penelitian
↓
import_csv_to_mysql.py
↓
price_history
↓
PriceRepository
5.2 Data scraping manual
Scraping tidak berjalan otomatis dan tidak memiliki scheduler.
Admin memilih komoditas dan tanggal
↓
POST /api/v1/admin/scraping/jobs
↓
Background thread
↓
SISKAPERBAPO
↓
Normalisasi harga
↓
price_history
↓
scraping_logs
Data baru dicatat menggunakan scraping_log_id, sehingga satu riwayat scraping
dapat ditelusuri dan dihapus bersama data yang dihasilkannya.
5.3 Preprocessing
Preprocessing manual dapat dijalankan terhadap satu log scraping yang dipilih. Metode yang digunakan adalah interpolasi linear untuk gap internal yang memenuhi batas sistem. Gap di awal/akhir atau gap terlalu panjang tidak diisi secara sembarangan dan dilaporkan sebagai warning.
Pilih riwayat scraping
↓
POST /api/v1/admin/preprocessing/jobs
↓
Pemeriksaan gap
↓
Interpolasi linear yang diizinkan
↓
price_history + preprocessing_runs
Repository juga melakukan interpolasi internal terbatas ketika membaca series untuk inference. Perilaku ini berfungsi sebagai validasi/fallback agar gap kecil tidak langsung membuat prediksi gagal.
5.4 Inference prediksi
Alur inference:
Data historis terbaru dari database
↓
Pilih data valid terakhir sesuai time_step
↓
Konversi input ke satuan ribuan untuk model
↓
Transform dengan scaler.pkl
↓
Model H5 menghasilkan prediksi
↓
Inverse transform
↓
Konversi kembali ke Rupiah penuh
↓
Recursive forecast 1, 3, atau 7 hari
↓
Response API
Data scraping baru tidak melatih ulang model. Data tersebut hanya menjadi data aktual terbaru yang digunakan sebagai input inference.
6. Satuan harga dan presisi
Aturan penyimpanan database:
Semua harga positif di
price_historydisimpan dalam Rupiah penuh.
Contoh:
8234 → Rp8.234
8500 → Rp8.500
9275 → Rp9.275
Model dapat bekerja dalam satuan ribuan Rupiah sesuai artifact training. API melakukan penyesuaian satuan ketika inference dan mengembalikan hasil dalam Rupiah penuh.
Harga prediksi tidak dibulatkan ke ribuan. Frontend menampilkan maksimal dua angka desimal jika hasil model memiliki pecahan.
Nilai 0, kosong, dan nilai tidak valid diperlakukan sebagai data kosong, bukan
harga aktual yang valid.
7. Fitur dashboard publik
Dashboard publik berada pada route utama website.
7.1 Pemilihan filter
Pengguna dapat memilih:
- jenis cabai;
- pasar;
- horizon prediksi 1, 3, atau 7 hari.
Prediksi tidak dijalankan otomatis ketika halaman pertama kali dibuka. Pengguna harus menekan tombol Prediksi.
7.2 Data terakhir
Bagian Data terakhir menampilkan tanggal data terbaru untuk setiap komoditas. Sistem mencari pasar aktif yang memiliki ketersediaan komoditas tersebut, sehingga komoditas tidak bergantung pada pasar yang kosong.
7.3 Peta interaktif
Peta menggunakan Leaflet dan OpenStreetMap tile layer. Fitur peta:
- marker lokasi pasar;
- marker terpilih;
- tooltip nama pasar dan harga;
- popup harga aktual, forecast, perubahan, dan tren;
- pemusatan peta ke pasar yang dipilih;
- mode Aktual dan Forecast;
- legenda status harga;
- peringkat pasar berdasarkan harga aktual atau forecast.
Pasar yang tidak memiliki model atau data tidak dipaksakan menjadi hasil prediksi.
7.4 Grafik dan tabel
Dashboard menampilkan:
- riwayat harga aktual;
- grafik aktual dan forecast;
- tabel forecast per tanggal;
- perubahan harga dalam Rupiah;
- perubahan persentase;
- indikator tren;
- indikator harga di bagian bawah dashboard.
7.5 Indikator harga
Indikator harga mengambil data dari response prediksi, bukan membuat prediksi sendiri di frontend. Indikator menampilkan:
- Naik;
- Turun;
- Stabil;
- perubahan Rupiah pada langkah terakhir;
- perubahan persentase pada langkah terakhir.
8. Fitur panel admin
Panel admin menggunakan route #/admin.
8.1 Autentikasi
Fitur autentikasi:
- register;
- login;
- logout;
- session cookie;
- role
userdanadmin.
Endpoint admin memerlukan role admin.
8.2 Ringkasan
Ringkasan menampilkan informasi operasional:
- jumlah data harga;
- jumlah komoditas;
- jumlah pasar;
- status pembaruan terakhir;
- jumlah data terbaru dari scraping terakhir.
8.3 Dataset harga
Halaman Dataset harga menyediakan:
- tabel data harga;
- filter komoditas;
- filter pasar;
- pagination;
- harga dan tanggal data.
8.4 Perbarui data
Fitur Perbarui data menyediakan:
- pilihan komoditas scraping;
- tanggal mulai dan tanggal akhir;
- progress bar scraping;
- log riwayat scraping;
- jenis cabai pada setiap log;
- status scraping;
- jumlah data baru;
- detail data yang masuk;
- filter detail berdasarkan komoditas dan pasar;
- pagination;
- tombol hapus log;
- modal konfirmasi penghapusan.
8.5 Preprocessing
Section preprocessing berada di bagian bawah halaman Perbarui data. Admin dapat:
- memilih satu riwayat scraping;
- melihat jenis cabai dan jumlah data pada dropdown;
- menjalankan preprocessing;
- melihat progress;
- melihat jumlah baris yang diisi;
- melihat warning gap yang tidak dapat diisi.
9. Endpoint API
Prefix API:
/api/v1
Endpoint publik
| Method | Endpoint | Keterangan |
|---|---|---|
GET |
/ |
Status API dasar |
GET |
/api/v1/health |
Status API dan artifact model |
GET |
/api/v1/commodities |
Daftar komoditas tersedia |
GET |
/api/v1/markets |
Daftar pasar dan ketersediaan komoditas |
GET |
/api/v1/history |
Riwayat harga |
GET |
/api/v1/predict |
Prediksi satu pasar |
GET |
/api/v1/predict/map |
Prediksi ringkas seluruh pasar |
Contoh:
GET /api/v1/history?commodity=rawit&market=pasar_tanjung&days=30
GET /api/v1/predict?commodity=rawit&market=pasar_tanjung&horizon=7
GET /api/v1/predict/map?commodity=rawit&horizon=7
Endpoint autentikasi
| Method | Endpoint | Keterangan |
|---|---|---|
GET |
/api/v1/auth/me |
User session saat ini |
POST |
/api/v1/auth/register |
Registrasi user |
POST |
/api/v1/auth/login |
Login |
POST |
/api/v1/auth/logout |
Logout |
Endpoint admin
| Method | Endpoint | Keterangan |
|---|---|---|
GET |
/api/v1/admin/overview |
Ringkasan operasional |
GET |
/api/v1/admin/models |
Metadata/status model |
GET |
/api/v1/admin/scraping/logs |
Riwayat scraping |
GET |
/api/v1/admin/scraping/logs/<id>/records |
Detail data dari log |
POST |
/api/v1/admin/scraping/jobs |
Memulai scraping |
GET |
/api/v1/admin/scraping/jobs/<id> |
Status scraping |
DELETE |
/api/v1/admin/scraping/logs/<id> |
Hapus log dan data terkait |
DELETE |
/api/v1/admin/scraping/history |
Hapus history scraping |
POST |
/api/v1/admin/preprocessing/jobs |
Memulai preprocessing |
GET |
/api/v1/admin/preprocessing/jobs/<id> |
Status preprocessing |
GET |
/api/v1/prices |
Dataset harga dengan pagination |
Format error API:
{
"error": {
"code": "ERROR_CODE",
"message": "Pesan untuk pengguna",
"details": {}
}
}
10. Struktur database
Schema lengkap tersedia pada database/panen_harga.sql.
Tabel utama
| Tabel | Fungsi |
|---|---|
commodities |
Master jenis cabai |
markets |
Master pasar dan koordinat |
price_history |
Harga aktual per komoditas, pasar, dan tanggal |
scraping_logs |
Riwayat proses scraping |
preprocessing_runs |
Riwayat proses preprocessing |
users |
Akun dan role |
training_runs |
Metadata training jika dikelola di luar API |
model_versions |
Metadata versi model |
predictions |
Struktur penyimpanan forecast jika digunakan |
Relasi penting:
commodities 1 ─── * price_history
markets 1 ─── * price_history
scraping_logs 1 ─── * price_history
commodities 1 ─── * training_runs
commodities 1 ─── * model_versions
Kunci unik price_history adalah kombinasi:
commodity_id + market_id + price_date
Karena itu scraping tanggal yang sama akan memperbarui data yang sudah ada, bukan membuat duplikat baru.
11. Konfigurasi environment
Variabel penting backend:
| Variabel | Default | Fungsi |
|---|---|---|
DATA_SOURCE |
mysql |
Sumber data aktif |
MYSQL_HOST |
127.0.0.1 |
Host MySQL |
MYSQL_PORT |
3306 |
Port MySQL |
MYSQL_DATABASE |
prediksicabe |
Nama database |
MYSQL_USER |
root |
User database |
MYSQL_PASSWORD |
kosong | Password database |
MODELS_DIR |
api/models |
Folder artifact |
DATA_DIR |
folder api | Folder CSV |
PRICE_UNIT_SCALE |
1000 |
Skala CSV lama ke Rupiah |
ALLOWED_HORIZONS |
1,3,7 |
Horizon yang diizinkan |
MAX_HORIZON |
7 |
Batas horizon |
CORS_ORIGINS |
localhost:5173 | Origin frontend |
STALE_DATA_DAYS |
30 |
Ambang data lama |
TREND_THRESHOLD_PCT |
1 |
Ambang status tren |
SISKAPERBAPO_TIMEOUT |
30 |
Timeout request scraper |
Untuk produksi, ganti SECRET_KEY default dan batasi CORS_ORIGINS hanya pada
origin frontend yang dipercaya.
12. Cara menjalankan aplikasi
12.1 Menjalankan backend
Gunakan environment Conda yang sudah tersedia:
cd C:\PrediksiHargaCabe\api
C:\Users\alfia\anaconda3\envs\tf_gpu39\python.exe main.py
Atau gunakan script restart:
cd C:\PrediksiHargaCabe\api
powershell -ExecutionPolicy Bypass -File .\restart_backend.ps1
Backend berjalan di:
http://127.0.0.1:8000
12.2 Menjalankan frontend
cd C:\PrediksiHargaCabe\website
npm run dev
Frontend Vite biasanya berjalan di:
http://localhost:5173
12.3 Build frontend
cd C:\PrediksiHargaCabe\website
npm run lint
npm run build
12.4 Pengujian backend
cd C:\PrediksiHargaCabe\api
C:\Users\alfia\anaconda3\envs\tf_gpu39\python.exe -m pytest
13. Keamanan dan batasan operasional
- Endpoint admin dilindungi autentikasi dan role admin.
- Password disimpan dalam bentuk hash.
- Frontend tidak terhubung langsung ke database.
- Scheduler scraping otomatis belum diaktifkan.
- Training ulang otomatis belum diaktifkan.
- API tidak menjalankan
model.fit(). - Data input scraping tidak boleh dianggap sebagai hasil evaluasi model baru.
- Data terbaru hasil scraping adalah data operasional untuk inference.
- Jangan mengklaim model sebagai “global optimum”. Gunakan istilah: “konfigurasi terbaik yang diperoleh dari skema eksperimen yang diterapkan pada dataset penelitian.”
14. Batasan model dan interpretasi hasil
Recursive forecasting
Prediksi lebih dari satu hari menggunakan hasil prediksi sebelumnya sebagai input berikutnya. Akibatnya, error dapat terakumulasi pada horizon yang lebih panjang.
Ketersediaan artifact
Tidak semua komoditas harus tersedia pada semua pasar. Kombinasi tanpa artifact lengkap ditampilkan sebagai tidak tersedia.
Data lama
API dapat memberikan warning data_stale apabila tanggal data terakhir melewati
ambang STALE_DATA_DAYS.
Model deployment tidak sama dengan training ulang
Scraping baru tidak mengubah bobot model. Jika penelitian memerlukan model baru, training harus dilakukan melalui proses eksperimen terpisah, divalidasi, lalu artifact baru dideploy secara sadar.
15. Cara menjelaskan aplikasi saat presentasi
Urutan penjelasan yang disarankan:
- Jelaskan masalah: harga cabai berbeda antar pasar dan berubah dari waktu ke waktu.
- Jelaskan sumber data: dataset penelitian dan data SISKAPERBAPO.
- Jelaskan tiga komoditas dan pasar yang diamati.
- Tunjukkan peta digital pasar.
- Pilih komoditas dan pasar.
- Pilih horizon prediksi.
- Tekan tombol Prediksi.
- Jelaskan harga aktual terakhir, forecast, grafik, tabel, dan indikator tren.
- Jelaskan bahwa model menggunakan artifact LSTM yang sudah divalidasi.
- Jelaskan bahwa scraping memperbarui data aktual, bukan melatih ulang model.
- Tunjukkan panel admin untuk log scraping dan preprocessing.
- Jelaskan keterbatasan model dan pasar yang artifact-nya belum tersedia.
16. Ringkasan satu paragraf
Panen Harga adalah aplikasi web berbasis React dan Flask yang menggunakan model LSTM tersimpan untuk memprediksi harga tiga komoditas cabai di pasar-pasar Kabupaten Jember. Data harga disimpan dalam MySQL menggunakan Rupiah penuh, sedangkan model dan scaler dimuat dari artifact saat backend dimulai. Pengguna dapat memilih komoditas, pasar, dan horizon prediksi, kemudian melihat hasilnya melalui peta Leaflet, ranking pasar, grafik riwayat, grafik forecast, tabel prediksi, dan indikator tren. Admin dapat melakukan scraping manual dari SISKAPERBAPO, memantau progress, melihat log, menghapus hasil scraping, dan menjalankan preprocessing terbatas. Sistem tidak melakukan scheduler maupun training ulang otomatis sehingga artifact model penelitian tetap terkendali.