Files
saat-app/README.md
2026-09-17 20:31:08 +07:00

7.0 KiB
Raw Permalink Blame History

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 admin verified) — endpoint yang akan dipakai Flutter
  • ✅ Addon saat_invest terinstal (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

  • .env berisi rahasia → tidak boleh di-commit (sudah di .gitignore)
  • PostgreSQL tidak di-publish ke host, hanya akses antar-container
  • Ganti ADMIN_PASSWD segera setelah setup awal