86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import api, fields, models
|
|
|
|
|
|
class SaatTransaksi(models.Model):
|
|
"""Catat setiap pembelian / penjualan saham."""
|
|
_name = 'saat.transaksi'
|
|
_description = "Transaksi Jual/Beli Saham"
|
|
_order = 'tanggal desc, id desc'
|
|
|
|
TIPE = [('buy', 'Beli'), ('sell', 'Jual')]
|
|
|
|
name = fields.Char(string="Referensi", compute='_compute_name', store=True)
|
|
tanggal = fields.Date(string="Tanggal", required=True, default=fields.Date.context_today)
|
|
tipe = fields.Selection(TIPE, string="Tipe", required=True, default='buy')
|
|
saham_id = fields.Many2one('saat.saham', string="Saham", required=True, ondelete='restrict')
|
|
volume = fields.Integer(string="Jumlah Lembar", required=True)
|
|
harga = fields.Monetary(string="Harga/Lembar", currency_field='currency_id', required=True)
|
|
fee = fields.Monetary(string="Biaya (Komisi/PPN)", currency_field='currency_id', default=0.0)
|
|
total = fields.Monetary(
|
|
string="Total Biaya", currency_field='currency_id',
|
|
compute='_compute_total', store=True)
|
|
catatan = fields.Text(string="Catatan")
|
|
user_id = fields.Many2one('res.users', string="Pencatat", default=lambda self: self.env.user)
|
|
currency_id = fields.Many2one(
|
|
'res.currency', string="Mata Uang", default=lambda self: self._default_currency())
|
|
|
|
@api.model
|
|
def _default_currency(self):
|
|
# IDR
|
|
return self.env.ref('base.IDR', raise_if_not_found=False) or self.env.company.currency_id
|
|
|
|
state = fields.Selection([
|
|
('done', 'Selesai'),
|
|
('cancel', 'Dibatalkan'),
|
|
], string="Status", default='done', required=True, copy=False)
|
|
|
|
@api.depends('tanggal', 'tipe', 'saham_id')
|
|
def _compute_name(self):
|
|
for r in self:
|
|
ticker = r.saham_id.name or ''
|
|
tipe_label = dict(self.TIPE).get(r.tipe, '')
|
|
r.name = f"{r.tanggal or ''} {tipe_label} {ticker}"
|
|
|
|
@api.depends('volume', 'harga', 'fee', 'tipe')
|
|
def _compute_total(self):
|
|
for r in self:
|
|
r.total = (r.volume or 0) * (r.harga or 0) + (r.fee or 0)
|
|
|
|
@api.constrains('volume', 'harga')
|
|
def _check_positive(self):
|
|
for r in self:
|
|
if r.volume <= 0:
|
|
raise models.ValidationError("Volume harus lebih dari 0.")
|
|
if r.harga < 0:
|
|
raise models.ValidationError("Harga tidak boleh negatif.")
|
|
|
|
def action_cancel(self):
|
|
self.write({'state': 'cancel'})
|
|
return True
|
|
|
|
def action_set_to_done(self):
|
|
self.write({'state': 'done'})
|
|
return True
|
|
|
|
# --- auto-sync portofolio: setiap transaksi berubah, portofolio diperbarui ---
|
|
def _resync_portofolio(self):
|
|
"""Rekalkulasi portofolio dari seluruh transaksi (idempoten)."""
|
|
self.env['saat.portofolio'].action_recalculate()
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
res = super().create(vals_list)
|
|
res._resync_portofolio()
|
|
return res
|
|
|
|
def write(self, vals):
|
|
res = super().write(vals)
|
|
self._resync_portofolio()
|
|
return res
|
|
|
|
def unlink(self):
|
|
res = super().unlink()
|
|
self._resync_portofolio()
|
|
return res
|