- 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)
1.7 KiB
1.7 KiB
Rancangan Addon saat_invest — Catat Jual/Beli Saham
Status: Disetujui oleh Bozz (2026-09-02) Backend: Odoo 17 Community
Keputusan (dari Bozz)
- Hitung P/L otomatis (computed) di Odoo dari data transaksi.
- Seed 5 saham contoh IDX saat install (BBRI, TLKM, BBCA, +2).
- Endpoint JSON-RPC khusus untuk Flutter (method Python, dipanggil via
execute_kw).
Model
saat.saham— master saham (tickername,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 posisisaat.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)