7.0 KiB
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/workspace/erp/odoo-app/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.
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.
Troubleshooting PermissionError sessions
Jika muncul:
PermissionError: [Errno 13] Permission denied: '/var/lib/odoo/sessions'
Odoo 17 berjalan sebagai user odoo dengan UID/GID 101. Perbaiki
ownership seluruh volume data Odoo dari container yang sedang berjalan:
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 write access sebagai user Odoo, lalu restart dan cek log:
docker exec --user odoo "$cid" sh -c \
'touch /var/lib/odoo/sessions/.write-check && \
rm /var/lib/odoo/sessions/.write-check'
docker compose restart odoo
docker compose logs --since=30s odoo
Gunakan hanya satu mount volume utama berikut pada Compose:
volumes:
- saat_odoo_filestore:/var/lib/odoo
Jangan menambahkan mount terpisah ke /var/lib/odoo/session (singular).
Path yang dipakai Odoo adalah /var/lib/odoo/sessions (plural). Jangan
menggunakan chmod 777; cukup berikan ownership kepada user Odoo.
Rencana migrasi Odoo 17 ke Odoo 18
Migrasi major version harus mengubah schema database. Mengganti image secara
langsung dari odoo:17.0 ke odoo:18.0 bukan prosedur migrasi dan dapat
menyebabkan error seperti column res_lang.short_time_format does not exist.
Compose harus tetap menggunakan odoo:17.0 sampai database selesai dimigrasi.
1. Persiapan dan backup
Pastikan .env terisi dan jangan commit file tersebut. Hentikan penulisan data,
lalu buat backup database dan filestore:
set -a && source .env && set +a
backup_dir="backups/odoo17-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
docker compose exec -T db pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc \
> "$backup_dir/database.dump"
volume=$(docker inspect saat-odoo --format '{{range .Mounts}}{{if eq .Destination "/var/lib/odoo"}}{{.Name}}{{end}}{{end}}')
docker run --rm -v "$volume:/source:ro" -v "$PWD/$backup_dir:/backup" alpine \
sh -c 'tar czf /backup/filestore.tar.gz -C /source .'
Validasi backup dengan pg_restore --list dari image PostgreSQL 16 dan pastikan
arsip filestore berisi direktori filestore/.
2. Migrasi pada salinan
Jangan menguji migrasi pada volume produksi. Restore database.dump dan
filestore.tar.gz ke environment staging yang terpisah, lalu gunakan salah
satu jalur resmi berikut:
- Odoo Upgrade Service untuk database Enterprise.
- OpenUpgrade dengan branch yang sesuai untuk migrasi Community 17 ke 18.
Migrasikan database terlebih dahulu. Sesuaikan custom addon saat_invest
dengan API, view, security, dan dependency Odoo 18, lalu install/upgrade addon
di database staging hasil migrasi.
3. Validasi staging
Uji login, menu saham, create/update/delete transaksi, kalkulasi portofolio,
cron harga pasar, attachment/filestore, dan seluruh endpoint JSON-RPC yang
dipakai Flutter. Periksa log untuk ERROR, Traceback, UndefinedColumn, dan
PermissionError.
4. Cutover produksi
Setelah staging lulus, hentikan Odoo 17, buat backup final, restore atau jalankan migrasi pada database produksi sesuai prosedur tool migrasi, kemudian ubah:
image: odoo:18.0
Pastikan ownership volume sesuai user Odoo 18 sebelum start, jalankan
docker compose up -d, dan ulangi seluruh validasi staging.
5. Rollback
Jika migrasi gagal, jangan menjalankan Odoo 17 pada database yang sudah sebagian
dimigrasi. Hentikan stack, restore database dan filestore dari backup Odoo 17
ke volume/database terpisah, ubah image kembali ke odoo:17.0, lalu validasi
aplikasi sebelum cutover ulang.
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