asset: online-quelle als liste

This commit is contained in:
Frederik Jaeckel 2022-11-29 21:54:27 +01:00
parent 7334e53f9f
commit 258c14e2b5
8 changed files with 171 additions and 100 deletions

View file

@ -4,7 +4,7 @@
# full copyright notices and license terms.
from trytond.pool import Pool
from .asset import Asset
from .asset import Asset, AssetSourceRel
from .rate import Rate
from .identifier import Identifier
from .cron import Cron
@ -16,6 +16,7 @@ from .diagram import GraphDef, ChartPoint
def register():
Pool.register(
OnlineSource,
AssetSourceRel,
Asset,
Rate,
Identifier,

View file

@ -78,15 +78,16 @@ class Asset(ModelSQL, ModelView):
help='Stock market symbol'),
'get_identifiers', searcher='search_identifier')
updtsource = fields.Many2One(string='Update Source',
help='Select a source for the course update.',
ondelete='SET NULL', model_name='investment.source')
updtsources = fields.Many2Many(string='Update Sources',
help='Select sources for the course update. The course sources are tried until a valid value has been read.',
relation_name='investment.asset_source_rel',
origin='asset', target='source')
updtdays = fields.Selection(string='Select days', required=True,
selection=sel_updtdays)
updttime = fields.Time(string='Time',
states={
'readonly': ~Bool(Eval('updtsource')),
}, depends=['updtsource'])
'readonly': ~Bool(Eval('updtsources')),
}, depends=['updtsources'])
nextupdate = fields.Function(fields.DateTime(string='Next Update',
readonly=True),
'get_nextupdates', searcher='search_nextupdate')
@ -113,12 +114,48 @@ class Asset(ModelSQL, ModelView):
readonly=True, digits=(16,digits_percent)),
'get_percentage_change', searcher='search_percentage')
@classmethod
def __register__(cls, module_name):
""" register and migrate
"""
super(Asset, cls).__register__(module_name)
cls.migrate_updtsource(module_name)
@classmethod
def __setup__(cls):
super(Asset, cls).__setup__()
cls._order.insert(0, ('name', 'ASC'))
cls._order.insert(0, ('date', 'DESC'))
@classmethod
def migrate_updtsource(cls, module_name):
""" replace 'updtsource' by relation
"""
pool = Pool()
Asset2 = pool.get('investment.asset')
asset_table = Asset2.__table_handler__(module_name)
if asset_table.column_exist('updtsource'):
AssetSourceRel = pool.get('investment.asset_source_rel')
tab_asset = Asset2.__table__()
cursor = Transaction().connection.cursor()
query = tab_asset.select(
tab_asset.id,
tab_asset.updtsource,
where = tab_asset.updtsource != None,
)
cursor.execute(*query)
records = cursor.fetchall()
to_create = [{
'asset': x[0],
'source': x[1],
} for x in records]
if len(to_create) > 0:
AssetSourceRel.create(to_create)
asset_table.drop_column('updtsource')
@classmethod
def view_attributes(cls):
return super().view_attributes() + [
@ -164,11 +201,11 @@ class Asset(ModelSQL, ModelView):
"""
return 'work'
@fields.depends('updtsource', 'updttime')
def on_change_updtsource(self):
@fields.depends('updtsources', 'updttime')
def on_change_updtsources(self):
""" clear time-fields
"""
if self.updtsource is None:
if len(self.updtsources) == 0:
self.updttime = None
else :
self.updttime = time(11, 30)
@ -513,15 +550,21 @@ class Asset(ModelSQL, ModelView):
"""
pool = Pool()
Asset = pool.get('investment.asset')
AssetSourceRel = pool.get('investment.asset_source_rel')
Rate = pool.get('investment.rate')
tab_asset = Asset.__table__()
tab_rate = Rate.__table__()
tab_rel = AssetSourceRel.__table__()
context = Transaction().context
query_date = context.get('qdate', CurrentDate() - Literal(1))
# get last date of rate
tab_date = tab_asset.join(tab_rate,
tab_date = tab_asset.join(tab_rel,
# link to asset-source-relation to check if
# there are online-sources set
condition=tab_rel.asset == tab_asset.id,
).join(tab_rate,
condition=tab_asset.id == tab_rate.asset,
type_ = 'LEFT OUTER',
).select(
@ -531,7 +574,6 @@ class Asset(ModelSQL, ModelView):
tab_asset.updttime,
distinct_on = [tab_asset.id],
order_by = [tab_asset.id, tab_rate.date.desc],
where=tab_asset.updtsource != None,
)
query = tab_date.select(
@ -768,27 +810,18 @@ class Asset(ModelSQL, ModelView):
]):
OnlineSource.update_rate(asset)
@classmethod
def create(cls, vlist):
""" add debit/credit
"""
vlist = [x.copy() for x in vlist]
for values in vlist:
if 'updtsource' in values.keys():
if values['updtsource'] is None:
values['updttime'] = None
return super(Asset, cls).create(vlist)
@classmethod
def write(cls, *args):
""" deny update if cashbook.line!='open',
add or update debit/credit
"""
actions = iter(args)
for lines, values in zip(actions, actions):
if 'updtsource' in values.keys():
if values['updtsource'] is None:
values['updttime'] = None
super(Asset, cls).write(*args)
# end Asset
class AssetSourceRel(ModelSQL):
'Asset Source Relation'
__name__ = 'investment.asset_source_rel'
source = fields.Many2One(string='Online Source', select=True,
required=True, model_name='investment.source',
ondelete='CASCADE')
asset = fields.Many2One(string='Asset', select=True,
required=True, model_name='investment.asset',
ondelete='CASCADE')
# end AssetSourceRel

View file

@ -182,13 +182,13 @@ msgctxt "help:investment.asset,date:"
msgid "Date of current rate"
msgstr "Datum des aktuellen Kurses"
msgctxt "field:investment.asset,updtsource:"
msgid "Update Source"
msgstr "Kursquelle"
msgctxt "field:investment.asset,updtsources:"
msgid "Update Sources"
msgstr "Kursquellen"
msgctxt "help:investment.asset,updtsource:"
msgid "Select a source for the course update."
msgstr "Wählen Sie eine Quelle für die Kursaktualisierung aus."
msgctxt "help:investment.asset,updtsources:"
msgid "Select sources for the course update. The course sources are tried until a valid value has been read."
msgstr "Wählen Sie Quellen für die Kursaktualisierung aus. Die Kursquellen werden probiert bis ein gültiger Wert gelesen wurde."
msgctxt "field:investment.asset,updttime:"
msgid "Time"
@ -251,6 +251,22 @@ msgid "Mon - Sun"
msgstr "Mo - So"
###############################
# investment.asset-source-rel #
###############################
msgctxt "model:investment.asset_source_rel,name:"
msgid "Asset Source Relation"
msgstr "Vermögenswert Quelle Verknüpfung"
msgctxt "field:investment.asset_source_rel,source:"
msgid "Source"
msgstr "Quelle"
msgctxt "field:investment.asset_source_rel,asset:"
msgid "Asset"
msgstr "Vermögenswert"
#####################
# investment.source #
#####################

View file

@ -154,13 +154,13 @@ msgctxt "help:investment.asset,date:"
msgid "Date of current rate"
msgstr "Date of current rate"
msgctxt "field:investment.asset,updtsource:"
msgid "Update Source"
msgstr "Update Source"
msgctxt "field:investment.asset,updtsources:"
msgid "Update Sources"
msgstr "Update Sources"
msgctxt "help:investment.asset,updtsource:"
msgid "Select a source for the course update."
msgstr "Select a source for the course update."
msgctxt "help:investment.asset,updtsources:"
msgid "Select sources for the course update. The course sources are tried until a valid value has been read."
msgstr "Select sources for the course update. The course sources are tried until a valid value has been read."
msgctxt "field:investment.asset,updttime:"
msgid "Time"
@ -222,6 +222,18 @@ msgctxt "selection:investment.asset,updtdays:"
msgid "Mon - Sun"
msgstr "Mon - Sun"
msgctxt "model:investment.asset_source_rel,name:"
msgid "Asset Source Relation"
msgstr "Asset Source Relation"
msgctxt "field:investment.asset_source_rel,source:"
msgid "Source"
msgstr "Source"
msgctxt "field:investment.asset_source_rel,asset:"
msgid "Asset"
msgstr "Asset"
msgctxt "model:investment.source,name:"
msgid "Online Source"
msgstr "Online Source"

View file

@ -222,48 +222,56 @@ class OnlineSource(ModelSQL, ModelView):
"""
pool = Pool()
Rate = pool.get('investment.rate')
IrDate = pool.get('ir.date')
if asset.updtsource is None:
if len(asset.updtsources) == 0:
return
rate_data = cls.read_from_website(
asset.updtsource,
isin = asset.isin,
nsin = asset.wkn,
symbol = asset.secsymb,
)
if len(asset.updtsource.rgxident or '') > 0:
# check result - same code?
code = rate_data.get('code', None)
if code:
asset_code = getattr(asset, {
'isin': 'isin',
'nsin': 'wkn',
'symbol': 'secsymb',
}[asset.updtsource.rgxidtype])
if (asset_code or '').lower() != code.lower():
# fail
logger.warning(
'update_rate: got wrong code "%(wrong)s" - expected "%(exp)s"' % {
'exp': asset_code,
'wrong': code,
})
return False
for updtsource in asset.updtsources:
rate_data = cls.read_from_website(
updtsource,
isin = asset.isin,
nsin = asset.wkn,
symbol = asset.secsymb,
)
to_create = {
'date': rate_data.get('date', None),
'rate': rate_data.get('rate', None),
'asset': asset.id,
}
if (to_create['date'] is not None) and \
(to_create['rate'] is not None):
# check if exists
if Rate.search_count([
('asset.id', '=', asset.id),
('date', '=', to_create['date']),
]) == 0:
Rate.create([to_create])
return True
if len(updtsource.rgxident or '') > 0:
# check result - same code?
code = rate_data.get('code', None)
if code:
asset_code = getattr(asset, {
'isin': 'isin',
'nsin': 'wkn',
'symbol': 'secsymb',
}[updtsource.rgxidtype])
if (asset_code or '').lower() != code.lower():
# fail
logger.warning(
'update_rate: got wrong code "%(wrong)s" - expected "%(exp)s"' % {
'exp': asset_code,
'wrong': code,
})
continue
to_create = {
'date': rate_data.get('date', None),
'rate': rate_data.get('rate', None),
'asset': asset.id,
}
if (to_create['date'] is not None) and \
(to_create['rate'] is not None):
# check if exists
if Rate.search_count([
('asset.id', '=', asset.id),
('date', '=', to_create['date']),
]) == 0:
Rate.create([to_create])
return True
else :
# if we got a record for today - stop
# otherwise try next source
if to_create['date'] == IrDate.today():
break
return False
def get_regex_result(self, html_text, field_name):

View file

@ -568,18 +568,19 @@ class AssetTestCase(ModuleTestCase):
'name': 'Source 1',
}])
self.assertEqual(asset.updtsource, None)
self.assertEqual(len(asset.updtsources), 0)
self.assertEqual(asset.updttime, time(14,0))
asset.updtsource = o_source
asset.updtsources = [o_source]
asset.updttime = time(10, 45)
asset.save()
self.assertEqual(asset.updtsource.rec_name, 'Source 1')
self.assertEqual(len(asset.updtsources), 1)
self.assertEqual(asset.updtsources[0].rec_name, 'Source 1')
self.assertEqual(asset.updttime, time(10, 45))
asset.updtsource = None
asset.on_change_updtsource()
self.assertEqual(asset.updtsource, None)
asset.updtsources = []
asset.on_change_updtsources()
self.assertEqual(len(asset.updtsources), 0)
self.assertEqual(asset.updttime, None)
@with_transaction()
@ -606,7 +607,7 @@ class AssetTestCase(ModuleTestCase):
Asset.write(*[
[asset],
{
'updtsource': o_source.id,
'updtsources': [('add', [o_source.id])],
'updttime': time(10, 45),
}])
@ -616,7 +617,8 @@ class AssetTestCase(ModuleTestCase):
# re-read to make context work
asset2, = Asset.browse([asset.id])
self.assertEqual(asset2.updtsource.rec_name, 'Source 1')
self.assertEqual(len(asset2.updtsources), 1)
self.assertEqual(asset2.updtsources[0].rec_name, 'Source 1')
self.assertEqual(asset2.updttime, time(10, 45))
self.assertEqual(len(asset2.rates), 0)
# qdate = 2022-10-14 simulates existence of record at this day
@ -643,7 +645,7 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(len(asset.rates), 1)
asset2, = Asset.browse([asset.id])
self.assertEqual(asset.updtsource.rec_name, 'Source 1')
self.assertEqual(asset.updtsources[0].rec_name, 'Source 1')
self.assertEqual(asset.updttime, time(10, 45))
self.assertEqual(len(asset.rates), 1)
self.assertEqual(asset.rates[0].date, date(2022, 10, 17))
@ -668,7 +670,7 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(len(asset.rates), 2)
asset2, = Asset.browse([asset.id])
self.assertEqual(asset2.updtsource.rec_name, 'Source 1')
self.assertEqual(asset2.updtsources[0].rec_name, 'Source 1')
self.assertEqual(asset2.updttime, time(10, 45))
self.assertEqual(len(asset2.rates), 2)
self.assertEqual(asset2.rates[0].date, date(2022, 10, 18))

View file

@ -64,7 +64,7 @@ class SourceTestCase(ModuleTestCase):
Asset.write(*[
[asset],
{
'updtsource': osource.id,
'updtsources': [('add', [osource.id])],
}])
with Transaction().set_context({
@ -76,7 +76,8 @@ class SourceTestCase(ModuleTestCase):
self.assertEqual(asset2.isin, 'XC0009655157')
self.assertEqual(asset2.secsymb, '1472977')
self.assertEqual(asset2.updttime, time(14, 0))
self.assertEqual(asset2.updtsource.rec_name, 'Source 1')
self.assertEqual(len(asset2.updtsources), 1)
self.assertEqual(asset2.updtsources[0].rec_name, 'Source 1')
self.assertEqual(asset2.updtdays, 'work')
self.assertEqual(asset2.nextupdate, datetime(2022, 10, 3, 14, 0))
self.assertEqual(len(asset.rates), 0)

View file

@ -57,14 +57,12 @@ full copyright notices and license terms. -->
<field name="rates" mode="tree,form,graph"/>
</page>
<page id="pgupdate" col="4" string="Course Update">
<label name="updtsource"/>
<field name="updtsource"/>
<label name="updttime"/>
<field name="updttime"/>
<label id="labupdt" colspan="2" string=" "/>
<label name="updtdays"/>
<field name="updtdays"/>
<field name="updtsources" colspan="4"/>
</page>
</notebook>