account_cash_rounding.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. # -*- coding: utf-8 -*-
  2. from odoo import models, fields, api, _
  3. from odoo.tools import float_round
  4. from odoo.exceptions import ValidationError
  5. class AccountCashRounding(models.Model):
  6. """
  7. In some countries, we need to be able to make appear on an invoice a rounding line, appearing there only because the
  8. smallest coinage has been removed from the circulation. For example, in Switzerland invoices have to be rounded to
  9. 0.05 CHF because coins of 0.01 CHF and 0.02 CHF aren't used anymore.
  10. see https://en.wikipedia.org/wiki/Cash_rounding for more details.
  11. """
  12. _name = 'account.cash.rounding'
  13. _description = 'Account Cash Rounding'
  14. name = fields.Char(string='Name', translate=True, required=True)
  15. rounding = fields.Float(string='Rounding Precision', required=True, default=0.01,
  16. help='Represent the non-zero value smallest coinage (for example, 0.05).')
  17. strategy = fields.Selection([('biggest_tax', 'Modify tax amount'), ('add_invoice_line', 'Add a rounding line')],
  18. string='Rounding Strategy', default='add_invoice_line', required=True,
  19. help='Specify which way will be used to round the invoice amount to the rounding precision')
  20. profit_account_id = fields.Many2one('account.account', string='Profit Account', company_dependent=True, domain="[('deprecated', '=', False), ('company_id', '=', current_company_id)]")
  21. loss_account_id = fields.Many2one('account.account', string='Loss Account', company_dependent=True, domain="[('deprecated', '=', False), ('company_id', '=', current_company_id)]")
  22. rounding_method = fields.Selection(string='Rounding Method', required=True,
  23. selection=[('UP', 'UP'), ('DOWN', 'DOWN'), ('HALF-UP', 'HALF-UP')],
  24. default='HALF-UP', help='The tie-breaking rule used for float rounding operations')
  25. company_id = fields.Many2one('res.company', related='profit_account_id.company_id')
  26. @api.constrains('rounding')
  27. def validate_rounding(self):
  28. for record in self:
  29. if record.rounding <= 0:
  30. raise ValidationError(_("Please set a strictly positive rounding value."))
  31. def round(self, amount):
  32. """Compute the rounding on the amount passed as parameter.
  33. :param amount: the amount to round
  34. :return: the rounded amount depending the rounding value and the rounding method
  35. """
  36. return float_round(amount, precision_rounding=self.rounding, rounding_method=self.rounding_method)
  37. def compute_difference(self, currency, amount):
  38. """Compute the difference between the base_amount and the amount after rounding.
  39. For example, base_amount=23.91, after rounding=24.00, the result will be 0.09.
  40. :param currency: The currency.
  41. :param amount: The amount
  42. :return: round(difference)
  43. """
  44. difference = self.round(amount) - amount
  45. return currency.round(difference)