asset: spalten tag/monat/3monate... ok + test

This commit is contained in:
Frederik Jaeckel 2022-11-25 21:55:43 +01:00
parent d70e674e58
commit 82c451377c
6 changed files with 377 additions and 177 deletions

339
asset.py
View file

@ -10,7 +10,7 @@ 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 CurrentDate, CurrentTimestamp
from sql.functions import CurrentDate, CurrentTimestamp, Round
from sql.conditionals import Case, Coalesce
from sql import Literal
@ -78,31 +78,31 @@ class Asset(ModelSQL, ModelView):
states={
'readonly': ~Bool(Eval('updtsource')),
}, depends=['updtsource'])
nextupdtate = fields.Function(fields.DateTime(string='Next Update',
nextupdate = fields.Function(fields.DateTime(string='Next Update',
readonly=True),
'get_nextupdtates', searcher='search_nextupdtate')
'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')
'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')
'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')
'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')
'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')
'get_percentage_change', searcher='search_percentage')
@classmethod
def view_attributes(cls):
@ -136,137 +136,10 @@ class Asset(ModelSQL, ModelView):
return 4
@classmethod
def get_percentage_sql(cls, table_asset, name_lst):
""" get table for percentages and dates
generate adapted query
def default_updttime(cls):
""" 14 o'clock UTC
"""
pool = Pool()
Rate = pool.get('investment.rate')
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
# 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 = table_asset.join(tab_rate_today,
condition=table_asset.id==tab_rate_today.asset,
).select(
table_asset.id,
tab_rate_today.date,
tab_rate_today.rate,
distinct_on=[table_asset.id],
order_by=[table_asset.id, tab_rate_today.date.desc],
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 3 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'] + 3))),
type_ = 'LEFT OUTER')
# add select for requested fields to join
select_lst = [
query_today.id,
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]
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],
order_by=order_by_lst,
)
# ~ query = query_today.join(tab_rate_1day,
# ~ # select newest date from yesterday until 3 days old
# ~ condition=(query_today.id==tab_rate_1day.asset) & \
# ~ (query_today.date > tab_rate_1day.date) & \
# ~ (query_today.date < tab_rate_1day.date + Literal(3)),
# ~ type_ = 'LEFT OUTER',
# ~ ).join(tab_rate_1month,
# ~ # select newest date from 1 month ago until +3 days old
# ~ condition=(query_today.id==tab_rate_1month.asset) & \
# ~ (query_today.date > tab_rate_1month.date + Literal(30)) & \
# ~ (query_today.date < tab_rate_1month.date + Literal(33)),
# ~ type_ = 'LEFT OUTER',
# ~ ).select(
# ~ query_today.id,
# ~ query_today.date,
# ~ Case(
# ~ ((tab_rate_1day.rate != None) & (query_today.rate != None) & \
# ~ (tab_rate_1day.rate != Literal(0.0)),
# ~ query_today.rate * Literal(100.0) / tab_rate_1day.rate - Literal(100.0)),
# ~ else_ = None,
# ~ ).as_('day1'),
# ~ Case(
# ~ ((tab_rate_1month.rate != None) & (query_today.rate != None) & \
# ~ (tab_rate_1month.rate != Literal(0.0)),
# ~ query_today.rate * Literal(100.0) / tab_rate_1month.rate - Literal(100.0)),
# ~ else_ = None,
# ~ ).as_('month1'),
# ~ distinct_on=[query_today.id],
# ~ order_by=[
# ~ query_today.id,
# ~ tab_rate_1day.date.desc,
# ~ tab_rate_1month.date.desc,
# ~ ],
# ~ )
return query
@classmethod
def get_percentage_change(cls, assets, names):
""" get percentage per period
"""
pool = Pool()
Asset = pool.get('investment.asset')
tab_asset = Asset.__table__()
cursor = Transaction().connection.cursor()
name_lst = [x[len('change_'):] for x in names]
tab_percent = cls.get_percentage_sql(tab_asset, 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
return time(14, 0)
@classmethod
def get_rate_data(cls, assets, names):
@ -365,6 +238,185 @@ class Asset(ModelSQL, ModelView):
if self.company.currency.id != self.currency.id:
return self.company.currency.id
@classmethod
def get_percentage_sql(cls, name_lst):
""" get table for percentages and dates,
generate adapted query
"""
pool = Pool()
Rate = pool.get('investment.rate')
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
# 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.date,
tab_rate_today.rate,
distinct_on=[tab_asset.id],
order_by=[tab_asset.id, tab_rate_today.date.desc],
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.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]
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],
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
@ -391,7 +443,7 @@ class Asset(ModelSQL, ModelView):
return query
@classmethod
def get_nextupdtates(cls, assets, names):
def get_nextupdates(cls, assets, names):
""" get timestamp of next update
"""
Asset2 = Pool().get('investment.asset')
@ -410,21 +462,19 @@ class Asset(ModelSQL, ModelView):
for record in records:
(id1, updt) = record
r1 = {'nextupdtate': updt}
r1 = {'nextupdate': updt}
for n in names:
result[n][id1] = r1[n]
return result
@classmethod
def search_nextupdtate(cls, names, clause):
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]]
context = Transaction().context
query = tab_updt.select(
tab_updt.id,
@ -539,10 +589,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([
('updttime', '<=', query_time),
('nextupdate', '<=', query_time),
]):
OnlineSource.update_rate(asset)