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. -->
-
+
+
+