diff --git a/account_move_line_used_currency/__init__.py b/account_move_line_used_currency/__init__.py new file mode 100644 index 000000000..4953e3fc4 --- /dev/null +++ b/account_move_line_used_currency/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .init_hooks import pre_init_hook diff --git a/account_move_line_used_currency/__manifest__.py b/account_move_line_used_currency/__manifest__.py new file mode 100644 index 000000000..46b59aa74 --- /dev/null +++ b/account_move_line_used_currency/__manifest__.py @@ -0,0 +1,13 @@ +# Copyright 2021 ForgeFlow, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +{ + "name": "Account Move Line Amount Currency", + "version": "13.0.1.0.0", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "category": "Accounts", + "license": "LGPL-3", + "depends": ["account"], + "data": ["views/account_move_line_view.xml", "views/account_move_view.xml"], + "pre_init_hook": "pre_init_hook", + "installable": True, +} diff --git a/account_move_line_used_currency/init_hooks.py b/account_move_line_used_currency/init_hooks.py new file mode 100644 index 000000000..b1b5e597e --- /dev/null +++ b/account_move_line_used_currency/init_hooks.py @@ -0,0 +1,53 @@ +# Copyright 2021 ForgeFlow, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +import logging + +try: + from openupgradelib import openupgrade +except Exception: + from odoo.tools import sql as openupgrade + +_logger = logging.getLogger(__name__) + + +def pre_init_hook(cr): + _logger.info("Pre-creating column amount_used_currency for table account_move_line") + if not openupgrade.column_exists(cr, "account_move_line", "amount_used_currency"): + cr.execute( + """ + ALTER TABLE account_move_line + ADD COLUMN amount_used_currency float; + COMMENT ON COLUMN account_move_line.amount_used_currency + IS 'Amount (Used Currency)'; + """ + ) + _logger.info("Pre-creating column used_currency_id for table account_move_line") + if not openupgrade.column_exists(cr, "account_move_line", "used_currency_id"): + cr.execute( + """ + ALTER TABLE account_move_line + ADD COLUMN used_currency_id INTEGER; + COMMENT ON COLUMN account_move_line.used_currency_id + IS 'Used Currency'; + """ + ) + _logger.info( + "Pre-computing the value of amount_used_currency " + "and used_currency_id to speed up the installation" + ) + cr.execute( + """ + UPDATE account_move_line + SET amount_used_currency = balance, + used_currency_id = company_currency_id + WHERE currency_id IS NULL; + """ + ) + cr.execute( + """ + UPDATE account_move_line + SET amount_used_currency = amount_currency, + used_currency_id = currency_id + WHERE currency_id IS NOT NULL; + """ + ) diff --git a/account_move_line_used_currency/models/__init__.py b/account_move_line_used_currency/models/__init__.py new file mode 100644 index 000000000..8795b3bea --- /dev/null +++ b/account_move_line_used_currency/models/__init__.py @@ -0,0 +1 @@ +from . import account_move_line diff --git a/account_move_line_used_currency/models/account_move_line.py b/account_move_line_used_currency/models/account_move_line.py new file mode 100644 index 000000000..209661de0 --- /dev/null +++ b/account_move_line_used_currency/models/account_move_line.py @@ -0,0 +1,39 @@ +# Copyright 2021 ForgeFlow, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import api, fields, models + + +class AccountMoveLine(models.Model): + _inherit = "account.move.line" + + amount_used_currency = fields.Monetary( + string="Amount (Used Currency)", + compute="_compute_used_currency", + store=True, + help="This amount is the foreign amount currency, if used, and the " + "company currency, if no foreign currency is used. It's purpose" + "is to allow reporting on journal items combining foreign " + "and company currencies.", + ) + used_currency_id = fields.Many2one( + "res.currency", + string="Used Currency", + compute="_compute_used_currency", + store=True, + help="Used currency of the journal item. It is the foreign currency, " + "or the company currency, where the foreign currency has not " + "been used.", + ) + + @api.depends( + "currency_id", "company_currency_id", "debit", "credit", "amount_currency" + ) + def _compute_used_currency(self): + for rec in self: + if rec.currency_id: + rec.amount_used_currency = rec.amount_currency + rec.used_currency_id = rec.currency_id + else: + rec.amount_used_currency = rec.balance + rec.used_currency_id = rec.company_currency_id diff --git a/account_move_line_used_currency/readme/CONTRIBUTORS.rst b/account_move_line_used_currency/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..a918dfe35 --- /dev/null +++ b/account_move_line_used_currency/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `ForgeFlow `_: + + * Jordi Ballester Alomar diff --git a/account_move_line_used_currency/readme/DESCRIPTION.rst b/account_move_line_used_currency/readme/DESCRIPTION.rst new file mode 100644 index 000000000..44212ebe8 --- /dev/null +++ b/account_move_line_used_currency/readme/DESCRIPTION.rst @@ -0,0 +1,15 @@ +This module introduces to journal items two new fields: + +* Amount (Used Currency) + +* Used Currency + +When the journal item is expressed in foreign currency, those fields will be +computed with the amount in foreign currency. Otherwise the company currency +and balance in company currency is filled in. + +Those fields are useful for reporting purposes. For example, in an +intercompany context company A (that operates using USD) sells to company B +(that operates using EUR) in EUR, and you want to be able to compare the +balances in a common account across the two companies, using the same +currency EUR. diff --git a/account_move_line_used_currency/tests/__init__.py b/account_move_line_used_currency/tests/__init__.py new file mode 100644 index 000000000..04fb713da --- /dev/null +++ b/account_move_line_used_currency/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_move_line_used_currency diff --git a/account_move_line_used_currency/tests/test_account_move_line_used_currency.py b/account_move_line_used_currency/tests/test_account_move_line_used_currency.py new file mode 100644 index 000000000..f4b382ea1 --- /dev/null +++ b/account_move_line_used_currency/tests/test_account_move_line_used_currency.py @@ -0,0 +1,118 @@ +# Copyright 2021 ForgeFlow, S.L. +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo.tests import common + + +class TestAccountMoveLineCurrency(common.SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + res_users_account_manager = cls.env.ref("account.group_account_manager") + partner_manager = cls.env.ref("base.group_partner_manager") + cls.env.user.write( + {"groups_id": [(6, 0, [res_users_account_manager.id, partner_manager.id])]} + ) + + # Partner + cls.res_partner_1 = cls.env["res.partner"].create({"name": "Wood Corner"}) + + # Products + cls.product_1 = cls.env["product.product"].create( + {"name": "Desk Combination", "list_price": 100} + ) + cls.product_2 = cls.env["product.product"].create( + {"name": "Desk Combination 2", "list_price": 100} + ) + + # Tax + cls.tax = cls.env["account.tax"].create( + {"name": "Tax 15", "type_tax_use": "sale", "amount": 20} + ) + + # Currencies + cls.currency_euro = cls.env["res.currency"].search([("name", "=", "EUR")]) + cls.currency_usd = cls.env["res.currency"].search([("name", "=", "USD")]) + cls.currency_rate = cls.env["res.currency.rate"].create( + {"rate": 1.30, "currency_id": cls.currency_usd.id} + ) + + # Invoices + cls.invoice_1 = cls.env["account.move"].create( + [ + { + "type": "out_invoice", + "partner_id": cls.res_partner_1.id, + "currency_id": cls.currency_euro.id, + "invoice_line_ids": [ + ( + 0, + None, + { + "product_id": cls.product_1.id, + "product_uom_id": cls.product_1.uom_id.id, + "quantity": 12, + "price_unit": 1000, + "tax_ids": cls.tax, + }, + ), + ], + } + ] + ) + cls.invoice_2 = cls.env["account.move"].create( + [ + { + "type": "out_invoice", + "partner_id": cls.res_partner_1.id, + "currency_id": cls.currency_usd.id, + "invoice_line_ids": [ + ( + 0, + None, + { + "product_id": cls.product_2.id, + "product_uom_id": cls.product_2.uom_id.id, + "quantity": 10, + "price_unit": 500, + "tax_ids": cls.tax, + }, + ), + ], + } + ] + ) + + cls.invoice_1.action_post() + cls.invoice_2.action_post() + + def test_account_move_line_used_currency(self): + self.assertEqual( + self.invoice_1.amount_total, 14400, + ) + + self.assertEqual( + self.invoice_2.amount_total, 6000, + ) + + item_1 = self.env["account.move.line"].browse( + self.invoice_1.invoice_line_ids.id + ) + self.assertEqual( + item_1.amount_used_currency, -12000, + ) + + self.assertEqual( + item_1.used_currency_id.id, self.currency_euro.id, + ) + + item_2 = self.env["account.move.line"].browse( + self.invoice_2.invoice_line_ids.id + ) + self.assertEqual( + item_2.amount_used_currency, -5000, + ) + + self.assertEqual( + item_2.used_currency_id.id, self.currency_usd.id, + ) diff --git a/account_move_line_used_currency/views/account_move_line_view.xml b/account_move_line_used_currency/views/account_move_line_view.xml new file mode 100644 index 000000000..a137f1eca --- /dev/null +++ b/account_move_line_used_currency/views/account_move_line_view.xml @@ -0,0 +1,35 @@ + + + + + account.move.line.form + account.move.line + + + + + + + + + + account.move.line.tree + account.move.line + + + + + + + + + diff --git a/account_move_line_used_currency/views/account_move_view.xml b/account_move_line_used_currency/views/account_move_view.xml new file mode 100644 index 000000000..a46f5b8ed --- /dev/null +++ b/account_move_line_used_currency/views/account_move_view.xml @@ -0,0 +1,17 @@ + + + + account.move.form + account.move + + + + + + + + + diff --git a/setup/account_move_line_used_currency/odoo/addons/account_move_line_used_currency b/setup/account_move_line_used_currency/odoo/addons/account_move_line_used_currency new file mode 120000 index 000000000..8253754f5 --- /dev/null +++ b/setup/account_move_line_used_currency/odoo/addons/account_move_line_used_currency @@ -0,0 +1 @@ +../../../../account_move_line_used_currency \ No newline at end of file diff --git a/setup/account_move_line_used_currency/setup.py b/setup/account_move_line_used_currency/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/account_move_line_used_currency/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)