From b77e25bb9824e55d9fe668b26a6849d1563f082b Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Fri, 16 Dec 2022 12:52:23 +0630 Subject: [PATCH 1/2] [ADD] currency_rate_update_mizuho --- currency_rate_update_mizuho/README.rst | 52 +++ currency_rate_update_mizuho/__init__.py | 1 + currency_rate_update_mizuho/__manifest__.py | 12 + .../models/__init__.py | 1 + .../res_currency_rate_provider_mizuho.py | 165 +++++++ .../readme/DESCRIPTION.rst | 1 + .../static/description/index.html | 407 ++++++++++++++++++ requirements.txt | 1 + .../odoo/addons/currency_rate_update_mizuho | 1 + setup/currency_rate_update_mizuho/setup.py | 6 + test-requirements.txt | 1 + 11 files changed, 648 insertions(+) create mode 100644 currency_rate_update_mizuho/README.rst create mode 100644 currency_rate_update_mizuho/__init__.py create mode 100644 currency_rate_update_mizuho/__manifest__.py create mode 100644 currency_rate_update_mizuho/models/__init__.py create mode 100644 currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py create mode 100644 currency_rate_update_mizuho/readme/DESCRIPTION.rst create mode 100644 currency_rate_update_mizuho/static/description/index.html create mode 100644 requirements.txt create mode 120000 setup/currency_rate_update_mizuho/odoo/addons/currency_rate_update_mizuho create mode 100644 setup/currency_rate_update_mizuho/setup.py create mode 100644 test-requirements.txt diff --git a/currency_rate_update_mizuho/README.rst b/currency_rate_update_mizuho/README.rst new file mode 100644 index 00000000..4f456d90 --- /dev/null +++ b/currency_rate_update_mizuho/README.rst @@ -0,0 +1,52 @@ +=========================== +Currency Rate Update Mizuho +=========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-qrtl%2Faxls--custom-lightgray.png?logo=github + :target: https://github.com/qrtl/axls-custom/tree/16.0/currency_rate_update_mizuho + :alt: qrtl/axls-custom + +|badge1| |badge2| |badge3| + +This module provides to update the currency exchange rate from the provider **Mizuho Bank**. + +**Table of contents** + +.. contents:: + :local: + +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 +~~~~~~~ + +* Quartile Limited + +Maintainers +~~~~~~~~~~~ + +This module is part of the `qrtl/axls-custom `_ project on GitHub. + +You are welcome to contribute. diff --git a/currency_rate_update_mizuho/__init__.py b/currency_rate_update_mizuho/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/currency_rate_update_mizuho/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/currency_rate_update_mizuho/__manifest__.py b/currency_rate_update_mizuho/__manifest__.py new file mode 100644 index 00000000..16321800 --- /dev/null +++ b/currency_rate_update_mizuho/__manifest__.py @@ -0,0 +1,12 @@ +# Copyright 2022 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Currency Rate Update Mizuho", + "version": "16.0.1.0.0", + "category": "Financial Management/Configuration", + "author": "Axelspace, Quartile Limited", + "website": "https://www.quartile.co", + "depends": ["currency_rate_update"], + "license": "AGPL-3", + "installable": True, +} diff --git a/currency_rate_update_mizuho/models/__init__.py b/currency_rate_update_mizuho/models/__init__.py new file mode 100644 index 00000000..c8a93f9d --- /dev/null +++ b/currency_rate_update_mizuho/models/__init__.py @@ -0,0 +1 @@ +from . import res_currency_rate_provider_mizuho diff --git a/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py b/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py new file mode 100644 index 00000000..cc4940f8 --- /dev/null +++ b/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py @@ -0,0 +1,165 @@ +# Copyright 2022 Axelspace +# Copyright 2022 Quartile Limited +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import csv +import xml.etree.ElementTree as et +import xml.sax +from collections import defaultdict +from datetime import date, datetime +from io import StringIO + +import requests + +from odoo import fields, models + + +class ResCurrencyRateProviderMizuho(models.Model): + _inherit = "res.currency.rate.provider" + + service = fields.Selection( + selection_add=[("Mizuho", "Mizuho Bank (Japan)")], + ondelete={"Mizuho": "set default"}, + ) + + def _get_supported_currencies(self): + self.ensure_one() + if self.service != "Mizuho": + return super()._get_supported_currencies() # pragma: no cover + # List of currencies obrained from: + # https://www.mizuhobank.co.jp/market/historical.html + return [ + "USD", + "GBP", + "EUR", + "CAD", + "CHF", + "SEK", + "DKK", + "NOK", + "AUD", + "NZD", + "ZAR", + "BHD", + "CNY", + "HKD", + "INR", + "MYR", + "PHP", + "SGD", + "THB", + "KWD", + "SAR", + "AED", + "MXN", + "PGK", + "HUF", + "CZK", + "PLN", + "TRY", + ] + + def _obtain_rates(self, base_currency, currencies, date_from, date_to): + self.ensure_one() + if self.service != "Mizuho": + return super()._obtain_rates( + base_currency, currencies, date_from, date_to + ) # pragma: no cover + invert_calculation = False + if base_currency != "JPY": + invert_calculation = True + if base_currency not in currencies: + currencies.append(base_currency) + # Depending on the date range, different URLs are used + url = "https://www.mizuhobank.co.jp/market/csv" + if self._Is_in_this_month(date_from, date_to): + url = url + "/tm_quote.csv" + else: + url = url + "/quote.csv" + handler = RatesHandler(currencies, date_from, date_to) + xml.sax.parseString(self._get_mizuho_rates(url, date_from), handler) + content = handler.content + if invert_calculation: + for k in content.keys(): + base_rate = float(content[k][base_currency]) + for rate in content[k].keys(): + content[k][rate] = str(float(content[k][rate]) / base_rate) + content[k]["JPY"] = str(1.0 / base_rate) + return content + + def _get_mizuho_rates(self, url: str, date_from: date) -> str: + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 " + "(KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36" + } + response = requests.get(url=url, headers=headers, timeout=10) + response.encoding = response.apparent_encoding + # Read CSV and adjustment + data = csv.reader(StringIO(response.text), delimiter=",") + next(data) + next(data) + list_of_column_names = [] + for row in data: + # adding the first row as column + list_of_column_names.append(row) + # breaking the loop after the + # first iteration itself + break + if list_of_column_names: + # Add first column name to Date + list_of_column_names[0][0] = "Date" + next(data) + # convert to XML + root = et.Element("root") + elm1 = et.Element("Cube") + root.append(elm1) + for row in data: + # Change date format + row[0] = row[0].replace("/", "-") + row[0] = datetime.strptime(row[0], "%Y-%m-%d").date() + if row[0] < date_from: + continue + sub_eml = et.SubElement(elm1, "Cube", attrib={"time": str(row[0])}) + for j, colName in enumerate(list_of_column_names[0]): + if colName == "Date" or colName == "": + continue + if str(row[j]) == "*****": + continue + et.SubElement( + sub_eml, + "Cube", + attrib={"currency": colName, "rate": str(1 / float(row[j]))}, + ) + return et.tostring(root) + + def _Is_in_this_month(self, date_from: date, date_to: date): + d_today = date.today() + ym_from = date_from.year + date_from.month + ym_to = date_to.year + date_to.month + ym_now = d_today.year + d_today.month + if ym_from == ym_to == ym_now: + return True + else: + return False + + +class RatesHandler(xml.sax.ContentHandler): + def __init__(self, currencies, date_from, date_to): + self.currencies = currencies + self.date_from = date_from + self.date_to = date_to + self.date = None + self.content = defaultdict(dict) + + def startElement(self, name, attrs): + if name == "Cube" and "time" in attrs: + self.date = fields.Date.from_string(attrs["time"]) + elif name == "Cube" and all([x in attrs for x in ["currency", "rate"]]): + currency = attrs["currency"] + rate = attrs["rate"] + if ( + (self.date_from is None or self.date >= self.date_from) + and (self.date_to is None or self.date <= self.date_to) + and currency in self.currencies + ): + self.content[self.date.isoformat()][currency] = rate diff --git a/currency_rate_update_mizuho/readme/DESCRIPTION.rst b/currency_rate_update_mizuho/readme/DESCRIPTION.rst new file mode 100644 index 00000000..2bb70fe1 --- /dev/null +++ b/currency_rate_update_mizuho/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module provides to update the currency exchange rate from the provider **Mizuho Bank**. diff --git a/currency_rate_update_mizuho/static/description/index.html b/currency_rate_update_mizuho/static/description/index.html new file mode 100644 index 00000000..509c4365 --- /dev/null +++ b/currency_rate_update_mizuho/static/description/index.html @@ -0,0 +1,407 @@ + + + + + + +Currency Rate Update Mizuho + + + +
+

Currency Rate Update Mizuho

+ + +

Beta License: AGPL-3 qrtl/axls-custom

+

This module provides to update the currency exchange rate from the provider Mizuho Bank.

+

Table of contents

+ +
+

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

+
    +
  • Quartile Limited
  • +
+
+
+

Maintainers

+

This module is part of the qrtl/axls-custom project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..9cd16292 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +# generated from manifests external_dependencies diff --git a/setup/currency_rate_update_mizuho/odoo/addons/currency_rate_update_mizuho b/setup/currency_rate_update_mizuho/odoo/addons/currency_rate_update_mizuho new file mode 120000 index 00000000..ee25d108 --- /dev/null +++ b/setup/currency_rate_update_mizuho/odoo/addons/currency_rate_update_mizuho @@ -0,0 +1 @@ +../../../../currency_rate_update_mizuho \ No newline at end of file diff --git a/setup/currency_rate_update_mizuho/setup.py b/setup/currency_rate_update_mizuho/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/currency_rate_update_mizuho/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 00000000..b6dae946 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +git+https://github.com/qrtl/axls-oca@16.0#subdirectory=setup/currency_rate_update From f624d236e2542c0ba03cc10b3b72ee01333303b0 Mon Sep 17 00:00:00 2001 From: Yoshi Tashiro Date: Tue, 20 Dec 2022 15:58:19 +0000 Subject: [PATCH 2/2] [REF] currency_rate_update_mizuho: skip xml conversion --- currency_rate_update_mizuho/README.rst | 3 +- currency_rate_update_mizuho/__manifest__.py | 1 + .../res_currency_rate_provider_mizuho.py | 156 ++++++------------ .../readme/DESCRIPTION.rst | 2 +- .../static/description/index.html | 3 +- 5 files changed, 58 insertions(+), 107 deletions(-) diff --git a/currency_rate_update_mizuho/README.rst b/currency_rate_update_mizuho/README.rst index 4f456d90..f5655e2d 100644 --- a/currency_rate_update_mizuho/README.rst +++ b/currency_rate_update_mizuho/README.rst @@ -19,7 +19,7 @@ Currency Rate Update Mizuho |badge1| |badge2| |badge3| -This module provides to update the currency exchange rate from the provider **Mizuho Bank**. +This module adds the provider **Mizuho Bank** to update currency rates. **Table of contents** @@ -42,6 +42,7 @@ Credits Authors ~~~~~~~ +* Axelspace * Quartile Limited Maintainers diff --git a/currency_rate_update_mizuho/__manifest__.py b/currency_rate_update_mizuho/__manifest__.py index 16321800..f27ea51e 100644 --- a/currency_rate_update_mizuho/__manifest__.py +++ b/currency_rate_update_mizuho/__manifest__.py @@ -1,3 +1,4 @@ +# Copyright 2022 Axelspace # Copyright 2022 Quartile Limited # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { diff --git a/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py b/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py index cc4940f8..dd0990f4 100644 --- a/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py +++ b/currency_rate_update_mizuho/models/res_currency_rate_provider_mizuho.py @@ -3,29 +3,25 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import csv -import xml.etree.ElementTree as et -import xml.sax -from collections import defaultdict -from datetime import date, datetime from io import StringIO import requests -from odoo import fields, models +from odoo import api, fields, models class ResCurrencyRateProviderMizuho(models.Model): _inherit = "res.currency.rate.provider" service = fields.Selection( - selection_add=[("Mizuho", "Mizuho Bank (Japan)")], - ondelete={"Mizuho": "set default"}, + selection_add=[("mizuho", "Mizuho Bank (Japan)")], + ondelete={"mizuho": "set default"}, ) def _get_supported_currencies(self): self.ensure_one() - if self.service != "Mizuho": - return super()._get_supported_currencies() # pragma: no cover + if self.service != "mizuho": + return super()._get_supported_currencies() # List of currencies obrained from: # https://www.mizuhobank.co.jp/market/historical.html return [ @@ -59,107 +55,59 @@ def _get_supported_currencies(self): "TRY", ] - def _obtain_rates(self, base_currency, currencies, date_from, date_to): + @api.model + def _is_in_this_month(self, date_from, date_to): + d_today = fields.Date.context_today(self) + ym_from = date_from.year + date_from.month + ym_to = date_to.year + date_to.month + ym_now = d_today.year + d_today.month + if ym_from == ym_to == ym_now: + return True + return False + + def _get_mizuho_rates(self, url, base_currency, currencies, date_from, date_to): self.ensure_one() - if self.service != "Mizuho": - return super()._obtain_rates( - base_currency, currencies, date_from, date_to - ) # pragma: no cover - invert_calculation = False + daily_rates = {} + response = requests.get(url=url, timeout=10) + response.encoding = response.apparent_encoding + csv_iterator = csv.reader(StringIO(response.text), delimiter=",") + next(csv_iterator) + next(csv_iterator) + # Field labels are on the third row. + field_labels = next(csv_iterator) + invert = False if base_currency != "JPY": - invert_calculation = True + invert = True if base_currency not in currencies: currencies.append(base_currency) + for row in csv_iterator: + # Change date format + row_date = row[0].replace("/", "-") + row_date_date = fields.Date.to_date(row_date) + if row_date_date < date_from or row_date_date > date_to: + continue + daily_rates[row_date] = {} + for currency in currencies: + row_curr_rate = row[field_labels.index(currency)] + daily_rates[row_date][currency] = 1 / float(row_curr_rate) + if invert: + for k in daily_rates.keys(): + base_rate = daily_rates[k][base_currency] + for curr in daily_rates[k].keys(): + daily_rates[k][curr] = daily_rates[k][curr] / base_rate + daily_rates[k]["JPY"] = 1.0 / base_rate + return daily_rates + + def _obtain_rates(self, base_currency, currencies, date_from, date_to): + self.ensure_one() + if self.service != "mizuho": + return super()._obtain_rates(base_currency, currencies, date_from, date_to) # Depending on the date range, different URLs are used url = "https://www.mizuhobank.co.jp/market/csv" - if self._Is_in_this_month(date_from, date_to): + if self._is_in_this_month(date_from, date_to): url = url + "/tm_quote.csv" else: url = url + "/quote.csv" - handler = RatesHandler(currencies, date_from, date_to) - xml.sax.parseString(self._get_mizuho_rates(url, date_from), handler) - content = handler.content - if invert_calculation: - for k in content.keys(): - base_rate = float(content[k][base_currency]) - for rate in content[k].keys(): - content[k][rate] = str(float(content[k][rate]) / base_rate) - content[k]["JPY"] = str(1.0 / base_rate) - return content - - def _get_mizuho_rates(self, url: str, date_from: date) -> str: - headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 " - "(KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36" - } - response = requests.get(url=url, headers=headers, timeout=10) - response.encoding = response.apparent_encoding - # Read CSV and adjustment - data = csv.reader(StringIO(response.text), delimiter=",") - next(data) - next(data) - list_of_column_names = [] - for row in data: - # adding the first row as column - list_of_column_names.append(row) - # breaking the loop after the - # first iteration itself - break - if list_of_column_names: - # Add first column name to Date - list_of_column_names[0][0] = "Date" - next(data) - # convert to XML - root = et.Element("root") - elm1 = et.Element("Cube") - root.append(elm1) - for row in data: - # Change date format - row[0] = row[0].replace("/", "-") - row[0] = datetime.strptime(row[0], "%Y-%m-%d").date() - if row[0] < date_from: - continue - sub_eml = et.SubElement(elm1, "Cube", attrib={"time": str(row[0])}) - for j, colName in enumerate(list_of_column_names[0]): - if colName == "Date" or colName == "": - continue - if str(row[j]) == "*****": - continue - et.SubElement( - sub_eml, - "Cube", - attrib={"currency": colName, "rate": str(1 / float(row[j]))}, - ) - return et.tostring(root) - - def _Is_in_this_month(self, date_from: date, date_to: date): - d_today = date.today() - ym_from = date_from.year + date_from.month - ym_to = date_to.year + date_to.month - ym_now = d_today.year + d_today.month - if ym_from == ym_to == ym_now: - return True - else: - return False - - -class RatesHandler(xml.sax.ContentHandler): - def __init__(self, currencies, date_from, date_to): - self.currencies = currencies - self.date_from = date_from - self.date_to = date_to - self.date = None - self.content = defaultdict(dict) - - def startElement(self, name, attrs): - if name == "Cube" and "time" in attrs: - self.date = fields.Date.from_string(attrs["time"]) - elif name == "Cube" and all([x in attrs for x in ["currency", "rate"]]): - currency = attrs["currency"] - rate = attrs["rate"] - if ( - (self.date_from is None or self.date >= self.date_from) - and (self.date_to is None or self.date <= self.date_to) - and currency in self.currencies - ): - self.content[self.date.isoformat()][currency] = rate + return self._get_mizuho_rates( + url, base_currency, currencies, date_from, date_to + ) diff --git a/currency_rate_update_mizuho/readme/DESCRIPTION.rst b/currency_rate_update_mizuho/readme/DESCRIPTION.rst index 2bb70fe1..a7973646 100644 --- a/currency_rate_update_mizuho/readme/DESCRIPTION.rst +++ b/currency_rate_update_mizuho/readme/DESCRIPTION.rst @@ -1 +1 @@ -This module provides to update the currency exchange rate from the provider **Mizuho Bank**. +This module adds the provider **Mizuho Bank** to update currency rates. diff --git a/currency_rate_update_mizuho/static/description/index.html b/currency_rate_update_mizuho/static/description/index.html index 509c4365..76912b52 100644 --- a/currency_rate_update_mizuho/static/description/index.html +++ b/currency_rate_update_mizuho/static/description/index.html @@ -368,7 +368,7 @@

Currency Rate Update Mizuho

!! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 qrtl/axls-custom

-

This module provides to update the currency exchange rate from the provider Mizuho Bank.

+

This module adds the provider Mizuho Bank to update currency rates.

Table of contents