From 8cfa54f6932af5421b5adc4892f5729e2682733f Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Sat, 7 Jan 2023 16:26:22 +0100 Subject: [PATCH] =?UTF-8?q?asset:=20abfragezeit=20f=C3=BCr=20prozente=20op?= =?UTF-8?q?timiert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __init__.py | 2 +- asset.py | 174 +++++++++++++++++++------------------------- asset.xml | 2 +- cron.py | 2 +- cron.xml | 2 +- diagram.py | 2 +- diagram.xml | 2 +- group.xml | 2 +- icon.xml | 2 +- identifier.py | 2 +- import_wiz.py | 2 +- import_wiz.xml | 2 +- menu.xml | 2 +- message.xml | 2 +- onlinesource.py | 2 +- onlinesource.xml | 2 +- rate.py | 2 +- rate.xml | 2 +- sources_def.xml | 2 +- tests/test_asset.py | 142 +++++------------------------------- update_wiz.py | 2 +- update_wiz.xml | 2 +- 22 files changed, 114 insertions(+), 242 deletions(-) diff --git a/__init__.py b/__init__.py index d0ee2ad..a1e9717 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/asset.py b/asset.py index e0c493e..148585e 100644 --- a/asset.py +++ b/asset.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. @@ -11,7 +11,7 @@ from trytond.report import Report from decimal import Decimal from datetime import time 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 .diagram import Concat2 @@ -116,7 +116,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView): 'get_percentage_change', searcher='search_percentage') change_symbol = fields.Function(fields.Many2One(string='Symbol', readonly=True, model_name='investment.rate'), - 'get_percentage_change') + 'get_rate_data') @classmethod def __register__(cls, module_name): @@ -317,6 +317,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView): tab_asset.id, Round(tab_rate.rate, tab_asset.currency_digits).as_('rate'), tab_rate.date, + tab_rate.id.as_('id_rate'), distinct_on=[tab_asset.id], 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} for record in records: - (id1, rate1, date1) = record + (id1, rate1, date1, id_rate) = record asset = Asset2(id1) 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: result[name][record[0]] = values[name] @@ -403,78 +408,48 @@ class Asset(SymbolMixin, ModelSQL, ModelView): return [query] @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, - generate adapted query - select_date: True = select newest date + days: delta-days to past to select percent-value + 0=yesterday, 30=last month, ... """ 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}, - } + Asset2 = pool.get('investment.asset') + tab_asset = Asset2.__table__() + tab_rate1 = Rate.__table__() + tab_rate2 = Rate.__table__() 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, + where_asset = tab_rate1.date <= query_date + 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( tab_asset.id, - tab_rate_today.id.as_('id_rate'), - tab_rate_today.date, - tab_rate_today.rate, + tab_rate1.date, + tab_rate1.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' - 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 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, + days_diff = days + 5 + query = tab_today.join(tab_rate2, + condition=(tab_today.id==tab_rate2.asset) & \ + (tab_today.date > (tab_rate2.date + days)) & \ + (tab_today.date <= (tab_rate2.date + days_diff)), + type_ = 'LEFT OUTER', + ).select( + tab_today.id, + tab_today.date, + tab_today.rate, + (tab_today.rate * 100.0 / NullIf(tab_rate2.rate, 0.00) - 100.0).as_('percent'), + distinct_on=[tab_today.id], + order_by=[tab_today.id, tab_today.date.desc] ) return query @@ -483,11 +458,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ order day1 """ Assert = Pool().get('investment.asset') - tab_asset = Asset.get_percentage_sql(['day1']) + tab_asset = Asset.get_percentage_sql(days=0) table, _ = tables[None] query = tab_asset.select( - tab_asset.day1, + tab_asset.percent, where=tab_asset.id==table.id, ) return [query] @@ -497,11 +472,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ order month1 """ Assert = Pool().get('investment.asset') - tab_asset = Asset.get_percentage_sql(['month1']) + tab_asset = Asset.get_percentage_sql(days=30) table, _ = tables[None] query = tab_asset.select( - tab_asset.month1, + tab_asset.percent, where=tab_asset.id==table.id, ) return [query] @@ -511,11 +486,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ order month1 """ Assert = Pool().get('investment.asset') - tab_asset = Asset.get_percentage_sql(['month3']) + tab_asset = Asset.get_percentage_sql(days=90) table, _ = tables[None] query = tab_asset.select( - tab_asset.month3, + tab_asset.percent, where=tab_asset.id==table.id, ) return [query] @@ -525,11 +500,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ order month1 """ Assert = Pool().get('investment.asset') - tab_asset = Asset.get_percentage_sql(['month6']) + tab_asset = Asset.get_percentage_sql(days=180) table, _ = tables[None] query = tab_asset.select( - tab_asset.month6, + tab_asset.percent, where=tab_asset.id==table.id, ) return [query] @@ -539,11 +514,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ order month1 """ Assert = Pool().get('investment.asset') - tab_asset = Asset.get_percentage_sql(['month12']) + tab_asset = Asset.get_percentage_sql(days=365) table, _ = tables[None] query = tab_asset.select( - tab_asset.month12, + tab_asset.percent, where=tab_asset.id==table.id, ) return [query] @@ -554,10 +529,16 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ Operator = fields.SQL_OPERATORS[clause[1]] 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, - where=Operator(Round(getattr(tab_percent, field_name), 2), + where=Operator(Round(tab_percent.percent, 2), clause[2])) return [('id', 'in', query)] @@ -567,29 +548,26 @@ class Asset(SymbolMixin, ModelSQL, ModelView): """ 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} 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 name_lst: - result['change_%s' % x][record[0]] = record[cnt1].quantize(exp) \ - if record[cnt1] is not None else None - cnt1 += 1 + for x in names: + tab_percent = cls.get_percentage_sql( + days={ + 'change_day1': 0, + '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 @classmethod diff --git a/asset.xml b/asset.xml index b3db885..1328873 100644 --- a/asset.xml +++ b/asset.xml @@ -1,5 +1,5 @@ - diff --git a/cron.py b/cron.py index 4dffd61..28ec6d4 100644 --- a/cron.py +++ b/cron.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/cron.xml b/cron.xml index 5757c5a..7d1454d 100644 --- a/cron.xml +++ b/cron.xml @@ -1,5 +1,5 @@ - diff --git a/diagram.py b/diagram.py index a2fe05b..2d3d769 100644 --- a/diagram.py +++ b/diagram.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/diagram.xml b/diagram.xml index 688d6aa..d8ac9f4 100644 --- a/diagram.xml +++ b/diagram.xml @@ -1,5 +1,5 @@ - diff --git a/group.xml b/group.xml index 8061883..5656ff9 100644 --- a/group.xml +++ b/group.xml @@ -1,5 +1,5 @@ - diff --git a/icon.xml b/icon.xml index 2a2e5c4..ea62f97 100644 --- a/icon.xml +++ b/icon.xml @@ -1,5 +1,5 @@ - diff --git a/identifier.py b/identifier.py index ca5692d..a1cfeda 100644 --- a/identifier.py +++ b/identifier.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/import_wiz.py b/import_wiz.py index 389456f..84b4dd8 100644 --- a/import_wiz.py +++ b/import_wiz.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/import_wiz.xml b/import_wiz.xml index 6a852ca..809c8b9 100644 --- a/import_wiz.xml +++ b/import_wiz.xml @@ -1,5 +1,5 @@ - diff --git a/menu.xml b/menu.xml index 18beb30..cc3b8ec 100644 --- a/menu.xml +++ b/menu.xml @@ -1,5 +1,5 @@ - diff --git a/message.xml b/message.xml index 2907923..3d5c831 100644 --- a/message.xml +++ b/message.xml @@ -1,5 +1,5 @@ - diff --git a/onlinesource.py b/onlinesource.py index 938806e..65380db 100644 --- a/onlinesource.py +++ b/onlinesource.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/onlinesource.xml b/onlinesource.xml index 21e2433..045d883 100644 --- a/onlinesource.xml +++ b/onlinesource.xml @@ -1,5 +1,5 @@ - diff --git a/rate.py b/rate.py index beca4a4..e59839b 100644 --- a/rate.py +++ b/rate.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/rate.xml b/rate.xml index dacff3d..e84e042 100644 --- a/rate.xml +++ b/rate.xml @@ -1,5 +1,5 @@ - diff --git a/sources_def.xml b/sources_def.xml index 6b88ad0..01dd440 100644 --- a/sources_def.xml +++ b/sources_def.xml @@ -1,5 +1,5 @@ - diff --git a/tests/test_asset.py b/tests/test_asset.py index 256331f..c08f345 100644 --- a/tests/test_asset.py +++ b/tests/test_asset.py @@ -250,131 +250,25 @@ class AssetTestCase(ModuleTestCase): 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() + tab_percent = Asset.get_percentage_sql(days=0) + with Transaction().set_context({ + 'qdate': date(2022, 5, 16), + }): + query = tab_percent.select( + tab_percent.id, + tab_percent.date, + tab_percent.percent, + where=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/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')) + # 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_daterange(self): diff --git a/update_wiz.py b/update_wiz.py index 0ddcbd5..8c6cbad 100644 --- a/update_wiz.py +++ b/update_wiz.py @@ -1,5 +1,5 @@ # -*- 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 # full copyright notices and license terms. diff --git a/update_wiz.xml b/update_wiz.xml index b84e96b..73ae6e6 100644 --- a/update_wiz.xml +++ b/update_wiz.xml @@ -1,5 +1,5 @@ -