# -*- coding: utf-8 -*- ############################################################################## # # Author: Yannick Vaucher # Copyright 2013 Camptocamp SA # Copyright (C) 2004-2010 OpenERP S.A. (www.odoo.com) # Copyright (C) 2015 Akretion (http://www.akretion.com) # @author Alexis de Lattre # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # 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 for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # ############################################################################## from datetime import datetime from dateutil.relativedelta import relativedelta import time from openerp import models, fields, api from openerp.tools.float_utils import float_round import openerp.addons.decimal_precision as dp from openerp.tools import DEFAULT_SERVER_DATE_FORMAT class AccountPaymentTermLine(models.Model): _inherit = "account.payment.term.line" amount_round = fields.Float( string='Amount Rounding', digits=dp.get_precision('Account'), # TODO : I don't understand this help msg ; what is surcharge ? help="Sets the amount so that it is a multiple of this value.\n" "To have amounts that end in 0.99, set rounding 1, " "surcharge -0.01") months = fields.Integer(string='Number of Months') weeks = fields.Integer(string='Number of Weeks') start_with_end_month = fields.Boolean( string='Start by End of Month', help="If you have a payment term 'End of month 45 days' " "(which is not the same as '45 days end of month' !), you " "should activate this option and then set " "'Number of days' = 45 and 'Day of the month' = 0.") @api.multi def compute_line_amount(self, total_amount, remaining_amount): """Compute the amount for a payment term line. In case of procent computation, use the payment term line rounding if defined :param total_amount: total balance to pay :param remaining_amount: total amount minus sum of previous lines computed amount :returns: computed amount for this line """ self.ensure_one() prec = self.env['decimal.precision'].precision_get('Account') if self.value == 'fixed': return float_round(self.value_amount, precision_digits=prec) elif self.value == 'procent': amt = total_amount * self.value_amount if self.amount_round: amt = float_round(amt, precision_rounding=self.amount_round) return float_round(amt, precision_digits=prec) elif self.value == 'balance': return float_round(remaining_amount, precision_digits=prec) return None class AccountPaymentTerm(models.Model): _inherit = "account.payment.term" def compute(self, cr, uid, id, value, date_ref=False, context=None): """Complete overwrite of compute method to add rounding on line computing and also to handle weeks and months """ obj_precision = self.pool['decimal.precision'] prec = obj_precision.precision_get(cr, uid, 'Account') if not date_ref: date_ref = datetime.now().strftime(DEFAULT_SERVER_DATE_FORMAT) pt = self.browse(cr, uid, id, context=context) amount = value result = [] for line in pt.line_ids: amt = line.compute_line_amount(value, amount) if not amt: continue next_date = fields.Date.from_string(date_ref) if line.start_with_end_month: next_date += relativedelta(day=1, months=1, days=-1) next_date += relativedelta( days=line.days, weeks=line.weeks, months=line.months) if line.days2 < 0: # Getting 1st of next month next_date += relativedelta(day=1, months=1, days=line.days2) if line.days2 > 0: next_date += relativedelta(day=line.days2, months=1) result.append( (fields.Date.to_string(next_date), amt)) amount -= amt amount = reduce(lambda x, y: x + y[1], result, 0.0) dist = round(value - amount, prec) if dist: result.append((time.strftime(DEFAULT_SERVER_DATE_FORMAT), dist)) return result