diff --git a/asset.py b/asset.py index f536b56..2d4e0c8 100644 --- a/asset.py +++ b/asset.py @@ -15,6 +15,9 @@ from sql.conditionals import Case, Coalesce from sql import Literal +digits_percent = 2 + + class Asset(ModelSQL, ModelView): 'Asset' __name__ = 'investment.asset' @@ -56,8 +59,7 @@ class Asset(ModelSQL, ModelView): currency = fields.Many2One(string='Currency', select=True, required=True, model_name='currency.currency', ondelete='RESTRICT') - currency_digits = fields.Integer(string='Currency Digits', - required=True) + currency_digits = fields.Integer(string='Digits', required=True) wkn = fields.Function(fields.Char(string='NSIN', readonly=True, help='National Securities Identifying Number'), @@ -81,33 +83,33 @@ class Asset(ModelSQL, ModelView): 'get_nextupdtates', searcher='search_nextupdtate') # percentage change - change_today = fields.Function(fields.Numeric(string='Previous Day', + change_day1 = fields.Function(fields.Numeric(string='Previous Day', help='percentage change in value compared to the previous day', - readonly=True, digits=(16,1)), + readonly=True, digits=(16,digits_percent)), 'get_percentage_change') - change_month = fields.Function(fields.Numeric(string='1 Month', + change_month1 = fields.Function(fields.Numeric(string='1 Month', help='percentage change in value compared to last month', - readonly=True, digits=(16,1)), + readonly=True, digits=(16,digits_percent)), 'get_percentage_change') - change_3month = fields.Function(fields.Numeric(string='3 Months', + change_month3 = fields.Function(fields.Numeric(string='3 Months', help='percentage change in value during 3 months', - readonly=True, digits=(16,1)), + readonly=True, digits=(16,digits_percent)), 'get_percentage_change') - change_6month = fields.Function(fields.Numeric(string='6 Months', + change_month6 = fields.Function(fields.Numeric(string='6 Months', help='percentage change in value during 6 months', - readonly=True, digits=(16,1)), + readonly=True, digits=(16,digits_percent)), 'get_percentage_change') - change_12month = fields.Function(fields.Numeric(string='1 Year', + change_month12 = fields.Function(fields.Numeric(string='1 Year', help='percentage change in value during 1 year', - readonly=True, digits=(16,1)), + readonly=True, digits=(16,digits_percent)), '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', '') + If(Eval('change_day1', 0) < 0, 'warning', + If(Eval('change_day1', 0) > 0, 'success', '') )), ] @@ -134,17 +136,25 @@ class Asset(ModelSQL, ModelView): return 4 @classmethod - def get_percentage_sql(cls, table_asset): + def get_percentage_sql(cls, table_asset, name_lst): """ get table for percentages and dates + generate adapted query """ 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__() + + 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 + # 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 = table_asset.join(tab_rate_today, condition=table_asset.id==tab_rate_today.asset, @@ -157,41 +167,76 @@ class Asset(ModelSQL, ModelView): 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, + # 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 3 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'] + 3))), + type_ = 'LEFT OUTER') + + # add select for requested fields to join + select_lst = [ + query_today.id, + query_today.date, + ] + for name in name_lst: + select_lst.append( 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)), + ((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_('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, - ], + ).as_(name)) + + order_by_lst = [query_today.id] + 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], + order_by=order_by_lst, ) + # ~ 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 @@ -203,33 +248,26 @@ class Asset(ModelSQL, ModelView): tab_asset = Asset.__table__() cursor = Transaction().connection.cursor() - tab_percent = cls.get_percentage_sql(tab_asset) + name_lst = [x[len('change_'):] for x in names] + tab_percent = cls.get_percentage_sql(tab_asset, name_lst) query = tab_percent.select( tab_percent.id, - tab_percent.day1, - tab_percent.month1, + *[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: - 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] + cnt1 = 1 + 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 return result - @classmethod def get_rate_data(cls, assets, names): """ get date and rate of asset diff --git a/locale/de.po b/locale/de.po index c1a0411..91eafca 100644 --- a/locale/de.po +++ b/locale/de.po @@ -86,6 +86,10 @@ msgctxt "view:investment.asset:" msgid "Currency and Units" msgstr "Währung und Einheiten" +msgctxt "view:investment.asset:" +msgid "Gain and Loss" +msgstr "Gewinn und Verlust" + msgctxt "view:investment.asset:" msgid "Identifiers" msgstr "Bezeichner" @@ -115,8 +119,8 @@ msgid "Currency" msgstr "Währung" msgctxt "field:investment.asset,currency_digits:" -msgid "Currency Digits" -msgstr "Nachkommastellen Währung" +msgid "Digits" +msgstr "Nachkommastellen" msgctxt "field:investment.asset,product:" msgid "Product" @@ -194,43 +198,43 @@ msgctxt "field:investment.asset,nextupdtate:" msgid "Next Update" msgstr "nächste Aktualisierung" -msgctxt "field:investment.asset,change_today:" +msgctxt "field:investment.asset,change_day1:" msgid "Previous Day" msgstr "Vortag" -msgctxt "help:investment.asset,change_today:" +msgctxt "help:investment.asset,change_day1:" msgid "percentage change in value compared to the previous day" msgstr "prozentuale Wertänderung zum Vortag" -msgctxt "field:investment.asset,change_month:" +msgctxt "field:investment.asset,change_month1:" msgid "1 Month" msgstr "1 Monat" -msgctxt "help:investment.asset,change_month:" +msgctxt "help:investment.asset,change_month1:" msgid "percentage change in value compared to last month" msgstr "prozentuale Wertänderung zum letzten Monat" -msgctxt "field:investment.asset,change_3month:" +msgctxt "field:investment.asset,change_month3:" msgid "3 Months" msgstr "3 Monate" -msgctxt "help:investment.asset,change_3month:" +msgctxt "help:investment.asset,change_month3:" msgid "percentage change in value during 3 months" msgstr "Prozentuale Wertänderung während 3 Monate" -msgctxt "field:investment.asset,change_6month:" +msgctxt "field:investment.asset,change_month6:" msgid "6 Months" msgstr "6 Monate" -msgctxt "help:investment.asset,change_6month:" +msgctxt "help:investment.asset,change_month6:" msgid "percentage change in value during 6 months" msgstr "Prozentuale Wertänderung während 6 Monate" -msgctxt "field:investment.asset,change_12month:" +msgctxt "field:investment.asset,change_month12:" msgid "1 Year" msgstr "1 Jahr" -msgctxt "help:investment.asset,change_12month:" +msgctxt "help:investment.asset,change_month12:" 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 2be0385..b5d63ef 100644 --- a/locale/en.po +++ b/locale/en.po @@ -58,6 +58,10 @@ msgctxt "view:investment.asset:" msgid "Currency and Units" msgstr "Currency and Units" +msgctxt "view:investment.asset:" +msgid "Gain and Loss" +msgstr "Gain and Loss" + msgctxt "view:investment.asset:" msgid "Identifiers" msgstr "Identifiers" @@ -87,8 +91,8 @@ msgid "Currency" msgstr "Currency" msgctxt "field:investment.asset,currency_digits:" -msgid "Currency Digits" -msgstr "Currency Digits" +msgid "Digits" +msgstr "Digits" msgctxt "field:investment.asset,product:" msgid "Product" @@ -166,43 +170,43 @@ msgctxt "field:investment.asset,nextupdtate:" msgid "Next Update" msgstr "Next Update" -msgctxt "field:investment.asset,change_today:" +msgctxt "field:investment.asset,change_day1:" msgid "Previous Day" msgstr "Previous Day" -msgctxt "help:investment.asset,change_today:" +msgctxt "help:investment.asset,change_day1:" 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:" +msgctxt "field:investment.asset,change_month1:" msgid "1 Month" msgstr "1 Month" -msgctxt "help:investment.asset,change_month:" +msgctxt "help:investment.asset,change_month1:" msgid "percentage change in value compared to last month" msgstr "percentage change in value compared to last month" -msgctxt "field:investment.asset,change_3month:" +msgctxt "field:investment.asset,change_month3:" msgid "3 Months" msgstr "3 Months" -msgctxt "help:investment.asset,change_3month:" +msgctxt "help:investment.asset,change_month3:" msgid "percentage change in value during 3 months" msgstr "percentage change in value during 3 months" -msgctxt "field:investment.asset,change_6month:" +msgctxt "field:investment.asset,change_month6:" msgid "6 Months" msgstr "6 Months" -msgctxt "help:investment.asset,change_6month:" +msgctxt "help:investment.asset,change_month6:" msgid "percentage change in value during 6 months" msgstr "percentage change in value during 6 months" -msgctxt "field:investment.asset,change_12month:" +msgctxt "field:investment.asset,change_month12:" msgid "1 Year" msgstr "1 Year" -msgctxt "help:investment.asset,change_12month:" +msgctxt "help:investment.asset,change_month12:" msgid "percentage change in value during 1 year" msgstr "percentage change in value during 1 year" diff --git a/tests/test_asset.py b/tests/test_asset.py index a66cd51..cfb666c 100644 --- a/tests/test_asset.py +++ b/tests/test_asset.py @@ -156,8 +156,8 @@ class AssetTestCase(ModuleTestCase): ]) self.assertEqual(asset1.rec_name, 'Product 1 - 2.6000 usd/Unit [05/16/2022]') self.assertEqual(asset2.rec_name, 'Product 1 - 5.2500 usd/Unit [05/15/2022]') - self.assertEqual(asset1.change_today, Decimal('6.1')) - self.assertEqual(asset2.change_today, Decimal('-8.7')) + self.assertEqual(asset1.change_day1, Decimal('6.1')) + self.assertEqual(asset2.change_day1, Decimal('-8.7')) @with_transaction() def test_asset_check_onlinesource_onoff(self): diff --git a/view/asset_form.xml b/view/asset_form.xml index f3586c0..8c26f03 100644 --- a/view/asset_form.xml +++ b/view/asset_form.xml @@ -8,12 +8,28 @@ full copyright notices and license terms. -->