summaryrefslogtreecommitdiff
path: root/addons/account/models/account_cash_rounding.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/account/models/account_cash_rounding.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/account/models/account_cash_rounding.py')
-rw-r--r--addons/account/models/account_cash_rounding.py54
1 files changed, 54 insertions, 0 deletions
diff --git a/addons/account/models/account_cash_rounding.py b/addons/account/models/account_cash_rounding.py
new file mode 100644
index 00000000..b4cb8a23
--- /dev/null
+++ b/addons/account/models/account_cash_rounding.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api, _
+from odoo.tools import float_round
+from odoo.exceptions import ValidationError
+
+
+class AccountCashRounding(models.Model):
+ """
+ In some countries, we need to be able to make appear on an invoice a rounding line, appearing there only because the
+ smallest coinage has been removed from the circulation. For example, in Switzerland invoices have to be rounded to
+ 0.05 CHF because coins of 0.01 CHF and 0.02 CHF aren't used anymore.
+ see https://en.wikipedia.org/wiki/Cash_rounding for more details.
+ """
+ _name = 'account.cash.rounding'
+ _description = 'Account Cash Rounding'
+
+ name = fields.Char(string='Name', translate=True, required=True)
+ rounding = fields.Float(string='Rounding Precision', required=True, default=0.01,
+ help='Represent the non-zero value smallest coinage (for example, 0.05).')
+ strategy = fields.Selection([('biggest_tax', 'Modify tax amount'), ('add_invoice_line', 'Add a rounding line')],
+ string='Rounding Strategy', default='add_invoice_line', required=True,
+ help='Specify which way will be used to round the invoice amount to the rounding precision')
+ profit_account_id = fields.Many2one('account.account', string='Profit Account', company_dependent=True, domain="[('deprecated', '=', False), ('company_id', '=', current_company_id)]")
+ loss_account_id = fields.Many2one('account.account', string='Loss Account', company_dependent=True, domain="[('deprecated', '=', False), ('company_id', '=', current_company_id)]")
+ rounding_method = fields.Selection(string='Rounding Method', required=True,
+ selection=[('UP', 'UP'), ('DOWN', 'DOWN'), ('HALF-UP', 'HALF-UP')],
+ default='HALF-UP', help='The tie-breaking rule used for float rounding operations')
+ company_id = fields.Many2one('res.company', related='profit_account_id.company_id')
+
+ @api.constrains('rounding')
+ def validate_rounding(self):
+ for record in self:
+ if record.rounding <= 0:
+ raise ValidationError(_("Please set a strictly positive rounding value."))
+
+ def round(self, amount):
+ """Compute the rounding on the amount passed as parameter.
+
+ :param amount: the amount to round
+ :return: the rounded amount depending the rounding value and the rounding method
+ """
+ return float_round(amount, precision_rounding=self.rounding, rounding_method=self.rounding_method)
+
+ def compute_difference(self, currency, amount):
+ """Compute the difference between the base_amount and the amount after rounding.
+ For example, base_amount=23.91, after rounding=24.00, the result will be 0.09.
+
+ :param currency: The currency.
+ :param amount: The amount
+ :return: round(difference)
+ """
+ difference = self.round(amount) - amount
+ return currency.round(difference)