asset: abfragezeit für prozente optimiert

This commit is contained in:
Frederik Jaeckel 2023-01-07 16:26:22 +01:00
parent 9064ac2980
commit 25fd69be0c
22 changed files with 114 additions and 242 deletions

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

174
asset.py
View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.
@ -11,7 +11,7 @@ from trytond.report import Report
from decimal import Decimal from decimal import Decimal
from datetime import time from datetime import time
from sql.functions import CurrentDate, CurrentTimestamp, Round, Extract from sql.functions import CurrentDate, CurrentTimestamp, Round, Extract
from sql.conditionals import Case, Coalesce from sql.conditionals import Case, Coalesce, NullIf
from sql import Literal from sql import Literal
from .diagram import Concat2 from .diagram import Concat2
@ -116,7 +116,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
'get_percentage_change', searcher='search_percentage') 'get_percentage_change', searcher='search_percentage')
change_symbol = fields.Function(fields.Many2One(string='Symbol', change_symbol = fields.Function(fields.Many2One(string='Symbol',
readonly=True, model_name='investment.rate'), readonly=True, model_name='investment.rate'),
'get_percentage_change') 'get_rate_data')
@classmethod @classmethod
def __register__(cls, module_name): def __register__(cls, module_name):
@ -317,6 +317,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
tab_asset.id, tab_asset.id,
Round(tab_rate.rate, tab_asset.currency_digits).as_('rate'), Round(tab_rate.rate, tab_asset.currency_digits).as_('rate'),
tab_rate.date, tab_rate.date,
tab_rate.id.as_('id_rate'),
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],
) )
@ -338,12 +339,16 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
result = {x:{y.id: None for y in assets} for x in names} result = {x:{y.id: None for y in assets} for x in names}
for record in records: for record in records:
(id1, rate1, date1) = record (id1, rate1, date1, id_rate) = record
asset = Asset2(id1) asset = Asset2(id1)
exp = Decimal(Decimal(1) / 10 ** (asset.currency_digits or 4)) exp = Decimal(Decimal(1) / 10 ** (asset.currency_digits or 4))
values = {'rate': record[1].quantize(exp), 'date': record[2]} values = {
'rate': record[1].quantize(exp),
'date': record[2],
'change_symbol': id_rate,
}
for name in names: for name in names:
result[name][record[0]] = values[name] result[name][record[0]] = values[name]
@ -403,78 +408,48 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
return [query] return [query]
@classmethod @classmethod
def get_percentage_sql(cls, name_lst, select_date=True): def get_percentage_sql(cls, days=0, asset_ids=None):
""" get table for percentages and dates, """ get table for percentages and dates,
generate adapted query days: delta-days to past to select percent-value
select_date: True = select newest date 0=yesterday, 30=last month, ...
""" """
pool = Pool() pool = Pool()
Rate = pool.get('investment.rate') Rate = pool.get('investment.rate')
Asset = pool.get('investment.asset') Asset2 = pool.get('investment.asset')
tab_asset = Asset.__table__() tab_asset = Asset2.__table__()
tab_rate_today = Rate.__table__() tab_rate1 = Rate.__table__()
tab_rate2 = 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 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_date = context.get('qdate', CurrentDate())
query_today = tab_asset.join(tab_rate_today, where_asset = tab_rate1.date <= query_date
condition=tab_asset.id==tab_rate_today.asset, if isinstance(asset_ids, list):
where_asset &= tab_asset.id.in_(asset_ids)
tab_today = tab_asset.join(tab_rate1,
condition=tab_asset.id==tab_rate1.asset,
).select( ).select(
tab_asset.id, tab_asset.id,
tab_rate_today.id.as_('id_rate'), tab_rate1.date,
tab_rate_today.date, tab_rate1.rate,
tab_rate_today.rate, distinct_on=[tab_asset.id],
order_by=[tab_asset.id, tab_rate1.date.desc],
where=where_asset,
) )
# limit to newest date until 'query_date' days_diff = days + 5
if select_date == True: query = tab_today.join(tab_rate2,
query_today.distinct_on=[tab_asset.id] condition=(tab_today.id==tab_rate2.asset) & \
query_today.order_by=[tab_asset.id, tab_rate_today.date.desc] (tab_today.date > (tab_rate2.date + days)) & \
query_today.where=tab_rate_today.date <= query_date (tab_today.date <= (tab_rate2.date + days_diff)),
type_ = 'LEFT OUTER',
# create join for requested fields, to minimize database-load ).select(
query = query_today tab_today.id,
for name in name_lst: tab_today.date,
query = query.join(rate_tab[name]['tab'], tab_today.rate,
# select newest date from <period> until 5 days older (tab_today.rate * 100.0 / NullIf(tab_rate2.rate, 0.00) - 100.0).as_('percent'),
condition=(query_today.id==rate_tab[name]['tab'].asset) & \ distinct_on=[tab_today.id],
(query_today.date > (rate_tab[name]['tab'].date + Literal(rate_tab[name]['day']))) & \ order_by=[tab_today.id, tab_today.date.desc]
(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 return query
@ -483,11 +458,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" order day1 """ order day1
""" """
Assert = Pool().get('investment.asset') Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['day1']) tab_asset = Asset.get_percentage_sql(days=0)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.day1, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id==table.id,
) )
return [query] return [query]
@ -497,11 +472,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month1']) tab_asset = Asset.get_percentage_sql(days=30)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.month1, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id==table.id,
) )
return [query] return [query]
@ -511,11 +486,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month3']) tab_asset = Asset.get_percentage_sql(days=90)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.month3, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id==table.id,
) )
return [query] return [query]
@ -525,11 +500,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month6']) tab_asset = Asset.get_percentage_sql(days=180)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.month6, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id==table.id,
) )
return [query] return [query]
@ -539,11 +514,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Assert = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(['month12']) tab_asset = Asset.get_percentage_sql(days=365)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.month12, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id==table.id,
) )
return [query] return [query]
@ -554,10 +529,16 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" """
Operator = fields.SQL_OPERATORS[clause[1]] Operator = fields.SQL_OPERATORS[clause[1]]
field_name = clause[0][len('change_'):] field_name = clause[0][len('change_'):]
tab_percent = cls.get_percentage_sql([field_name]) tab_percent = cls.get_percentage_sql(days={
'day1': 0,
'month1': 30,
'month3': 90,
'month6': 180,
'month12': 365,
}[field_name])
query = tab_percent.select(tab_percent.id, query = tab_percent.select(tab_percent.id,
where=Operator(Round(getattr(tab_percent, field_name), 2), where=Operator(Round(tab_percent.percent, 2),
clause[2])) clause[2]))
return [('id', 'in', query)] return [('id', 'in', query)]
@ -567,29 +548,26 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" """
cursor = Transaction().connection.cursor() cursor = Transaction().connection.cursor()
name_lst = [x[len('change_'):] for x in names
if x != 'change_symbol']
tab_percent = cls.get_percentage_sql(name_lst)
query = tab_percent.select(
tab_percent.id,
tab_percent.id_rate,
*[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} result = {x:{y.id: None for y in assets} for x in names}
exp = Decimal(Decimal(1) / 10 ** digits_percent) exp = Decimal(Decimal(1) / 10 ** digits_percent)
for record in records:
if 'change_symbol' in names:
result['change_symbol'][record[0]] = record[1]
cnt1 = 2 for x in names:
for x in name_lst: tab_percent = cls.get_percentage_sql(
result['change_%s' % x][record[0]] = record[cnt1].quantize(exp) \ days={
if record[cnt1] is not None else None 'change_day1': 0,
cnt1 += 1 'change_month1': 30,
'change_month3': 90,
'change_month6': 180,
'change_month12': 365,
}[x],
asset_ids=[x.id for x in assets]
)
cursor.execute(*tab_percent)
records = cursor.fetchall()
for record in records:
result[x][record[0]] = record[3].quantize(exp) \
if record[3] is not None else None
return result return result
@classmethod @classmethod

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the cashbook-module from m-ds for Tryton. <!-- This file is part of the cashbook-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>

View file

@ -250,13 +250,15 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(asset1.rates[3].date, date(2022, 5, 3)) self.assertEqual(asset1.rates[3].date, date(2022, 5, 3))
# query fixed date # query fixed date
tab_percent = Asset.get_percentage_sql(['day1'], select_date = False) tab_percent = Asset.get_percentage_sql(days=0)
with Transaction().set_context({
'qdate': date(2022, 5, 16),
}):
query = tab_percent.select( query = tab_percent.select(
tab_percent.id, tab_percent.id,
tab_percent.date, tab_percent.date,
tab_percent.day1, tab_percent.percent,
where=(tab_percent.date==date(2022, 5, 16)) & \ where=tab_percent.id==asset1.id,
(tab_percent.id==asset1.id),
) )
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
@ -268,114 +270,6 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(records[0][1], date(2022, 5, 16)) self.assertEqual(records[0][1], date(2022, 5, 16))
self.assertEqual(records[0][2].quantize(Decimal('0.01')), Decimal('6.12')) 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/u | 05/16/2022')
self.assertEqual(len(asset1.rates), 4)
self.assertEqual(asset2.rec_name, 'Product 1 | 1.5000 usd/u | 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() @with_transaction()
def test_asset_percentages_daterange(self): def test_asset_percentages_daterange(self):
""" create asset, add rates, check selection of """ create asset, add rates, check selection of

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton. # This file is part of the investment-module from m-ds.de for Tryton.
# 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.

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!-- This file is part of the investment-module from m-ds for Tryton. <!-- This file is part of the investment-module from m-ds.de for Tryton.
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. -->
<tryton> <tryton>