Aplikasi Catat Jual-Beli Saham — Odoo 17 + Flutter
Backend Odoo ERP (Community 17) untuk mencatat pembelian & penjualan saham, diakses dari aplikasi Flutter (Android).
Arsitektur
Flutter app (Android) ──JSON-RPC──► Odoo 17 (Python)
│ custom addon: saat_invest
▼
PostgreSQL 16
Stack
| Layer | Teknologi | Port |
|---|---|---|
| Backend | Odoo 17 Community (odoo:17.0) |
18069 (host) |
| Database | PostgreSQL 16 (postgres:16) |
internal (5432, tdk di-publish) |
| Mobile | Flutter (Android) | — |
Struktur proyek
saat-app/
├── docker-compose.yml # Odoo 17 + PostgreSQL 16
├── .env # RAHASIA: password (jangan commit)
├── addons/ # custom addon buatan sendiri (saat_invest)
└── README.md
Cara menjalankan
cd /home/ardhi/Application/saat-app
docker compose config # validasi
docker compose up -d # start
Akses UI: http://localhost:18069 — login admin dengan password
ODOO_ADMIN_PASSWORD di .env.
Troubleshooting
PermissionError: /var/lib/odoo/sessions
Odoo 17 berjalan sebagai user dengan UID/GID 101. Perbaiki ownership
named volume Odoo tanpa menghapus database atau filestore:
cid=$(docker compose ps -q odoo)
docker exec --user root "$cid" sh -c \
'chown -R 101:101 /var/lib/odoo && \
chmod 755 /var/lib/odoo && chmod 700 /var/lib/odoo/sessions'
Verifikasi bahwa user Odoo dapat menulis session:
docker exec --user odoo "$cid" sh -c \
'touch /var/lib/odoo/sessions/.write-check && \
rm /var/lib/odoo/sessions/.write-check'
Gunakan satu volume utama berikut pada docker-compose.yml; jangan membuat
mount terpisah untuk /var/lib/odoo/session (singular):
volumes:
- saat_odoo_filestore:/var/lib/odoo
column res_lang.short_time_format does not exist
Pastikan versi image Odoo sama dengan versi database. Database proyek ini adalah Odoo 17, jadi gunakan:
image: odoo:17.0
Jangan menjalankan database Odoo 17 dengan image Odoo 18 tanpa proses upgrade major-version yang resmi.
Tidak bisa login sebagai admin
Jika log menunjukkan Login failed dan user admin aktif, reset password
melalui ORM Odoo menggunakan nilai ODOO_ADMIN_PASSWORD dari .env:
set -a && source .env && set +a
docker compose exec -T -e RESET_PASSWORD="$ODOO_ADMIN_PASSWORD" odoo \
odoo shell -d "$POSTGRES_DB" --db_host=db --db_port=5432 \
--db_user="$POSTGRES_USER" --db_password="$POSTGRES_PASSWORD" --no-http <<'PY'
import os
user = env['res.users'].search([('login', '=', 'admin')], limit=1)
if not user.exists() or not user.active:
raise RuntimeError('Active admin user was not found')
user.write({'password': os.environ['RESET_PASSWORD']})
env.cr.commit()
print('Admin password reset')
PY
Setelah itu login dengan user admin dan password ODOO_ADMIN_PASSWORD.
Status
- ✅ Odoo 17 container jalan (port 18069), DB PostgreSQL 16 healthy
- ✅ JSON-RPC aktif (uid
adminverified) — endpoint yang akan dipakai Flutter - ✅ Addon
saat_investterinstal (model saham, transaksi, portofolio + seed 5 saham IDX) - ✅ Portofolio auto-sync: otomatis diperbarui tiap transaksi ditambah/ubah/hapus (tidak perlu tombol manual; buka menu Portofolio selalu datanya segar)
- ✅ Live harga pasar (cron): ambil & update harga dari Yahoo Finance (.JK) tiap 6 menit SAAT jam bursa IDX (08:45–16:00 WIB). Update hanya bila berubah.
- ✅ End-to-end teruji: buat beli/jual → portofolio ter-update → hitung avg cost & realized/unrealized P/L
- ⏳ Aplikasi Flutter (login, catat jual/beli, portfolio, P/L)
Install / upgrade addon saat_invest
cd /home/ardhi/Application/saat-app
set -a && source .env && set +a
# install pertama kali
docker exec -e PASSWORD="$POSTGRES_PASSWORD" saat-odoo odoo \
-d "$POSTGRES_DB" --db_host=db --db_user="$POSTGRES_USER" \
--db_password="$POSTGRES_PASSWORD" --no-http --stop-after-init -i saat_invest
# upgrade setelah ubah kode
docker exec -e PASSWORD="$POSTGRES_PASSWORD" saat-odoo odoo \
-d "$POSTGRES_DB" --db_host=db --db_user="$POSTGRES_USER" \
--db_password="$POSTGRES_PASSWORD" --no-http --stop-after-init -u saat_invest
docker restart saat-odoo
Catatan Odoo:
<list>view di Odoo 17 kadang bermasalah, pakai<tree>(kompatibel lintas versi) seperti yang sudah dilakukan.
API untuk Flutter (via JSON-RPC execute_kw)
Semua melalui POST /jsonrpc dengan {service:'object', method:'execute_kw'}.
Login: common.authenticate(db, user, pass) → uid.
- List saham:
saat.saham search_read [domain] {fields} - Catat transaksi:
saat.transaksi create [{vals}] - List transaksi:
saat.transaksi search_read [domain] {fields} - Rekalkulasi portofolio:
saat.portofolio action_recalculate [[]] - Baca portofolio:
saat.portofolio search_read [domain] {fields}(sisa_lembar, avg_cost, total_beli_biaya, realized_pl, unrealized_pl, nilai_sekarang)
Catatan keamanan
.envberisi rahasia → tidak boleh di-commit (sudah di.gitignore)- PostgreSQL tidak di-publish ke host, hanya akses antar-container
- Ganti
ADMIN_PASSWDsegera setelah setup awal