Files
saat-app/PLAN.md
Alex Ardhian d657a0a8f0 Aplikasi catat jual-beli saham: Odoo 17 + Postgres 16 + addon saat_invest
- docker-compose.yml: odoo:17.0 (port 8069) + postgres:16 (internal, no publish)
- Addon saat_invest: model saat.saham / saat.transaksi / saat.portofolio
  - P/L computed (realized FIFO, unrealized dari harga_sekarang)
  - action_recalculate() endpoint untuk Flutter
  - seed 5 saham IDX (BBRI, TLKM, BBCA, ASII, PTBA)
- JSON-RPC end-to-end terverifikasi: create beli/jual -> recalculate -> portfolio
  (avg_cost 4525, realized 65000, unrealized 220000, nilai 3840000)
- PLAN.md: rancangan disetujui Bozz
- Login Odoo admin/admin (ganti password master di .env, jangan commit)
2026-09-02 11:23:39 +07:00

1.7 KiB
Raw Permalink Blame History

Rancangan Addon saat_invest — Catat Jual/Beli Saham

Status: Disetujui oleh Bozz (2026-09-02) Backend: Odoo 17 Community

Keputusan (dari Bozz)

  1. Hitung P/L otomatis (computed) di Odoo dari data transaksi.
  2. Seed 5 saham contoh IDX saat install (BBRI, TLKM, BBCA, +2).
  3. Endpoint JSON-RPC khusus untuk Flutter (method Python, dipanggil via execute_kw).

Model

  • saat.saham — master saham (ticker name, perusahaan, sector)
  • saat.transaksi — catat beli/jual (tanggal, tipe buy/sell, saham, volume, harga, fee, catatan)
  • saat.portofolio — ringkasan per saham (jumlah lembar, avg_cost, investasi, realized/unrealized P/L — semua computed dari transaksi)

Relasi & perhitungan

  • Total lembar = Σ(buy.volume) − Σ(sell.volume) per saham
  • Realized P/L = saat sell: (harga_jual − avg_cost) × volume − fee
  • Unrealized P/L = (harga_sekarang − avg_cost) × sisa lembar
  • Avg cost = weighted average (total beli ÷ jumlah lembar beli)

API (untuk Flutter, via execute_kw JSON-RPC)

  • saat.portofolio.search_read — daftar posisi
  • saat.transaksi.create / search_read — catat & lihat transaksi
  • Method khusus: action_calculate_portfolio() pada saat.portofolio akselerasi agregasi

Struktur file

addons/saat_invest/
├── __manifest__.py
├── __init__.py
├── models/{__init__,saham,transaksi,portofolio}.py
├── security/ir.model.access.csv
├── data/saat.demo.saham.csv   (seed)
└── views/{saham,transaksi,portofolio}_views.xml

Keamanan

  • Model internal (group Sales? no → buat group "User Investasi" via access CSV)
  • Record rule: user hanya akses data miliknya (default res.users via owner field opsional; v1 sederhana → semua internal user bisa CRUD)