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.
193 lines
9.7 KiB
193 lines
9.7 KiB
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
|
# Author: Ammu Raj(odoo@cybrosys.com)
|
|
#
|
|
# You can modify it under the terms of the GNU LESSER
|
|
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
|
# (LGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
#############################################################################
|
|
import math
|
|
from dateutil import relativedelta
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
""" Extending model Invoice model to compute the interest amount for
|
|
overdue invoices based on the chosen payment term configurations."""
|
|
|
|
_inherit = "account.move"
|
|
|
|
interest_amount = fields.Monetary(string='Interest Amount', readonly=True,
|
|
help='The amount of interest accrued.')
|
|
interest_overdue_act = fields.Boolean(related="invoice_payment_term_id"
|
|
".interest_overdue_act",
|
|
help='Flag indicating whether overdue interest is active.')
|
|
interest_calculated_period = fields.Char(string="Interest calculated date",
|
|
help='The date when interest was calculated.')
|
|
interest_type = fields.Selection(related="invoice_payment_term_id"
|
|
".interest_type",
|
|
help='The type of interest applied.')
|
|
interest_percentage = fields.Float(related="invoice_payment_term_id"
|
|
".interest_percentage",
|
|
help='The percentage rate of interest applied.')
|
|
|
|
def get_period_time(self, today_date):
|
|
""" Compute period duration based on Interest duration type. """
|
|
self.ensure_one()
|
|
r_obj = relativedelta. \
|
|
relativedelta(today_date, self.invoice_date_due)
|
|
if self.invoice_payment_term_id.interest_type == 'monthly':
|
|
period = (r_obj.years * 12) + r_obj.months
|
|
if r_obj and r_obj.days > 0:
|
|
period = period + 1
|
|
elif self.invoice_payment_term_id.interest_type == 'weekly':
|
|
period = math.ceil(
|
|
(today_date - self.invoice_date_due).days / 7)
|
|
else:
|
|
period = (today_date - self.invoice_date_due).days
|
|
return period
|
|
|
|
def action_interest_compute(self):
|
|
""" Action for computing Interest amount based on the chosen payment
|
|
term configurations"""
|
|
today_date = fields.Date.today()
|
|
for rec in self:
|
|
if rec.invoice_date_due \
|
|
and rec.invoice_date_due < fields.Date.today() \
|
|
and rec.state == 'draft' \
|
|
and rec.move_type == 'out_invoice' \
|
|
and rec.interest_overdue_act \
|
|
and rec.invoice_payment_term_id.interest_percentage > 0:
|
|
period = rec.get_period_time(today_date)
|
|
if rec.invoice_payment_term_id.interest_type == 'monthly':
|
|
if rec.interest_calculated_period \
|
|
and rec.interest_calculated_period == str(period) \
|
|
+ "-m":
|
|
raise ValidationError(_('Your payment term is '
|
|
'monthly, and you can update '
|
|
'it only once in a month.'))
|
|
rec.interest_calculated_period = str(period) + "-m"
|
|
elif rec.invoice_payment_term_id.interest_type == 'weekly':
|
|
if rec.interest_calculated_period \
|
|
and rec.interest_calculated_period == str(period) \
|
|
+ "-w":
|
|
raise ValidationError(_('Your payment term is weekly, '
|
|
'and you can update it only '
|
|
'once in a week.'))
|
|
rec.interest_calculated_period = str(period) + "-w"
|
|
else:
|
|
if rec.interest_calculated_period \
|
|
and rec.interest_calculated_period == str(period) \
|
|
+ "-d":
|
|
raise ValidationError(_('Your payment term is daily, '
|
|
'and you can update it only '
|
|
'once in a day.'))
|
|
rec.interest_calculated_period = str(period) + "-d"
|
|
interest_line = rec.invoice_line_ids.search(
|
|
[('name', '=', 'Interest Amount for Overdue'),
|
|
('move_id', '=', rec.id)],
|
|
limit=1)
|
|
if interest_line:
|
|
rec.invoice_line_ids = ([(2, interest_line.id, 0)])
|
|
rec.interest_amount = rec.amount_total * rec \
|
|
.invoice_payment_term_id.interest_percentage * period / 100
|
|
vals = {'name': 'Interest Amount for Overdue',
|
|
'price_unit': rec.interest_amount,
|
|
'quantity': 1,
|
|
}
|
|
if rec.invoice_payment_term_id.interest_account_id:
|
|
vals.update({
|
|
'account_id': rec.invoice_payment_term_id
|
|
.interest_account_id.id})
|
|
if rec.interest_amount > 0:
|
|
rec.invoice_line_ids = ([(0, 0, vals)])
|
|
elif rec.interest_amount > 0:
|
|
rec.action_interest_reset()
|
|
|
|
def _get_interest_check(self):
|
|
""" Method for Interest computation via scheduled action """
|
|
|
|
today_date = fields.Date.today()
|
|
for rec in self.sudo().search([('state', '=', 'draft')]):
|
|
if rec.invoice_date_due and rec.invoice_date_due < today_date \
|
|
and rec.state == 'draft' \
|
|
and rec.move_type == 'out_invoice' \
|
|
and rec.interest_overdue_act \
|
|
and rec.invoice_payment_term_id.interest_percentage > 0:
|
|
period = rec.get_period_time(today_date)
|
|
if rec.invoice_payment_term_id.interest_type == 'monthly':
|
|
if rec.interest_calculated_period \
|
|
and rec.interest_calculated_period == str(period) \
|
|
+ "-m":
|
|
continue
|
|
rec.interest_calculated_period = str(period) + "-m"
|
|
elif rec.invoice_payment_term_id.interest_type == 'weekly':
|
|
if rec.interest_calculated_period \
|
|
and rec.interest_calculated_period == str(period) \
|
|
+ "-w":
|
|
continue
|
|
rec.interest_calculated_period = str(period) + "-w"
|
|
else:
|
|
if rec.interest_calculated_period \
|
|
and rec.interest_calculated_period == str(period) \
|
|
+ "-d":
|
|
continue
|
|
rec.interest_calculated_period = str(period) + "-d"
|
|
interest_line = rec.invoice_line_ids.search(
|
|
[('name', '=', 'Interest Amount for Overdue'),
|
|
('move_id', '=', rec.id)], limit=1)
|
|
if interest_line:
|
|
rec.invoice_line_ids = ([(2, interest_line.id, 0)])
|
|
rec.interest_amount = rec.amount_total * rec \
|
|
.invoice_payment_term_id.interest_percentage * period / 100
|
|
vals = {'name': 'Interest Amount for Overdue',
|
|
'price_unit': rec.interest_amount,
|
|
'quantity': 1,
|
|
}
|
|
if rec.invoice_payment_term_id.interest_account_id:
|
|
vals.update({
|
|
'account_id': rec.invoice_payment_term_id.
|
|
interest_account_id.id})
|
|
if rec.interest_amount > 0:
|
|
rec.invoice_line_ids = ([(0, 0, vals)])
|
|
elif rec.interest_amount > 0:
|
|
rec.action_interest_reset()
|
|
|
|
def action_interest_reset(self):
|
|
"""Method for resetting the interest lines and Interest amount in
|
|
Invoice"""
|
|
self.interest_amount = 0
|
|
interest_line = self.invoice_line_ids.search(
|
|
[('name', '=', 'Interest Amount for Overdue'),
|
|
('move_id', '=', self.id)], limit=1)
|
|
if interest_line:
|
|
self.invoice_line_ids = ([(2, interest_line.id, 0)])
|
|
self.interest_calculated_period = False
|
|
|
|
@api.onchange('invoice_payment_term_id', 'invoice_line_ids',
|
|
'invoice_date_due')
|
|
def _onchange_invoice_payment_term_id(self):
|
|
"""Method for removing interest from Invoice when user changes dependent
|
|
values of interest."""
|
|
for rec in self:
|
|
if rec.move_type == 'out_invoice':
|
|
rec.interest_amount = 0
|
|
interest_line = rec.invoice_line_ids.search(
|
|
[('name', '=', 'Interest Amount for Overdue')], limit=1)
|
|
if interest_line:
|
|
rec.invoice_line_ids = ([(2, interest_line.id, 0)])
|
|
rec.interest_calculated_period = False
|
|
return
|
|
|