119 lines
4.1 KiB
Python
119 lines
4.1 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from decimal import Decimal
|
|
|
|
from lxml import objectify
|
|
from zeep import Client, Transport
|
|
from zeep.exceptions import Error
|
|
|
|
import trytond.config as config
|
|
from trytond.cache import Cache
|
|
from trytond.i18n import gettext
|
|
from trytond.model import fields
|
|
from trytond.modules.currency.currency import CronFetchError
|
|
from trytond.pool import Pool, PoolMeta
|
|
from trytond.pyson import Eval, If
|
|
|
|
from .exceptions import RSCredentialWarning
|
|
|
|
URL = (
|
|
'https://webservices.nbs.rs/CommunicationOfficeService1_0/'
|
|
'ExchangeRateXmlService.asmx?WSDL')
|
|
|
|
|
|
def get_client(username, password, license_id):
|
|
timeout = config.getfloat('currency_rs', 'requests_timeout', default=300)
|
|
client = Client(URL, transport=Transport(operation_timeout=timeout))
|
|
client.set_default_soapheaders({
|
|
'AuthenticationHeader': {
|
|
'UserName': username,
|
|
'Password': password,
|
|
'LicenceID': license_id,
|
|
},
|
|
})
|
|
return client
|
|
|
|
|
|
class Cron(metaclass=PoolMeta):
|
|
__name__ = 'currency.cron'
|
|
|
|
_states = {
|
|
'required': Eval('source') == 'nbs_rs',
|
|
'invisible': Eval('source') != 'nbs_rs',
|
|
}
|
|
|
|
rs_username = fields.Char("Username", states=_states, strip=False)
|
|
rs_password = fields.Char("Password", states=_states, strip=False)
|
|
rs_license_id = fields.Char("License ID", states=_states, strip=False)
|
|
rs_list_type = fields.Selection(
|
|
'get_rs_list_types', "List Type", states=_states)
|
|
_rs_list_types = Cache(__name__ + '.get_rs_list_types', context=False)
|
|
|
|
del _states
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super().__setup__()
|
|
cls.source.selection.append(('nbs_rs', "Serbian National Bank"))
|
|
cls.currency.domain = [
|
|
cls.currency.domain or [],
|
|
If(Eval('source') == 'nbs_rs',
|
|
('code', '=', 'RSD'),
|
|
()),
|
|
]
|
|
|
|
@fields.depends('rs_username', 'rs_password', 'rs_license_id')
|
|
def _rs_client(self):
|
|
return get_client(
|
|
self.rs_username, self.rs_password, self.rs_license_id)
|
|
|
|
@fields.depends('rs_list_type', methods=['_rs_client'])
|
|
def get_rs_list_types(self):
|
|
types = self._rs_list_types.get(None)
|
|
if types is not None:
|
|
return types
|
|
try:
|
|
client = self._rs_client()
|
|
response = client.service.GetExchangeRateListType()
|
|
except Error:
|
|
return [(self.rs_list_type, self.rs_list_type or "")]
|
|
types = []
|
|
data = objectify.fromstring(response)
|
|
for list_type in data.iterchildren():
|
|
types.append(
|
|
(str(list_type.ExchangeRateListTypeID), str(list_type.Name)))
|
|
self._rs_list_types.set(None, types)
|
|
return types
|
|
|
|
def fetch_nbs_rs(self, date):
|
|
try:
|
|
client = self._rs_client()
|
|
response = client.service.GetExchangeRateByDate(
|
|
date.strftime('%Y%m%d'), self.rs_list_type)
|
|
except Error as e:
|
|
raise CronFetchError() from e
|
|
data = objectify.fromstring(response)
|
|
return {
|
|
r.CurrencyCodeAlfaChar: (
|
|
Decimal(r.Unit.text) / Decimal(r.MiddleRate.text))
|
|
for r in data.iterchildren()
|
|
if r.Date == date.strftime('%d.%m.%Y')}
|
|
|
|
@classmethod
|
|
def check_modification(cls, mode, crons, values=None, external=False):
|
|
pool = Pool()
|
|
Warning = pool.get('res.user.warning')
|
|
|
|
super().check_modification(
|
|
mode, crons, values=values, external=external)
|
|
|
|
if (mode == 'write'
|
|
and external
|
|
and values.keys() & {
|
|
'rs_username', 'rs_password', 'rs_license_id'}):
|
|
warning_name = Warning.format('rs_credential', crons)
|
|
if Warning.check(warning_name):
|
|
raise RSCredentialWarning(
|
|
warning_name,
|
|
gettext('currency_rs.msg_rs_credential_modified'))
|