diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index db19cfb..ff4a8a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -113,7 +113,7 @@ repos: - requirements.txt - --header - "# generated from manifests external_dependencies" - - repo: https://gitlab.com/PyCQA/flake8 + - repo: https://github.com/PyCQA/flake8 rev: 3.8.3 hooks: - id: flake8 diff --git a/currency_rate_update_nbu/README.rst b/currency_rate_update_nbu/README.rst new file mode 100644 index 0000000..a117d28 --- /dev/null +++ b/currency_rate_update_nbu/README.rst @@ -0,0 +1,85 @@ +======================== +Currency Rate Update NBU +======================== + +This module provides base for building exchange rates providers and bundles +following built-in providers: + + * **National Bank of Ukraine**: + the official currency rate of the Ukrainian hryvnia to foreign currencies. + Source in UAH, for more details see `corresponding + NBU page `_. + +This module is compatible with ``currency_rate_inverted`` module provided by +OCA, that allows to maintain exchange rates in inverted format, helping to +resolve rounding issues. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To enable scheduled currency rates update: + +# Go to *Invoicing > Configuration > Settings* +# Ensure *Automatic Currency Rates (OCA)* is checked + +To configure currency rates providers: + +# Go to *Invoicing > Configuration > Currency Rates Providers* +# The default NBU provider will be added during module installation with two +available currencies: USD, EUR. + +Usage +===== + +To update historical currency rates: + +# Go to *Invoicing > Configuration > Currency Rates Providers* +# Select the "National Bank of Ukraine" provider +# Add or remove available currencies if you need. +# Launch *Actions > Update Rates Wizard* +# Configure date interval and click *Update* + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* GarazdCreation + +Contributors +~~~~~~~~~~~~ + +* Yurii Razumovskyi + +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/l10n-ukraine `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/currency_rate_update_nbu/__init__.py b/currency_rate_update_nbu/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/currency_rate_update_nbu/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/currency_rate_update_nbu/__manifest__.py b/currency_rate_update_nbu/__manifest__.py new file mode 100644 index 0000000..fe757ec --- /dev/null +++ b/currency_rate_update_nbu/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2022 Garazd Creation (https://garazd.biz) +# @author: Yurii Razumovskyi (garazdcreation@gmail.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Currency Rate Update NBU", + "version": "14.0.1.0.0", + "category": "Accounting & Finance", + "summary": "Allows to download currency exchange rates from " + "National Bank of Ukraine", + "author": "Garazd Creation, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/l10n-ukraine", + "license": "AGPL-3", + "depends": [ + "currency_rate_update", + ], + "data": [ + "data/res_currency_rate_provider_data.xml", + "data/ir_config_parameter_data.xml", + ], + "installable": True, +} diff --git a/currency_rate_update_nbu/data/ir_config_parameter_data.xml b/currency_rate_update_nbu/data/ir_config_parameter_data.xml new file mode 100644 index 0000000..cc0e015 --- /dev/null +++ b/currency_rate_update_nbu/data/ir_config_parameter_data.xml @@ -0,0 +1,13 @@ + + + + + currency_rate_update_nbu.api_url + https://bank.gov.ua/NBU_Exchange/exchange_site?json + + + diff --git a/currency_rate_update_nbu/data/res_currency_rate_provider_data.xml b/currency_rate_update_nbu/data/res_currency_rate_provider_data.xml new file mode 100644 index 0000000..d45cdc8 --- /dev/null +++ b/currency_rate_update_nbu/data/res_currency_rate_provider_data.xml @@ -0,0 +1,13 @@ + + + + + National Bank of Ukraine + NBU + + + + diff --git a/currency_rate_update_nbu/models/__init__.py b/currency_rate_update_nbu/models/__init__.py new file mode 100644 index 0000000..c08252b --- /dev/null +++ b/currency_rate_update_nbu/models/__init__.py @@ -0,0 +1 @@ +from . import res_currency_rate_provider_nbu diff --git a/currency_rate_update_nbu/models/res_currency_rate_provider_nbu.py b/currency_rate_update_nbu/models/res_currency_rate_provider_nbu.py new file mode 100644 index 0000000..a4c7e47 --- /dev/null +++ b/currency_rate_update_nbu/models/res_currency_rate_provider_nbu.py @@ -0,0 +1,104 @@ +# Copyright 2022 Garazd Creation (https://garazd.biz) +# @author: Yurii Razumovskyi (garazdcreation@gmail.com) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +import json +import logging +from collections import defaultdict +from typing import List + +import dateutil.parser +import requests +from requests.exceptions import Timeout, TooManyRedirects + +from odoo import _, api, fields, models +from odoo.exceptions import UserError +from odoo.tools.float_utils import float_compare + +_logger = logging.getLogger(__name__) + + +class ResCurrencyRateProviderNBU(models.Model): + """Implementation for National Bank of Ukraine""" + + _inherit = "res.currency.rate.provider" + + service = fields.Selection( + selection_add=[("NBU", "National Bank of Ukraine")], + ondelete={"NBU": "set default"}, + ) + + def _get_supported_currencies(self): + self.ensure_one() + if self.service != "NBU": + return super()._get_supported_currencies() + # List of currencies obrained from: + # https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json + return self._nbu_get_available_currencies() + + def _nbu_process_request(self, params=None, headers=None): + try: + url = self.env["ir.config_parameter"].get_param( + "currency_rate_update_nbu.api_url" + ) + response = requests.get(url=url, params=params, headers=headers, timeout=60) + response_data = json.loads(response.text) + if response.status_code != 200: + raise Exception( + _( + "Failed to fetch from https://bank.gov.ua/ " + "with error code: %s and error message: %s" + ) + % (response.status_code, response.reason) + ) + except (ConnectionError, Timeout, TooManyRedirects) as e: + raise Exception(str(e)) + return response_data + + def _nbu_get_available_currencies(self): + """Get available currency list from NBU. + :return: list of currency codes + """ + data = self._nbu_process_request() + return [cur["cc"] for cur in data] + + def _nbu_get_rate( + self, currencies: List, date_from, date_to, invert_calculation=True + ): + """Get currency rates from NBU. + :param currencies: list or currency codes to return + :param date_from: date from which rates will be given + :param date_to: date to which rates will be given + :return: dict + """ + content = defaultdict(dict) + params = { + "start": date_from.strftime("%Y%m%d"), + "end": date_to.strftime("%Y%m%d"), + "sort": "exchangedate", + "order": "asc", + } + data = self._nbu_process_request(params=params) + for line in data: + currency = line.get("cc") + if currency in currencies: + timestamp = fields.Date.to_string( + dateutil.parser.parse(line.get("exchangedate"), dayfirst=True) + ) + rate = float(line.get("rate", 0)) + if invert_calculation: + rate = 1.0 / rate + content[timestamp].update({currency: rate}) + return content + + @api.model + def _obtain_rates(self, base_currency, currencies, date_from, date_to): + self.ensure_one() + if self.service != "NBU": + return super()._obtain_rates(base_currency, currencies, date_from, date_to) + if base_currency != self.env.ref("base.UAH").name: + raise UserError( + _('The base company currency should be "UAH" to get NBU rates.') + ) + if float_compare(self.env.ref("base.UAH").rate, 1.0, precision_digits=12) != 0: + raise UserError(_("The base company currency rate should be equal to 1.0")) + return self._nbu_get_rate(currencies, date_from, date_to) diff --git a/currency_rate_update_nbu/readme/CONFIGURE.rst b/currency_rate_update_nbu/readme/CONFIGURE.rst new file mode 100644 index 0000000..ede01a2 --- /dev/null +++ b/currency_rate_update_nbu/readme/CONFIGURE.rst @@ -0,0 +1,9 @@ +To enable scheduled currency rates update: + +#. Go to *Invoicing > Configuration > Settings* +#. Ensure *Automatic Currency Rates (OCA)* is checked + +To configure currency rates providers: + +#. Go to *Invoicing > Configuration > Currency Rates Providers* +#. The default NBU provider will be added during module installation with two available currencies: USD, EUR. diff --git a/currency_rate_update_nbu/readme/CONTRIBUTORS.rst b/currency_rate_update_nbu/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..89b6933 --- /dev/null +++ b/currency_rate_update_nbu/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Garazd Creation `__ + + * Yurii Razumovskyi diff --git a/currency_rate_update_nbu/readme/DESCRIPTION.rst b/currency_rate_update_nbu/readme/DESCRIPTION.rst new file mode 100644 index 0000000..349abc4 --- /dev/null +++ b/currency_rate_update_nbu/readme/DESCRIPTION.rst @@ -0,0 +1,11 @@ +This module provides base for building exchange rates providers and bundles +following built-in providers: + + * **National Bank of Ukraine**: + the official currency rate of the Ukrainian hryvnia to foreign currencies. + Source in UAH, for more details see `corresponding + NBU page `_. + +This module is compatible with ``currency_rate_inverted`` module provided by +OCA, that allows to maintain exchange rates in inverted format, helping to +resolve rounding issues. diff --git a/currency_rate_update_nbu/readme/USAGE.rst b/currency_rate_update_nbu/readme/USAGE.rst new file mode 100644 index 0000000..367be1a --- /dev/null +++ b/currency_rate_update_nbu/readme/USAGE.rst @@ -0,0 +1,7 @@ +To update historical currency rates: + +#. Go to *Invoicing > Configuration > Currency Rates Providers* +#. Select the "National Bank of Ukraine" provider +#. Add or remove available currencies if you need. +#. Launch *Actions > Update Rates Wizard* +#. Configure date interval and click *Update* diff --git a/currency_rate_update_nbu/static/description/icon.png b/currency_rate_update_nbu/static/description/icon.png new file mode 100644 index 0000000..3a0328b Binary files /dev/null and b/currency_rate_update_nbu/static/description/icon.png differ diff --git a/oca_dependencies.txt b/oca_dependencies.txt index ca3c726..82abbc6 100644 --- a/oca_dependencies.txt +++ b/oca_dependencies.txt @@ -1 +1,2 @@ # See https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst#oca_dependencies-txt +currency diff --git a/setup/currency_rate_update_nbu/odoo/addons/currency_rate_update_nbu b/setup/currency_rate_update_nbu/odoo/addons/currency_rate_update_nbu new file mode 120000 index 0000000..854b54a --- /dev/null +++ b/setup/currency_rate_update_nbu/odoo/addons/currency_rate_update_nbu @@ -0,0 +1 @@ +../../../../currency_rate_update_nbu/ \ No newline at end of file diff --git a/setup/currency_rate_update_nbu/setup.py b/setup/currency_rate_update_nbu/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/currency_rate_update_nbu/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)