diff --git a/README.rst b/README.rst
index 3eb85fe..b7ca0ab 100644
--- a/README.rst
+++ b/README.rst
@@ -14,6 +14,24 @@ Requires
Changes
=======
+*6.0.4 - 25.11.2022*
+
+- add: assets - colors for percentual success/loss
+- updt: optimize timestamp for next online-update
+
+*6.0.3 - 23.11.2022*
+
+- fix: bug in searcher
+- add: online-sources
+
+*6.0.2 - 23.11.2022*
+
+- asset: add field 'date', optimized 'rec_name'
+
+*6.0.1 - 22.11.2022*
+
+- works
+
*6.0.0 - 09.11.2022*
- init
diff --git a/asset.py b/asset.py
index 4d658b0..f536b56 100644
--- a/asset.py
+++ b/asset.py
@@ -6,17 +6,21 @@
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
-from sql.conditionals import Case
+from sql.functions import CurrentDate, CurrentTimestamp
+from sql.conditionals import Case, Coalesce
+from sql import Literal
class Asset(ModelSQL, ModelView):
'Asset'
__name__ = 'investment.asset'
+ name = fields.Function(fields.Char(string='Name', readonly=True),
+ 'on_change_with_name')
company = fields.Many2One(string='Company', model_name='company.company',
required=True, ondelete="RESTRICT")
product = fields.Many2One(string='Product', required=True,
@@ -38,7 +42,9 @@ class Asset(ModelSQL, ModelView):
model_name='investment.rate')
rate = fields.Function(fields.Numeric(string='Current Rate',
readonly=True, digits=(16, Eval('currency_digits', 4)),
- depends=['currency_digits']), 'on_change_with_rate')
+ depends=['currency_digits']), 'get_rate_data')
+ date = fields.Function(fields.Date(string='Date', readonly=True,
+ help='Date of current rate'), 'get_rate_data')
company_currency = fields.Function(fields.Many2One(readonly=True,
string='Company Currency', states={'invisible': True},
@@ -70,9 +76,40 @@ 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',
+ help='percentage change in value compared to the previous day',
+ readonly=True, digits=(16,1)),
+ 'get_percentage_change')
+ change_month = fields.Function(fields.Numeric(string='1 Month',
+ help='percentage change in value compared to last month',
+ readonly=True, digits=(16,1)),
+ 'get_percentage_change')
+ change_3month = fields.Function(fields.Numeric(string='3 Months',
+ help='percentage change in value during 3 months',
+ readonly=True, digits=(16,1)),
+ 'get_percentage_change')
+ change_6month = fields.Function(fields.Numeric(string='6 Months',
+ help='percentage change in value during 6 months',
+ readonly=True, digits=(16,1)),
+ 'get_percentage_change')
+ change_12month = fields.Function(fields.Numeric(string='1 Year',
+ help='percentage change in value during 1 year',
+ 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):
@@ -96,6 +133,142 @@ class Asset(ModelSQL, ModelView):
"""
return 4
+ @classmethod
+ def get_percentage_sql(cls, table_asset):
+ """ get table for percentages and dates
+ """
+ pool = Pool()
+ Rate = pool.get('investment.rate')
+ tab_rate_today = Rate.__table__()
+ tab_rate_1day = Rate.__table__()
+ tab_rate_1month = Rate.__table__()
+ tab_rate_3month = Rate.__table__()
+ context = Transaction().context
+
+ 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,
+ )
+
+ 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()
+
+ tab_percent = cls.get_percentage_sql(tab_asset)
+ query = tab_percent.select(
+ tab_percent.id,
+ tab_percent.day1,
+ tab_percent.month1,
+ 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}
+ for record in records:
+ values = {
+ 'change_today': record[1].quantize(Decimal('0.1')) \
+ if record[1] is not None else None,
+ 'change_month': record[2].quantize(Decimal('0.1')) \
+ if record[2] is not None else None,
+ 'change_3month': None,
+ 'change_6month': None,
+ 'change_12month': None,
+ }
+
+ for name in names:
+ result[name][record[0]] = values[name]
+ return result
+
+
+ @classmethod
+ def get_rate_data(cls, assets, names):
+ """ get date and rate of asset
+ """
+ pool = Pool()
+ Asset = pool.get('investment.asset')
+ Rate = pool.get('investment.rate')
+ tab_asset = Asset.__table__()
+ tab_rate = Rate.__table__()
+ cursor = Transaction().connection.cursor()
+
+ query = tab_asset.join(tab_rate,
+ condition=tab_asset.id==tab_rate.asset
+ ).select(
+ tab_asset.id,
+ tab_rate.rate,
+ tab_rate.date,
+ distinct_on=[tab_asset.id],
+ order_by=[tab_asset.id, tab_rate.date.desc],
+ where=tab_asset.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, rate1, date1) = record
+
+ asset = Asset(id1)
+ exp = Decimal(Decimal(1) / 10 ** (asset.currency_digits or 4))
+
+ values = {'rate': record[1].quantize(exp), 'date': record[2]}
+
+ for name in names:
+ result[name][record[0]] = values[name]
+
+ return result
+
@fields.depends('updtsource', 'updttime')
def on_change_updtsource(self):
""" clear time-fields
@@ -105,23 +278,6 @@ class Asset(ModelSQL, ModelView):
else :
self.updttime = time(11, 30)
- @fields.depends('id', 'currency_digits')
- def on_change_with_rate(self, name=None):
- """ get current rate
- """
- pool = Pool()
- Rate = pool.get('investment.rate')
- IrDate = pool.get('ir.date')
-
- if self.id:
- rates = Rate.search([
- ('date', '<=', IrDate.today()),
- ('asset.id', '=', self.id),
- ], order=[('date', 'DESC')], limit=1)
- if len(rates) > 0:
- exp = Decimal(Decimal(1) / 10 ** (self.currency_digits or 4))
- return rates[0].rate.quantize(exp)
-
@fields.depends('product', 'uom')
def on_change_product(self):
""" update unit by product
@@ -138,6 +294,13 @@ class Asset(ModelSQL, ModelView):
if self.currency:
self.currency_digits = self.currency.digits
+ @fields.depends('product')
+ def on_change_with_name(self, name=None):
+ """ get name of product
+ """
+ if self.product:
+ return self.product.name
+
@fields.depends('product')
def on_change_with_product_uom(self, name=None):
""" get category of product-uom
@@ -164,51 +327,72 @@ 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')
- IrDate = pool.get('ir.date')
- 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', IrDate.today())
- 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', '=', query)]
+ return [('id', 'in', query)]
@classmethod
def get_identifier_sql(cls, tab_asset):
@@ -294,10 +478,14 @@ class Asset(ModelSQL, ModelView):
def get_rec_name(self, name):
""" record name
"""
- return '%(prod)s [%(curr)s/%(unit)s]' % {
+ return '%(prod)s - %(rate)s %(curr)s/%(unit)s [%(date)s]' % {
'prod': getattr(self.product, 'rec_name', '-'),
- 'curr': getattr(self.currency, 'rec_name', '-'),
+ 'curr': getattr(self.currency, 'symbol', '-'),
'unit': getattr(self.uom, 'rec_name', '-'),
+ 'rate': Report.format_number(self.rate, lang=None,
+ digits=self.currency_digits or 4) \
+ if self.rate is not None else '-',
+ 'date': Report.format_date(self.date) if self.date is not None else '-',
}
@classmethod
@@ -314,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 0d27885..c1a0411 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -162,10 +162,22 @@ msgctxt "field:investment.asset,rates:"
msgid "Rates"
msgstr "Kurse"
+msgctxt "field:investment.asset,name:"
+msgid "Name"
+msgstr "Name"
+
msgctxt "field:investment.asset,rate:"
msgid "Current Rate"
msgstr "aktueller Kurs"
+msgctxt "field:investment.asset,date:"
+msgid "Date"
+msgstr "Datum"
+
+msgctxt "help:investment.asset,date:"
+msgid "Date of current rate"
+msgstr "Datum des aktuellen Kurses"
+
msgctxt "field:investment.asset,updtsource:"
msgid "Update Source"
msgstr "Kursquelle"
@@ -178,9 +190,49 @@ 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"
+msgstr "Vortag"
+
+msgctxt "help:investment.asset,change_today:"
+msgid "percentage change in value compared to the previous day"
+msgstr "prozentuale Wertänderung zum Vortag"
+
+msgctxt "field:investment.asset,change_month:"
+msgid "1 Month"
+msgstr "1 Monat"
+
+msgctxt "help:investment.asset,change_month:"
+msgid "percentage change in value compared to last month"
+msgstr "prozentuale Wertänderung zum letzten Monat"
+
+msgctxt "field:investment.asset,change_3month:"
+msgid "3 Months"
+msgstr "3 Monate"
+
+msgctxt "help:investment.asset,change_3month:"
+msgid "percentage change in value during 3 months"
+msgstr "Prozentuale Wertänderung während 3 Monate"
+
+msgctxt "field:investment.asset,change_6month:"
+msgid "6 Months"
+msgstr "6 Monate"
+
+msgctxt "help:investment.asset,change_6month:"
+msgid "percentage change in value during 6 months"
+msgstr "Prozentuale Wertänderung während 6 Monate"
+
+msgctxt "field:investment.asset,change_12month:"
+msgid "1 Year"
+msgstr "1 Jahr"
+
+msgctxt "help:investment.asset,change_12month:"
+msgid "percentage change in value during 1 year"
+msgstr "Prozentuale Wertänderung während 1 Jahr"
#####################
diff --git a/locale/en.po b/locale/en.po
index 2ef7e68..2be0385 100644
--- a/locale/en.po
+++ b/locale/en.po
@@ -134,10 +134,22 @@ msgctxt "field:investment.asset,rates:"
msgid "Rates"
msgstr "Rates"
+msgctxt "field:investment.asset,name:"
+msgid "Name"
+msgstr "Name"
+
msgctxt "field:investment.asset,rate:"
msgid "Current Rate"
msgstr "Current Rate"
+msgctxt "field:investment.asset,date:"
+msgid "Date"
+msgstr "Date"
+
+msgctxt "help:investment.asset,date:"
+msgid "Date of current rate"
+msgstr "Date of current rate"
+
msgctxt "field:investment.asset,updtsource:"
msgid "Update Source"
msgstr "Update Source"
@@ -150,9 +162,49 @@ 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"
+msgstr "Previous Day"
+
+msgctxt "help:investment.asset,change_today:"
+msgid "percentage change in value compared to the previous day"
+msgstr "percentage change in value compared to the previous day"
+
+msgctxt "field:investment.asset,change_month:"
+msgid "1 Month"
+msgstr "1 Month"
+
+msgctxt "help:investment.asset,change_month:"
+msgid "percentage change in value compared to last month"
+msgstr "percentage change in value compared to last month"
+
+msgctxt "field:investment.asset,change_3month:"
+msgid "3 Months"
+msgstr "3 Months"
+
+msgctxt "help:investment.asset,change_3month:"
+msgid "percentage change in value during 3 months"
+msgstr "percentage change in value during 3 months"
+
+msgctxt "field:investment.asset,change_6month:"
+msgid "6 Months"
+msgstr "6 Months"
+
+msgctxt "help:investment.asset,change_6month:"
+msgid "percentage change in value during 6 months"
+msgstr "percentage change in value during 6 months"
+
+msgctxt "field:investment.asset,change_12month:"
+msgid "1 Year"
+msgstr "1 Year"
+
+msgctxt "help:investment.asset,change_12month:"
+msgid "percentage change in value during 1 year"
+msgstr "percentage change in value during 1 year"
msgctxt "model:investment.source,name:"
msgid "Online Source"
diff --git a/onlinesource.py b/onlinesource.py
index cf9a858..125cf6b 100644
--- a/onlinesource.py
+++ b/onlinesource.py
@@ -30,6 +30,7 @@ sel_rgxdatefmt = [
('%d.%m.%Y', 'dd.mm.yyyy'),
('%m/%d/%Y', 'mm/dd/yyyy'),
('%Y-%m-%d', 'yyyy-mm-dd'),
+ ('%b %d %Y', 'mon dd yyyy'),
]
fields_check = ['url', 'nsin', 'isin', 'symbol', 'text', 'http_state', \
diff --git a/sources_def.xml b/sources_def.xml
index 25e148c..2ff2d1d 100644
--- a/sources_def.xml
+++ b/sources_def.xml
@@ -16,6 +16,35 @@ full copyright notices and license terms. -->