account.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Yannick Vaucher
  5. # Copyright 2013 Camptocamp SA
  6. # Copyright (C) 2004-2010 OpenERP S.A. (www.odoo.com)
  7. # Copyright (C) 2015 Akretion (http://www.akretion.com)
  8. # @author Alexis de Lattre <alexis.delattre@akretion.com>
  9. #
  10. # This program is free software: you can redistribute it and/or modify
  11. # it under the terms of the GNU Affero General Public License as
  12. # published by the Free Software Foundation, either version 3 of the
  13. # License, or (at your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU Affero General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU Affero General Public License
  21. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. #
  23. ##############################################################################
  24. from datetime import datetime
  25. from dateutil.relativedelta import relativedelta
  26. import time
  27. from openerp import models, fields, api
  28. from openerp.tools.float_utils import float_round
  29. import openerp.addons.decimal_precision as dp
  30. from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
  31. class AccountPaymentTermLine(models.Model):
  32. _inherit = "account.payment.term.line"
  33. amount_round = fields.Float(
  34. string='Amount Rounding',
  35. digits=dp.get_precision('Account'),
  36. # TODO : I don't understand this help msg ; what is surcharge ?
  37. help="Sets the amount so that it is a multiple of this value.\n"
  38. "To have amounts that end in 0.99, set rounding 1, "
  39. "surcharge -0.01")
  40. months = fields.Integer(string='Number of Months')
  41. weeks = fields.Integer(string='Number of Weeks')
  42. start_with_end_month = fields.Boolean(
  43. string='Start by End of Month',
  44. help="If you have a payment term 'End of month 45 days' "
  45. "(which is not the same as '45 days end of month' !), you "
  46. "should activate this option and then set "
  47. "'Number of days' = 45 and 'Day of the month' = 0.")
  48. @api.multi
  49. def compute_line_amount(self, total_amount, remaining_amount):
  50. """Compute the amount for a payment term line.
  51. In case of procent computation, use the payment
  52. term line rounding if defined
  53. :param total_amount: total balance to pay
  54. :param remaining_amount: total amount minus sum of previous lines
  55. computed amount
  56. :returns: computed amount for this line
  57. """
  58. self.ensure_one()
  59. prec = self.env['decimal.precision'].precision_get('Account')
  60. if self.value == 'fixed':
  61. return float_round(self.value_amount, precision_digits=prec)
  62. elif self.value == 'procent':
  63. amt = total_amount * self.value_amount
  64. if self.amount_round:
  65. amt = float_round(amt, precision_rounding=self.amount_round)
  66. return float_round(amt, precision_digits=prec)
  67. elif self.value == 'balance':
  68. return float_round(remaining_amount, precision_digits=prec)
  69. return None
  70. class AccountPaymentTerm(models.Model):
  71. _inherit = "account.payment.term"
  72. def compute(self, cr, uid, id, value, date_ref=False, context=None):
  73. """Complete overwrite of compute method to add rounding on line
  74. computing and also to handle weeks and months
  75. """
  76. obj_precision = self.pool['decimal.precision']
  77. prec = obj_precision.precision_get(cr, uid, 'Account')
  78. if not date_ref:
  79. date_ref = datetime.now().strftime(DEFAULT_SERVER_DATE_FORMAT)
  80. pt = self.browse(cr, uid, id, context=context)
  81. amount = value
  82. result = []
  83. for line in pt.line_ids:
  84. amt = line.compute_line_amount(value, amount)
  85. if not amt:
  86. continue
  87. next_date = fields.Date.from_string(date_ref)
  88. if line.start_with_end_month:
  89. next_date += relativedelta(day=1, months=1, days=-1)
  90. next_date += relativedelta(
  91. days=line.days, weeks=line.weeks, months=line.months)
  92. if line.days2 < 0:
  93. # Getting 1st of next month
  94. next_date += relativedelta(day=1, months=1, days=line.days2)
  95. if line.days2 > 0:
  96. next_date += relativedelta(day=line.days2, months=1)
  97. result.append(
  98. (fields.Date.to_string(next_date), amt))
  99. amount -= amt
  100. amount = reduce(lambda x, y: x + y[1], result, 0.0)
  101. dist = round(value - amount, prec)
  102. if dist:
  103. result.append((time.strftime(DEFAULT_SERVER_DATE_FORMAT), dist))
  104. return result