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, })