Compare commits
109 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1ce8ea145d | ||
![]() |
66fcc5483d | ||
![]() |
34fa28eeb9 | ||
![]() |
1a55e9fa7e | ||
![]() |
2354c4cf4f | ||
![]() |
b672efcd6d | ||
![]() |
5573f26e9e | ||
![]() |
8f226427d6 | ||
![]() |
43f7f7ed0f | ||
![]() |
826b8b7213 | ||
![]() |
548212553f | ||
![]() |
95997ea512 | ||
![]() |
7d2e4c510a | ||
![]() |
0275ee09e9 | ||
![]() |
b28723cfb1 | ||
![]() |
2166da5509 | ||
![]() |
0a143e8768 | ||
![]() |
3a60020eac | ||
![]() |
9df76e8e59 | ||
![]() |
491efcc773 | ||
![]() |
b9bcfc1f29 | ||
![]() |
c6c0cb4ce4 | ||
![]() |
73dac7b33c | ||
![]() |
4bb7641959 | ||
![]() |
7087c151ab | ||
![]() |
89f19ceae5 | ||
![]() |
5eec999d41 | ||
![]() |
2fb2bef8b4 | ||
![]() |
03d0ce0a5b | ||
![]() |
c18b07def1 | ||
![]() |
a4242421f0 | ||
![]() |
c9330c7195 | ||
![]() |
25fd69be0c | ||
![]() |
9064ac2980 | ||
![]() |
23238b8419 | ||
![]() |
11e9134dc9 | ||
![]() |
9d461b6d76 | ||
![]() |
06fdbace50 | ||
![]() |
553aa80acd | ||
![]() |
c9a6df2371 | ||
![]() |
92cd89ef2e | ||
![]() |
4dde704e57 | ||
![]() |
0e8dc38abb | ||
![]() |
f9b4f12055 | ||
![]() |
76ea68489c | ||
![]() |
ed6dae7d59 | ||
![]() |
d76951d2f2 | ||
![]() |
2c38ddd357 | ||
![]() |
f5b9929c51 | ||
![]() |
46a19fe4c4 | ||
![]() |
f74ee23a76 | ||
![]() |
2c750b2253 | ||
![]() |
e703c759a3 | ||
![]() |
36e6fb52d5 | ||
![]() |
b8648d629b | ||
![]() |
7dd7c9a140 | ||
![]() |
813a794db4 | ||
![]() |
2977e5187f | ||
![]() |
77c287fc90 | ||
![]() |
c73584af32 | ||
![]() |
6b3b44e9af | ||
![]() |
331c62a3f6 | ||
![]() |
693dc175f1 | ||
![]() |
5b6883cdde | ||
![]() |
6311d0e79e | ||
![]() |
b531d51a7d | ||
![]() |
08ca00a6b9 | ||
![]() |
3cc92ccecb | ||
![]() |
c3d323714f | ||
![]() |
53dfb14254 | ||
![]() |
4ab79e4200 | ||
![]() |
528a6e5a86 | ||
![]() |
d88703f117 | ||
![]() |
6241601fa7 | ||
![]() |
0fe7df4b61 | ||
![]() |
ebca4642fb | ||
![]() |
37aece3c65 | ||
![]() |
5c588abe96 | ||
![]() |
c6f2661f9b | ||
![]() |
bda4f66b47 | ||
![]() |
d097395825 | ||
![]() |
f1b00e376b | ||
![]() |
f462b11758 | ||
![]() |
d431a422e8 | ||
![]() |
b8495231e5 | ||
![]() |
8760fd4aab | ||
![]() |
aaa143f373 | ||
![]() |
99e18094aa | ||
![]() |
d1421403b1 | ||
![]() |
475457d202 | ||
![]() |
c1cc1acb5f | ||
![]() |
7bb3e4f929 | ||
![]() |
047b6980e4 | ||
![]() |
9d88cf1067 | ||
![]() |
620c42fc62 | ||
![]() |
6311dce3d1 | ||
![]() |
64b8383096 | ||
![]() |
a99d11a4a0 | ||
![]() |
4ae5601c04 | ||
![]() |
31c76dfb48 | ||
![]() |
57cb06d60e | ||
![]() |
5587bfea3a | ||
![]() |
f919d9e290 | ||
![]() |
e8614b1242 | ||
![]() |
a71bc0a79a | ||
![]() |
f1d9b3b1dd | ||
![]() |
4947b495c2 | ||
![]() |
aeb949cc20 | ||
![]() |
916d73ef12 |
17 changed files with 255 additions and 213 deletions
114
README.rst
114
README.rst
|
@ -9,7 +9,7 @@ pip install mds-investment
|
||||||
|
|
||||||
Requires
|
Requires
|
||||||
========
|
========
|
||||||
- Tryton 7.0
|
- Tryton 6.0
|
||||||
|
|
||||||
How to
|
How to
|
||||||
======
|
======
|
||||||
|
@ -22,6 +22,114 @@ You can define the course sources yourself.
|
||||||
Changes
|
Changes
|
||||||
=======
|
=======
|
||||||
|
|
||||||
*7.0.0 - 01.12.2023*
|
*6.0.25 - 01.12.2023*
|
||||||
|
|
||||||
- compatibility to Tryton 7.0
|
- code/speed optimized
|
||||||
|
|
||||||
|
*6.0.24 - 07.06.2023*
|
||||||
|
|
||||||
|
- code optimized
|
||||||
|
|
||||||
|
*6.0.23 - 21.01.2023*
|
||||||
|
|
||||||
|
- updt: online-source optimized for external extension
|
||||||
|
|
||||||
|
*6.0.22 - 10.01.2023*
|
||||||
|
|
||||||
|
- updt: optimze rate, remove caching
|
||||||
|
|
||||||
|
*6.0.21 - 08.01.2023*
|
||||||
|
|
||||||
|
- add: caching for percentual changes
|
||||||
|
|
||||||
|
*6.0.20 - 07.01.2023*
|
||||||
|
|
||||||
|
- updt: asset - percent-values optimize for speed
|
||||||
|
|
||||||
|
*6.0.19 - 05.01.2023*
|
||||||
|
|
||||||
|
- updt: rate - optimize for speed
|
||||||
|
|
||||||
|
*6.0.18 - 04.01.2023*
|
||||||
|
|
||||||
|
- add: units to lists
|
||||||
|
- updt: online-sources
|
||||||
|
|
||||||
|
*6.0.17 - 19.12.2022*
|
||||||
|
|
||||||
|
- add: import wizard
|
||||||
|
|
||||||
|
*6.0.16 - 18.12.2022*
|
||||||
|
|
||||||
|
- add: onlinesource - sorting, sources
|
||||||
|
|
||||||
|
*6.0.15 - 16.12.2022*
|
||||||
|
|
||||||
|
- fix: recoursion
|
||||||
|
- add: enable after-update actions
|
||||||
|
|
||||||
|
*6.0.14 - 09.12.2022*
|
||||||
|
|
||||||
|
- updt: translated symbol of asset-currency
|
||||||
|
|
||||||
|
*6.0.13 - 06.12.2022*
|
||||||
|
|
||||||
|
- updt: asset-form - units for percent-values, asset-list - day-negative in red-color
|
||||||
|
|
||||||
|
*6.0.12 - 05.12.2022*
|
||||||
|
|
||||||
|
- import-script - add field-delimter to param-list
|
||||||
|
|
||||||
|
*6.0.11 - 03.12.2022*
|
||||||
|
|
||||||
|
- add: tabs for asset-list, new icons, queries optimized
|
||||||
|
|
||||||
|
*6.0.10 - 01.12.2022*
|
||||||
|
|
||||||
|
- updt: optimized asset-list, unit as symbol
|
||||||
|
|
||||||
|
*6.0.9 - 30.11.2022*
|
||||||
|
|
||||||
|
- add: script to import historical rates
|
||||||
|
|
||||||
|
*6.0.8 - 29.11.2022*
|
||||||
|
|
||||||
|
- add: online-source as list to allow multiple sources
|
||||||
|
for asset
|
||||||
|
|
||||||
|
*6.0.7 - 28.11.2022*
|
||||||
|
|
||||||
|
- fix: add diagram-interpolate
|
||||||
|
- fix: corrected nextupdate
|
||||||
|
|
||||||
|
*6.0.6 - 26.11.2022*
|
||||||
|
|
||||||
|
- add: diagram-display
|
||||||
|
|
||||||
|
*6.0.5 - 25.11.2022*
|
||||||
|
|
||||||
|
- add: sorter for name/nsin/isin/symbol
|
||||||
|
- add: columns percentage by day/month/3month/6month/12month
|
||||||
|
- fix: online-updater
|
||||||
|
|
||||||
|
*6.0.4 - 25.11.2022*
|
||||||
|
|
||||||
|
- add: assets - colors for percentual success/loss
|
||||||
|
- updt: optimize timestamp for next online-update
|
||||||
|
|
||||||
|
*6.0.3 - 23.11.2022*
|
||||||
|
|
||||||
|
- fix: bug in searcher
|
||||||
|
- add: online-sources
|
||||||
|
|
||||||
|
*6.0.2 - 23.11.2022*
|
||||||
|
|
||||||
|
- asset: add field 'date', optimized 'rec_name'
|
||||||
|
|
||||||
|
*6.0.1 - 22.11.2022*
|
||||||
|
|
||||||
|
- works
|
||||||
|
|
||||||
|
*6.0.0 - 09.11.2022*
|
||||||
|
|
||||||
|
- init
|
||||||
|
|
117
asset.py
117
asset.py
|
@ -3,7 +3,7 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the
|
# The COPYRIGHT file at the top level of this repository contains the
|
||||||
# full copyright notices and license terms.
|
# full copyright notices and license terms.
|
||||||
|
|
||||||
from trytond.model import ModelView, ModelSQL, fields, SymbolMixin, Index
|
from trytond.model import ModelView, ModelSQL, fields, SymbolMixin
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.pyson import Eval, Bool, If, Date
|
from trytond.pyson import Eval, Bool, If, Date
|
||||||
|
@ -32,7 +32,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
name = fields.Function(fields.Char(
|
name = fields.Function(fields.Char(
|
||||||
string='Name', readonly=True),
|
string='Name', readonly=True),
|
||||||
'get_name_symbol', searcher='search_rec_name')
|
'get_name_symbol', searcher='search_rec_name')
|
||||||
company = fields.Many2One(
|
company = fields.Many2One(
|
||||||
string='Company', model_name='company.company',
|
string='Company', model_name='company.company',
|
||||||
required=True, ondelete="RESTRICT")
|
required=True, ondelete="RESTRICT")
|
||||||
|
@ -46,9 +46,12 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
uom = fields.Many2One(
|
uom = fields.Many2One(
|
||||||
string='UOM', required=True, model_name='product.uom',
|
string='UOM', required=True, model_name='product.uom',
|
||||||
ondelete='RESTRICT',
|
ondelete='RESTRICT',
|
||||||
states={'readonly': ~Bool(Eval('product'))},
|
states={
|
||||||
domain=[('category', '=', Eval('product_uom'))],
|
'readonly': ~Bool(Eval('product')),
|
||||||
depends=['product_uom', 'product'])
|
},
|
||||||
|
domain=[
|
||||||
|
('category', '=', Eval('product_uom')),
|
||||||
|
], depends=['product_uom', 'product'])
|
||||||
symbol = fields.Function(fields.Char(
|
symbol = fields.Function(fields.Char(
|
||||||
string='UOM', readonly=True), 'get_name_symbol',
|
string='UOM', readonly=True), 'get_name_symbol',
|
||||||
searcher='search_uom_symbol')
|
searcher='search_uom_symbol')
|
||||||
|
@ -67,11 +70,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
'get_rate_data', searcher='search_date')
|
'get_rate_data', searcher='search_date')
|
||||||
|
|
||||||
currency = fields.Many2One(
|
currency = fields.Many2One(
|
||||||
string='Currency', required=True,
|
string='Currency', select=True, required=True,
|
||||||
model_name='currency.currency', ondelete='RESTRICT')
|
model_name='currency.currency', ondelete='RESTRICT')
|
||||||
currency_digits = fields.Integer(
|
currency_digits = fields.Integer(
|
||||||
string='Digits', required=True,
|
string='Digits', required=True,
|
||||||
domain=[('currency_digits', '>=', 0), ('currency_digits', '<=', 6)])
|
domain=[
|
||||||
|
('currency_digits', '>=', 0),
|
||||||
|
('currency_digits', '<=', 6)])
|
||||||
|
|
||||||
wkn = fields.Function(fields.Char(
|
wkn = fields.Function(fields.Char(
|
||||||
string='NSIN', readonly=True,
|
string='NSIN', readonly=True,
|
||||||
|
@ -107,8 +112,9 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
string='Select days', required=True, selection=sel_updtdays)
|
string='Select days', required=True, selection=sel_updtdays)
|
||||||
updttime = fields.Time(
|
updttime = fields.Time(
|
||||||
string='Time',
|
string='Time',
|
||||||
states={'readonly': ~Bool(Eval('updtsources'))},
|
states={
|
||||||
depends=['updtsources'])
|
'readonly': ~Bool(Eval('updtsources')),
|
||||||
|
}, depends=['updtsources'])
|
||||||
nextupdate = fields.Function(fields.DateTime(
|
nextupdate = fields.Function(fields.DateTime(
|
||||||
string='Next Update', readonly=True),
|
string='Next Update', readonly=True),
|
||||||
'get_nextupdates', searcher='search_nextupdate')
|
'get_nextupdates', searcher='search_nextupdate')
|
||||||
|
@ -154,21 +160,6 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
super(Asset, cls).__setup__()
|
super(Asset, cls).__setup__()
|
||||||
cls._order.insert(0, ('name', 'ASC'))
|
cls._order.insert(0, ('name', 'ASC'))
|
||||||
cls._order.insert(0, ('date', 'DESC'))
|
cls._order.insert(0, ('date', 'DESC'))
|
||||||
t = cls.__table__()
|
|
||||||
cls._sql_indexes.update({
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.product, Index.Equality())),
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.currency, Index.Equality())),
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.uom, Index.Equality())),
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.updtdays, Index.Equality())),
|
|
||||||
})
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def migrate_updtsource(cls, module_name):
|
def migrate_updtsource(cls, module_name):
|
||||||
|
@ -195,7 +186,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
'source': x[1],
|
'source': x[1],
|
||||||
} for x in records]
|
} for x in records]
|
||||||
|
|
||||||
if to_create:
|
if len(to_create) > 0:
|
||||||
AssetSourceRel.create(to_create)
|
AssetSourceRel.create(to_create)
|
||||||
asset_table.drop_column('updtsource')
|
asset_table.drop_column('updtsource')
|
||||||
|
|
||||||
|
@ -256,7 +247,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
def on_change_updtsources(self):
|
def on_change_updtsources(self):
|
||||||
""" clear time-fields
|
""" clear time-fields
|
||||||
"""
|
"""
|
||||||
if not self.updtsources:
|
if len(self.updtsources) == 0:
|
||||||
self.updttime = None
|
self.updttime = None
|
||||||
else:
|
else:
|
||||||
self.updttime = time(11, 30)
|
self.updttime = time(11, 30)
|
||||||
|
@ -417,7 +408,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_query.select(
|
query = tab_query.select(
|
||||||
tab_query.id,
|
tab_query.id,
|
||||||
where=Operator(tab_query.date, clause[2]))
|
where=Operator(tab_query.date, clause[2]),
|
||||||
|
)
|
||||||
return [('id', 'in', query)]
|
return [('id', 'in', query)]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -429,7 +421,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_query.select(
|
query = tab_query.select(
|
||||||
tab_query.id,
|
tab_query.id,
|
||||||
where=Operator(tab_query.rate, clause[2]))
|
where=Operator(tab_query.rate, clause[2]),
|
||||||
|
)
|
||||||
return [('id', 'in', query)]
|
return [('id', 'in', query)]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -441,7 +434,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_query.select(
|
query = tab_query.select(
|
||||||
tab_query.date,
|
tab_query.date,
|
||||||
where=tab_query.id == table.id)
|
where=tab_query.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -453,7 +447,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_query.select(
|
query = tab_query.select(
|
||||||
tab_query.rate,
|
tab_query.rate,
|
||||||
where=tab_query.id == table.id)
|
where=tab_query.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -479,7 +474,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
tab_rate1.rate,
|
tab_rate1.rate,
|
||||||
distinct_on=[tab_rate1.asset],
|
distinct_on=[tab_rate1.asset],
|
||||||
order_by=[tab_rate1.asset, tab_rate1.date.desc],
|
order_by=[tab_rate1.asset, tab_rate1.date.desc],
|
||||||
where=where_asset)
|
where=where_asset,
|
||||||
|
)
|
||||||
|
|
||||||
days_diff = days + 5
|
days_diff = days + 5
|
||||||
query = tab_today.join(
|
query = tab_today.join(
|
||||||
|
@ -495,7 +491,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
(tab_today.rate * 100.0 / NullIf(tab_rate2.rate, 0.00) -
|
(tab_today.rate * 100.0 / NullIf(tab_rate2.rate, 0.00) -
|
||||||
100.0).as_('percent'),
|
100.0).as_('percent'),
|
||||||
distinct_on=[tab_today.id],
|
distinct_on=[tab_today.id],
|
||||||
order_by=[tab_today.id, tab_rate2.date.desc])
|
order_by=[tab_today.id, tab_rate2.date.desc]
|
||||||
|
)
|
||||||
return query
|
return query
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -508,7 +505,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_asset.select(
|
query = tab_asset.select(
|
||||||
tab_asset.percent,
|
tab_asset.percent,
|
||||||
where=tab_asset.id == table.id)
|
where=tab_asset.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -521,7 +519,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_asset.select(
|
query = tab_asset.select(
|
||||||
tab_asset.percent,
|
tab_asset.percent,
|
||||||
where=tab_asset.id == table.id)
|
where=tab_asset.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -534,7 +533,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_asset.select(
|
query = tab_asset.select(
|
||||||
tab_asset.percent,
|
tab_asset.percent,
|
||||||
where=tab_asset.id == table.id)
|
where=tab_asset.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -547,7 +547,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_asset.select(
|
query = tab_asset.select(
|
||||||
tab_asset.percent,
|
tab_asset.percent,
|
||||||
where=tab_asset.id == table.id)
|
where=tab_asset.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -560,7 +561,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_asset.select(
|
query = tab_asset.select(
|
||||||
tab_asset.percent,
|
tab_asset.percent,
|
||||||
where=tab_asset.id == table.id)
|
where=tab_asset.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -602,13 +604,14 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
'change_month6': 180,
|
'change_month6': 180,
|
||||||
'change_month12': 365,
|
'change_month12': 365,
|
||||||
}[x],
|
}[x],
|
||||||
asset_ids=asset_id_lst)
|
asset_ids=asset_id_lst,
|
||||||
|
)
|
||||||
cursor.execute(*tab_percent)
|
cursor.execute(*tab_percent)
|
||||||
records = cursor.fetchall()
|
records = cursor.fetchall()
|
||||||
|
|
||||||
for record in records:
|
for record in records:
|
||||||
result[x][record[0]] = record[3].quantize(exp) \
|
result[x][record[0]] = record[3].quantize(exp) \
|
||||||
if record[3] is not None else None
|
if record[3] is not None else None
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -642,7 +645,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
tab_asset.updtdays,
|
tab_asset.updtdays,
|
||||||
tab_asset.updttime,
|
tab_asset.updttime,
|
||||||
distinct_on=[tab_asset.id],
|
distinct_on=[tab_asset.id],
|
||||||
order_by=[tab_asset.id, tab_rate.date.desc])
|
order_by=[tab_asset.id, tab_rate.date.desc],
|
||||||
|
)
|
||||||
|
|
||||||
query = tab_date.select(
|
query = tab_date.select(
|
||||||
tab_date.id,
|
tab_date.id,
|
||||||
|
@ -654,7 +658,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
(Extract('dow', tab_date.date) == 6),
|
(Extract('dow', tab_date.date) == 6),
|
||||||
tab_date.date + Literal(2)),
|
tab_date.date + Literal(2)),
|
||||||
else_=tab_date.date,
|
else_=tab_date.date,
|
||||||
) + tab_date.updttime).as_('updttime'))
|
) + tab_date.updttime).as_('updttime'),
|
||||||
|
)
|
||||||
return query
|
return query
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -668,7 +673,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
query = tab_updt.select(
|
query = tab_updt.select(
|
||||||
tab_updt.id,
|
tab_updt.id,
|
||||||
tab_updt.updttime,
|
tab_updt.updttime,
|
||||||
where=tab_updt.id.in_([x.id for x in assets]))
|
where=tab_updt.id.in_([x.id for x in assets]),
|
||||||
|
)
|
||||||
cursor.execute(*query)
|
cursor.execute(*query)
|
||||||
records = cursor.fetchall()
|
records = cursor.fetchall()
|
||||||
|
|
||||||
|
@ -692,7 +698,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_updt.select(
|
query = tab_updt.select(
|
||||||
tab_updt.id,
|
tab_updt.id,
|
||||||
where=Operator(tab_updt.updttime, clause[2]))
|
where=Operator(tab_updt.updttime, clause[2]),
|
||||||
|
)
|
||||||
return [('id', 'in', query)]
|
return [('id', 'in', query)]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -729,7 +736,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
tab_asset.id,
|
tab_asset.id,
|
||||||
tab_wkn.code.as_('wkn'),
|
tab_wkn.code.as_('wkn'),
|
||||||
tab_secsymb.code.as_('secsymb'),
|
tab_secsymb.code.as_('secsymb'),
|
||||||
tab_isin.code.as_('isin'))
|
tab_isin.code.as_('isin'),
|
||||||
|
)
|
||||||
return query
|
return query
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -753,7 +761,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
condition=tab_templ.id == tab_prod.template
|
condition=tab_templ.id == tab_prod.template
|
||||||
).select(
|
).select(
|
||||||
tab_templ.name,
|
tab_templ.name,
|
||||||
where=tab_asset.id == table.id)
|
where=tab_asset.id == table.id
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -766,7 +775,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_ids.select(
|
query = tab_ids.select(
|
||||||
getattr(tab_ids, 'wkn'),
|
getattr(tab_ids, 'wkn'),
|
||||||
where=tab_ids.id == table.id)
|
where=tab_ids.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -779,7 +789,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_ids.select(
|
query = tab_ids.select(
|
||||||
getattr(tab_ids, 'isin'),
|
getattr(tab_ids, 'isin'),
|
||||||
where=tab_ids.id == table.id)
|
where=tab_ids.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -792,7 +803,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
query = tab_ids.select(
|
query = tab_ids.select(
|
||||||
getattr(tab_ids, 'secsymb'),
|
getattr(tab_ids, 'secsymb'),
|
||||||
where=tab_ids.id == table.id)
|
where=tab_ids.id == table.id,
|
||||||
|
)
|
||||||
return [query]
|
return [query]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -812,7 +824,8 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
).select(
|
).select(
|
||||||
tab_asset.id,
|
tab_asset.id,
|
||||||
where=Operator(field_qu, clause[2]) &
|
where=Operator(field_qu, clause[2]) &
|
||||||
(field_qu != DEF_NONE))
|
(field_qu != DEF_NONE),
|
||||||
|
)
|
||||||
|
|
||||||
return [('id', 'in', query)]
|
return [('id', 'in', query)]
|
||||||
|
|
||||||
|
@ -885,7 +898,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
|
||||||
if OnlineSource.update_rate(asset):
|
if OnlineSource.update_rate(asset):
|
||||||
to_run_activities.append(asset)
|
to_run_activities.append(asset)
|
||||||
|
|
||||||
if to_run_activities:
|
if len(to_run_activities) > 0:
|
||||||
cls.after_update_actions(to_run_activities)
|
cls.after_update_actions(to_run_activities)
|
||||||
|
|
||||||
# end Asset
|
# end Asset
|
||||||
|
@ -896,11 +909,11 @@ class AssetSourceRel(ModelSQL):
|
||||||
__name__ = 'investment.asset_source_rel'
|
__name__ = 'investment.asset_source_rel'
|
||||||
|
|
||||||
source = fields.Many2One(
|
source = fields.Many2One(
|
||||||
string='Online Source',
|
string='Online Source', select=True,
|
||||||
required=True, model_name='investment.source',
|
required=True, model_name='investment.source',
|
||||||
ondelete='CASCADE')
|
ondelete='CASCADE')
|
||||||
asset = fields.Many2One(
|
asset = fields.Many2One(
|
||||||
string='Asset',
|
string='Asset', select=True,
|
||||||
required=True, model_name='investment.asset',
|
required=True, model_name='investment.asset',
|
||||||
ondelete='CASCADE')
|
ondelete='CASCADE')
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ class ChartPoint(metaclass=PoolMeta):
|
||||||
"""
|
"""
|
||||||
Rate = Pool().get('investment.rate')
|
Rate = Pool().get('investment.rate')
|
||||||
|
|
||||||
if not keyname:
|
if keyname is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# check if query is for us
|
# check if query is for us
|
||||||
|
|
|
@ -84,14 +84,14 @@ class ImportWizard(Wizard):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
ImportWiz = pool.get('investment.imp_wiz', type='wizard')
|
ImportWiz = pool.get('investment.imp_wiz', type='wizard')
|
||||||
|
|
||||||
if self.start.file_:
|
if self.start.file_ is not None:
|
||||||
(lines, max_date, min_date) = ImportWiz.read_csv_file(
|
(lines, max_date, min_date) = ImportWiz.read_csv_file(
|
||||||
self.start.file_.decode('utf8'),
|
self.start.file_.decode('utf8'),
|
||||||
dec_divider=self.start.dec_divider,
|
dec_divider=self.start.dec_divider,
|
||||||
date_fmt=self.start.date_fmt,
|
date_fmt=self.start.date_fmt,
|
||||||
delimiter=self.start.field_delimiter)
|
delimiter=self.start.field_delimiter)
|
||||||
|
|
||||||
if lines:
|
if len(lines) > 0:
|
||||||
ImportWiz.upload_rates(
|
ImportWiz.upload_rates(
|
||||||
self.start.asset,
|
self.start.asset,
|
||||||
lines, min_date, max_date)
|
lines, min_date, max_date)
|
||||||
|
|
|
@ -50,10 +50,6 @@ msgctxt "model:ir.message,text:msg_missing_url"
|
||||||
msgid "URL for the online source '%(oname)s' is missing."
|
msgid "URL for the online source '%(oname)s' is missing."
|
||||||
msgstr "URL für die Onlinequelle '%(oname)s' fehlt."
|
msgstr "URL für die Onlinequelle '%(oname)s' fehlt."
|
||||||
|
|
||||||
msgctxt "model:ir.message,text:msg_bug_in_regexquery"
|
|
||||||
msgid "Error in regex code of field '%(fname)s': %(errmsg)s [%(code)s]"
|
|
||||||
msgstr "Fehler in Regex-Code des Feldes '%(fname)s': %(errmsg)s [%(code)s]"
|
|
||||||
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
# ir.ui.menu #
|
# ir.ui.menu #
|
||||||
|
|
16
locale/en.po
16
locale/en.po
|
@ -38,10 +38,6 @@ msgctxt "model:ir.message,text:msg_missing_url"
|
||||||
msgid "URL for the online source '%(oname)s' is missing."
|
msgid "URL for the online source '%(oname)s' is missing."
|
||||||
msgstr "URL for the online source '%(oname)s' is missing."
|
msgstr "URL for the online source '%(oname)s' is missing."
|
||||||
|
|
||||||
msgctxt "model:ir.message,text:msg_bug_in_regexquery"
|
|
||||||
msgid "Error in regex code of field '%(fname)s': %(errmsg)s [%(code)s]"
|
|
||||||
msgstr "Error in regex code of field '%(fname)s': %(errmsg)s [%(code)s]"
|
|
||||||
|
|
||||||
msgctxt "model:ir.ui.menu,name:menu_investment"
|
msgctxt "model:ir.ui.menu,name:menu_investment"
|
||||||
msgid "Investment"
|
msgid "Investment"
|
||||||
msgstr "Investment"
|
msgstr "Investment"
|
||||||
|
@ -298,18 +294,6 @@ msgctxt "selection:investment.asset,updtdays:"
|
||||||
msgid "Mon - Sun"
|
msgid "Mon - Sun"
|
||||||
msgstr "Mon - Sun"
|
msgstr "Mon - Sun"
|
||||||
|
|
||||||
msgctxt "field:investment.asset,updturl:"
|
|
||||||
msgid "URL"
|
|
||||||
msgstr "URL"
|
|
||||||
|
|
||||||
msgctxt "help:investment.asset,updturl:"
|
|
||||||
msgid "URL for data retrieval."
|
|
||||||
msgstr "URL for data retrieval."
|
|
||||||
|
|
||||||
msgctxt "field:investment.asset,updturl_enable:"
|
|
||||||
msgid "URL required"
|
|
||||||
msgstr "URL required"
|
|
||||||
|
|
||||||
msgctxt "model:investment.asset_source_rel,name:"
|
msgctxt "model:investment.asset_source_rel,name:"
|
||||||
msgid "Asset Source Relation"
|
msgid "Asset Source Relation"
|
||||||
msgstr "Asset Source Relation"
|
msgstr "Asset Source Relation"
|
||||||
|
|
|
@ -23,9 +23,6 @@ full copyright notices and license terms. -->
|
||||||
<record model="ir.message" id="msg_missing_url">
|
<record model="ir.message" id="msg_missing_url">
|
||||||
<field name="text">URL for the online source '%(oname)s' is missing.</field>
|
<field name="text">URL for the online source '%(oname)s' is missing.</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="ir.message" id="msg_bug_in_regexquery">
|
|
||||||
<field name="text">Error in regex code of field '%(fname)s': %(errmsg)s [%(code)s]</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -63,14 +63,16 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
url = fields.Char(string='URL', states=STATES_WEB, depends=DEPENDS_WEB)
|
url = fields.Char(string='URL', states=STATES_WEB, depends=DEPENDS_WEB)
|
||||||
fixed_url = fields.Boolean(
|
fixed_url = fields.Boolean(
|
||||||
string='Fixed URL',
|
string='Fixed URL',
|
||||||
states={'invisible': Eval('query_method', '') != 'web'},
|
states={
|
||||||
depends=DEPENDS_WEB,
|
'invisible': Eval('query_method', '') != 'web',
|
||||||
|
}, depends=DEPENDS_WEB,
|
||||||
help='URL must be defined at investment record.')
|
help='URL must be defined at investment record.')
|
||||||
nohtml = fields.Boolean(
|
nohtml = fields.Boolean(
|
||||||
string='Remove HTML',
|
string='Remove HTML',
|
||||||
help='Removes HTML tags before the text is interpreted.',
|
help='Removes HTML tags before the text is interpreted.',
|
||||||
states={'invisible': STATES_WEB['invisible']},
|
states={
|
||||||
depends=DEPENDS_WEB)
|
'invisible': STATES_WEB['invisible'],
|
||||||
|
}, depends=DEPENDS_WEB)
|
||||||
rgxdate = fields.Char(
|
rgxdate = fields.Char(
|
||||||
string='Date',
|
string='Date',
|
||||||
help='Regex code to find the date in the downloaded HTML file.',
|
help='Regex code to find the date in the downloaded HTML file.',
|
||||||
|
@ -90,8 +92,9 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
rgxident = fields.Char(
|
rgxident = fields.Char(
|
||||||
string='Identifier',
|
string='Identifier',
|
||||||
help='Regex code to find the identifier in the downloaded HTML file.',
|
help='Regex code to find the identifier in the downloaded HTML file.',
|
||||||
states={'invisible': STATES_WEB['invisible']},
|
states={
|
||||||
depends=DEPENDS_WEB)
|
'invisible': STATES_WEB['invisible'],
|
||||||
|
}, depends=DEPENDS_WEB)
|
||||||
rgxidtype = fields.Selection(
|
rgxidtype = fields.Selection(
|
||||||
string='ID-Type', selection=sel_rgxidtype,
|
string='ID-Type', selection=sel_rgxidtype,
|
||||||
help='Type of identifier used to validate the result.',
|
help='Type of identifier used to validate the result.',
|
||||||
|
@ -240,13 +243,16 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
isin=self.isin,
|
isin=self.isin,
|
||||||
nsin=self.nsin,
|
nsin=self.nsin,
|
||||||
symbol=self.symbol,
|
symbol=self.symbol,
|
||||||
url=self.url)
|
url=self.url,
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_query_methods(cls):
|
def get_query_methods(cls):
|
||||||
""" get list of query-methods
|
""" get list of query-methods
|
||||||
"""
|
"""
|
||||||
return [('web', gettext('investment.msg_querytype_web'))]
|
return [
|
||||||
|
('web', gettext('investment.msg_querytype_web')),
|
||||||
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_test_value(cls, record, name, value):
|
def set_test_value(cls, record, name, value):
|
||||||
|
@ -254,15 +260,6 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def validate(cls, records):
|
|
||||||
""" check regex-code
|
|
||||||
"""
|
|
||||||
for record in records:
|
|
||||||
for x in ['rgxdate', 'rgxrate', 'rgxident']:
|
|
||||||
if x:
|
|
||||||
record.get_regex_result('', x)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_query_method(cls, osource, isin, nsin, symbol, url, debug=False):
|
def run_query_method(cls, osource, isin, nsin, symbol, url, debug=False):
|
||||||
""" run selected query to retrive data
|
""" run selected query to retrive data
|
||||||
|
@ -283,7 +280,8 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
nsin=nsin,
|
nsin=nsin,
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
debug=debug,
|
debug=debug,
|
||||||
url=url)
|
url=url,
|
||||||
|
)
|
||||||
|
|
||||||
def call_online_source(self):
|
def call_online_source(self):
|
||||||
""" use updated values to call online-source,
|
""" use updated values to call online-source,
|
||||||
|
@ -294,7 +292,7 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
result = OSourc.run_query_method(
|
result = OSourc.run_query_method(
|
||||||
self, self.isin, self.nsin, self.url,
|
self, self.isin, self.nsin, self.url,
|
||||||
self.symbol, debug=True)
|
self.symbol, debug=True)
|
||||||
if result:
|
if result is not None:
|
||||||
self.text = result.get('text', None)
|
self.text = result.get('text', None)
|
||||||
self.http_state = result.get('http_state', None)
|
self.http_state = result.get('http_state', None)
|
||||||
self.fnddate = result.get('date', None)
|
self.fnddate = result.get('date', None)
|
||||||
|
@ -306,17 +304,19 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
""" generate url
|
""" generate url
|
||||||
"""
|
"""
|
||||||
if self.fixed_url is True:
|
if self.fixed_url is True:
|
||||||
if not url:
|
if url is None:
|
||||||
raise UserError(gettext(
|
raise UserError(gettext(
|
||||||
'investment.msg_missing_url',
|
'investment.msg_missing_url',
|
||||||
oname=self.rec_name))
|
oname=self.rec_name,
|
||||||
|
))
|
||||||
return url
|
return url
|
||||||
|
else:
|
||||||
if self.url:
|
if self.url:
|
||||||
return Template(self.url).substitute({
|
return Template(self.url).substitute({
|
||||||
'isin': isin if isin is not None else '',
|
'isin': isin if isin is not None else '',
|
||||||
'nsin': nsin if nsin is not None else '',
|
'nsin': nsin if nsin is not None else '',
|
||||||
'symbol': symbol if symbol is not None else ''})
|
'symbol': symbol if symbol is not None else '',
|
||||||
|
})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_rate(cls, asset):
|
def update_rate(cls, asset):
|
||||||
|
@ -335,7 +335,8 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
isin=asset.isin,
|
isin=asset.isin,
|
||||||
nsin=asset.wkn,
|
nsin=asset.wkn,
|
||||||
symbol=asset.secsymb,
|
symbol=asset.secsymb,
|
||||||
url=asset.updturl)
|
url=asset.updturl,
|
||||||
|
)
|
||||||
|
|
||||||
if len(updtsource.rgxident or '') > 0:
|
if len(updtsource.rgxident or '') > 0:
|
||||||
# check result - same code?
|
# check result - same code?
|
||||||
|
@ -352,13 +353,15 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
'update_rate: got wrong code ' +
|
'update_rate: got wrong code ' +
|
||||||
'"%(wrong)s" - expected "%(exp)s"' % {
|
'"%(wrong)s" - expected "%(exp)s"' % {
|
||||||
'exp': asset_code,
|
'exp': asset_code,
|
||||||
'wrong': code})
|
'wrong': code,
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
to_create = {
|
to_create = {
|
||||||
'date': rate_data.get('date', None),
|
'date': rate_data.get('date', None),
|
||||||
'rate': rate_data.get('rate', None),
|
'rate': rate_data.get('rate', None),
|
||||||
'asset': asset.id}
|
'asset': asset.id,
|
||||||
|
}
|
||||||
if (to_create['date'] is not None) and \
|
if (to_create['date'] is not None) and \
|
||||||
(to_create['rate'] is not None):
|
(to_create['rate'] is not None):
|
||||||
# check if exists
|
# check if exists
|
||||||
|
@ -377,22 +380,13 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
def get_regex_result(self, html_text, field_name):
|
def get_regex_result(self, html_text, field_name):
|
||||||
""" run regex on html-text, convert result
|
""" run regex on html-text, convert result
|
||||||
"""
|
"""
|
||||||
OSource = Pool().get('investment.source')
|
|
||||||
|
|
||||||
rgxcode = getattr(self, field_name) or ''
|
rgxcode = getattr(self, field_name) or ''
|
||||||
if len(rgxcode) == 0:
|
if len(rgxcode) == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
search_result = re.compile(rgxcode).search(html_text)
|
||||||
search_result = re.compile(rgxcode).search(html_text)
|
if search_result is None:
|
||||||
if search_result is None:
|
return None
|
||||||
return None
|
|
||||||
except Exception as e1:
|
|
||||||
raise UserError(gettext(
|
|
||||||
'investment.msg_bug_in_regexquery',
|
|
||||||
errmsg=str(e1),
|
|
||||||
fname=getattr(OSource, field_name).string,
|
|
||||||
code=rgxcode))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = search_result.group(1)
|
result = search_result.group(1)
|
||||||
|
@ -433,7 +427,8 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
isin=isin,
|
isin=isin,
|
||||||
nsin=nsin,
|
nsin=nsin,
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
url=url),
|
url=url,
|
||||||
|
),
|
||||||
allow_redirects=True,
|
allow_redirects=True,
|
||||||
timeout=5.0)
|
timeout=5.0)
|
||||||
|
|
||||||
|
@ -442,7 +437,7 @@ class OnlineSource(ModelSQL, ModelView):
|
||||||
'msg': res1.reason,
|
'msg': res1.reason,
|
||||||
}
|
}
|
||||||
|
|
||||||
if res1.status_code in [200, 204, 410]:
|
if res1.status_code in [200, 204]:
|
||||||
html = res1.text
|
html = res1.text
|
||||||
|
|
||||||
# remove html-tags
|
# remove html-tags
|
||||||
|
|
23
rate.py
23
rate.py
|
@ -4,7 +4,7 @@
|
||||||
# full copyright notices and license terms.
|
# full copyright notices and license terms.
|
||||||
|
|
||||||
from trytond.model import (
|
from trytond.model import (
|
||||||
ModelView, ModelSQL, fields, Unique, Check, SymbolMixin, Index)
|
ModelView, ModelSQL, fields, Unique, Check, SymbolMixin)
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.pyson import Eval
|
from trytond.pyson import Eval
|
||||||
|
@ -15,11 +15,11 @@ class Rate(SymbolMixin, ModelSQL, ModelView):
|
||||||
__name__ = 'investment.rate'
|
__name__ = 'investment.rate'
|
||||||
|
|
||||||
asset = fields.Many2One(
|
asset = fields.Many2One(
|
||||||
string='Asset', required=True, ondelete='CASCADE',
|
string='Asset', required=True, select=True, ondelete='CASCADE',
|
||||||
model_name='investment.asset')
|
model_name='investment.asset')
|
||||||
date = fields.Date(string='Date', required=True)
|
date = fields.Date(string='Date', required=True, select=True)
|
||||||
rate = fields.Numeric(
|
rate = fields.Numeric(
|
||||||
string='Rate', required=True,
|
string='Rate', required=True, select=True,
|
||||||
digits=(16, Eval('asset_digits', 4)), depends=['asset_digits'])
|
digits=(16, Eval('asset_digits', 4)), depends=['asset_digits'])
|
||||||
|
|
||||||
asset_digits = fields.Function(fields.Integer(
|
asset_digits = fields.Function(fields.Integer(
|
||||||
|
@ -46,21 +46,6 @@ class Rate(SymbolMixin, ModelSQL, ModelView):
|
||||||
'currency.msg_rate_positive'),
|
'currency.msg_rate_positive'),
|
||||||
]
|
]
|
||||||
cls._order.insert(0, ('date', 'DESC'))
|
cls._order.insert(0, ('date', 'DESC'))
|
||||||
cls._sql_indexes.update({
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.date, Index.Range(order='DESC'))),
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.rate, Index.Range())),
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.asset, Index.Equality())),
|
|
||||||
Index(
|
|
||||||
t,
|
|
||||||
(t.asset, Index.Equality()),
|
|
||||||
(t.date, Index.Range(order='DESC'))),
|
|
||||||
})
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_date(cls):
|
def default_date(cls):
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -39,7 +39,7 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f:
|
||||||
modversion[l2[0]] = {'min': l2[1], 'max': l2[2], 'prefix': l2[3]}
|
modversion[l2[0]] = {'min': l2[1], 'max': l2[2], 'prefix': l2[3]}
|
||||||
|
|
||||||
# tryton-version
|
# tryton-version
|
||||||
major_version = 7
|
major_version = 6
|
||||||
minor_version = 0
|
minor_version = 0
|
||||||
|
|
||||||
requires = ['requests>=2.26', 'html2text']
|
requires = ['requests>=2.26', 'html2text']
|
||||||
|
@ -91,7 +91,6 @@ setup(
|
||||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
'Programming Language :: Python :: 3.9',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
keywords='tryton investment shares commodities',
|
keywords='tryton investment shares commodities',
|
||||||
|
|
|
@ -71,9 +71,9 @@ full copyright notices and license terms. -->
|
||||||
<field name="name">www.sbroker.de</field>
|
<field name="name">www.sbroker.de</field>
|
||||||
<field name="url">https://www.sbroker.de/sbl/mdaten_analyse/dksuche_a?SEARCH_VALUE=${isin}</field>
|
<field name="url">https://www.sbroker.de/sbl/mdaten_analyse/dksuche_a?SEARCH_VALUE=${isin}</field>
|
||||||
<field name="nohtml" eval="True"/>
|
<field name="nohtml" eval="True"/>
|
||||||
<field name="rgxdate">\nDatum\s*(?:\/ Uhrzeit)*: (\d+\.\d+\.\d+)\s*(?:\/ \d+:\d+)*\s*\n</field>
|
<field name="rgxdate">\nDatum / Uhrzeit: (\d+\.\d+\.\d+) / \d+:\d+\s+\n</field>
|
||||||
<field name="rgxdatefmt">%d.%m.%y</field>
|
<field name="rgxdatefmt">%d.%m.%y</field>
|
||||||
<field name="rgxrate">(?:Kurs aktuell|Rucknahmepreis)\s+[()\w\./\[\]!]+\s+(\d+,\d+)\s+(EUR|€)</field>
|
<field name="rgxrate">Kurs aktuell .* (\d+,\d+)\s+EUR.*\n</field>
|
||||||
<field name="rgxdecimal">,</field>
|
<field name="rgxdecimal">,</field>
|
||||||
<field name="rgxident">\nWKN / ISIN: [A-Z,0-9]+ / ([A-Z,0-9]+)\s+\n</field>
|
<field name="rgxident">\nWKN / ISIN: [A-Z,0-9]+ / ([A-Z,0-9]+)\s+\n</field>
|
||||||
<field name="rgxidtype">isin</field>
|
<field name="rgxidtype">isin</field>
|
||||||
|
|
|
@ -1,2 +1,17 @@
|
||||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import trytond.tests.test_tryton
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from .test_module import InvestmentTestCase
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ['suite']
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
suite = trytond.tests.test_tryton.suite()
|
||||||
|
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
|
||||||
|
InvestmentTestCase))
|
||||||
|
return suite
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
from trytond.tests.test_tryton import with_transaction
|
from trytond.tests.test_tryton import with_transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.exceptions import UserError
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from datetime import time, date, datetime
|
from datetime import time, date, datetime
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
@ -132,54 +131,5 @@ High 34,87 EUR
|
||||||
'rgxdate'
|
'rgxdate'
|
||||||
), date(2022, 3, 14))
|
), date(2022, 3, 14))
|
||||||
|
|
||||||
@with_transaction()
|
|
||||||
def test_waitlist_source_check_regex_validate(self):
|
|
||||||
""" create source, check validation of regex-code
|
|
||||||
"""
|
|
||||||
pool = Pool()
|
|
||||||
OSource = pool.get('investment.source')
|
|
||||||
|
|
||||||
self.assertRaisesRegex(
|
|
||||||
UserError,
|
|
||||||
r"Error in regex code of field 'Date': nothing to repeat " +
|
|
||||||
r"at position 0 \[\*+ multiple repeat\]",
|
|
||||||
OSource.create,
|
|
||||||
[{
|
|
||||||
'name': 'Check date',
|
|
||||||
'rgxdate': '** multiple repeat',
|
|
||||||
'rgxrate': 'rate -- multiple repeat',
|
|
||||||
'rgxident': 'identifiert ** multiple repeat',
|
|
||||||
}])
|
|
||||||
|
|
||||||
self.assertRaisesRegex(
|
|
||||||
UserError,
|
|
||||||
r"Error in regex code of field 'Rate': multiple repeat " +
|
|
||||||
r"at position 6 \[rate \*+ multiple repeat\]",
|
|
||||||
OSource.create,
|
|
||||||
[{
|
|
||||||
'name': 'Check rate',
|
|
||||||
'rgxdate': '-- multiple repeat',
|
|
||||||
'rgxrate': 'rate ** multiple repeat',
|
|
||||||
'rgxident': 'identifiert -- multiple repeat',
|
|
||||||
}])
|
|
||||||
|
|
||||||
self.assertRaisesRegex(
|
|
||||||
UserError,
|
|
||||||
r"Error in regex code of field 'Identifier': multiple " +
|
|
||||||
r"repeat at position 13 \[identifiert \*+ multiple repeat\]",
|
|
||||||
OSource.create,
|
|
||||||
[{
|
|
||||||
'name': 'Check rgxident',
|
|
||||||
'rgxdate': '-- multiple repeat',
|
|
||||||
'rgxrate': 'rate -- multiple repeat',
|
|
||||||
'rgxident': 'identifiert ** multiple repeat',
|
|
||||||
}])
|
|
||||||
|
|
||||||
OSource.create([{
|
|
||||||
'name': 'Check rgxident',
|
|
||||||
'rgxdate': '-- multiple repeat',
|
|
||||||
'rgxrate': 'rate -- multiple repeat',
|
|
||||||
'rgxident': 'identifiert -- multiple repeat',
|
|
||||||
}])
|
|
||||||
|
|
||||||
# end SourceTestCase
|
# end SourceTestCase
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tryton]
|
[tryton]
|
||||||
version=7.0.0
|
version=6.0.25
|
||||||
depends:
|
depends:
|
||||||
ir
|
ir
|
||||||
res
|
res
|
||||||
|
|
|
@ -29,7 +29,7 @@ class UpdateSoureWizard(Wizard):
|
||||||
if OnlineSource.update_rate(asset):
|
if OnlineSource.update_rate(asset):
|
||||||
to_run_activities.append(asset)
|
to_run_activities.append(asset)
|
||||||
|
|
||||||
if to_run_activities:
|
if len(to_run_activities) > 0:
|
||||||
Asset.after_update_actions(to_run_activities)
|
Asset.after_update_actions(to_run_activities)
|
||||||
|
|
||||||
return 'end'
|
return 'end'
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
|
diagram;6.0.7;6.0.999;mds
|
||||||
|
|
|
@ -4,12 +4,12 @@ The COPYRIGHT file at the top level of this repository contains the
|
||||||
full copyright notices and license terms. -->
|
full copyright notices and license terms. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="name" expand="1"/>
|
<field name="name" expand="1"/>
|
||||||
<field name="change_day1" optional="0"/>
|
<field name="change_day1"/>
|
||||||
<field name="change_month1" optional="0"/>
|
<field name="change_month1"/>
|
||||||
<field name="change_month3" optional="0"/>
|
<field name="change_month3"/>
|
||||||
<field name="change_month6" optional="0"/>
|
<field name="change_month6"/>
|
||||||
<field name="date" optional="0"/>
|
<field name="date"/>
|
||||||
<field name="rate" symbol="asset_symbol" optional="0"/>
|
<field name="rate" symbol="asset_symbol"/>
|
||||||
<field name="isin" optional="0"/>
|
<field name="isin"/>
|
||||||
<field name="wkn" optional="0"/>
|
<field name="wkn" />
|
||||||
</tree>
|
</tree>
|
||||||
|
|
Loading…
Reference in a new issue