Compare commits

...

19 commits

Author SHA1 Message Date
Frederik Jaeckel
c1cc1acb5f Version 6.0.7 2022-11-26 22:51:04 +01:00
Frederik Jaeckel
7bb3e4f929 asset:tabellenzugriff optimiert,
diagram: darstellung in diagramm ergänzt
2022-11-26 22:42:02 +01:00
Frederik Jaeckel
047b6980e4 Etikett ver 6.0.5 zum Änderungssatz 6e85642a2e97 hinzugefügt 2022-11-25 22:50:14 +01:00
Frederik Jaeckel
9d88cf1067 Version 6.0.5 2022-11-25 22:50:03 +01:00
Frederik Jaeckel
620c42fc62 asset: suche in name, sortiert nach name, sortierer für wkn, isin, symbl 2022-11-25 22:46:32 +01:00
Frederik Jaeckel
6311dce3d1 asset: spalten tag/monat/3monate... ok + test 2022-11-25 21:55:43 +01:00
Frederik Jaeckel
64b8383096 abfrage der prozentwerte für tag/1 monat, 3 monate, 6 monate, 12 monate
test muß noch
2022-11-25 15:28:49 +01:00
Frederik Jaeckel
a99d11a4a0 Etikett ver 6.0.4 zum Änderungssatz 8e3f0b006892 hinzugefügt 2022-11-25 11:02:13 +01:00
Frederik Jaeckel
4ae5601c04 Version 6.0.4 2022-11-25 11:01:55 +01:00
Frederik Jaeckel
31c76dfb48 asset: abfrage updatezeitpunkt optimiert, anzeige der vortagsprozente, farbe für zeilen 2022-11-25 11:00:03 +01:00
Frederik Jaeckel
57cb06d60e prozentwerte begonnen 2022-11-24 23:17:44 +01:00
Frederik Jaeckel
5587bfea3a Etikett ver 6.0.3 zum Änderungssatz 0a2f82baca7e hinzugefügt 2022-11-23 22:23:49 +01:00
Frederik Jaeckel
f919d9e290 Version 6.0.3 2022-11-23 22:23:42 +01:00
Frederik Jaeckel
e8614b1242 bug in updtneeded-suche, online-quellen erweitert 2022-11-23 22:22:22 +01:00
Frederik Jaeckel
a71bc0a79a Etikett ver 6.0.2 zum Änderungssatz 76feab691fd9 hinzugefügt 2022-11-23 10:45:38 +01:00
Frederik Jaeckel
f1d9b3b1dd Version 6.0.2 2022-11-23 10:45:28 +01:00
Frederik Jaeckel
4947b495c2 asset: feld 'Datum' + 'Name' neu, rec_name optimiert, Test korrigiert 2022-11-23 10:44:09 +01:00
Frederik Jaeckel
aeb949cc20 Etikett ver 6.0.1 zum Änderungssatz e16a79cd456e hinzugefügt 2022-11-22 22:47:03 +01:00
Frederik Jaeckel
916d73ef12 Version 6.0.1 2022-11-22 22:45:15 +01:00
16 changed files with 1303 additions and 151 deletions

View file

@ -14,6 +14,34 @@ Requires
Changes
=======
*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

View file

@ -10,6 +10,7 @@ from .identifier import Identifier
from .cron import Cron
from .onlinesource import OnlineSource
from .update_wiz import UpdateSoureWizard
from .diagram import GraphDef, ChartPoint
def register():
@ -20,6 +21,10 @@ def register():
Identifier,
Cron,
module='investment', type_='model')
Pool.register(
GraphDef,
ChartPoint,
module='investment', type_='model', depends=['diagram'])
Pool.register(
UpdateSoureWizard,
module='investment', type_='wizard')

490
asset.py
View file

@ -6,17 +6,24 @@
from trytond.model import ModelView, ModelSQL, fields
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.pyson import Eval, Bool, And
from trytond.pyson import Eval, Bool, And, If
from trytond.report import Report
from decimal import Decimal
from datetime import time
from sql.functions import CurrentTime
from sql.conditionals import Case
from sql.functions import CurrentDate, CurrentTimestamp, Round
from sql.conditionals import Case, Coalesce
from sql import Literal
digits_percent = 2
class Asset(ModelSQL, ModelView):
'Asset'
__name__ = 'investment.asset'
name = fields.Function(fields.Char(string='Name', readonly=True),
'on_change_with_name', searcher='search_rec_name')
company = fields.Many2One(string='Company', model_name='company.company',
required=True, ondelete="RESTRICT")
product = fields.Many2One(string='Product', required=True,
@ -38,7 +45,9 @@ class Asset(ModelSQL, ModelView):
model_name='investment.rate')
rate = fields.Function(fields.Numeric(string='Current Rate',
readonly=True, digits=(16, Eval('currency_digits', 4)),
depends=['currency_digits']), 'on_change_with_rate')
depends=['currency_digits']), 'get_rate_data')
date = fields.Function(fields.Date(string='Date', readonly=True,
help='Date of current rate'), 'get_rate_data')
company_currency = fields.Function(fields.Many2One(readonly=True,
string='Company Currency', states={'invisible': True},
@ -50,8 +59,7 @@ class Asset(ModelSQL, ModelView):
currency = fields.Many2One(string='Currency', select=True,
required=True, model_name='currency.currency', ondelete='RESTRICT')
currency_digits = fields.Integer(string='Currency Digits',
required=True)
currency_digits = fields.Integer(string='Digits', required=True)
wkn = fields.Function(fields.Char(string='NSIN', readonly=True,
help='National Securities Identifying Number'),
@ -70,9 +78,45 @@ class Asset(ModelSQL, ModelView):
states={
'readonly': ~Bool(Eval('updtsource')),
}, depends=['updtsource'])
updtneeded = fields.Function(fields.Boolean(string='Course update needed',
nextupdate = fields.Function(fields.DateTime(string='Next Update',
readonly=True),
'on_change_with_updtneeded', searcher='search_updtneeded')
'get_nextupdates', searcher='search_nextupdate')
# percentage change
change_day1 = fields.Function(fields.Numeric(string='Previous Day',
help='percentage change in value compared to the previous day',
readonly=True, digits=(16,digits_percent)),
'get_percentage_change', searcher='search_percentage')
change_month1 = fields.Function(fields.Numeric(string='1 Month',
help='percentage change in value compared to last month',
readonly=True, digits=(16,digits_percent)),
'get_percentage_change', searcher='search_percentage')
change_month3 = fields.Function(fields.Numeric(string='3 Months',
help='percentage change in value during 3 months',
readonly=True, digits=(16,digits_percent)),
'get_percentage_change', searcher='search_percentage')
change_month6 = fields.Function(fields.Numeric(string='6 Months',
help='percentage change in value during 6 months',
readonly=True, digits=(16,digits_percent)),
'get_percentage_change', searcher='search_percentage')
change_month12 = fields.Function(fields.Numeric(string='1 Year',
help='percentage change in value during 1 year',
readonly=True, digits=(16,digits_percent)),
'get_percentage_change', searcher='search_percentage')
@classmethod
def __setup__(cls):
super(Asset, cls).__setup__()
cls._order.insert(0, ('name', 'ASC'))
@classmethod
def view_attributes(cls):
return super().view_attributes() + [
('/tree', 'visual',
If(Eval('change_day1', 0) < 0, 'warning',
If(Eval('change_day1', 0) > 0, 'success', '')
)),
]
@classmethod
def default_currency(cls):
@ -96,6 +140,51 @@ class Asset(ModelSQL, ModelView):
"""
return 4
@classmethod
def default_updttime(cls):
""" 14 o'clock UTC
"""
return time(14, 0)
@classmethod
def get_rate_data(cls, assets, names):
""" get date and rate of asset
"""
pool = Pool()
Asset = pool.get('investment.asset')
Rate = pool.get('investment.rate')
tab_asset = Asset.__table__()
tab_rate = Rate.__table__()
cursor = Transaction().connection.cursor()
query = tab_asset.join(tab_rate,
condition=tab_asset.id==tab_rate.asset
).select(
tab_asset.id,
tab_rate.rate,
tab_rate.date,
distinct_on=[tab_asset.id],
order_by=[tab_asset.id, tab_rate.date.desc],
where=tab_asset.id.in_([x.id for x in assets]),
)
cursor.execute(*query)
records = cursor.fetchall()
result = {x:{y.id: None for y in assets} for x in names}
for record in records:
(id1, rate1, date1) = record
asset = Asset(id1)
exp = Decimal(Decimal(1) / 10 ** (asset.currency_digits or 4))
values = {'rate': record[1].quantize(exp), 'date': record[2]}
for name in names:
result[name][record[0]] = values[name]
return result
@fields.depends('updtsource', 'updttime')
def on_change_updtsource(self):
""" clear time-fields
@ -105,23 +194,6 @@ class Asset(ModelSQL, ModelView):
else :
self.updttime = time(11, 30)
@fields.depends('id', 'currency_digits')
def on_change_with_rate(self, name=None):
""" get current rate
"""
pool = Pool()
Rate = pool.get('investment.rate')
IrDate = pool.get('ir.date')
if self.id:
rates = Rate.search([
('date', '<=', IrDate.today()),
('asset.id', '=', self.id),
], order=[('date', 'DESC')], limit=1)
if len(rates) > 0:
exp = Decimal(Decimal(1) / 10 ** (self.currency_digits or 4))
return rates[0].rate.quantize(exp)
@fields.depends('product', 'uom')
def on_change_product(self):
""" update unit by product
@ -138,6 +210,13 @@ class Asset(ModelSQL, ModelView):
if self.currency:
self.currency_digits = self.currency.digits
@fields.depends('product')
def on_change_with_name(self, name=None):
""" get name of product
"""
if self.product:
return self.product.name
@fields.depends('product')
def on_change_with_product_uom(self, name=None):
""" get category of product-uom
@ -164,51 +243,255 @@ class Asset(ModelSQL, ModelView):
if self.company.currency.id != self.currency.id:
return self.company.currency.id
@fields.depends('id')
def on_change_with_updtneeded(self, name=None):
""" get state of update
"""
Asset2 = Pool().get('investment.asset')
if self.id:
if Asset2.search_count([
('updtneeded', '=', True),
('id', '=', self.id)
]) == 1:
return True
return False
@classmethod
def search_updtneeded(cls, names, clause):
""" search for assets to update
def get_percentage_sql(cls, name_lst, select_date=True):
""" get table for percentages and dates,
generate adapted query
select_date: True = select newest date
"""
pool = Pool()
Asset2 = pool.get('investment.asset')
Rate = pool.get('investment.rate')
IrDate = pool.get('ir.date')
tab_asset = Asset2.__table__()
tab_rate = Rate.__table__()
Operator = fields.SQL_OPERATORS[clause[1]]
Asset = pool.get('investment.asset')
tab_asset = Asset.__table__()
tab_rate_today = Rate.__table__()
rate_tab = {
'day1': {'tab': Rate.__table__(), 'day': 0},
'month1': {'tab': Rate.__table__(), 'day': 30},
'month3': {'tab': Rate.__table__(), 'day': 3*30},
'month6': {'tab': Rate.__table__(), 'day': 6*30},
'month12': {'tab': Rate.__table__(), 'day': 12*30},
}
context = Transaction().context
query_date = context.get('qdate', IrDate.today())
query_time = context.get('qtime', CurrentTime())
query = tab_asset.join(tab_rate,
condition=(tab_asset.id==tab_rate.asset) & \
(tab_rate.date == query_date),
type_ = 'LEFT OUTER',
).select(tab_asset.id,
where=Operator(
Case(
((tab_rate.id == None) & \
(tab_asset.updtsource != None) & \
(tab_asset.updttime <= query_time), True),
default_ = False,
),
clause[2]),
# create tables to query percentual changes for
# 1 day, 30 days, 3 months, 6 months, 1 year
query_date = context.get('qdate', CurrentDate())
query_today = tab_asset.join(tab_rate_today,
condition=tab_asset.id==tab_rate_today.asset,
).select(
tab_asset.id,
tab_rate_today.id.as_('id_rate'),
tab_rate_today.date,
tab_rate_today.rate,
)
return [('id', '=', query)]
# limit to newest date until 'query_date'
if select_date == True:
query_today.distinct_on=[tab_asset.id]
query_today.order_by=[tab_asset.id, tab_rate_today.date.desc]
query_today.where=tab_rate_today.date <= query_date
# create join for requested fields, to minimize database-load
query = query_today
for name in name_lst:
query = query.join(rate_tab[name]['tab'],
# select newest date from <period> until 5 days older
condition=(query_today.id==rate_tab[name]['tab'].asset) & \
(query_today.date > (rate_tab[name]['tab'].date + Literal(rate_tab[name]['day']))) & \
(query_today.date <= (rate_tab[name]['tab'].date + Literal(rate_tab[name]['day'] + 5))),
type_ = 'LEFT OUTER')
# add select for requested fields to join
select_lst = [
query_today.id,
query_today.id_rate,
query_today.date,
]
for name in name_lst:
select_lst.append(
Case(
((rate_tab[name]['tab'].rate != None) & (query_today.rate != None) & \
(rate_tab[name]['tab'].rate != Literal(0.0)),
query_today.rate * Literal(100.0) / rate_tab[name]['tab'].rate - Literal(100.0)),
else_ = None,
).as_(name))
order_by_lst = [query_today.id, query_today.id_rate]
order_by_lst.extend([
rate_tab[name]['tab'].date.desc for name in name_lst
])
query = query.select(
*select_lst,
distinct_on=[query_today.id, query_today.id_rate],
order_by=order_by_lst,
)
return query
@staticmethod
def order_change_day1(tables):
""" order day1
"""
Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['day1'])
table, _ = tables[None]
query = tab_asset.select(
getattr(tab_asset, 'day1'),
where=tab_asset.id==table.id,
)
return [query]
@staticmethod
def order_change_month1(tables):
""" order month1
"""
Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month1'])
table, _ = tables[None]
query = tab_asset.select(
getattr(tab_asset, 'month1'),
where=tab_asset.id==table.id,
)
return [query]
@staticmethod
def order_change_month3(tables):
""" order month1
"""
Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month3'])
table, _ = tables[None]
query = tab_asset.select(
getattr(tab_asset, 'month3'),
where=tab_asset.id==table.id,
)
return [query]
@staticmethod
def order_change_month6(tables):
""" order month1
"""
Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month6'])
table, _ = tables[None]
query = tab_asset.select(
getattr(tab_asset, 'month6'),
where=tab_asset.id==table.id,
)
return [query]
@staticmethod
def order_change_month12(tables):
""" order month1
"""
Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month12'])
table, _ = tables[None]
query = tab_asset.select(
getattr(tab_asset, 'month12'),
where=tab_asset.id==table.id,
)
return [query]
@classmethod
def search_percentage(cls, names, clause):
""" search for percentages
"""
Operator = fields.SQL_OPERATORS[clause[1]]
field_name = clause[0][len('change_'):]
tab_percent = cls.get_percentage_sql([field_name])
query = tab_percent.select(tab_percent.id,
where=Operator(Round(getattr(tab_percent, field_name), 2),
clause[2]))
return [('id', 'in', query)]
@classmethod
def get_percentage_change(cls, assets, names):
""" get percentage per period
"""
cursor = Transaction().connection.cursor()
name_lst = [x[len('change_'):] for x in names]
tab_percent = cls.get_percentage_sql(name_lst)
query = tab_percent.select(
tab_percent.id,
*[getattr(tab_percent, x) for x in name_lst],
where=tab_percent.id.in_([x.id for x in assets]),
)
cursor.execute(*query)
records = cursor.fetchall()
result = {x:{y.id: None for y in assets} for x in names}
exp = Decimal(Decimal(1) / 10 ** digits_percent)
for record in records:
cnt1 = 1
for x in name_lst:
result['change_%s' % x][record[0]] = record[cnt1].quantize(exp) \
if record[cnt1] is not None else None
cnt1 += 1
return result
@classmethod
def get_next_update_datetime_sql(cls):
""" get sql for datetime of next planned update
"""
pool = Pool()
Asset = pool.get('investment.asset')
Rate = pool.get('investment.rate')
tab_asset = Asset.__table__()
tab_rate = Rate.__table__()
context = Transaction().context
query_date = context.get('qdate', CurrentDate() - Literal(1))
query = tab_asset.join(tab_rate,
condition=tab_asset.id == tab_rate.asset,
type_ = 'LEFT OUTER',
).select(
tab_asset.id,
((Coalesce(tab_rate.date, query_date) + Literal(1)) + \
tab_asset.updttime).as_('updttime'),
distinct_on = [tab_asset.id],
order_by = [tab_asset.id, tab_rate.date.desc],
where=(tab_asset.updtsource != None),
)
return query
@classmethod
def get_nextupdates(cls, assets, names):
""" get timestamp of next update
"""
Asset2 = Pool().get('investment.asset')
tab_updt = Asset2.get_next_update_datetime_sql()
cursor = Transaction().connection.cursor()
query = tab_updt.select(
tab_updt.id,
tab_updt.updttime,
where=tab_updt.id.in_([x.id for x in assets]),
)
cursor.execute(*query)
records = cursor.fetchall()
result = {x:{y.id: None for y in assets} for x in names}
for record in records:
(id1, updt) = record
r1 = {'nextupdate': updt}
for n in names:
result[n][id1] = r1[n]
return result
@classmethod
def search_nextupdate(cls, names, clause):
""" search for assets to update
"""
Asset2 = Pool().get('investment.asset')
tab_updt = Asset2.get_next_update_datetime_sql()
Operator = fields.SQL_OPERATORS[clause[1]]
query = tab_updt.select(
tab_updt.id,
where=Operator(tab_updt.updttime, clause[2]),
)
return [('id', 'in', query)]
@classmethod
def get_identifier_sql(cls, tab_asset):
@ -244,6 +527,70 @@ class Asset(ModelSQL, ModelView):
)
return query
@staticmethod
def order_name(tables):
""" order name
"""
pool = Pool()
Templ = pool.get('product.template')
Product = pool.get('product.product')
Asset = pool.get('investment.asset')
table, _ = tables[None]
tab_asset = Asset.__table__()
tab_prod = Product.__table__()
tab_templ = Templ.__table__()
query = tab_asset.join(tab_prod,
condition=tab_asset.product==tab_prod.id
).join(tab_templ,
condition=tab_templ.id==tab_prod.template
).select(tab_templ.name,
where=tab_asset.id==table.id
)
return [query]
@staticmethod
def order_wkn(tables):
""" order wkn
"""
Asset = Pool().get('investment.asset')
tab_ids = Asset.get_identifier_sql(Asset.__table__())
table, _ = tables[None]
query = tab_ids.select(
getattr(tab_ids, 'wkn'),
where=tab_ids.id==table.id,
)
return [query]
@staticmethod
def order_isin(tables):
""" order isin
"""
Asset = Pool().get('investment.asset')
tab_ids = Asset.get_identifier_sql(Asset.__table__())
table, _ = tables[None]
query = tab_ids.select(
getattr(tab_ids, 'isin'),
where=tab_ids.id==table.id,
)
return [query]
@staticmethod
def order_secsymb(tables):
""" order secsymb
"""
Asset = Pool().get('investment.asset')
tab_ids = Asset.get_identifier_sql(Asset.__table__())
table, _ = tables[None]
query = tab_ids.select(
getattr(tab_ids, 'secsymb'),
where=tab_ids.id==table.id,
)
return [query]
@classmethod
def search_identifier(cls, names, clause):
""" search in identifier
@ -294,17 +641,24 @@ class Asset(ModelSQL, ModelView):
def get_rec_name(self, name):
""" record name
"""
return '%(prod)s [%(curr)s/%(unit)s]' % {
return '%(prod)s - %(rate)s %(curr)s/%(unit)s [%(date)s]' % {
'prod': getattr(self.product, 'rec_name', '-'),
'curr': getattr(self.currency, 'rec_name', '-'),
'curr': getattr(self.currency, 'symbol', '-'),
'unit': getattr(self.uom, 'rec_name', '-'),
'rate': Report.format_number(self.rate, lang=None,
digits=self.currency_digits or 4) \
if self.rate is not None else '-',
'date': Report.format_date(self.date) if self.date is not None else '-',
}
@classmethod
def search_rec_name(cls, name, clause):
""" search in rec_name
"""
return [('product.rec_name',) + tuple(clause[1:])]
return ['OR',
('product.rec_name',) + tuple(clause[1:]),
('product.identifiers.code',) + tuple(clause[1:]),
]
@classmethod
def cron_update(cls):
@ -313,9 +667,11 @@ class Asset(ModelSQL, ModelView):
pool = Pool()
Asset2 = pool.get('investment.asset')
OnlineSource = pool.get('investment.source')
context = Transaction().context
query_time = context.get('qdatetime', CurrentTimestamp())
for asset in Asset2.search([
('updtneeded', '=', True),
('nextupdate', '<=', query_time),
]):
OnlineSource.update_rate(asset)

112
diagram.py Normal file
View file

@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton.
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields
from trytond.transaction import Transaction
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
from sql.functions import Function
from datetime import timedelta
from decimal import Decimal
class Concat2(Function):
""" concat columns
"""
__slots__ = ()
_function = 'concat'
# end Concat2
class GraphDef(metaclass=PoolMeta):
__name__ = 'diagram.graphdef'
asset = fields.Many2One(string='Asset',
model_name='investment.asset',
states={
'invisible': Eval('dtype', '') != 'investment.asset',
'required': Eval('dtype', '') == 'investment.asset',
}, depends=['dtype'])
@classmethod
def _get_dtypes(cls):
""" return list of types
"""
l1 = super(GraphDef, cls)._get_dtypes()
l1.append('investment.asset')
return l1
def get_recname_value(self):
""" value by dtype
"""
if self.dtype == 'investment.asset':
return getattr(self.asset, 'rec_name', '-')
return super(GraphDef, self).get_recname_value()
def get_field_key(self):
""" get to read value from json
"""
if self.dtype == 'investment.asset':
return 'asset%d' % self.asset.id
return super(GraphDef, self).get_field_key()
def get_scaling_for_investment_asset(self):
""" get scaling for currency
"""
Rate = Pool().get('investment.rate')
if self.scaling == 'fix':
return None
if self.scaling == 'alldata':
query = [('asset.id', '=', self.asset.id)]
elif self.scaling == 'view':
query = [
('asset.id', '=', self.asset.id),
('date', '>=', self.chart.used_start_date()),
('date', '<=', self.chart.used_end_date()),
]
elif self.scaling == 'six':
query = [
('asset.id', '=', self.asset.id),
('date', '>=', self.chart.used_start_date() - timedelta(days=180)),
('date', '<=', self.chart.used_end_date()),
]
min_rec = Rate.search(query, limit=1, order=[('rate', 'ASC')])
max_rec = Rate.search(query, limit=1, order=[('rate', 'DESC')])
min_val = min_rec[0].rate if len(min_rec) > 0 else None
max_val = max_rec[0].rate if len(max_rec) > 0 else None
return self.compute_scaling_factor(min_val, max_val)
# end GraphDef
class ChartPoint(metaclass=PoolMeta):
__name__ = 'diagram.point'
@classmethod
def get_table_parts(cls):
""" return a list of tables to union,
table must contain the columns:
date, key, val
"""
pool = Pool()
Rate = pool.get('investment.rate')
tab_rate = Rate.__table__()
tabparts = super(ChartPoint, cls).get_table_parts()
# rate
tabparts.append(tab_rate.select(
tab_rate.date,
Concat2('asset', tab_rate.asset).as_('key'),
tab_rate.rate.as_('val'),
))
return tabparts
# end ChartPoint

16
diagram.xml Normal file
View file

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<tryton>
<data depends="diagram">
<!-- views -->
<record model="ir.ui.view" id="graph_view_form">
<field name="model">diagram.graphdef</field>
<field name="inherit" ref="diagram.graph_view_form"/>
<field name="name">graph_form</field>
</record>
</data>
</tryton>

View file

@ -86,6 +86,10 @@ msgctxt "view:investment.asset:"
msgid "Currency and Units"
msgstr "Währung und Einheiten"
msgctxt "view:investment.asset:"
msgid "Gain and Loss"
msgstr "Gewinn und Verlust"
msgctxt "view:investment.asset:"
msgid "Identifiers"
msgstr "Bezeichner"
@ -115,8 +119,8 @@ msgid "Currency"
msgstr "Währung"
msgctxt "field:investment.asset,currency_digits:"
msgid "Currency Digits"
msgstr "Nachkommastellen Währung"
msgid "Digits"
msgstr "Nachkommastellen"
msgctxt "field:investment.asset,product:"
msgid "Product"
@ -162,10 +166,22 @@ msgctxt "field:investment.asset,rates:"
msgid "Rates"
msgstr "Kurse"
msgctxt "field:investment.asset,name:"
msgid "Name"
msgstr "Name"
msgctxt "field:investment.asset,rate:"
msgid "Current Rate"
msgstr "aktueller Kurs"
msgctxt "field:investment.asset,date:"
msgid "Date"
msgstr "Datum"
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"
@ -178,9 +194,49 @@ msgctxt "field:investment.asset,updttime:"
msgid "Time"
msgstr "Zeitpunkt"
msgctxt "field:investment.asset,updtneeded:"
msgid "Course update needed"
msgstr "Kursaktualisierung nötig"
msgctxt "field:investment.asset,nextupdate:"
msgid "Next Update"
msgstr "nächste Aktualisierung"
msgctxt "field:investment.asset,change_day1:"
msgid "Previous Day"
msgstr "Vortag"
msgctxt "help:investment.asset,change_day1:"
msgid "percentage change in value compared to the previous day"
msgstr "prozentuale Wertänderung zum Vortag"
msgctxt "field:investment.asset,change_month1:"
msgid "1 Month"
msgstr "1 Monat"
msgctxt "help:investment.asset,change_month1:"
msgid "percentage change in value compared to last month"
msgstr "prozentuale Wertänderung zum letzten Monat"
msgctxt "field:investment.asset,change_month3:"
msgid "3 Months"
msgstr "3 Monate"
msgctxt "help:investment.asset,change_month3:"
msgid "percentage change in value during 3 months"
msgstr "Prozentuale Wertänderung während 3 Monate"
msgctxt "field:investment.asset,change_month6:"
msgid "6 Months"
msgstr "6 Monate"
msgctxt "help:investment.asset,change_month6:"
msgid "percentage change in value during 6 months"
msgstr "Prozentuale Wertänderung während 6 Monate"
msgctxt "field:investment.asset,change_month12:"
msgid "1 Year"
msgstr "1 Jahr"
msgctxt "help:investment.asset,change_month12:"
msgid "percentage change in value during 1 year"
msgstr "Prozentuale Wertänderung während 1 Jahr"
#####################
@ -393,3 +449,15 @@ msgstr "Wertpapierkennnummer (WKN)"
msgctxt "selection:product.identifier,type:"
msgid "Stock market symbol"
msgstr "Börsensymbol"
####################
# diagram.graphdef #
####################
msgctxt "view:diagram.graphdef:"
msgid "Asset"
msgstr "Vermögenswert"
msgctxt "field:diagram.graphdef,asset:"
msgid "Asset"
msgstr "Vermögenswert"

View file

@ -58,6 +58,10 @@ msgctxt "view:investment.asset:"
msgid "Currency and Units"
msgstr "Currency and Units"
msgctxt "view:investment.asset:"
msgid "Gain and Loss"
msgstr "Gain and Loss"
msgctxt "view:investment.asset:"
msgid "Identifiers"
msgstr "Identifiers"
@ -87,8 +91,8 @@ msgid "Currency"
msgstr "Currency"
msgctxt "field:investment.asset,currency_digits:"
msgid "Currency Digits"
msgstr "Currency Digits"
msgid "Digits"
msgstr "Digits"
msgctxt "field:investment.asset,product:"
msgid "Product"
@ -134,10 +138,22 @@ msgctxt "field:investment.asset,rates:"
msgid "Rates"
msgstr "Rates"
msgctxt "field:investment.asset,name:"
msgid "Name"
msgstr "Name"
msgctxt "field:investment.asset,rate:"
msgid "Current Rate"
msgstr "Current Rate"
msgctxt "field:investment.asset,date:"
msgid "Date"
msgstr "Date"
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"
@ -150,9 +166,49 @@ msgctxt "field:investment.asset,updttime:"
msgid "Time"
msgstr "Time"
msgctxt "field:investment.asset,updtneeded:"
msgid "Course update needed"
msgstr "Course update needed"
msgctxt "field:investment.asset,nextupdate:"
msgid "Next Update"
msgstr "Next Update"
msgctxt "field:investment.asset,change_day1:"
msgid "Previous Day"
msgstr "Previous Day"
msgctxt "help:investment.asset,change_day1:"
msgid "percentage change in value compared to the previous day"
msgstr "percentage change in value compared to the previous day"
msgctxt "field:investment.asset,change_month1:"
msgid "1 Month"
msgstr "1 Month"
msgctxt "help:investment.asset,change_month1:"
msgid "percentage change in value compared to last month"
msgstr "percentage change in value compared to last month"
msgctxt "field:investment.asset,change_month3:"
msgid "3 Months"
msgstr "3 Months"
msgctxt "help:investment.asset,change_month3:"
msgid "percentage change in value during 3 months"
msgstr "percentage change in value during 3 months"
msgctxt "field:investment.asset,change_month6:"
msgid "6 Months"
msgstr "6 Months"
msgctxt "help:investment.asset,change_month6:"
msgid "percentage change in value during 6 months"
msgstr "percentage change in value during 6 months"
msgctxt "field:investment.asset,change_month12:"
msgid "1 Year"
msgstr "1 Year"
msgctxt "help:investment.asset,change_month12:"
msgid "percentage change in value during 1 year"
msgstr "percentage change in value during 1 year"
msgctxt "model:investment.source,name:"
msgid "Online Source"
@ -350,3 +406,11 @@ msgctxt "selection:product.identifier,type:"
msgid "National Securities Identifying Number (NSIN)"
msgstr "National Securities Identifying Number (NSIN)"
msgctxt "selection:product.identifier,type:"
msgid "Stock market symbol"
msgstr "Stock market symbol"
msgctxt "view:diagram.graphdef:"
msgid "Asset"
msgstr "Asset"

View file

@ -30,6 +30,7 @@ sel_rgxdatefmt = [
('%d.%m.%Y', 'dd.mm.yyyy'),
('%m/%d/%Y', 'mm/dd/yyyy'),
('%Y-%m-%d', 'yyyy-mm-dd'),
('%b %d %Y', 'mon dd yyyy'),
]
fields_check = ['url', 'nsin', 'isin', 'symbol', 'text', 'http_state', \

View file

@ -16,6 +16,35 @@ full copyright notices and license terms. -->
<field name="rgxident">WKN:.* ISIN: ([A-Z,0-9]+).*</field>
<field name="rgxidtype">isin</field>
</record>
<record model="investment.source" id="web_finanzen_fonds">
<field name="name">www.finanzen.net - Fonds</field>
<field name="url">https://www.finanzen.net/fonds/${isin}/tgt</field>
<field name="nohtml" eval="True"/>
<field name="rgxdate">\n\*\*Kursdatum\*\* (\d+\.\d+\.\d+).*\n</field>
<field name="rgxdatefmt">%d.%m.%Y</field>
<field name="rgxrate">\n\*\*Kurs\*\* (\d+,\d+) EUR.*\n</field>
<field name="rgxdecimal">,</field>
<field name="rgxident">WKN:.* ISIN: ([A-Z,0-9]+).*</field>
<field name="rgxidtype">isin</field>
</record>
<record model="investment.source" id="web_finanzen_rohstoffe">
<field name="name">www.finanzen.net - Rohstoffe</field>
<field name="url">https://www.finanzen.net/rohstoffe/${symbol}</field>
<field name="nohtml" eval="True"/>
<field name="rgxdate">\nKurszeit (\d+\.\d+\.\d+) \d+:\d+:\d+.*\n</field>
<field name="rgxdatefmt">%d.%m.%Y</field>
<field name="rgxrate">\nKurs ([\d+\.]*\d+,\d+) USD\n</field>
<field name="rgxdecimal">,</field>
</record>
<record model="investment.source" id="web_markets_ft_com">
<field name="name">Financial Times UK</field>
<field name="url">https://markets.ft.com/data/etfs/tearsheet/summary?s=${symbol}</field>
<field name="nohtml" eval="True"/>
<field name="rgxdate">Data delayed at least 15 minutes, as of (.*) \d+:\d+ GMT\.</field>
<field name="rgxdatefmt">%b %d %Y</field>
<field name="rgxrate">Price\D+([\d,]*\d+\.\d+)</field>
<field name="rgxdecimal">.</field>
</record>
</data>
</tryton>

View file

@ -8,7 +8,7 @@ from trytond.pool import Pool
from trytond.modules.company.tests import create_company
from trytond.transaction import Transaction
from decimal import Decimal
from datetime import time, date
from datetime import time, date, datetime
class AssetTestCase(ModuleTestCase):
@ -61,7 +61,7 @@ class AssetTestCase(ModuleTestCase):
'currency_digits': 4,
'uom': product.default_uom.id,
}])
self.assertEqual(asset.rec_name, '%s [usd/%s]' % (
self.assertEqual(asset.rec_name, '%s - - usd/%s [-]' % (
product.rec_name,
asset.uom.rec_name,
))
@ -84,6 +84,393 @@ class AssetTestCase(ModuleTestCase):
company=company,
product = product)
@with_transaction()
def test_asset_rec_name(self):
""" create asset
"""
Asset = Pool().get('investment.asset')
company = self.prep_asset_company()
product = self.prep_asset_product(
name='Product 1',
description='some asset')
asset = self.prep_asset_item(
company=company,
product = product)
self.assertEqual(asset.rec_name, 'Product 1 - - usd/Unit [-]')
Asset.write(*[
[asset],
{
'rates': [('create', [{
'date': date(2022, 5, 15),
'rate': Decimal('2.45'),
}])],
}])
self.assertEqual(asset.rec_name, 'Product 1 - 2.4500 usd/Unit [05/15/2022]')
self.assertEqual(Asset.search_count([('name', '=', 'Product 1')]), 1)
@with_transaction()
def test_asset_percentages_dateselect1(self):
""" create asset, add rates, check selection of
specific date - fixed date
"""
Asset = Pool().get('investment.asset')
cursor = Transaction().connection.cursor()
company = self.prep_asset_company()
product = self.prep_asset_product(
name='Product 1',
description='some asset')
asset1 = self.prep_asset_item(
company=company,
product = product)
self.assertEqual(asset1.rec_name, 'Product 1 - - usd/Unit [-]')
Asset.write(*[
[asset1],
{
'rates': [('create', [{
'date': date(2022, 5, 15),
'rate': Decimal('2.45'),
}, {
'date': date(2022, 5, 16),
'rate': Decimal('2.6'),
}, {
'date': date(2022, 5, 12),
'rate': Decimal('2.0'),
}, {
'date': date(2022, 5, 3),
'rate': Decimal('3.6'),
}])],
},
])
self.assertEqual(asset1.rec_name, 'Product 1 - 2.6000 usd/Unit [05/16/2022]')
self.assertEqual(len(asset1.rates), 4)
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 15))
self.assertEqual(asset1.rates[2].date, date(2022, 5, 12))
self.assertEqual(asset1.rates[3].date, date(2022, 5, 3))
# query fixed date
tab_percent = Asset.get_percentage_sql(['day1'], select_date = False)
query = tab_percent.select(
tab_percent.id,
tab_percent.date,
tab_percent.day1,
where=(tab_percent.date==date(2022, 5, 16)) & \
(tab_percent.id==asset1.id),
)
cursor.execute(*query)
records = cursor.fetchall()
# there should be one record, three colums
self.assertEqual(len(records), 1)
self.assertEqual(len(records[0]), 3)
self.assertEqual(records[0][0], asset1.id)
self.assertEqual(records[0][1], date(2022, 5, 16))
self.assertEqual(records[0][2].quantize(Decimal('0.01')), Decimal('6.12'))
@with_transaction()
def test_asset_percentages_dateselect2(self):
""" create asset, add rates, check selection of
specific date - date-column
"""
pool = Pool()
Asset = pool.get('investment.asset')
Rate = pool.get('investment.rate')
tab_rate = Rate.__table__()
cursor = Transaction().connection.cursor()
company = self.prep_asset_company()
product = self.prep_asset_product(
name='Product 1',
description='some asset')
asset1 = self.prep_asset_item(
company=company,
product = product)
asset2 = self.prep_asset_item(
company=company,
product = product)
Asset.write(*[
[asset1],
{
'rates': [('create', [{
'date': date(2022, 5, 15),
'rate': Decimal('2.45'),
}, {
'date': date(2022, 5, 16),
'rate': Decimal('2.6'),
}, {
'date': date(2022, 5, 12),
'rate': Decimal('2.0'),
}, {
'date': date(2022, 5, 3),
'rate': Decimal('3.6'),
}])],
},
[asset2],
{
'rates': [('create', [{
'date': date(2022, 5, 17),
'rate': Decimal('1.5'),
}, {
'date': date(2022, 5, 16),
'rate': Decimal('2.0'),
}, {
'date': date(2022, 5, 15),
'rate': Decimal('2.5'),
}, {
'date': date(2022, 5, 14),
'rate': Decimal('3.0'),
}, {
'date': date(2022, 5, 13),
'rate': Decimal('3.5'),
}, {
'date': date(2022, 5, 12),
'rate': Decimal('4.0'),
}, {
'date': date(2022, 5, 11),
'rate': Decimal('4.5'),
}, ])],
},
])
self.assertEqual(asset1.rec_name, 'Product 1 - 2.6000 usd/Unit [05/16/2022]')
self.assertEqual(len(asset1.rates), 4)
self.assertEqual(asset2.rec_name, 'Product 1 - 1.5000 usd/Unit [05/17/2022]')
self.assertEqual(len(asset2.rates), 7)
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 15))
self.assertEqual(asset1.rates[2].date, date(2022, 5, 12))
self.assertEqual(asset1.rates[3].date, date(2022, 5, 3))
# query date-column
tab_percent = Asset.get_percentage_sql(['day1'], select_date = False)
query = tab_rate.join(tab_percent,
condition=(tab_percent.id_rate == tab_rate.id)
).select(
tab_percent.id,
tab_percent.date,
tab_percent.day1,
where=tab_percent.id==asset1.id,
order_by=[tab_percent.date.asc]
)
cursor.execute(*query)
records = cursor.fetchall()
# there should be 4x records, three colums
self.assertEqual(len(records), 4)
self.assertEqual(len(records[0]), 3)
self.assertEqual(records[0][0], asset1.id)
self.assertEqual(records[0][1], date(2022, 5, 3))
self.assertEqual(records[0][2], None)
self.assertEqual(records[1][0], asset1.id)
self.assertEqual(records[1][1], date(2022, 5, 12))
self.assertEqual(records[1][2], None)
self.assertEqual(records[2][0], asset1.id)
self.assertEqual(records[2][1], date(2022, 5, 15))
self.assertEqual(records[2][2].quantize(Decimal('0.01')), Decimal('22.5'))
self.assertEqual(records[3][0], asset1.id)
self.assertEqual(records[3][1], date(2022, 5, 16))
self.assertEqual(records[3][2].quantize(Decimal('0.01')), Decimal('6.12'))
@with_transaction()
def test_asset_percentages_daterange(self):
""" create asset, add rates, check selection of
value
"""
Asset = Pool().get('investment.asset')
company = self.prep_asset_company()
product = self.prep_asset_product(
name='Product 1',
description='some asset')
asset1 = self.prep_asset_item(
company=company,
product = product)
asset2 = self.prep_asset_item(
company=company,
product = product)
self.assertEqual(asset1.rec_name, 'Product 1 - - usd/Unit [-]')
self.assertEqual(asset2.rec_name, 'Product 1 - - usd/Unit [-]')
Asset.write(*[
[asset1],
{
'rates': [('create', [{
'date': date(2022, 5, 15),
'rate': Decimal('2.45'),
}, {
'date': date(2022, 5, 16),
'rate': Decimal('2.6'),
}])],
},
[asset2],
{
'rates': [('create', [{
'date': date(2022, 5, 14),
'rate': Decimal('5.75'),
}, {
'date': date(2022, 5, 15),
'rate': Decimal('5.25'),
}])],
},
])
self.assertEqual(asset1.rec_name, 'Product 1 - 2.6000 usd/Unit [05/16/2022]')
self.assertEqual(asset2.rec_name, 'Product 1 - 5.2500 usd/Unit [05/15/2022]')
self.assertEqual(asset1.change_day1, Decimal('6.12'))
self.assertEqual(asset2.change_day1, Decimal('-8.7'))
self.assertEqual(asset1.change_month1, None)
self.assertEqual(asset2.change_month1, None)
self.assertEqual(asset1.change_month3, None)
self.assertEqual(asset2.change_month3, None)
self.assertEqual(asset1.change_month6, None)
self.assertEqual(asset2.change_month6, None)
self.assertEqual(asset1.change_month12, None)
self.assertEqual(asset2.change_month12, None)
# check ordering
assets = Asset.search([
('change_day1', '!=', Decimal('0.0')),
], order=[('change_day1', 'ASC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].change_day1, Decimal('-8.7'))
self.assertEqual(assets[1].change_day1, Decimal('6.12'))
assets = Asset.search([
('change_day1', '!=', Decimal('0.0')),
], order=[('change_day1', 'DESC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].change_day1, Decimal('6.12'))
self.assertEqual(assets[1].change_day1, Decimal('-8.7'))
# check 5-day-range
# four days
Asset.write(*[
[asset1],
{
'rates': [('write', [asset1.rates[1]], {
'date': date(2022, 5, 12),
})],
}])
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 12))
self.assertEqual(asset1.change_day1, Decimal('6.12'))
# five days
Asset.write(*[
[asset1],
{
'rates': [('write', [asset1.rates[1]], {
'date': date(2022, 5, 11),
})],
}])
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 11))
self.assertEqual(asset1.change_day1, Decimal('6.12'))
# six days
Asset.write(*[
[asset1],
{
'rates': [('write', [asset1.rates[1]], {
'date': date(2022, 5, 10),
})],
}])
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 10))
self.assertEqual(asset1.change_day1, None)
@with_transaction()
def test_asset_percentges_values(self):
""" create asset, add rates, check percentages
"""
Asset = Pool().get('investment.asset')
company = self.prep_asset_company()
product = self.prep_asset_product(
name='Product 1',
description='some asset')
asset1 = self.prep_asset_item(
company=company,
product = product)
self.assertEqual(asset1.rec_name, 'Product 1 - - usd/Unit [-]')
Asset.write(*[
[asset1],
{
'rates': [('create', [{
'date': date(2022, 5, 15),
'rate': Decimal('2.45'),
}, {
'date': date(2022, 5, 16),
'rate': Decimal('2.6'),
}, {
'date': date(2022, 4, 14),
'rate': Decimal('2.2'),
}, {
'date': date(2022, 2, 14),
'rate': Decimal('2.8'),
},])],
}])
self.assertEqual(asset1.rec_name, 'Product 1 - 2.6000 usd/Unit [05/16/2022]')
self.assertEqual(len(asset1.rates), 4)
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 15))
self.assertEqual(asset1.rates[2].date, date(2022, 4, 14))
self.assertEqual(asset1.rates[3].date, date(2022, 2, 14))
self.assertEqual(asset1.change_day1, Decimal('6.12'))
self.assertEqual(asset1.change_month1, Decimal('18.18'))
self.assertEqual(asset1.change_month3, Decimal('-7.14'))
self.assertEqual(asset1.change_month6, None)
self.assertEqual(asset1.change_month12, None)
# call order-functions
Asset.search([], order=[('change_day1', 'ASC')])
Asset.search([], order=[('change_month1', 'ASC')])
Asset.search([], order=[('change_month3', 'ASC')])
Asset.search([], order=[('change_month6', 'ASC')])
Asset.search([], order=[('change_month12', 'ASC')])
# searcher
self.assertEqual(
Asset.search_count([('change_day1', '>', Decimal('6.1'))]),
1)
self.assertEqual(
Asset.search_count([('change_day1', '>', Decimal('6.15'))]),
0)
self.assertEqual(
Asset.search_count([('change_day1', '=', Decimal('6.12'))]),
1)
self.assertEqual(
Asset.search_count([('change_month1', '>', Decimal('18.0'))]),
1)
self.assertEqual(
Asset.search_count([('change_month1', '>', Decimal('18.18'))]),
0)
self.assertEqual(
Asset.search_count([('change_month1', '=', Decimal('18.18'))]),
1)
self.assertEqual(
Asset.search_count([('change_month3', '=', Decimal('-7.14'))]),
1)
self.assertEqual(
Asset.search_count([('change_month6', '=', None)]),
1)
@with_transaction()
def test_asset_check_onlinesource_onoff(self):
""" create asset, switch online-source on/off
@ -106,7 +493,7 @@ class AssetTestCase(ModuleTestCase):
}])
self.assertEqual(asset.updtsource, None)
self.assertEqual(asset.updttime, None)
self.assertEqual(asset.updttime, time(14,0))
asset.updtsource = o_source
asset.updttime = time(10, 45)
@ -146,28 +533,23 @@ class AssetTestCase(ModuleTestCase):
'updtsource': o_source.id,
'updttime': time(10, 45),
}])
self.assertEqual(asset.updtsource.rec_name, 'Source 1')
self.assertEqual(asset.updttime, time(10, 45))
self.assertEqual(len(asset.rates), 0)
with Transaction().set_context({
'qdate': date(2022, 10, 15),
'qtime': time(10, 30),
'qdate': date(2022, 10, 14),
}):
# no rates exists - wait for 10:45
self.assertEqual(asset.updtneeded, True)
# re-read to make context work
asset2, = Asset.browse([asset.id])
self.assertEqual(asset2.updtsource.rec_name, 'Source 1')
self.assertEqual(asset2.updttime, time(10, 45))
self.assertEqual(len(asset2.rates), 0)
self.assertEqual(asset2.nextupdate, datetime(2022, 10, 15, 10, 45))
self.assertEqual(
Asset.search_count([('updtneeded', '=', True)]),
Asset.search_count([('nextupdate', '<', datetime(2022, 10, 15, 10, 45))]),
0)
with Transaction().set_context({
'qdate': date(2022, 10, 15),
'qtime': time(10, 46),
}):
# no rates exists - run at 10:46
self.assertEqual(asset.updtneeded, True)
self.assertEqual(
Asset.search_count([('updtneeded', '=', True)]),
Asset.search_count([('nextupdate', '>=', datetime(2022, 10, 15, 10, 45))]),
1)
# add rate at yesterday
@ -181,24 +563,18 @@ class AssetTestCase(ModuleTestCase):
}])
self.assertEqual(len(asset.rates), 1)
with Transaction().set_context({
'qdate': date(2022, 10, 15),
'qtime': time(10, 30),
}):
# 1x rate exists - run at 10:30
self.assertEqual(asset.updtneeded, True)
self.assertEqual(
Asset.search_count([('updtneeded', '=', True)]),
0)
asset2, = Asset.browse([asset.id])
self.assertEqual(asset.updtsource.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, 14))
self.assertEqual(asset.nextupdate, datetime(2022, 10, 15, 10, 45))
with Transaction().set_context({
'qdate': date(2022, 10, 15),
'qtime': time(10, 46),
}):
# 1x rate exists yesterday - run at 10:46
self.assertEqual(asset.updtneeded, True)
self.assertEqual(
Asset.search_count([('updtneeded', '=', True)]),
Asset.search_count([('nextupdate', '<', datetime(2022, 10, 15, 10, 45))]),
0)
self.assertEqual(
Asset.search_count([('nextupdate', '>=', datetime(2022, 10, 15, 10, 45))]),
1)
# add rate at today
@ -212,15 +588,19 @@ class AssetTestCase(ModuleTestCase):
}])
self.assertEqual(len(asset.rates), 2)
with Transaction().set_context({
'qdate': date(2022, 10, 15),
'qtime': time(10, 47),
}):
# 1x rate exists today - run at 10:47
self.assertEqual(asset.updtneeded, True)
asset2, = Asset.browse([asset.id])
self.assertEqual(asset2.updtsource.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, 15))
self.assertEqual(asset2.nextupdate, datetime(2022, 10, 16, 10, 45))
self.assertEqual(
Asset.search_count([('updtneeded', '=', True)]),
Asset.search_count([('nextupdate', '<', datetime(2022, 10, 15, 10, 45))]),
0)
self.assertEqual(
Asset.search_count([('nextupdate', '>=', datetime(2022, 10, 15, 10, 45))]),
1)
@with_transaction()
def test_asset_indentifiers(self):
@ -280,6 +660,16 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(Asset.search_count([('isin', '=', 'XC0009655157')]), 1)
self.assertEqual(Asset.search_count([('secsymb', '=', '1472977')]), 1)
self.assertEqual(Asset.search_count([('rec_name', '=', '965515')]), 1)
self.assertEqual(Asset.search_count([('rec_name', '=', 'XC0009655157')]), 1)
self.assertEqual(Asset.search_count([('rec_name', '=', '1472977')]), 1)
self.assertEqual(Asset.search_count([('name', '=', '965515')]), 1)
self.assertEqual(Asset.search_count([('name', '=', 'XC0009655157')]), 1)
self.assertEqual(Asset.search_count([('name', '=', '1472977')]), 1)
self.assertEqual(Asset.search_count([('name', '=', 'Product unit')]), 1)
self.assertEqual(Asset.search_count([
('wkn', 'ilike', '9655%'),
]), 1)
@ -291,6 +681,36 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(asset2.isin, 'XC0009653103')
self.assertEqual(asset2.secsymb, '1431157')
# order wkn
assets = Asset.search([], order=[('wkn', 'ASC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].wkn, '965310')
self.assertEqual(assets[1].wkn, '965515')
assets = Asset.search([], order=[('wkn', 'DESC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].wkn, '965515')
self.assertEqual(assets[1].wkn, '965310')
# order isin
assets = Asset.search([], order=[('isin', 'ASC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].isin, 'XC0009653103')
self.assertEqual(assets[1].isin, 'XC0009655157')
assets = Asset.search([], order=[('wkn', 'DESC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].isin, 'XC0009655157')
self.assertEqual(assets[1].isin, 'XC0009653103')
# order secsymb
assets = Asset.search([], order=[('secsymb', 'ASC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].secsymb, '1431157')
self.assertEqual(assets[1].secsymb, '1472977')
assets = Asset.search([], order=[('wkn', 'DESC')])
self.assertEqual(len(assets), 2)
self.assertEqual(assets[0].secsymb, '1472977')
self.assertEqual(assets[1].secsymb, '1431157')
@with_transaction()
def test_asset_check_product_update(self):
""" check update of product on asset

View file

@ -8,7 +8,7 @@ from trytond.pool import Pool
from trytond.modules.company.tests import create_company
from trytond.transaction import Transaction
from decimal import Decimal
from datetime import time, date
from datetime import time, date, datetime
from unittest.mock import MagicMock
from requests import Response
import requests
@ -66,10 +66,18 @@ class SourceTestCase(ModuleTestCase):
{
'updtsource': osource.id,
}])
self.assertEqual(asset.wkn, '965515')
self.assertEqual(asset.isin, 'XC0009655157')
self.assertEqual(asset.secsymb, '1472977')
self.assertEqual(asset.updtsource.rec_name, 'Source 1')
with Transaction().set_context({
'qdate': date(2022, 10, 1),
'qdatetime': datetime(2022, 10, 2, 10, 0, 0),
}):
asset2, = Asset.browse([asset])
self.assertEqual(asset2.wkn, '965515')
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(asset2.nextupdate, datetime(2022, 10, 2, 14, 0))
self.assertEqual(len(asset.rates), 0)
# fake server-response

View file

@ -1,11 +1,13 @@
[tryton]
version=6.0.0
version=6.0.6
depends:
ir
res
company
currency
product
extras_depends:
diagram
xml:
icon.xml
message.xml
@ -15,5 +17,6 @@ xml:
sources_def.xml
update_wiz.xml
rate.xml
diagram.xml
menu.xml
cron.xml

View file

@ -1 +1 @@
diagram;6.0.7;6.0.999;mds

View file

@ -2,24 +2,48 @@
<!-- This file is part of the investment-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<form col="4">
<form col="6">
<label name="product" />
<field name="product" />
<field name="product" colspan="3"/>
<label name="rate" />
<field name="rate" symbol="currency"/>
<separator id="sepunits" colspan="4" string="Currency and Units"/>
<label id="labdate" string=" "/>
<label name="nextupdate" colspan="2"/>
<field name="nextupdate"/>
<label name="date" />
<field name="date"/>
<separator id="sepperc" colspan="6" string="Gain and Loss"/>
<label name="change_day1" />
<field name="change_day1" />
<label name="change_month1" />
<field name="change_month1" />
<label name="change_month3" />
<field name="change_month3" />
<label name="change_month6" />
<field name="change_month6" />
<label name="change_month12" />
<field name="change_month12" />
<newline/>
<separator id="sepunits" colspan="6" string="Currency and Units"/>
<label name="currency" />
<field name="currency" />
<label name="currency_digits" />
<field name="currency_digits" />
<newline/>
<label name="uom" />
<field name="uom" />
<label name="product_uom" />
<field name="product_uom" />
<newline/>
<notebook>
<notebook colspan="6">
<page id="pgids" col="4" string="Identifiers">
<label name="wkn" />
<field name="wkn" />

View file

@ -3,11 +3,15 @@
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<tree>
<field name="rec_name"/>
<field name="isin"/>
<field name="secsymb"/>
<field name="wkn"/>
<field name="rate"/>
<field name="name" expand="2"/>
<field name="isin" expand="1"/>
<field name="wkn" expand="1"/>
<field name="change_day1" />
<field name="change_month1" />
<field name="change_month3" />
<field name="change_month6" />
<field name="date" expand="1"/>
<field name="rate" expand="1"/>
<field name="currency"/>
<field name="uom"/>
<field name="uom" />
</tree>

14
view/graph_form.xml Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<data>
<xpath expr="/form/separator[@name='currency']" position="before">
<separator name="asset" colspan="6" string="Asset"/>
<label name="asset"/>
<field name="asset"/>
<newline/>
</xpath>
</data>