Odoo-Tutorial/loan_management/models/loan_contract.py
2025-06-21 09:44:01 +07:00

177 lines
6.0 KiB
Python

from odoo import models, fields, api
from dateutil.relativedelta import relativedelta
class LoanContract(models.Model):
_name = 'loan.contract'
_description = 'Loan Contract'
code_contract = fields.Char(
string='Contract Code',
required=True,
copy=False,
readonly=True,
default=lambda self: self.env['ir.sequence'].next_by_code('loan.contract')
)
repayment_line_ids = fields.One2many('repayment.line', 'contract_id', string='Lịch trả nợ')
loan_request_id = fields.Many2one(
'loan.request',
string='Loan Request',
required=True,
ondelete='restrict'
)
borrower_id = fields.Many2one(
'loan.borrower',
string='Borrower',
required=True,
ondelete='restrict'
)
loan_type_id = fields.Many2one(
'loan.type1',
string='Loan Type',
readonly=True
)
amount = fields.Float(
string='Loan Amount',
required=True
)
term = fields.Integer(
string='Term (Months)',
required=True
)
payment_method = fields.Selection([
('cash', 'Cash'),
('bank_transfer', 'Bank Transfer'),
('check', 'Check')
], string='Payment Method', required=True, default='cash',readonly=True)
repayment_type = fields.Selection([
('fixed_principal', 'Trả gốc đều, lãi giảm dần'),
('annuity', 'Trả góp đều (gốc + lãi)'),
('interest_only', 'Chỉ trả lãi hàng kỳ, gốc trả cuối'),
('lump_sum', 'Trả 1 lần cuối kỳ'),
], string='Kiểu trả nợ', required=True, readonly=True)
interest_rate = fields.Float(
string='Interest Rate (%)',
required=True
)
processing_fee = fields.Float(
string='Processing Fee',
compute='_compute_processing_fee_amount_count',
store=True,
readonly=True
)
amount_count = fields.Float(
string='Amount Count',
compute='_compute_processing_fee_amount_count',
store=True,
readonly=True
)
start_date = fields.Date(
string='Start Date',
required=True,
default=fields.Date.context_today
)
end_date = fields.Date(
string='End Date',
compute='_compute_end_date',
store=True,
readonly=True,
)
state = fields.Selection([
('draft', 'Draft'),
('active', 'Active'),
('done', 'Completed'),
('cancelled', 'Cancelled')
], string='Status', default='draft')
note = fields.Text(string='Notes')
@api.depends('start_date', 'term')
def _compute_end_date(self):
for rec in self:
if rec.start_date and rec.term:
rec.end_date = rec.start_date + relativedelta(months=rec.term)
else:
rec.end_date = False
@api.onchange('loan_request_id')
def _onchange_loan_request_id(self):
for rec in self:
if rec.loan_request_id:
rec.borrower_id = rec.loan_request_id.borrower_id
rec.loan_type_id = rec.loan_request_id.loan_type_id
rec.amount = rec.loan_request_id.amount
rec.interest_rate = rec.loan_request_id.interest_rate
rec.term = rec.loan_request_id.term
rec.repayment_type = rec.loan_request_id.repayment_type
@api.depends('loan_request_id')
def _compute_processing_fee_amount_count(self):
for rec in self:
if rec.loan_request_id:
rec.tinterest_rate = rec.loan_request_id.interest_rate or 0.0
rec.amount = rec.loan_request_id.amount or 0.0
rec.processing_fee = rec.amount - (rec.amount * rec.rate / 100)
rec.amount_count = rec.amount + rec.processing_fee
else:
rec.processing_fee = 0.0
rec.amount_count = 0.0
@api.model
def create(self, vals):
if vals.get('loan_request_id'):
request = self.env['loan.request'].browse(vals['loan_request_id'])
vals['repayment_type'] = request.repayment_type
vals['payment_method'] = request.payment_method
return super().create(vals)
@api.model
def write(self, vals):
res = super().write(vals)
for contract in self:
if vals.get('state') == 'active':
contract._generate_repayment_schedule()
return res
def _generate_repayment_schedule(self):
self.repayment_line_ids.unlink() # Xóa cũ nếu có
start_date = self.start_date
monthly_rate = self.interest_rate / 100 / 12
principal = self.amount
term = self.term
for i in range(1, term + 1):
due_date = start_date + relativedelta(months=i)
if self.repayment_type == 'fixed_principal':
principal_amount = principal / term
remaining = principal - principal_amount * (i - 1)
interest = remaining * monthly_rate
elif self.repayment_type == 'annuity':
annuity = principal * monthly_rate / (1 - (1 + monthly_rate) ** (-term))
interest = (principal - (i - 1) * (annuity - principal * monthly_rate)) * monthly_rate
principal_amount = annuity - interest
elif self.repayment_type == 'interest_only':
principal_amount = 0.0 if i < term else principal
interest = principal * monthly_rate
elif self.repayment_type == 'lump_sum':
principal_amount = principal if i == term else 0.0
interest = principal * monthly_rate if i == term else 0.0
else:
principal_amount = interest = 0.0
self.env['repayment.line'].create({
'contract_id': self.id,
'installment': i,
'due_date': due_date,
'principal': principal_amount,
'interest': interest,
'total': principal_amount + interest,
})