From dbb77935840811c362065c400dfff83e1e1ef4be Mon Sep 17 00:00:00 2001 From: Claude Perrin Date: Sun, 14 Jun 2026 09:07:05 +0200 Subject: [PATCH] [17.0][MIG] currency_rate_inverted: Migration to 17.0 Forward-port of currency_rate_inverted from 14.0 (dropped from OCA after 14.0). Lets a currency rate be maintained using the inversion method. Framework migration only; the test is updated to pass context as keywords. Signed-off-by: Claude Perrin --- currency_rate_inverted/README.rst | 106 +++++ currency_rate_inverted/__init__.py | 3 + currency_rate_inverted/__manifest__.py | 18 + currency_rate_inverted/i18n/ca.po | 42 ++ .../i18n/currency_rate_inverted.pot | 39 ++ currency_rate_inverted/i18n/es.po | 42 ++ currency_rate_inverted/i18n/es_AR.po | 42 ++ currency_rate_inverted/i18n/fr.po | 45 ++ currency_rate_inverted/i18n/hr.po | 43 ++ currency_rate_inverted/i18n/it.po | 42 ++ currency_rate_inverted/models/__init__.py | 3 + currency_rate_inverted/models/res_currency.py | 36 ++ currency_rate_inverted/pyproject.toml | 3 + currency_rate_inverted/readme/CONFIGURE.md | 4 + currency_rate_inverted/readme/CONTRIBUTORS.md | 8 + currency_rate_inverted/readme/DESCRIPTION.md | 12 + .../static/description/icon.png | Bin 0 -> 28262 bytes .../static/description/index.html | 450 ++++++++++++++++++ currency_rate_inverted/tests/__init__.py | 3 + .../tests/test_currency_rate_inverted.py | 107 +++++ .../views/res_currency_view.xml | 23 + 21 files changed, 1071 insertions(+) create mode 100644 currency_rate_inverted/README.rst create mode 100644 currency_rate_inverted/__init__.py create mode 100644 currency_rate_inverted/__manifest__.py create mode 100644 currency_rate_inverted/i18n/ca.po create mode 100644 currency_rate_inverted/i18n/currency_rate_inverted.pot create mode 100644 currency_rate_inverted/i18n/es.po create mode 100644 currency_rate_inverted/i18n/es_AR.po create mode 100644 currency_rate_inverted/i18n/fr.po create mode 100644 currency_rate_inverted/i18n/hr.po create mode 100644 currency_rate_inverted/i18n/it.po create mode 100644 currency_rate_inverted/models/__init__.py create mode 100644 currency_rate_inverted/models/res_currency.py create mode 100644 currency_rate_inverted/pyproject.toml create mode 100644 currency_rate_inverted/readme/CONFIGURE.md create mode 100644 currency_rate_inverted/readme/CONTRIBUTORS.md create mode 100644 currency_rate_inverted/readme/DESCRIPTION.md create mode 100644 currency_rate_inverted/static/description/icon.png create mode 100644 currency_rate_inverted/static/description/index.html create mode 100644 currency_rate_inverted/tests/__init__.py create mode 100644 currency_rate_inverted/tests/test_currency_rate_inverted.py create mode 100644 currency_rate_inverted/views/res_currency_view.xml diff --git a/currency_rate_inverted/README.rst b/currency_rate_inverted/README.rst new file mode 100644 index 00000000..2273d94c --- /dev/null +++ b/currency_rate_inverted/README.rst @@ -0,0 +1,106 @@ +====================== +Currency Rate Inverted +====================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:5320232dc12a7405479ad155d83e1e267868f45e81228196dc5551d654be9c46 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcurrency-lightgray.png?logo=github + :target: https://github.com/OCA/currency/tree/17.0/currency_rate_inverted + :alt: OCA/currency +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/currency-17-0/currency-17-0-currency_rate_inverted + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/currency&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module applies the inverse method in the conversion between two +currencies. + +The inverse method is a calculation method that uses the inverse +(reciprocal) exchange rate for the multiplier and divisor when +converting amounts from one currency to another. + +The exchange rate of the multiplier and divisor are the reciprocal, or +opposite, of each other. + +The inverse method multiplies the foreign amount by the exchange rate to +calculate the company currency (also called domestic) amount. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To convert amounts from one currency to another using the inverse +method, you have to go to *Accounting / Configuration / Accounting / +Currencies*. Then select the foreign currency that you wish to maintain +inversion for and set the flag *Inverted exchange rate*. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* ForgeFlow + +Contributors +------------ + +- ForgeFlow (`www.forgeflow.com `__) +- Techrifiv Solutions Pte Ltd + (`www.techrifiv.com.sg `__) +- Statecraft Systems Pte Ltd + (`www.statecraftsystems.sg `__) +- Komit (Jean-Charles Drubay ) +- `CorporateHub `__ + + - Alexey Pelykh + +- Pimolnat Suntian +- SkiBY (Sergej Ruzki ) + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/currency `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/currency_rate_inverted/__init__.py b/currency_rate_inverted/__init__.py new file mode 100644 index 00000000..31660d6a --- /dev/null +++ b/currency_rate_inverted/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models diff --git a/currency_rate_inverted/__manifest__.py b/currency_rate_inverted/__manifest__.py new file mode 100644 index 00000000..e3f86e05 --- /dev/null +++ b/currency_rate_inverted/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2019 Brainbean Apps (https://brainbeanapps.com) +# Copyright 2021 ForgeFlow, S.L. +# Copyright 2015 Techrifiv Solutions Pte Ltd +# Copyright 2015 Statecraft Systems Pte Ltd +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Currency Rate Inverted", + "version": "17.0.1.0.0", + "category": "Accounting & Finance", + "summary": "Allows to maintain an exchange rate using the inversion method", + "author": "ForgeFlow, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/currency", + "license": "AGPL-3", + "depends": ["base"], + "data": ["views/res_currency_view.xml"], + "installable": True, +} diff --git a/currency_rate_inverted/i18n/ca.po b/currency_rate_inverted/i18n/ca.po new file mode 100644 index 00000000..5e055994 --- /dev/null +++ b/currency_rate_inverted/i18n/ca.po @@ -0,0 +1,42 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-03-26 19:46+0000\n" +"Last-Translator: eduardgm \n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "Moneda" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "Tipus de canvi invertit" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "" diff --git a/currency_rate_inverted/i18n/currency_rate_inverted.pot b/currency_rate_inverted/i18n/currency_rate_inverted.pot new file mode 100644 index 00000000..f4425c28 --- /dev/null +++ b/currency_rate_inverted/i18n/currency_rate_inverted.pot @@ -0,0 +1,39 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "" diff --git a/currency_rate_inverted/i18n/es.po b/currency_rate_inverted/i18n/es.po new file mode 100644 index 00000000..f09ada96 --- /dev/null +++ b/currency_rate_inverted/i18n/es.po @@ -0,0 +1,42 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-12-19 14:36+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "Moneda" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "Tipo de cambio invertido" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "Última Modificación el" diff --git a/currency_rate_inverted/i18n/es_AR.po b/currency_rate_inverted/i18n/es_AR.po new file mode 100644 index 00000000..6ba8d8af --- /dev/null +++ b/currency_rate_inverted/i18n/es_AR.po @@ -0,0 +1,42 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-07-28 05:06+0000\n" +"Last-Translator: Ignacio Buioli \n" +"Language-Team: none\n" +"Language: es_AR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "Moneda" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "ID" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "Tasa de cambio invertida" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "Última modificación en" diff --git a/currency_rate_inverted/i18n/fr.po b/currency_rate_inverted/i18n/fr.po new file mode 100644 index 00000000..cd088470 --- /dev/null +++ b/currency_rate_inverted/i18n/fr.po @@ -0,0 +1,45 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +# Translators: +# Quentin THEURET , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-04-11 12:43+0000\n" +"PO-Revision-Date: 2023-06-10 20:18+0000\n" +"Last-Translator: Claude R Perrin \n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "Devise" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "ID" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "Taux de change inversé" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" diff --git a/currency_rate_inverted/i18n/hr.po b/currency_rate_inverted/i18n/hr.po new file mode 100644 index 00000000..dfa28a58 --- /dev/null +++ b/currency_rate_inverted/i18n/hr.po @@ -0,0 +1,43 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-11-13 15:34+0000\n" +"Last-Translator: Bole \n" +"Language-Team: none\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.8\n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "Valuta" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "Inverzni tečaj" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "" diff --git a/currency_rate_inverted/i18n/it.po b/currency_rate_inverted/i18n/it.po new file mode 100644 index 00000000..6c10a5f6 --- /dev/null +++ b/currency_rate_inverted/i18n/it.po @@ -0,0 +1,42 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * currency_rate_inverted +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-12-29 12:36+0000\n" +"Last-Translator: Francesco Foresti \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: currency_rate_inverted +#: model:ir.model,name:currency_rate_inverted.model_res_currency +msgid "Currency" +msgstr "Valuta" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__id +msgid "ID" +msgstr "ID" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency__rate_inverted +msgid "Inverted exchange rate" +msgstr "Tasso di cambio invertito" + +#. module: currency_rate_inverted +#: model:ir.model.fields,field_description:currency_rate_inverted.field_res_currency____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" diff --git a/currency_rate_inverted/models/__init__.py b/currency_rate_inverted/models/__init__.py new file mode 100644 index 00000000..e6fbed83 --- /dev/null +++ b/currency_rate_inverted/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import res_currency diff --git a/currency_rate_inverted/models/res_currency.py b/currency_rate_inverted/models/res_currency.py new file mode 100644 index 00000000..e38cbd5a --- /dev/null +++ b/currency_rate_inverted/models/res_currency.py @@ -0,0 +1,36 @@ +# Copyright 2021 Sergej Ruzki. ReSuSolutions. +# Copyright 2021 ForgeFlow, S.L. +# Copyright 2015 Techrifiv Solutions Pte Ltd +# Copyright 2015 Statecraft Systems Pte Ltd +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class ResCurrency(models.Model): + _inherit = "res.currency" + + rate_inverted = fields.Boolean( + string="Inverted exchange rate", + company_dependent=True, + ) + + @api.model + def _get_conversion_rate(self, from_currency, to_currency, company, date): + rate = super()._get_conversion_rate(from_currency, to_currency, company, date) + + from_currency = from_currency.with_company(company) + to_currency = to_currency.with_company(company) + + if not from_currency.rate_inverted and not to_currency.rate_inverted: + return rate + elif from_currency.rate_inverted and to_currency.rate_inverted: + return 1 / rate + + currency_rates = (from_currency + to_currency)._get_rates(company, date) + l_rate = currency_rates.get(to_currency.id) + r_rate = currency_rates.get(from_currency.id) + if not from_currency.rate_inverted and to_currency.rate_inverted: + return 1 / (l_rate * r_rate) + elif from_currency.rate_inverted and not to_currency.rate_inverted: + return l_rate * r_rate diff --git a/currency_rate_inverted/pyproject.toml b/currency_rate_inverted/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/currency_rate_inverted/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/currency_rate_inverted/readme/CONFIGURE.md b/currency_rate_inverted/readme/CONFIGURE.md new file mode 100644 index 00000000..a0239375 --- /dev/null +++ b/currency_rate_inverted/readme/CONFIGURE.md @@ -0,0 +1,4 @@ +To convert amounts from one currency to another using the inverse +method, you have to go to *Accounting / Configuration / Accounting / +Currencies*. Then select the foreign currency that you wish to maintain +inversion for and set the flag *Inverted exchange rate*. diff --git a/currency_rate_inverted/readme/CONTRIBUTORS.md b/currency_rate_inverted/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..81d6eb95 --- /dev/null +++ b/currency_rate_inverted/readme/CONTRIBUTORS.md @@ -0,0 +1,8 @@ +- ForgeFlow (www.forgeflow.com) +- Techrifiv Solutions Pte Ltd (www.techrifiv.com.sg) +- Statecraft Systems Pte Ltd (www.statecraftsystems.sg) +- Komit (Jean-Charles Drubay \) +- [CorporateHub](https://corporatehub.eu/) + - Alexey Pelykh \ +- Pimolnat Suntian \ +- SkiBY (Sergej Ruzki \) diff --git a/currency_rate_inverted/readme/DESCRIPTION.md b/currency_rate_inverted/readme/DESCRIPTION.md new file mode 100644 index 00000000..76498a4c --- /dev/null +++ b/currency_rate_inverted/readme/DESCRIPTION.md @@ -0,0 +1,12 @@ +This module applies the inverse method in the conversion between two +currencies. + +The inverse method is a calculation method that uses the inverse +(reciprocal) exchange rate for the multiplier and divisor when +converting amounts from one currency to another. + +The exchange rate of the multiplier and divisor are the reciprocal, or +opposite, of each other. + +The inverse method multiplies the foreign amount by the exchange rate to +calculate the company currency (also called domestic) amount. diff --git a/currency_rate_inverted/static/description/icon.png b/currency_rate_inverted/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..69a8569dc104547d87bf713e93f6d67318c2a140 GIT binary patch literal 28262 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 literal 0 HcmV?d00001 diff --git a/currency_rate_inverted/static/description/index.html b/currency_rate_inverted/static/description/index.html new file mode 100644 index 00000000..b3cc25f8 --- /dev/null +++ b/currency_rate_inverted/static/description/index.html @@ -0,0 +1,450 @@ + + + + + +Currency Rate Inverted + + + +
+

Currency Rate Inverted

+ + +

Beta License: AGPL-3 OCA/currency Translate me on Weblate Try me on Runboat

+

This module applies the inverse method in the conversion between two +currencies.

+

The inverse method is a calculation method that uses the inverse +(reciprocal) exchange rate for the multiplier and divisor when +converting amounts from one currency to another.

+

The exchange rate of the multiplier and divisor are the reciprocal, or +opposite, of each other.

+

The inverse method multiplies the foreign amount by the exchange rate to +calculate the company currency (also called domestic) amount.

+

Table of contents

+ +
+

Configuration

+

To convert amounts from one currency to another using the inverse +method, you have to go to Accounting / Configuration / Accounting / +Currencies. Then select the foreign currency that you wish to maintain +inversion for and set the flag Inverted exchange rate.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/currency project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/currency_rate_inverted/tests/__init__.py b/currency_rate_inverted/tests/__init__.py new file mode 100644 index 00000000..e342d64b --- /dev/null +++ b/currency_rate_inverted/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import test_currency_rate_inverted diff --git a/currency_rate_inverted/tests/test_currency_rate_inverted.py b/currency_rate_inverted/tests/test_currency_rate_inverted.py new file mode 100644 index 00000000..5d2c8a0b --- /dev/null +++ b/currency_rate_inverted/tests/test_currency_rate_inverted.py @@ -0,0 +1,107 @@ +# Copyright 2019 Brainbean Apps +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from datetime import timedelta + +from odoo import fields +from odoo.tests import common + + +class TestCurrencyRateInverted(common.SavepointCase): + def setUp(self): + super().setUp() + + self.today = fields.Date.today() + self.Currency = self.env["res.currency"] + self.SudoCurrency = self.Currency.sudo() + self.eur = self.SudoCurrency.search([("name", "=", "EUR")], limit=1) + self.usd = self.SudoCurrency.search([("name", "=", "USD")], limit=1) + self.gbp = self.SudoCurrency.search( + [("name", "=", "GBP"), ("active", "=", False)], limit=1 + ) + self.gbp.active = True + + def test_1(self): + self.eur.write( + {"rate_ids": [(0, False, {"name": self.today + timedelta(days=10)})]} + ) + self.usd.write( + { + "rate_ids": [ + (0, False, {"name": self.today + timedelta(days=10), "rate": 0.8}) + ], + } + ) + self.gbp.write( + { + "rate_ids": [ + (0, False, {"name": self.today + timedelta(days=10), "rate": 1.1}) + ], + } + ) + + self.usd.rate_inverted = True + self.assertAlmostEqual( + self.eur.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.usd + ), + 1.25, + 2, + ) + self.assertAlmostEqual( + self.usd.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.eur + ), + 0.8, + 2, + ) + + self.gbp.rate_inverted = True + self.assertAlmostEqual( + self.gbp.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.usd + ), + 1.38, + 2, + ) + self.gbp.rate_inverted = False + self.assertAlmostEqual( + self.gbp.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.usd + ), + 1.14, + 2, + ) + + self.usd.rate_inverted = False + self.assertAlmostEqual( + self.eur.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.usd + ), + 0.8, + 2, + ) + self.assertAlmostEqual( + self.usd.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.eur + ), + 1.25, + 2, + ) + + self.gbp.rate_inverted = True + self.assertAlmostEqual( + self.gbp.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.usd + ), + 0.88, + 2, + ) + self.gbp.rate_inverted = False + self.assertAlmostEqual( + self.gbp.with_context(date=self.today + timedelta(days=10)).compute( + 1.0, self.usd + ), + 0.73, + 2, + ) diff --git a/currency_rate_inverted/views/res_currency_view.xml b/currency_rate_inverted/views/res_currency_view.xml new file mode 100644 index 00000000..1b741dcc --- /dev/null +++ b/currency_rate_inverted/views/res_currency_view.xml @@ -0,0 +1,23 @@ + + + + res.currency.tree + res.currency + + + + + + + + + res.currency.form + res.currency + + + + + + + +