You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

265 lines
12 KiB

# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Megha (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from datetime import datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class LoanRequest(models.Model):
"""Can create new loan requests and manage records"""
_name = 'loan.request'
_inherit = ['mail.thread']
_description = 'Loan Request'
name = fields.Char(string='Loan Reference', readonly=True,
copy=False, help="Sequence number for loan requests",
default=lambda self: 'New')
company_id = fields.Many2one('res.company', string='Company',
readonly=True,
help="Company Name",
default=lambda self: self.env.company)
currency_id = fields.Many2one('res.currency', string='Currency',
required=True, help="Currency",
default=lambda self: self.env.user.company_id.
currency_id)
loan_type_id = fields.Many2one('loan.type', string='Loan Type',
required=True, help="Can choose different "
"loan types suitable")
loan_amount = fields.Float(string="Loan Amount",
help="Total loan amount", )
disbursal_amount = fields.Float(string="Disbursal Amount",
help="Total loan amount "
"available to disburse")
tenure = fields.Integer(string="Tenure", default=1,
help="Installment period")
interest_rate = fields.Float(string="Interest Rate", help="Interest "
"percentage")
date = fields.Date(string="Date", default=fields.Date.today(),
readonly=True, help="Date")
partner_id = fields.Many2one('res.partner', string="Partner",
required=True,
help="Partner")
repayment_lines_ids = fields.One2many('repayment.line',
'loan_id',
string="Loan Line", index=True,
help="Repayment lines")
documents_ids = fields.Many2many('loan.documents',
string="Proofs",
help="Documents as proof")
img_attachment_ids = fields.Many2many('ir.attachment',
relation="m2m_ir_identity_card_rel",
column1="documents_ids",
string="Images",
help="Image proofs")
journal_id = fields.Many2one('account.journal',
string="Journal",
help="Journal types",
domain="[('type', '=', 'purchase'),"
"('company_id', '=', company_id)]",
)
debit_account_id = fields.Many2one('account.account',
string="Debit account",
help="Choose account for "
"disbursement debit")
credit_account_id = fields.Many2one('account.account',
string="Credit account",
help="Choose account for "
"disbursement credit")
reject_reason = fields.Text(string="Reason", help="Displays "
"rejected reason")
request = fields.Boolean(string="Request",
help="For monitoring the record")
state = fields.Selection(string='State',
selection=[('draft', 'Draft'), ('confirmed', 'Confirmed'),
('waiting', 'Waiting For Approval'),
('approved', 'Approved'), ('disbursed', 'Disbursed'),
('rejected', 'Rejected'), ('closed', 'Closed')],
copy=False, tracking=True, default='draft', help="Loan request states")
@api.model
def create(self, vals):
"""create auto sequence for the loan request records"""
loan_count = self.env['loan.request'].search(
[('partner_id', '=', vals['partner_id']),
('state', 'not in', ('draft', 'rejected', 'closed'))])
if loan_count:
for rec in loan_count:
if rec.state != 'closed':
raise UserError(
_('The partner has already an ongoing loan.'))
else:
if vals.get('name', 'New') == 'New':
vals['name'] = self.env['ir.sequence'].next_by_code(
'increment_loan_ref')
res = super().create(vals)
return res
@api.onchange('loan_type_id')
def _onchange_loan_type_id(self):
"""Changing field values based on the chosen loan type"""
type_id = self.loan_type_id
self.loan_amount = type_id.loan_amount
self.disbursal_amount = type_id.disbursal_amount
self.tenure = type_id.tenure
self.interest_rate = type_id.interest_rate
self.documents_ids = type_id.documents_ids
def action_loan_request(self):
"""Changes the state to confirmed and send confirmation mail"""
self.write({'state': "confirmed"})
partner = self.partner_id
loan_no = self.name
subject = 'Loan Confirmation'
message = (f"Dear {partner.name},<br/> This is a confirmation mail "
f"for your loan{loan_no}. We have submitted your loan "
f"for approval.")
outgoing_mail = self.company_id.email
mail_values = {
'subject': subject,
'email_from': outgoing_mail,
'author_id': self.env.user.partner_id.id,
'email_to': partner.email,
'body_html': message,
}
mail = self.env['mail.mail'].sudo().create(mail_values)
mail.send()
def action_request_for_loan(self):
"""Change the state to waiting for approval"""
if self.request:
self.write({'state': "waiting"})
else:
message_id = self.env['message.popup'].create(
{'message': _("Compute the repayments before requesting")})
return {
'name': _('Repayment'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'message.popup',
'res_id': message_id.id,
'target': 'new'
}
def action_loan_approved(self):
"""Change to Approved state"""
self.write({'state': "approved"})
def action_disburse_loan(self):
"""Disbursing the loan to customer and creating journal
entry for the disbursement"""
self.write({'state': "disbursed"})
for loan in self:
amount = loan.disbursal_amount
loan_name = loan.partner_id.name
reference = loan.name
journal_id = loan.journal_id.id
debit_account_id = loan.debit_account_id.id
credit_account_id = loan.credit_account_id.id
date_now = loan.date
debit_vals = {
'name': loan_name,
'account_id': debit_account_id,
'journal_id': journal_id,
'date': date_now,
'debit': amount > 0.0 and amount or 0.0,
'credit': amount < 0.0 and -amount or 0.0,
}
credit_vals = {
'name': loan_name,
'account_id': credit_account_id,
'journal_id': journal_id,
'date': date_now,
'debit': amount < 0.0 and -amount or 0.0,
'credit': amount > 0.0 and amount or 0.0,
}
vals = {
'name': f'DIS / {reference}',
'narration': reference,
'ref': reference,
'journal_id': journal_id,
'date': date_now,
'line_ids': [(0, 0, debit_vals), (0, 0, credit_vals)]
}
move = self.env['account.move'].create(vals)
move.action_post()
return True
def action_close_loan(self):
"""Closing the loan"""
demo = []
for check in self.repayment_lines_ids:
if check.state == 'unpaid':
demo.append(check)
if len(demo) >= 1:
message_id = self.env['message.popup'].create(
{'message': _("Pending Repayments")})
return {
'name': _('Repayment'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'message.popup',
'res_id': message_id.id,
'target': 'new'
}
self.write({'state': "closed"})
def action_loan_rejected(self):
"""You can add reject reasons here"""
return {'type': 'ir.actions.act_window',
'name': 'Loan Rejection',
'res_model': 'reject.reason',
'target': 'new',
'view_mode': 'form',
'context': {'default_loan': self.name}
}
def action_compute_repayment(self):
"""This automatically create the installment the employee need to pay to
company based on payment start date and the no of installments.
"""
self.request = True
for loan in self:
loan.repayment_lines_ids.unlink()
date_start = datetime.strptime(str(loan.date),'%Y-%m-%d') + relativedelta(months=1)
amount = loan.loan_amount / loan.tenure
interest = loan.loan_amount * loan.interest_rate
interest_amount = interest / loan.tenure
total_amount = amount + interest_amount
partner = self.partner_id
for rand_num in range(1, loan.tenure + 1):
self.env['repayment.line'].create({
'name': f"{loan.name}/{rand_num}",
'partner_id': partner.id,
'date': date_start,
'amount': amount,
'interest_amount': interest_amount,
'total_amount': total_amount,
'interest_account_id': self.env.ref('advanced_loan_management.'
'loan_management_'
'inrst_accounts').id,
'repayment_account_id': self.env.ref('advanced_loan_management.'
'demo_'
'loan_accounts').id,
'loan_id': loan.id})
date_start += relativedelta(months=1)
return True