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.
125 lines
6.0 KiB
125 lines
6.0 KiB
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
|
|
# Author: Tintuk Tomin(<https://www.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 odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
|
|
class AccountPaymentTermLine(models.Model):
|
|
_inherit = "account.payment.term.line"
|
|
|
|
value = fields.Selection([
|
|
('balance', 'Balance'),
|
|
('percent', 'Percent'),
|
|
('fixed', 'Fixed Amount'),
|
|
('instalment', 'Instalment')
|
|
], string='Type', required=True, default='balance',
|
|
help="Select here the kind of valuation related to this payment term line.")
|
|
period_type = fields.Selection([
|
|
('daily', 'Day(s)'),
|
|
('weekly', 'Week(s)'),
|
|
('monthly', 'Month(s)'),
|
|
('yearly', 'Year(s)'),
|
|
], string='Period Type', default='monthly')
|
|
period_count = fields.Integer('Number of instalments', default=1)
|
|
|
|
|
|
class AccountPaymentTerm(models.Model):
|
|
_inherit = "account.payment.term"
|
|
|
|
@api.constrains('line_ids')
|
|
def _check_lines(self):
|
|
print("djbdjbdbdik")
|
|
payment_term_lines = self.line_ids.sorted()
|
|
if payment_term_lines and payment_term_lines[-1].value not in ['balance', 'instalment']:
|
|
raise ValidationError(_('A Payment Term should have its last line of type Balance/Instalment.'))
|
|
lines = self.line_ids.filtered(lambda r: r.value == 'balance') or []
|
|
if len(lines) > 1:
|
|
raise ValidationError(_('A Payment Term should have only one line of type Balance.'))
|
|
lines = self.line_ids.filtered(lambda r: r.value == 'instalment') or []
|
|
if len(lines) > 1:
|
|
raise ValidationError(_('A Payment Term should have only one line of type Instalment.'))
|
|
lines = self.line_ids.filtered(lambda r: r.value in ['balance', 'instalment']) or []
|
|
if len(lines) > 1:
|
|
raise ValidationError(_('A Payment Term should have only one of type Balance and Instalment.'))
|
|
lines = self.line_ids.filtered(lambda r: r.value == 'instalment') or []
|
|
for line in lines:
|
|
if line.period_count == 0:
|
|
raise ValidationError(_('A Payment Term of type Instalment should have number of instalments more than 0.'))
|
|
|
|
def compute(self, value, date_ref=False, currency=None):
|
|
# self.ensure_one()
|
|
date_ref = date_ref or fields.Date.today()
|
|
amount = value
|
|
sign = value < 0 and -1 or 1
|
|
result = []
|
|
if not currency and self.env.context.get('currency_id'):
|
|
currency = self.env['res.currency'].browse(self.env.context['currency_id'])
|
|
elif not currency:
|
|
currency = self.env.company.currency_id
|
|
for line in self.line_ids:
|
|
if line.value == 'fixed':
|
|
amt = sign * currency.round(line.value_amount)
|
|
elif line.value == 'percent':
|
|
amt = currency.round(value * (line.value_amount / 100.0))
|
|
elif line.value == 'balance':
|
|
amt = currency.round(amount)
|
|
|
|
if line.value != 'instalment' and amt:
|
|
next_date = fields.Date.from_string(date_ref)
|
|
if line.option == 'day_after_invoice_date':
|
|
next_date += relativedelta(days=line.days)
|
|
if line.day_of_the_month > 0:
|
|
months_delta = (line.day_of_the_month < next_date.day) and 1 or 0
|
|
next_date += relativedelta(day=line.day_of_the_month, months=months_delta)
|
|
elif line.option == 'after_invoice_month':
|
|
next_first_date = next_date + relativedelta(day=1, months=1) # Getting 1st of next month
|
|
next_date = next_first_date + relativedelta(days=line.days - 1)
|
|
elif line.option == 'day_following_month':
|
|
next_date += relativedelta(day=line.days, months=1)
|
|
elif line.option == 'day_current_month':
|
|
next_date += relativedelta(day=line.days, months=0)
|
|
result.append((fields.Date.to_string(next_date), amt))
|
|
amount -= amt
|
|
elif line.value == 'instalment':
|
|
amt = currency.round(amount)
|
|
count = line.period_count
|
|
instalment_amount = currency.round(amt/count)
|
|
while count > 0:
|
|
next_date = fields.Date.from_string(date_ref)
|
|
if line.period_type == 'daily':
|
|
next_date += relativedelta(days=count)
|
|
elif line.period_type == 'weekly':
|
|
next_date += relativedelta(weeks=count)
|
|
elif line.period_type == 'monthly':
|
|
next_date += relativedelta(months=count)
|
|
else:
|
|
next_date += relativedelta(years=count)
|
|
result.append([fields.Date.to_string(next_date), instalment_amount])
|
|
count -= 1
|
|
amount -= amt
|
|
amount = sum(amt for _, amt in result)
|
|
dist = currency.round(value - amount)
|
|
if dist:
|
|
result[0][1] += dist
|
|
return result
|
|
|