mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
Fix PEP8 of module currency_rate_update in order to be able to activate flake8 testing on travis.
No refactoring has been done despite the current need
This commit is contained in:
@@ -22,11 +22,11 @@
|
||||
#
|
||||
##############################################################################
|
||||
{
|
||||
"name" : "Currency Rate Update",
|
||||
"version" : "0.7",
|
||||
"author" : "Camptocamp",
|
||||
"website" : "http://camptocamp.com",
|
||||
"category" : "Financial Management/Configuration",
|
||||
"name": "Currency Rate Update",
|
||||
"version": "0.7",
|
||||
"author": "Camptocamp",
|
||||
"website": "http://camptocamp.com",
|
||||
"category": "Financial Management/Configuration",
|
||||
"description": """Import exchange rates from the Internet.
|
||||
|
||||
The module is able to use 4 different sources:
|
||||
@@ -48,7 +48,7 @@ The module is able to use 4 different sources:
|
||||
You should check when rates should apply to bookkeeping. If next day you should
|
||||
change the update hour in schedule settings because in OpenERP they apply from
|
||||
date of update (date - no hours).
|
||||
|
||||
|
||||
5. Banxico for USD & MXN (created by Agustín Cruz)
|
||||
Updated daily
|
||||
|
||||
@@ -64,7 +64,7 @@ The module uses internal ir_cron feature from OpenERP, so the job is launched on
|
||||
the server starts if the 'first execute date' is before the current day.
|
||||
The module supports multi-company currency in two ways:
|
||||
|
||||
* the currencies are shared, you can set currency update only on one
|
||||
* the currencies are shared, you can set currency update only on one
|
||||
company
|
||||
* the currency are separated, you can set currency on every company
|
||||
separately
|
||||
@@ -76,16 +76,16 @@ found in database.
|
||||
|
||||
Thanks to main contributors: Grzegorz Grzelak, Alexis de Lattre
|
||||
""",
|
||||
"depends" : [
|
||||
"depends": [
|
||||
"base",
|
||||
"account", #Added to ensure account security groups are present
|
||||
],
|
||||
"data" : [
|
||||
"account", # Added to ensure account security groups are present
|
||||
],
|
||||
"data": [
|
||||
"currency_rate_update.xml",
|
||||
"company_view.xml",
|
||||
"security/security.xml",
|
||||
],
|
||||
"demo" : [],
|
||||
],
|
||||
"demo": [],
|
||||
"active": False,
|
||||
'installable': True
|
||||
}
|
||||
|
||||
@@ -18,17 +18,21 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import netsvc
|
||||
from openerp.osv import fields, orm
|
||||
|
||||
|
||||
class res_company(orm.Model):
|
||||
"""override company to add currency update"""
|
||||
|
||||
def _multi_curr_enable(self, cr, uid, ids, field_name, arg, context={}):
|
||||
"check if multi company currency is enabled"
|
||||
result = {}
|
||||
if self.pool.get('ir.model.fields').search(cr, uid, [('name', '=', 'company_id'), ('model', '=', 'res.currency')])==[]:
|
||||
fields = self.pool.get('ir.model.fields').search(
|
||||
cr, uid,
|
||||
[('name', '=', 'company_id'),
|
||||
('model', '=', 'res.currency')]
|
||||
)
|
||||
if not fields:
|
||||
enable = 0
|
||||
else:
|
||||
enable = 1
|
||||
@@ -36,18 +40,15 @@ class res_company(orm.Model):
|
||||
result[id] = enable
|
||||
return result
|
||||
|
||||
|
||||
def button_refresh_currency(self, cr, uid, ids, context=None):
|
||||
"""Refrech the currency !!for all the company
|
||||
now"""
|
||||
"""Refrech the currency for all the company now"""
|
||||
currency_updater_obj = self.pool.get('currency.rate.update')
|
||||
try:
|
||||
currency_updater_obj.run_currency_update(cr, uid)
|
||||
except Exception, e:
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def on_change_auto_currency_up(self, cr, uid, id, value):
|
||||
"""handle the activation of the currecny update on compagnies.
|
||||
There are two ways of implementing multi_company currency,
|
||||
@@ -56,102 +57,100 @@ class res_company(orm.Model):
|
||||
auto update on one company, this will avoid to have unusefull cron
|
||||
object running.
|
||||
If yours currency are not share you will be able to activate the
|
||||
auto update on each separated company"""
|
||||
auto update on each separated company
|
||||
|
||||
if len(id) :
|
||||
"""
|
||||
|
||||
if len(id):
|
||||
id = id[0]
|
||||
else :
|
||||
else:
|
||||
return {}
|
||||
enable = self.browse(cr, uid, id).multi_company_currency_enable
|
||||
compagnies = self.search(cr, uid, [])
|
||||
compagnies = self.search(cr, uid, [])
|
||||
activate_cron = 'f'
|
||||
if not value :
|
||||
if not value:
|
||||
# this statement is here beacaus we do no want to save in case of error
|
||||
self.write(cr, uid, id,{'auto_currency_up':value})
|
||||
for comp in compagnies :
|
||||
self.write(cr, uid, id, {'auto_currency_up': value})
|
||||
for comp in compagnies:
|
||||
if self.browse(cr, uid, comp).auto_currency_up:
|
||||
activate_cron = 't'
|
||||
break
|
||||
self.pool.get('currency.rate.update').save_cron(
|
||||
cr,
|
||||
uid,
|
||||
{'active':activate_cron}
|
||||
)
|
||||
cr,
|
||||
uid,
|
||||
{'active': activate_cron}
|
||||
)
|
||||
return {}
|
||||
else :
|
||||
for comp in compagnies :
|
||||
else:
|
||||
for comp in compagnies:
|
||||
if comp != id and not enable:
|
||||
if self.browse(cr, uid, comp).multi_company_currency_enable:
|
||||
#we ensure taht we did not have write a true value
|
||||
self.write(cr, uid, id,{'auto_currency_up':False})
|
||||
self.write(cr, uid, id, {'auto_currency_up': False})
|
||||
return {
|
||||
'value':{
|
||||
'auto_currency_up':False
|
||||
},
|
||||
'value': {'auto_currency_up': False},
|
||||
|
||||
'warning':{
|
||||
'title':"Warning",
|
||||
'message': 'Yon can not activate auto currency '+\
|
||||
'update on more thant one company with this '+
|
||||
'multi company configuration'
|
||||
}
|
||||
}
|
||||
self.write(cr, uid, id,{'auto_currency_up':value})
|
||||
for comp in compagnies :
|
||||
'warning': {
|
||||
'title': "Warning",
|
||||
'message': 'You can not activate auto currency '
|
||||
'update on more thant one company with this '
|
||||
'multi company configuration'
|
||||
}
|
||||
}
|
||||
self.write(cr, uid, id, {'auto_currency_up': value})
|
||||
for comp in compagnies:
|
||||
if self.browse(cr, uid, comp).auto_currency_up:
|
||||
activate_cron = 't'
|
||||
self.pool.get('currency.rate.update').save_cron(
|
||||
cr,
|
||||
uid,
|
||||
{'active':activate_cron}
|
||||
)
|
||||
cr,
|
||||
uid,
|
||||
{'active': activate_cron}
|
||||
)
|
||||
break
|
||||
return {}
|
||||
|
||||
|
||||
def on_change_intervall(self, cr, uid, id, interval) :
|
||||
###Function that will update the cron
|
||||
###freqeuence
|
||||
def on_change_intervall(self, cr, uid, id, interval):
|
||||
# Function that will update the cron freqeuence
|
||||
self.pool.get('currency.rate.update').save_cron(
|
||||
cr,
|
||||
uid,
|
||||
{'interval_type':interval}
|
||||
)
|
||||
compagnies = self.search(cr, uid, [])
|
||||
for comp in compagnies :
|
||||
self.write(cr, uid, comp,{'interval_type':interval})
|
||||
cr,
|
||||
uid,
|
||||
{'interval_type': interval}
|
||||
)
|
||||
compagnies = self.search(cr, uid, [])
|
||||
for comp in compagnies:
|
||||
self.write(cr, uid, comp, {'interval_type': interval})
|
||||
return {}
|
||||
|
||||
_inherit = "res.company"
|
||||
_columns = {
|
||||
### activate the currency update
|
||||
'auto_currency_up': fields.boolean('Automatical update of the currency this company'),
|
||||
'services_to_use' : fields.one2many(
|
||||
'currency.rate.update.service',
|
||||
'company_id',
|
||||
'Currency update services'
|
||||
),
|
||||
###predifine cron frequence
|
||||
# Activate the currency update
|
||||
'auto_currency_up': fields.boolean(
|
||||
'Automatical update of the currency this company'
|
||||
),
|
||||
'services_to_use': fields.one2many(
|
||||
'currency.rate.update.service',
|
||||
'company_id',
|
||||
'Currency update services'
|
||||
),
|
||||
# Predifine cron frequence
|
||||
'interval_type': fields.selection(
|
||||
[
|
||||
('days','Day(s)'),
|
||||
('weeks', 'Week(s)'),
|
||||
('months', 'Month(s)')
|
||||
],
|
||||
'Currency update frequence',
|
||||
help="""changing this value will
|
||||
also affect other compagnies"""
|
||||
),
|
||||
###function field that allows to know the
|
||||
###mutli company currency implementation
|
||||
'multi_company_currency_enable' : fields.function(
|
||||
_multi_curr_enable,
|
||||
method=True,
|
||||
type='boolean',
|
||||
string="Multi company currency",
|
||||
help='if this case is not check you can'+\
|
||||
' not set currency is active on two company'
|
||||
),
|
||||
[
|
||||
('days', 'Day(s)'),
|
||||
('weeks', 'Week(s)'),
|
||||
('months', 'Month(s)')
|
||||
],
|
||||
'Currency update frequence',
|
||||
help="Changing this value will "
|
||||
"also affect other compagnies"
|
||||
),
|
||||
# Function field that allows to know the
|
||||
# mutli company currency implementation
|
||||
'multi_company_currency_enable': fields.function(
|
||||
_multi_curr_enable,
|
||||
method=True,
|
||||
type='boolean',
|
||||
string="Multi company currency",
|
||||
help="If this case is not check you can"
|
||||
" not set currency is active on two company"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2009 Camptocamp SA
|
||||
# @author Nicolas Bessi
|
||||
# @source JBA and AWST inpiration
|
||||
# @contributor Grzegorz Grzelak (grzegorz.grzelak@birdglobe.com), Joel Grand-Guillaume
|
||||
# Copyright (c) 2010 Alexis de Lattre (alexis@via.ecp.fr)
|
||||
@@ -31,68 +30,75 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# TODO "nice to have" : restain the list of currencies that can be added for
|
||||
# TODO "nice to have" : restrain the list of currencies that can be added for
|
||||
# a webservice to the list of currencies supported by the Webservice
|
||||
# TODO : implement max_delta_days for Yahoo webservice
|
||||
|
||||
from openerp.osv import fields, osv, orm
|
||||
import logging
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
from openerp.osv import fields, osv, orm
|
||||
from openerp.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Currency_rate_update_service(osv.Model):
|
||||
"""Class thats tell for wich services wich currencies
|
||||
have to be updated"""
|
||||
"""Class that tells for wich services wich currencies have to be updated
|
||||
|
||||
"""
|
||||
_name = "currency.rate.update.service"
|
||||
_description = "Currency Rate Update"
|
||||
_columns = {
|
||||
##list of webservicies the value sould be a class name
|
||||
'service' : fields.selection(
|
||||
[
|
||||
('Admin_ch_getter','Admin.ch'),
|
||||
('ECB_getter','European Central Bank'),
|
||||
#('NYFB_getter','Federal Reserve Bank of NY'),
|
||||
#('Google_getter','Google Finance'),
|
||||
('Yahoo_getter','Yahoo Finance '),
|
||||
('PL_NBP_getter','Narodowy Bank Polski'), # Added for polish rates
|
||||
('Banxico_getter', 'Banco de México'), # Added for mexican rates
|
||||
# Bank of Canada is using RSS-CB http://www.cbwiki.net/wiki/index.php/Specification_1.1 :
|
||||
# This RSS format is used by other national banks (Thailand, Malaysia, Mexico...)
|
||||
('CA_BOC_getter','Bank of Canada - noon rates'), # Added for canadian rates
|
||||
],
|
||||
"Webservice to use",
|
||||
required = True
|
||||
),
|
||||
##list of currency to update
|
||||
'currency_to_update' : fields.many2many(
|
||||
'res.currency',
|
||||
'res_curreny_auto_udate_rel',
|
||||
'service_id',
|
||||
'currency_id',
|
||||
'currency to update with this service',
|
||||
),
|
||||
#back ref
|
||||
'company_id' : fields.many2one(
|
||||
'res.company',
|
||||
'linked company',
|
||||
),
|
||||
##note fileds that will be used as a logger
|
||||
'note':fields.text('update notice'),
|
||||
'max_delta_days': fields.integer('Max delta days', required=True, help="If the time delta between the rate date given by the webservice and the current date exeeds this value, then the currency rate is not updated in OpenERP."),
|
||||
}
|
||||
_defaults = {
|
||||
'max_delta_days': lambda *a: 4,
|
||||
# List of webservicies the value sould be a class name
|
||||
'service': fields.selection(
|
||||
[
|
||||
('Admin_ch_getter', 'Admin.ch'),
|
||||
('ECB_getter', 'European Central Bank'),
|
||||
#('NYFB_getter','Federal Reserve Bank of NY'),
|
||||
#('Google_getter','Google Finance'),
|
||||
('Yahoo_getter', 'Yahoo Finance '),
|
||||
('PL_NBP_getter', 'Narodowy Bank Polski'), # Added for polish rates
|
||||
('Banxico_getter', 'Banco de México'), # Added for mexican rates
|
||||
# Bank of Canada is using RSS-CB http://www.cbwiki.net/wiki/index.php/Specification_1.1 :
|
||||
# This RSS format is used by other national banks (Thailand, Malaysia, Mexico...)
|
||||
('CA_BOC_getter', 'Bank of Canada - noon rates'), # Added for canadian rates
|
||||
],
|
||||
"Webservice to use",
|
||||
required=True
|
||||
),
|
||||
# List of currency to update
|
||||
'currency_to_update': fields.many2many(
|
||||
'res.currency',
|
||||
'res_curreny_auto_udate_rel',
|
||||
'service_id',
|
||||
'currency_id',
|
||||
'currency to update with this service',
|
||||
),
|
||||
# Back ref
|
||||
'company_id': fields.many2one(
|
||||
'res.company',
|
||||
'linked company',
|
||||
),
|
||||
# Note fileds that will be used as a logger
|
||||
'note': fields.text('update notice'),
|
||||
'max_delta_days': fields.integer(
|
||||
'Max delta days',
|
||||
required=True,
|
||||
help="If the time delta between the "
|
||||
"rate date given by the webservice and "
|
||||
"the current date exeeds this value, "
|
||||
"then the currency rate is not updated in OpenERP."
|
||||
),
|
||||
}
|
||||
_defaults = {'max_delta_days': lambda *a: 4}
|
||||
_sql_constraints = [
|
||||
(
|
||||
'curr_service_unique',
|
||||
'unique (service, company_id)',
|
||||
_('You can use a service one time per company !')
|
||||
)
|
||||
]
|
||||
(
|
||||
'curr_service_unique',
|
||||
'unique (service, company_id)',
|
||||
_('You can use a service one time per company !')
|
||||
)
|
||||
]
|
||||
|
||||
def _check_max_delta_days(self, cr, uid, ids):
|
||||
for company in self.read(cr, uid, ids, ['max_delta_days']):
|
||||
@@ -103,7 +109,9 @@ class Currency_rate_update_service(osv.Model):
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_max_delta_days, "'Max delta days' must be >= 0", ['max_delta_days']),
|
||||
(_check_max_delta_days,
|
||||
"'Max delta days' must be >= 0",
|
||||
['max_delta_days']),
|
||||
]
|
||||
|
||||
|
||||
@@ -112,58 +120,59 @@ class Currency_rate_update(osv.Model):
|
||||
update currencies based on a web url"""
|
||||
_name = "currency.rate.update"
|
||||
_description = "Currency Rate Update"
|
||||
##dict that represent a cron object
|
||||
# Dict that represent a cron object
|
||||
cron = {
|
||||
'active' : False,
|
||||
'priority' : 1,
|
||||
'interval_number' : 1,
|
||||
'interval_type' : 'weeks',
|
||||
'nextcall' : time.strftime("%Y-%m-%d %H:%M:%S", (datetime.today() + timedelta(days=1)).timetuple() ), #tomorrow same time
|
||||
'numbercall' : -1,
|
||||
'doall' : True,
|
||||
'model' : 'currency.rate.update',
|
||||
'function' : 'run_currency_update',
|
||||
'args' : '()',
|
||||
'active': False,
|
||||
'priority': 1,
|
||||
'interval_number': 1,
|
||||
'interval_type': 'weeks',
|
||||
'nextcall': time.strftime("%Y-%m-%d %H:%M:%S",
|
||||
datetime.today() + timedelta(days=1)).timetuple(),
|
||||
'numbercall': -1,
|
||||
'doall': True,
|
||||
'model': 'currency.rate.update',
|
||||
'function': 'run_currency_update',
|
||||
'args': '()',
|
||||
}
|
||||
|
||||
LOG_NAME = 'cron-rates'
|
||||
MOD_NAME = 'currency_rate_update: '
|
||||
|
||||
def get_cron_id(self, cr, uid, context):
|
||||
"""return the updater cron's id. Create one if the cron does not exists """
|
||||
"""Returns the updater cron's id.
|
||||
Create one if the cron does not exists
|
||||
"""
|
||||
|
||||
cron_id = 0
|
||||
cron_obj = self.pool.get('ir.cron')
|
||||
try:
|
||||
#find the cron that send messages
|
||||
#Finds the cron that send messages
|
||||
cron_id = cron_obj.search(
|
||||
cr,
|
||||
uid,
|
||||
[
|
||||
('function', 'ilike', self.cron['function']),
|
||||
('model', 'ilike', self.cron['model'])
|
||||
],
|
||||
context={
|
||||
'active_test': False
|
||||
}
|
||||
)
|
||||
cr,
|
||||
uid,
|
||||
[
|
||||
('function', 'ilike', self.cron['function']),
|
||||
('model', 'ilike', self.cron['model'])
|
||||
],
|
||||
context={
|
||||
'active_test': False
|
||||
}
|
||||
)
|
||||
cron_id = int(cron_id[0])
|
||||
except Exception,e :
|
||||
except Exception:
|
||||
_logger.info('warning cron not found one will be created')
|
||||
pass # ignore if the cron is missing cause we are going to create it in db
|
||||
pass # Ignore if the cron is missing cause we are going to create it in db
|
||||
|
||||
#the cron does not exists
|
||||
if not cron_id :
|
||||
#translate
|
||||
#The cron does not exists
|
||||
if not cron_id:
|
||||
self.cron['name'] = _('Currency Rate Update')
|
||||
cron_id = cron_obj.create(cr, uid, self.cron, context)
|
||||
|
||||
return cron_id
|
||||
|
||||
def save_cron(self, cr, uid, datas, context={}):
|
||||
"""save the cron config data should be a dict"""
|
||||
#modify the cron
|
||||
cron_id = self.get_cron_id(cr, uid, context)
|
||||
result = self.pool.get('ir.cron').write(cr, uid, [cron_id], datas)
|
||||
return self.pool.get('ir.cron').write(cr, uid, [cron_id], datas)
|
||||
|
||||
def run_currency_update(self, cr, uid):
|
||||
"update currency at the given frequence"
|
||||
@@ -172,123 +181,145 @@ class Currency_rate_update(osv.Model):
|
||||
rate_obj = self.pool.get('res.currency.rate')
|
||||
companies = self.pool.get('res.company').search(cr, uid, [])
|
||||
for comp in self.pool.get('res.company').browse(cr, uid, companies):
|
||||
##the multi company currency can beset or no so we handle
|
||||
##the two case
|
||||
if not comp.auto_currency_up :
|
||||
#The multi company currency can beset or no so we handle
|
||||
#The two case
|
||||
if not comp.auto_currency_up:
|
||||
continue
|
||||
#we initialise the multi compnay search filter or not serach filter
|
||||
search_filter = []
|
||||
if comp.multi_company_currency_enable :
|
||||
search_filter = [('company_id','=',comp.id)]
|
||||
#we fetch the main currency looking for currency with base = true. The main rate should be set at 1.00
|
||||
main_curr_ids = curr_obj.search(cr, uid, [('base','=',True),('company_id','=',comp.id)])
|
||||
#We fetch the main currency looking for currency with base = true.
|
||||
#The main rate should be set at 1.00
|
||||
main_curr_ids = curr_obj.search(
|
||||
cr, uid,
|
||||
[('base', '=', True), ('company_id', '=', comp.id)]
|
||||
)
|
||||
if not main_curr_ids:
|
||||
# If we can not find a base currency for this company we look for one with no company set
|
||||
main_curr_ids = curr_obj.search(cr, uid, [('base','=',True),('company_id','=', False)])
|
||||
# If we can not find a base currency for this company
|
||||
# we look for one with no company set
|
||||
main_curr_ids = curr_obj.search(
|
||||
cr, uid,
|
||||
[('base', '=', True), ('company_id', '=', False)]
|
||||
)
|
||||
if main_curr_ids:
|
||||
main_curr_rec = curr_obj.browse(cr, uid, main_curr_ids[0])
|
||||
else:
|
||||
raise orm.except_orm(_('Error!'),('There is no base currency set!'))
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
('There is no base currency set!')
|
||||
)
|
||||
if main_curr_rec.rate != 1:
|
||||
raise orm.except_orm(_('Error!'),('Base currency rate should be 1.00!'))
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
('Base currency rate should be 1.00!')
|
||||
)
|
||||
main_curr = main_curr_rec.name
|
||||
for service in comp.services_to_use :
|
||||
print "comp.services_to_use =", comp.services_to_use
|
||||
for service in comp.services_to_use:
|
||||
note = service.note or ''
|
||||
try :
|
||||
## we initalize the class that will handle the request
|
||||
## and return a dict of rate
|
||||
try:
|
||||
#We initalize the class that will handle the request
|
||||
#and return a dict of rate
|
||||
getter = factory.register(service.service)
|
||||
print "getter =", getter
|
||||
curr_to_fetch = map(lambda x : x.name, service.currency_to_update)
|
||||
res, log_info = getter.get_updated_currency(curr_to_fetch, main_curr, service.max_delta_days)
|
||||
curr_to_fetch = map(lambda x: x.name, service.currency_to_update)
|
||||
res, log_info = getter.get_updated_currency(
|
||||
curr_to_fetch,
|
||||
main_curr,
|
||||
service.max_delta_days
|
||||
)
|
||||
rate_name = time.strftime('%Y-%m-%d')
|
||||
for curr in service.currency_to_update :
|
||||
if curr.name == main_curr :
|
||||
for curr in service.currency_to_update:
|
||||
if curr.name == main_curr:
|
||||
continue
|
||||
do_create = True
|
||||
for rate in curr.rate_ids :
|
||||
if rate.name == rate_name :
|
||||
rate.write({'rate':res[curr.name]})
|
||||
for rate in curr.rate_ids:
|
||||
if rate.name == rate_name:
|
||||
rate.write({'rate': res[curr.name]})
|
||||
do_create = False
|
||||
break
|
||||
if do_create :
|
||||
if do_create:
|
||||
vals = {
|
||||
'currency_id': curr.id,
|
||||
'rate':res[curr.name],
|
||||
'name': rate_name
|
||||
}
|
||||
'currency_id': curr.id,
|
||||
'rate': res[curr.name],
|
||||
'name': rate_name
|
||||
}
|
||||
rate_obj.create(
|
||||
cr,
|
||||
uid,
|
||||
vals,
|
||||
)
|
||||
cr,
|
||||
uid,
|
||||
vals,
|
||||
)
|
||||
|
||||
# show the most recent note at the top
|
||||
note = "\n%s currency updated. "\
|
||||
%(datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S'))\
|
||||
+ note
|
||||
note = (log_info or '') + note
|
||||
service.write({'note':note})
|
||||
except Exception, e:
|
||||
error_msg = "\n%s ERROR : %s"\
|
||||
%(datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S'), str(e))\
|
||||
+ note
|
||||
_logger.info(str(e))
|
||||
service.write({'note':error_msg})
|
||||
# Show the most recent note at the top
|
||||
msg = "%s \n%s currency updated. %s" % \
|
||||
(log_info or '',
|
||||
datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S'),
|
||||
note)
|
||||
service.write({'note': msg})
|
||||
except Exception as exc:
|
||||
error_msg = "\n%s ERROR : %s %s" %\
|
||||
(datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S'),
|
||||
repr(exc),
|
||||
note)
|
||||
_logger.info(repr(exc))
|
||||
service.write({'note': error_msg})
|
||||
|
||||
|
||||
|
||||
### Error Definition as specified in python 2.6 PEP
|
||||
class AbstractClassError(Exception):
|
||||
def __str__(self):
|
||||
return 'Abstract Class'
|
||||
|
||||
def __repr__(self):
|
||||
return 'Abstract Class'
|
||||
return 'Abstract Class'
|
||||
|
||||
|
||||
class AbstractMethodError(Exception):
|
||||
def __str__(self):
|
||||
return 'Abstract Method'
|
||||
|
||||
def __repr__(self):
|
||||
return 'Abstract Method'
|
||||
|
||||
|
||||
class UnknowClassError(Exception):
|
||||
def __str__(self):
|
||||
return 'Unknown Class'
|
||||
|
||||
def __repr__(self):
|
||||
return 'Unknown Class'
|
||||
|
||||
|
||||
class UnsuportedCurrencyError(Exception):
|
||||
def __init__(self, value):
|
||||
self.curr = value
|
||||
def __str__(self):
|
||||
return 'Unsupported currency '+self.curr
|
||||
def __repr__(self):
|
||||
return 'Unsupported currency '+self.curr
|
||||
self.curr = value
|
||||
|
||||
def __str__(self):
|
||||
return 'Unsupported currency %s' % self.curr
|
||||
|
||||
def __repr__(self):
|
||||
return 'Unsupported currency %s' % self.curr
|
||||
|
||||
|
||||
### end of error definition
|
||||
class Currency_getter_factory():
|
||||
"""Factory pattern class that will return
|
||||
a currency getter class base on the name passed
|
||||
to the register method"""
|
||||
to the register method
|
||||
|
||||
"""
|
||||
def register(self, class_name):
|
||||
allowed = [
|
||||
'Admin_ch_getter',
|
||||
'PL_NBP_getter',
|
||||
'ECB_getter',
|
||||
'NYFB_getter',
|
||||
'Google_getter',
|
||||
'Yahoo_getter',
|
||||
'Banxico_getter',
|
||||
'CA_BOC_getter',
|
||||
]
|
||||
'Admin_ch_getter',
|
||||
'PL_NBP_getter',
|
||||
'ECB_getter',
|
||||
'NYFB_getter',
|
||||
'Google_getter',
|
||||
'Yahoo_getter',
|
||||
'Banxico_getter',
|
||||
'CA_BOC_getter',
|
||||
]
|
||||
if class_name in allowed:
|
||||
class_def = eval(class_name)
|
||||
return class_def()
|
||||
else :
|
||||
else:
|
||||
raise UnknowClassError
|
||||
|
||||
|
||||
class Curreny_getter_interface(object) :
|
||||
class Curreny_getter_interface(object):
|
||||
"Abstract class of currency getter"
|
||||
|
||||
#remove in order to have a dryer code
|
||||
@@ -297,47 +328,49 @@ class Curreny_getter_interface(object) :
|
||||
|
||||
log_info = " "
|
||||
|
||||
supported_currency_array = \
|
||||
['AFN', 'ALL', 'DZD', 'USD', 'USD', 'USD', 'EUR', 'AOA', 'XCD', 'XCD', 'ARS',
|
||||
'AMD', 'AWG', 'AUD', 'EUR', 'AZN', 'EUR', 'BSD', 'BHD', 'EUR', 'BDT', 'BBD',
|
||||
'XCD', 'BYR', 'EUR', 'BZD', 'XOF', 'BMD', 'BTN', 'INR', 'BOB', 'ANG', 'BAM',
|
||||
'BWP', 'NOK', 'BRL', 'GBP', 'USD', 'USD', 'BND', 'BGN', 'XOF', 'MMK', 'BIF',
|
||||
'XOF', 'USD', 'KHR', 'XAF', 'CAD', 'EUR', 'CVE', 'KYD', 'XAF', 'XAF', 'CLP',
|
||||
'CNY', 'AUD', 'AUD', 'COP', 'XAF', 'KMF', 'XPF', 'XAF', 'CDF', 'NZD', 'CRC',
|
||||
'HRK', 'CUP', 'ANG', 'EUR', 'CYP', 'CZK', 'DKK', 'DJF', 'XCD', 'DOP', 'EUR',
|
||||
'XCD', 'IDR', 'USD', 'EGP', 'EUR', 'SVC', 'USD', 'GBP', 'XAF', 'ETB', 'ERN',
|
||||
'EEK', 'ETB', 'EUR', 'FKP', 'DKK', 'FJD', 'EUR', 'EUR', 'EUR', 'XPF', 'XPF',
|
||||
'EUR', 'XPF', 'XAF', 'GMD', 'GEL', 'EUR', 'GHS', 'GIP', 'XAU', 'GBP', 'EUR',
|
||||
'DKK', 'XCD', 'XCD', 'EUR', 'USD', 'GTQ', 'GGP', 'GNF', 'XOF', 'GYD', 'HTG',
|
||||
'USD', 'AUD', 'BAM', 'EUR', 'EUR', 'HNL', 'HKD', 'HUF', 'ISK', 'INR', 'IDR',
|
||||
'XDR', 'IRR', 'IQD', 'EUR', 'IMP', 'ILS', 'EUR', 'JMD', 'NOK', 'JPY', 'JEP',
|
||||
'JOD', 'KZT', 'AUD', 'KES', 'AUD', 'KPW', 'KRW', 'KWD', 'KGS', 'LAK', 'LVL',
|
||||
'LBP', 'LSL', 'ZAR', 'LRD', 'LYD', 'CHF', 'LTL', 'EUR', 'MOP', 'MKD', 'MGA',
|
||||
'EUR', 'MWK', 'MYR', 'MVR', 'XOF', 'EUR', 'MTL', 'FKP', 'USD', 'USD', 'EUR',
|
||||
'MRO', 'MUR', 'EUR', 'AUD', 'MXN', 'USD', 'USD', 'EUR', 'MDL', 'EUR', 'MNT',
|
||||
'EUR', 'XCD', 'MAD', 'MZN', 'MMK', 'NAD', 'ZAR', 'AUD', 'NPR', 'ANG', 'EUR',
|
||||
'XCD', 'XPF', 'NZD', 'NIO', 'XOF', 'NGN', 'NZD', 'AUD', 'USD', 'NOK', 'OMR',
|
||||
'PKR', 'USD', 'XPD', 'PAB', 'USD', 'PGK', 'PYG', 'PEN', 'PHP', 'NZD', 'XPT',
|
||||
'PLN', 'EUR', 'STD', 'USD', 'QAR', 'EUR', 'RON', 'RUB', 'RWF', 'STD', 'ANG',
|
||||
'MAD', 'XCD', 'SHP', 'XCD', 'XCD', 'EUR', 'XCD', 'EUR', 'USD', 'WST', 'EUR',
|
||||
'SAR', 'SPL', 'XOF', 'RSD', 'SCR', 'SLL', 'XAG', 'SGD', 'ANG', 'ANG', 'EUR',
|
||||
'EUR', 'SBD', 'SOS', 'ZAR', 'GBP', 'GBP', 'EUR', 'XDR', 'LKR', 'SDG', 'SRD',
|
||||
'NOK', 'SZL', 'SEK', 'CHF', 'SYP', 'TWD', 'RUB', 'TJS', 'TZS', 'THB', 'IDR',
|
||||
'TTD', 'XOF', 'NZD', 'TOP', 'TTD', 'TND', 'TRY', 'TMM', 'USD', 'TVD', 'UGX',
|
||||
'UAH', 'AED', 'GBP', 'USD', 'USD', 'UYU', 'USD', 'UZS', 'VUV', 'EUR', 'VEB',
|
||||
'VEF', 'VND', 'USD', 'USD', 'USD', 'XPF', 'MAD', 'YER', 'ZMK', 'ZWD']
|
||||
supported_currency_array = [
|
||||
'AFN', 'ALL', 'DZD', 'USD', 'USD', 'USD', 'EUR', 'AOA', 'XCD', 'XCD', 'ARS',
|
||||
'AMD', 'AWG', 'AUD', 'EUR', 'AZN', 'EUR', 'BSD', 'BHD', 'EUR', 'BDT', 'BBD',
|
||||
'XCD', 'BYR', 'EUR', 'BZD', 'XOF', 'BMD', 'BTN', 'INR', 'BOB', 'ANG', 'BAM',
|
||||
'BWP', 'NOK', 'BRL', 'GBP', 'USD', 'USD', 'BND', 'BGN', 'XOF', 'MMK', 'BIF',
|
||||
'XOF', 'USD', 'KHR', 'XAF', 'CAD', 'EUR', 'CVE', 'KYD', 'XAF', 'XAF', 'CLP',
|
||||
'CNY', 'AUD', 'AUD', 'COP', 'XAF', 'KMF', 'XPF', 'XAF', 'CDF', 'NZD', 'CRC',
|
||||
'HRK', 'CUP', 'ANG', 'EUR', 'CYP', 'CZK', 'DKK', 'DJF', 'XCD', 'DOP', 'EUR',
|
||||
'XCD', 'IDR', 'USD', 'EGP', 'EUR', 'SVC', 'USD', 'GBP', 'XAF', 'ETB', 'ERN',
|
||||
'EEK', 'ETB', 'EUR', 'FKP', 'DKK', 'FJD', 'EUR', 'EUR', 'EUR', 'XPF', 'XPF',
|
||||
'EUR', 'XPF', 'XAF', 'GMD', 'GEL', 'EUR', 'GHS', 'GIP', 'XAU', 'GBP', 'EUR',
|
||||
'DKK', 'XCD', 'XCD', 'EUR', 'USD', 'GTQ', 'GGP', 'GNF', 'XOF', 'GYD', 'HTG',
|
||||
'USD', 'AUD', 'BAM', 'EUR', 'EUR', 'HNL', 'HKD', 'HUF', 'ISK', 'INR', 'IDR',
|
||||
'XDR', 'IRR', 'IQD', 'EUR', 'IMP', 'ILS', 'EUR', 'JMD', 'NOK', 'JPY', 'JEP',
|
||||
'JOD', 'KZT', 'AUD', 'KES', 'AUD', 'KPW', 'KRW', 'KWD', 'KGS', 'LAK', 'LVL',
|
||||
'LBP', 'LSL', 'ZAR', 'LRD', 'LYD', 'CHF', 'LTL', 'EUR', 'MOP', 'MKD', 'MGA',
|
||||
'EUR', 'MWK', 'MYR', 'MVR', 'XOF', 'EUR', 'MTL', 'FKP', 'USD', 'USD', 'EUR',
|
||||
'MRO', 'MUR', 'EUR', 'AUD', 'MXN', 'USD', 'USD', 'EUR', 'MDL', 'EUR', 'MNT',
|
||||
'EUR', 'XCD', 'MAD', 'MZN', 'MMK', 'NAD', 'ZAR', 'AUD', 'NPR', 'ANG', 'EUR',
|
||||
'XCD', 'XPF', 'NZD', 'NIO', 'XOF', 'NGN', 'NZD', 'AUD', 'USD', 'NOK', 'OMR',
|
||||
'PKR', 'USD', 'XPD', 'PAB', 'USD', 'PGK', 'PYG', 'PEN', 'PHP', 'NZD', 'XPT',
|
||||
'PLN', 'EUR', 'STD', 'USD', 'QAR', 'EUR', 'RON', 'RUB', 'RWF', 'STD', 'ANG',
|
||||
'MAD', 'XCD', 'SHP', 'XCD', 'XCD', 'EUR', 'XCD', 'EUR', 'USD', 'WST', 'EUR',
|
||||
'SAR', 'SPL', 'XOF', 'RSD', 'SCR', 'SLL', 'XAG', 'SGD', 'ANG', 'ANG', 'EUR',
|
||||
'EUR', 'SBD', 'SOS', 'ZAR', 'GBP', 'GBP', 'EUR', 'XDR', 'LKR', 'SDG', 'SRD',
|
||||
'NOK', 'SZL', 'SEK', 'CHF', 'SYP', 'TWD', 'RUB', 'TJS', 'TZS', 'THB', 'IDR',
|
||||
'TTD', 'XOF', 'NZD', 'TOP', 'TTD', 'TND', 'TRY', 'TMM', 'USD', 'TVD', 'UGX',
|
||||
'UAH', 'AED', 'GBP', 'USD', 'USD', 'UYU', 'USD', 'UZS', 'VUV', 'EUR', 'VEB',
|
||||
'VEF', 'VND', 'USD', 'USD', 'USD', 'XPF', 'MAD', 'YER', 'ZMK', 'ZWD'
|
||||
]
|
||||
|
||||
##updated currency this arry will contain the final result
|
||||
#Updated currency this arry will contain the final result
|
||||
updated_currency = {}
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days) :
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days):
|
||||
"""Interface method that will retrieve the currency
|
||||
This function has to be reinplemented in child"""
|
||||
This function has to be reinplemented in child
|
||||
"""
|
||||
raise AbstractMethodError
|
||||
|
||||
def validate_cur(self, currency) :
|
||||
def validate_cur(self, currency):
|
||||
"""Validate if the currency to update is supported"""
|
||||
if currency not in self.supported_currency_array :
|
||||
if currency not in self.supported_currency_array:
|
||||
raise UnsuportedCurrencyError(currency)
|
||||
|
||||
def get_url(self, url):
|
||||
@@ -349,65 +382,83 @@ class Curreny_getter_interface(object) :
|
||||
objfile.close()
|
||||
return rawfile
|
||||
except ImportError:
|
||||
raise osv.except_osv('Error !', self.MOD_NAME+'Unable to import urllib !')
|
||||
raise osv.except_osv(
|
||||
'Error !',
|
||||
self.MOD_NAME + 'Unable to import urllib !'
|
||||
)
|
||||
except IOError:
|
||||
raise osv.except_osv('Error !', self.MOD_NAME+'Web Service does not exist !')
|
||||
raise osv.except_osv(
|
||||
'Error !',
|
||||
self.MOD_NAME + 'Web Service does not exist !'
|
||||
)
|
||||
|
||||
def check_rate_date(self, rate_date, max_delta_days):
|
||||
"""Check date constrains. WARN : rate_date must be of datetime type"""
|
||||
"""Check date constrains. rate_date must be of datetime type"""
|
||||
days_delta = (datetime.today() - rate_date).days
|
||||
if days_delta > max_delta_days:
|
||||
raise Exception('The rate timestamp (%s) is %d days away from today, which is over the limit (%d days). Rate not updated in OpenERP.'%(rate_date, days_delta, max_delta_days))
|
||||
# We always have a warning when rate_date <> today
|
||||
raise Exception(
|
||||
'The rate timestamp (%s) is %d days away from today, '
|
||||
'which is over the limit (%d days). '
|
||||
'Rate not updated in OpenERP.' % (rate_date,
|
||||
days_delta,
|
||||
max_delta_days)
|
||||
)
|
||||
|
||||
#We always have a warning when rate_date != today
|
||||
rate_date_str = datetime.strftime(rate_date, '%Y-%m-%d')
|
||||
if rate_date_str != datetime.strftime(datetime.today(), '%Y-%m-%d'):
|
||||
self.log_info = "WARNING : the rate timestamp (%s) is not today's date" % rate_date_str
|
||||
_logger.warning("the rate timestamp (%s) is not today's date", rate_date_str)
|
||||
msg = "The rate timestamp (%s) is not today's date"
|
||||
self.log_info = ("WARNING : %s %s") % (msg, rate_date_str)
|
||||
_logger.warning(msg, rate_date_str)
|
||||
|
||||
|
||||
#Yahoo ###################################################################################
|
||||
class Yahoo_getter(Curreny_getter_interface) :
|
||||
#Yahoo ########################################################################
|
||||
class Yahoo_getter(Curreny_getter_interface):
|
||||
"""Implementation of Currency_getter_factory interface
|
||||
for Yahoo finance service"""
|
||||
for Yahoo finance service
|
||||
"""
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days):
|
||||
"""implementation of abstract method of Curreny_getter_interface"""
|
||||
"""implementation of abstract method of curreny_getter_interface"""
|
||||
self.validate_cur(main_currency)
|
||||
url='http://download.finance.yahoo.com/d/quotes.txt?s="%s"=X&f=sl1c1abg'
|
||||
if main_currency in currency_array :
|
||||
url = 'http://download.finance.yahoo.com/d/quotes.txt?s="%s"=X&f=sl1c1abg'
|
||||
if main_currency in currency_array:
|
||||
currency_array.remove(main_currency)
|
||||
for curr in currency_array :
|
||||
for curr in currency_array:
|
||||
self.validate_cur(curr)
|
||||
res = self.get_url(url%(main_currency+curr))
|
||||
res = self.get_url(url % (main_currency + curr))
|
||||
val = res.split(',')[1]
|
||||
if val :
|
||||
if val:
|
||||
self.updated_currency[curr] = val
|
||||
else :
|
||||
raise Exception('Could not update the %s'%(curr))
|
||||
else:
|
||||
raise Exception('Could not update the %s' % (curr))
|
||||
|
||||
return self.updated_currency, self.log_info # empty string added by polish changes
|
||||
##Admin CH ############################################################################
|
||||
class Admin_ch_getter(Curreny_getter_interface) :
|
||||
return self.updated_currency, self.log_info
|
||||
|
||||
|
||||
#Admin CH #####################################################################
|
||||
class Admin_ch_getter(Curreny_getter_interface):
|
||||
"""Implementation of Currency_getter_factory interface
|
||||
for Admin.ch service"""
|
||||
for Admin.ch service
|
||||
|
||||
def rate_retrieve(self, dom, ns, curr) :
|
||||
""" Parse a dom node to retrieve-
|
||||
currencies data"""
|
||||
"""
|
||||
|
||||
def rate_retrieve(self, dom, ns, curr):
|
||||
"""Parse a dom node to retrieve currencies data"""
|
||||
res = {}
|
||||
xpath_rate_currency = "/def:wechselkurse/def:devise[@code='%s']/def:kurs/text()"%(curr.lower())
|
||||
xpath_rate_ref = "/def:wechselkurse/def:devise[@code='%s']/def:waehrung/text()"%(curr.lower())
|
||||
xpath_rate_currency = "/def:wechselkurse/def:devise[@code='%s']/def:kurs/text()" % (curr.lower())
|
||||
xpath_rate_ref = "/def:wechselkurse/def:devise[@code='%s']/def:waehrung/text()" % (curr.lower())
|
||||
res['rate_currency'] = float(dom.xpath(xpath_rate_currency, namespaces=ns)[0])
|
||||
res['rate_ref'] = float((dom.xpath(xpath_rate_ref, namespaces=ns)[0]).split(' ')[0])
|
||||
return res
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days):
|
||||
"""implementation of abstract method of Curreny_getter_interface"""
|
||||
url='http://www.afd.admin.ch/publicdb/newdb/mwst_kurse/wechselkurse.php'
|
||||
#we do not want to update the main currency
|
||||
if main_currency in currency_array :
|
||||
"""Implementation of abstract method of Curreny_getter_interface"""
|
||||
url = 'http://www.afd.admin.ch/publicdb/newdb/mwst_kurse/wechselkurse.php'
|
||||
#We do not want to update the main currency
|
||||
if main_currency in currency_array:
|
||||
currency_array.remove(main_currency)
|
||||
# Move to new XML lib cf Launchpad bug #645263
|
||||
#Move to new XML lib cf Launchpad bug #645263
|
||||
from lxml import etree
|
||||
_logger.debug("Admin.ch currency rate service : connecting...")
|
||||
rawfile = self.get_url(url)
|
||||
@@ -428,60 +479,70 @@ class Admin_ch_getter(Curreny_getter_interface) :
|
||||
main_curr_data = self.rate_retrieve(dom, adminch_ns, main_currency)
|
||||
# 1 MAIN_CURRENCY = main_rate CHF
|
||||
main_rate = main_curr_data['rate_currency'] / main_curr_data['rate_ref']
|
||||
for curr in currency_array :
|
||||
for curr in currency_array:
|
||||
self.validate_cur(curr)
|
||||
if curr == 'CHF':
|
||||
rate = main_rate
|
||||
else:
|
||||
curr_data = self.rate_retrieve(dom, adminch_ns, curr)
|
||||
# 1 MAIN_CURRENCY = rate CURR
|
||||
if main_currency == 'CHF' :
|
||||
if main_currency == 'CHF':
|
||||
rate = curr_data['rate_ref'] / curr_data['rate_currency']
|
||||
else :
|
||||
else:
|
||||
rate = main_rate * curr_data['rate_ref'] / curr_data['rate_currency']
|
||||
self.updated_currency[curr] = rate
|
||||
_logger.debug("Rate retrieved : 1 " + main_currency + ' = ' + str(rate) + ' ' + curr)
|
||||
_logger.debug(
|
||||
"Rate retrieved : 1 %s = %s %s" % (main_currency, rate, curr)
|
||||
)
|
||||
return self.updated_currency, self.log_info
|
||||
|
||||
## ECB getter ############################################################################
|
||||
|
||||
class ECB_getter(Curreny_getter_interface) :
|
||||
## ECB getter #################################################################
|
||||
class ECB_getter(Curreny_getter_interface):
|
||||
"""Implementation of Currency_getter_factory interface
|
||||
for ECB service"""
|
||||
for ECB service
|
||||
"""
|
||||
|
||||
def rate_retrieve(self, dom, ns, curr) :
|
||||
""" Parse a dom node to retrieve-
|
||||
currencies data"""
|
||||
def rate_retrieve(self, dom, ns, curr):
|
||||
"""Parse a dom node to retrieve-
|
||||
currencies data
|
||||
|
||||
"""
|
||||
res = {}
|
||||
xpath_curr_rate = "/gesmes:Envelope/def:Cube/def:Cube/def:Cube[@currency='%s']/@rate"%(curr.upper())
|
||||
xpath_curr_rate = "/gesmes:Envelope/def:Cube/def:Cube/def:Cube[@currency='%s']/@rate" % (curr.upper())
|
||||
res['rate_currency'] = float(dom.xpath(xpath_curr_rate, namespaces=ns)[0])
|
||||
return res
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days):
|
||||
"""implementation of abstract method of Curreny_getter_interface"""
|
||||
url='http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
|
||||
url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
|
||||
# Important : as explained on the ECB web site, the currencies are
|
||||
# at the beginning of the afternoon ; so, until 3 p.m. Paris time
|
||||
# the currency rates are the ones of trading day N-1
|
||||
# see http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html
|
||||
|
||||
#we do not want to update the main currency
|
||||
if main_currency in currency_array :
|
||||
#We do not want to update the main currency
|
||||
if main_currency in currency_array:
|
||||
currency_array.remove(main_currency)
|
||||
# Move to new XML lib cf Launchpad bug #645263
|
||||
#Move to new XML lib cf Launchpad bug #645263
|
||||
from lxml import etree
|
||||
_logger.debug("ECB currency rate service : connecting...")
|
||||
rawfile = self.get_url(url)
|
||||
dom = etree.fromstring(rawfile)
|
||||
_logger.debug("ECB sent a valid XML file")
|
||||
ecb_ns = {'gesmes': 'http://www.gesmes.org/xml/2002-08-01', 'def': 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref'}
|
||||
rate_date = dom.xpath('/gesmes:Envelope/def:Cube/def:Cube/@time', namespaces=ecb_ns)[0]
|
||||
ecb_ns = {
|
||||
'gesmes': 'http://www.gesmes.org/xml/2002-08-01',
|
||||
'def': 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref'
|
||||
}
|
||||
rate_date = dom.xpath('/gesmes:Envelope/def:Cube/def:Cube/@time',
|
||||
namespaces=ecb_ns)[0]
|
||||
rate_date_datetime = datetime.strptime(rate_date, '%Y-%m-%d')
|
||||
self.check_rate_date(rate_date_datetime, max_delta_days)
|
||||
#we dynamically update supported currencies
|
||||
self.supported_currency_array = dom.xpath("/gesmes:Envelope/def:Cube/def:Cube/def:Cube/@currency", namespaces=ecb_ns)
|
||||
self.supported_currency_array = dom.xpath("/gesmes:Envelope/def:Cube/def:Cube/def:Cube/@currency",
|
||||
namespaces=ecb_ns)
|
||||
self.supported_currency_array.append('EUR')
|
||||
_logger.debug("Supported currencies = " + str(self.supported_currency_array))
|
||||
_logger.debug("Supported currencies = %s " % self.supported_currency_array)
|
||||
self.validate_cur(main_currency)
|
||||
if main_currency != 'EUR':
|
||||
main_curr_data = self.rate_retrieve(dom, ecb_ns, main_currency)
|
||||
@@ -496,56 +557,53 @@ class ECB_getter(Curreny_getter_interface) :
|
||||
else:
|
||||
rate = curr_data['rate_currency'] / main_curr_data['rate_currency']
|
||||
self.updated_currency[curr] = rate
|
||||
_logger.debug("Rate retrieved : 1 " + main_currency + ' = ' + str(rate) + ' ' + curr)
|
||||
_logger.debug("Rate retrieved : 1 %s = %s %s" % (main_currency, rate, curr))
|
||||
return self.updated_currency, self.log_info
|
||||
|
||||
##PL NBP ############################################################################
|
||||
class PL_NBP_getter(Curreny_getter_interface) : # class added according to polish needs = based on class Admin_ch_getter
|
||||
"""Implementation of Currency_getter_factory interface
|
||||
for PL NBP service"""
|
||||
|
||||
def rate_retrieve(self, dom, ns, curr) :
|
||||
#PL NBP #######################################################################
|
||||
class PL_NBP_getter(Curreny_getter_interface):
|
||||
"""Implementation of Currency_getter_factory interface
|
||||
for PL NBP service
|
||||
|
||||
"""
|
||||
|
||||
def rate_retrieve(self, dom, ns, curr):
|
||||
""" Parse a dom node to retrieve
|
||||
currencies data"""
|
||||
res = {}
|
||||
xpath_rate_currency = "/tabela_kursow/pozycja[kod_waluty='%s']/kurs_sredni/text()"%(curr.upper())
|
||||
xpath_rate_ref = "/tabela_kursow/pozycja[kod_waluty='%s']/przelicznik/text()"%(curr.upper())
|
||||
res['rate_currency'] = float(dom.xpath(xpath_rate_currency, namespaces=ns)[0].replace(',','.'))
|
||||
xpath_rate_currency = "/tabela_kursow/pozycja[kod_waluty='%s']/kurs_sredni/text()" % (curr.upper())
|
||||
xpath_rate_ref = "/tabela_kursow/pozycja[kod_waluty='%s']/przelicznik/text()" % (curr.upper())
|
||||
res['rate_currency'] = float(dom.xpath(xpath_rate_currency, namespaces=ns)[0].replace(',', '.'))
|
||||
res['rate_ref'] = float(dom.xpath(xpath_rate_ref, namespaces=ns)[0])
|
||||
return res
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days):
|
||||
"""implementation of abstract method of Curreny_getter_interface"""
|
||||
url='http://www.nbp.pl/kursy/xml/LastA.xml' # LastA.xml is always the most recent one
|
||||
url = 'http://www.nbp.pl/kursy/xml/LastA.xml' # LastA.xml is always the most recent one
|
||||
#we do not want to update the main currency
|
||||
if main_currency in currency_array :
|
||||
if main_currency in currency_array:
|
||||
currency_array.remove(main_currency)
|
||||
# Move to new XML lib cf Launchpad bug #645263
|
||||
from lxml import etree
|
||||
_logger.debug("NBP.pl currency rate service : connecting...")
|
||||
rawfile = self.get_url(url)
|
||||
dom = etree.fromstring(rawfile) # If rawfile is not XML, it crashes here
|
||||
ns = {} # Cool, there are no namespaces !
|
||||
dom = etree.fromstring(rawfile)
|
||||
ns = {} # Cool, there are no namespaces !
|
||||
_logger.debug("NBP.pl sent a valid XML file")
|
||||
#node = xpath.Evaluate("/tabela_kursow", dom) # BEGIN Polish - rates table name
|
||||
#if isinstance(node, list) :
|
||||
# node = node[0]
|
||||
#self.log_info = node.getElementsByTagName('numer_tabeli')[0].childNodes[0].data
|
||||
#self.log_info = self.log_info + " " + node.getElementsByTagName('data_publikacji')[0].childNodes[0].data # END Polish - rates table name
|
||||
|
||||
rate_date = dom.xpath('/tabela_kursow/data_publikacji/text()', namespaces=ns)[0]
|
||||
rate_date_datetime = datetime.strptime(rate_date, '%Y-%m-%d')
|
||||
self.check_rate_date(rate_date_datetime, max_delta_days)
|
||||
#we dynamically update supported currencies
|
||||
self.supported_currency_array = dom.xpath('/tabela_kursow/pozycja/kod_waluty/text()', namespaces=ns)
|
||||
self.supported_currency_array.append('PLN')
|
||||
_logger.debug("Supported currencies = " + str(self.supported_currency_array))
|
||||
_logger.debug("Supported currencies = %s" % self.supported_currency_array)
|
||||
self.validate_cur(main_currency)
|
||||
if main_currency != 'PLN':
|
||||
main_curr_data = self.rate_retrieve(dom, ns, main_currency)
|
||||
# 1 MAIN_CURRENCY = main_rate PLN
|
||||
main_rate = main_curr_data['rate_currency'] / main_curr_data['rate_ref']
|
||||
for curr in currency_array :
|
||||
for curr in currency_array:
|
||||
self.validate_cur(curr)
|
||||
if curr == 'PLN':
|
||||
rate = main_rate
|
||||
@@ -557,14 +615,16 @@ class PL_NBP_getter(Curreny_getter_interface) : # class added according to pol
|
||||
else:
|
||||
rate = main_rate * curr_data['rate_ref'] / curr_data['rate_currency']
|
||||
self.updated_currency[curr] = rate
|
||||
_logger.debug("Rate retrieved : 1 " + main_currency + ' = ' + str(rate) + ' ' + curr)
|
||||
_logger.debug("Rate retrieved : %s = %s %s" % (main_currency, rate, curr))
|
||||
return self.updated_currency, self.log_info
|
||||
|
||||
|
||||
##Banco de México ############################################################################
|
||||
class Banxico_getter(Curreny_getter_interface) : # class added for Mexico rates
|
||||
##Banco de México #############################################################
|
||||
class Banxico_getter(Curreny_getter_interface):
|
||||
"""Implementation of Currency_getter_factory interface
|
||||
for Banco de México service"""
|
||||
for Banco de México service
|
||||
|
||||
"""
|
||||
|
||||
def rate_retrieve(self):
|
||||
""" Get currency exchange from Banxico.xml and proccess it
|
||||
@@ -587,17 +647,16 @@ class Banxico_getter(Curreny_getter_interface) : # class added for Mexico rates
|
||||
|
||||
return float(rate)
|
||||
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days=1):
|
||||
"""implementation of abstract method of Curreny_getter_interface"""
|
||||
logger = logging.getLogger(__name__)
|
||||
# we do not want to update the main currency
|
||||
if main_currency in currency_array :
|
||||
if main_currency in currency_array:
|
||||
currency_array.remove(main_currency)
|
||||
|
||||
# Suported currencies
|
||||
suported = ['MXN', 'USD']
|
||||
for curr in currency_array :
|
||||
for curr in currency_array:
|
||||
if curr in suported:
|
||||
# Get currency data
|
||||
main_rate = self.rate_retrieve()
|
||||
@@ -606,17 +665,19 @@ class Banxico_getter(Curreny_getter_interface) : # class added for Mexico rates
|
||||
else:
|
||||
rate = main_rate
|
||||
else:
|
||||
""" No other currency supported
|
||||
"""
|
||||
# No other currency supported
|
||||
continue
|
||||
|
||||
self.updated_currency[curr] = rate
|
||||
logger.debug("Rate retrieved : " + main_currency + ' = ' + str(rate) + ' ' + curr)
|
||||
logger.debug("Rate retrieved : %s = %s %s" % (main_currency, rate, curr))
|
||||
|
||||
|
||||
##CA BOC ##### Bank of Canada ############################################################
|
||||
class CA_BOC_getter(Curreny_getter_interface) :
|
||||
"""Implementation of Curreny_getter_factory interface for Bank of Canada RSS service"""
|
||||
##CA BOC ##### Bank of Canada #############################################
|
||||
class CA_BOC_getter(Curreny_getter_interface):
|
||||
"""Implementation of Curreny_getter_factory interface
|
||||
for Bank of Canada RSS service
|
||||
|
||||
"""
|
||||
|
||||
def get_updated_currency(self, currency_array, main_currency, max_delta_days):
|
||||
"""implementation of abstract method of Curreny_getter_interface"""
|
||||
@@ -643,7 +704,7 @@ class CA_BOC_getter(Curreny_getter_interface) :
|
||||
self.validate_cur(curr)
|
||||
|
||||
# check if BOC service is running
|
||||
if dom.bozo and dom.status <> 404:
|
||||
if dom.bozo and dom.status != 404:
|
||||
_logger.error("Bank of Canada - service is down - try again\
|
||||
later...")
|
||||
|
||||
@@ -664,8 +725,7 @@ class CA_BOC_getter(Curreny_getter_interface) :
|
||||
.astimezone(pytz.utc).replace(tzinfo=None)
|
||||
self.check_rate_date(rate_date_datetime, max_delta_days)
|
||||
self.updated_currency[curr] = rate
|
||||
_logger.debug("BOC Rate retrieved : 1 " + main_currency +
|
||||
' = ' + str(rate) + ' ' + curr)
|
||||
_logger.debug("BOC Rate retrieved : %s = %s %s" % (main_currency, rate, curr))
|
||||
else:
|
||||
_logger.error("Exchange data format error for Bank of Canada -\
|
||||
%s. Please check provider data format and/or source code." % curr)
|
||||
|
||||
Reference in New Issue
Block a user