From cba2117d13b95bfd526161f6aafbe8d4ceaf6d17 Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Fri, 25 Nov 2022 11:00:03 +0100 Subject: [PATCH] =?UTF-8?q?asset:=20abfrage=20updatezeitpunkt=20optimiert,?= =?UTF-8?q?=20anzeige=20der=20vortagsprozente,=20farbe=20f=C3=BCr=20zeilen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- asset.py | 114 ++++++++++++++++++++++++++++---------------- locale/de.po | 6 +-- locale/en.po | 6 +-- tests/test_asset.py | 85 ++++++++++++++------------------- view/asset_form.xml | 4 +- 5 files changed, 117 insertions(+), 98 deletions(-) diff --git a/asset.py b/asset.py index 0b1ef2c..f536b56 100644 --- a/asset.py +++ b/asset.py @@ -6,12 +6,12 @@ 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, CurrentDate -from sql.conditionals import Case +from sql.functions import CurrentDate, CurrentTimestamp +from sql.conditionals import Case, Coalesce from sql import Literal @@ -76,9 +76,9 @@ class Asset(ModelSQL, ModelView): states={ 'readonly': ~Bool(Eval('updtsource')), }, depends=['updtsource']) - updtneeded = fields.Function(fields.Boolean(string='Course update needed', + nextupdtate = fields.Function(fields.DateTime(string='Next Update', readonly=True), - 'on_change_with_updtneeded', searcher='search_updtneeded') + 'get_nextupdtates', searcher='search_nextupdtate') # percentage change change_today = fields.Function(fields.Numeric(string='Previous Day', @@ -102,6 +102,15 @@ class Asset(ModelSQL, ModelView): readonly=True, digits=(16,1)), 'get_percentage_change') + @classmethod + def view_attributes(cls): + return super().view_attributes() + [ + ('/tree', 'visual', + If(Eval('change_today', 0) < 0, 'warning', + If(Eval('change_today', 0) > 0, 'success', '') + )), + ] + @classmethod def default_currency(cls): """ currency of company @@ -218,8 +227,6 @@ class Asset(ModelSQL, ModelView): for name in names: result[name][record[0]] = values[name] - - print('-- result:', result) return result @@ -320,48 +327,70 @@ 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_next_update_datetime_sql(cls): + """ get sql for datetime of next planned update """ pool = Pool() - Asset2 = pool.get('investment.asset') + Asset = pool.get('investment.asset') Rate = pool.get('investment.rate') - tab_asset = Asset2.__table__() + 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_nextupdtates(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 = {'nextupdtate': updt} + + for n in names: + result[n][id1] = r1[n] + return result + + @classmethod + def search_nextupdtate(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_date = context.get('qdate', CurrentDate()) - 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]), + query = tab_updt.select( + tab_updt.id, + where=Operator(tab_updt.updttime, clause[2]), ) return [('id', 'in', query)] @@ -473,8 +502,9 @@ class Asset(ModelSQL, ModelView): Asset2 = pool.get('investment.asset') OnlineSource = pool.get('investment.source') + query_time = context.get('qdatetime', CurrentTimestamp()) for asset in Asset2.search([ - ('updtneeded', '=', True), + ('updttime', '<=', query_time), ]): OnlineSource.update_rate(asset) diff --git a/locale/de.po b/locale/de.po index 1a91ba8..c1a0411 100644 --- a/locale/de.po +++ b/locale/de.po @@ -190,9 +190,9 @@ 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,nextupdtate:" +msgid "Next Update" +msgstr "nächste Aktualisierung" msgctxt "field:investment.asset,change_today:" msgid "Previous Day" diff --git a/locale/en.po b/locale/en.po index 12bd997..2be0385 100644 --- a/locale/en.po +++ b/locale/en.po @@ -162,9 +162,9 @@ 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,nextupdtate:" +msgid "Next Update" +msgstr "Next Update" msgctxt "field:investment.asset,change_today:" msgid "Previous Day" diff --git a/tests/test_asset.py b/tests/test_asset.py index d2928a1..a66cd51 100644 --- a/tests/test_asset.py +++ b/tests/test_asset.py @@ -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): @@ -221,31 +221,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), }): # re-read to make context work asset2, = Asset.browse([asset.id]) - # no rates exists - wait for 10:45 - self.assertEqual(asset2.updtneeded, False) - self.assertEqual( - Asset.search_count([('updtneeded', '=', True)]), - 0) - with Transaction().set_context({ - 'qdate': date(2022, 10, 15), - 'qtime': time(10, 46), - }): - # no rates exists - run at 10:46 - asset2, = Asset.browse([asset.id]) - self.assertEqual(asset2.updtneeded, True) + self.assertEqual(asset2.updtsource.rec_name, 'Source 1') + self.assertEqual(asset2.updttime, time(10, 45)) + self.assertEqual(len(asset2.rates), 0) + self.assertEqual(asset2.nextupdtate, datetime(2022, 10, 15, 10, 45)) + self.assertEqual( - Asset.search_count([('updtneeded', '=', True)]), + Asset.search_count([('nextupdtate', '<', datetime(2022, 10, 15, 10, 45))]), + 0) + self.assertEqual( + Asset.search_count([('nextupdtate', '>=', datetime(2022, 10, 15, 10, 45))]), 1) # add rate at yesterday @@ -259,27 +251,19 @@ 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 - asset2, = Asset.browse([asset.id]) - self.assertEqual(asset2.updtneeded, False) - 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.nextupdtate, 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 - asset2, = Asset.browse([asset.id]) - self.assertEqual(asset2.updtneeded, True) - self.assertEqual( - Asset.search_count([('updtneeded', '=', True)]), - 1) + self.assertEqual( + Asset.search_count([('nextupdtate', '<', datetime(2022, 10, 15, 10, 45))]), + 0) + self.assertEqual( + Asset.search_count([('nextupdtate', '>=', datetime(2022, 10, 15, 10, 45))]), + 1) # add rate at today Asset.write(*[ @@ -292,16 +276,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 - asset2, = Asset.browse([asset.id]) - self.assertEqual(asset2.updtneeded, False) - self.assertEqual( - Asset.search_count([('updtneeded', '=', True)]), - 0) + 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.nextupdtate, datetime(2022, 10, 16, 10, 45)) + + self.assertEqual( + Asset.search_count([('nextupdtate', '<', datetime(2022, 10, 15, 10, 45))]), + 0) + self.assertEqual( + Asset.search_count([('nextupdtate', '>=', datetime(2022, 10, 15, 10, 45))]), + 1) @with_transaction() def test_asset_indentifiers(self): diff --git a/view/asset_form.xml b/view/asset_form.xml index a64c6a3..f3586c0 100644 --- a/view/asset_form.xml +++ b/view/asset_form.xml @@ -8,7 +8,9 @@ full copyright notices and license terms. -->