formatting

This commit is contained in:
Frederik Jaeckel 2023-06-07 18:44:53 +02:00
parent 82f9d3a792
commit 8f12741d76
14 changed files with 411 additions and 344 deletions

View file

@ -32,4 +32,3 @@ def register():
UpdateSoureWizard, UpdateSoureWizard,
ImportWizard, ImportWizard,
module='investment', type_='wizard') module='investment', type_='wizard')

332
asset.py
View file

@ -8,7 +8,6 @@ from trytond.transaction import Transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.pyson import Eval, Bool, If, Date from trytond.pyson import Eval, Bool, If, Date
from trytond.report import Report from trytond.report import Report
from trytond.exceptions import UserError
from decimal import Decimal from decimal import Decimal
from datetime import time from datetime import time
@ -30,59 +29,71 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
'Asset' 'Asset'
__name__ = 'investment.asset' __name__ = 'investment.asset'
name = fields.Function(fields.Char(string='Name', readonly=True), name = fields.Function(fields.Char(
'get_name_symbol', searcher='search_rec_name') string='Name', readonly=True),
company = fields.Many2One(string='Company', model_name='company.company', 'get_name_symbol', searcher='search_rec_name')
company = fields.Many2One(
string='Company', model_name='company.company',
required=True, ondelete="RESTRICT") required=True, ondelete="RESTRICT")
product = fields.Many2One(string='Product', required=True, product = fields.Many2One(
model_name='product.product', ondelete='RESTRICT', string='Product', required=True, model_name='product.product',
domain=[('type', '=', 'assets')]) ondelete='RESTRICT', domain=[('type', '=', 'assets')])
product_uom = fields.Function(fields.Many2One(string='UOM Category', product_uom = fields.Function(fields.Many2One(
readonly=True, model_name='product.uom.category', string='UOM Category', readonly=True,
model_name='product.uom.category',
help='Category of unit on the product.'), 'get_name_symbol') help='Category of unit on the product.'), 'get_name_symbol')
uom = fields.Many2One(string='UOM', required=True, uom = fields.Many2One(
model_name='product.uom', ondelete='RESTRICT', string='UOM', required=True, model_name='product.uom',
ondelete='RESTRICT',
states={ states={
'readonly': ~Bool(Eval('product')), 'readonly': ~Bool(Eval('product')),
}, },
domain=[ domain=[
('category', '=', Eval('product_uom')), ('category', '=', Eval('product_uom')),
], depends=['product_uom', 'product']) ], depends=['product_uom', 'product'])
symbol = fields.Function(fields.Char(string='UOM', readonly=True), symbol = fields.Function(fields.Char(
'get_name_symbol', searcher='search_uom_symbol') string='UOM', readonly=True), 'get_name_symbol',
asset_symbol = fields.Function(fields.Many2One(string='Symbol', searcher='search_uom_symbol')
readonly=True, model_name='investment.asset'), asset_symbol = fields.Function(fields.Many2One(
string='Symbol', readonly=True, model_name='investment.asset'),
'get_name_symbol') 'get_name_symbol')
rates = fields.One2Many(string='Rates', field='asset', rates = fields.One2Many(
model_name='investment.rate') string='Rates', field='asset', model_name='investment.rate')
rate = fields.Function(fields.Numeric(string='Current Rate', rate = fields.Function(fields.Numeric(
readonly=True, digits=(16, Eval('currency_digits', 4)), string='Current Rate', readonly=True,
depends=['currency_digits']), digits=(16, Eval('currency_digits', 4)), depends=['currency_digits']),
'get_rate_data', searcher='search_rate') 'get_rate_data', searcher='search_rate')
date = fields.Function(fields.Date(string='Date', readonly=True, date = fields.Function(fields.Date(
help='Date of current rate'), string='Date', readonly=True, help='Date of current rate'),
'get_rate_data', searcher='search_date') 'get_rate_data', searcher='search_date')
currency = fields.Many2One(string='Currency', select=True, currency = fields.Many2One(
required=True, model_name='currency.currency', ondelete='RESTRICT') string='Currency', select=True, required=True,
currency_digits = fields.Integer(string='Digits', required=True, model_name='currency.currency', ondelete='RESTRICT')
currency_digits = fields.Integer(
string='Digits', required=True,
domain=[ domain=[
('currency_digits', '>=', 0), ('currency_digits', '>=', 0),
('currency_digits', '<=', 6)]) ('currency_digits', '<=', 6)])
wkn = fields.Function(fields.Char(string='NSIN', readonly=True, wkn = fields.Function(fields.Char(
string='NSIN', readonly=True,
help='National Securities Identifying Number'), help='National Securities Identifying Number'),
'get_identifiers', searcher='search_identifier') 'get_identifiers', searcher='search_identifier')
isin = fields.Function(fields.Char(string='ISIN', readonly=True, isin = fields.Function(fields.Char(
string='ISIN', readonly=True,
help='International Securities Identification Number'), help='International Securities Identification Number'),
'get_identifiers', searcher='search_identifier') 'get_identifiers', searcher='search_identifier')
secsymb = fields.Function(fields.Char(string='Symbol', readonly=True, secsymb = fields.Function(fields.Char(
string='Symbol', readonly=True,
help='Stock market symbol'), help='Stock market symbol'),
'get_identifiers', searcher='search_identifier') 'get_identifiers', searcher='search_identifier')
updtsources = fields.Many2Many(string='Update Sources', updtsources = fields.Many2Many(
help='Select sources for the course update. The course sources are tried until a valid value has been read.', string='Update Sources',
help='Select sources for the course update. The course sources ' +
'are tried until a valid value has been read.',
relation_name='investment.asset_source_rel', relation_name='investment.asset_source_rel',
origin='asset', target='source') origin='asset', target='source')
updturl = fields.Char( updturl = fields.Char(
@ -98,37 +109,42 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
'on_change_with_updturl_enable') 'on_change_with_updturl_enable')
updtdays = fields.Selection( updtdays = fields.Selection(
string='Select days', required=True, selection=sel_updtdays) string='Select days', required=True, selection=sel_updtdays)
updttime = fields.Time(string='Time', updttime = fields.Time(
string='Time',
states={ states={
'readonly': ~Bool(Eval('updtsources')), 'readonly': ~Bool(Eval('updtsources')),
}, depends=['updtsources']) }, depends=['updtsources'])
nextupdate = fields.Function(fields.DateTime(string='Next Update', nextupdate = fields.Function(fields.DateTime(
readonly=True), string='Next Update', readonly=True),
'get_nextupdates', searcher='search_nextupdate') 'get_nextupdates', searcher='search_nextupdate')
# percentage change # percentage change
change_day1 = fields.Function(fields.Numeric(string='Previous Day', change_day1 = fields.Function(fields.Numeric(
help='percentage change in value compared to the previous day', string='Previous Day', readonly=True,
readonly=True, digits=(16,digits_percent)), digits=(16, digits_percent)),
'get_percentage_change', searcher='search_percentage') 'get_percentage_change', searcher='search_percentage')
change_month1 = fields.Function(fields.Numeric(string='1 Month', change_month1 = fields.Function(fields.Numeric(
string='1 Month', readonly=True,
help='percentage change in value compared to last month', help='percentage change in value compared to last month',
readonly=True, digits=(16,digits_percent)), digits=(16, digits_percent)),
'get_percentage_change', searcher='search_percentage') 'get_percentage_change', searcher='search_percentage')
change_month3 = fields.Function(fields.Numeric(string='3 Months', change_month3 = fields.Function(fields.Numeric(
string='3 Months',
help='percentage change in value during 3 months', help='percentage change in value during 3 months',
readonly=True, digits=(16,digits_percent)), digits=(16, digits_percent)),
'get_percentage_change', searcher='search_percentage') 'get_percentage_change', searcher='search_percentage')
change_month6 = fields.Function(fields.Numeric(string='6 Months', change_month6 = fields.Function(fields.Numeric(
string='6 Months', readonly=True,
help='percentage change in value during 6 months', help='percentage change in value during 6 months',
readonly=True, digits=(16,digits_percent)), digits=(16, digits_percent)),
'get_percentage_change', searcher='search_percentage') 'get_percentage_change', searcher='search_percentage')
change_month12 = fields.Function(fields.Numeric(string='1 Year', change_month12 = fields.Function(fields.Numeric(
string='1 Year', readonly=True,
help='percentage change in value during 1 year', help='percentage change in value during 1 year',
readonly=True, digits=(16,digits_percent)), digits=(16, digits_percent)),
'get_percentage_change', searcher='search_percentage') 'get_percentage_change', searcher='search_percentage')
change_symbol = fields.Function(fields.Many2One(string='Symbol', change_symbol = fields.Function(fields.Many2One(
readonly=True, model_name='investment.rate'), string='Symbol', readonly=True, model_name='investment.rate'),
'get_rate_data') 'get_rate_data')
@classmethod @classmethod
@ -160,7 +176,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query = tab_asset.select( query = tab_asset.select(
tab_asset.id, tab_asset.id,
tab_asset.updtsource, tab_asset.updtsource,
where = tab_asset.updtsource != None, where=tab_asset.updtsource != None,
) )
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
@ -179,9 +195,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
('/tree', 'visual', ('/tree', 'visual',
If(Eval('date', Date()) < Date(delta_days=-5), 'muted', If(Eval('date', Date()) < Date(delta_days=-5), 'muted',
If(Eval('change_day1', 0) < 0, 'danger', If(Eval('change_day1', 0) < 0, 'danger',
If(Eval('change_day1', 0) > 0, 'success', '') If(Eval('change_day1', 0) > 0, 'success', '')))),
))
),
] ]
@classmethod @classmethod
@ -224,7 +238,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" """
if self.updtsources: if self.updtsources:
for usource in self.updtsources: for usource in self.updtsources:
if usource.fixed_url == True: if usource.fixed_url is True:
return True return True
return False return False
@ -234,7 +248,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" """
if len(self.updtsources) == 0: if len(self.updtsources) == 0:
self.updttime = None self.updttime = None
else : else:
self.updttime = time(11, 30) self.updttime = time(11, 30)
@fields.depends('product', 'uom') @fields.depends('product', 'uom')
@ -272,16 +286,21 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
(tab1, join1, col1) = Uom.symbol._get_translation_column(Uom, 'symbol') (tab1, join1, col1) = Uom.symbol._get_translation_column(Uom, 'symbol')
tab_symb = join1.select(tab1.id, col1.as_('symbol')) tab_symb = join1.select(tab1.id, col1.as_('symbol'))
query = tab_asset.join(tab_prod, query = tab_asset.join(
condition=tab_asset.product==tab_prod.id, tab_prod,
).join(tab_templ, condition=tab_asset.product == tab_prod.id,
condition=tab_templ.id==tab_prod.template, ).join(
).join(tab_uom, tab_templ,
condition=tab_templ.default_uom==tab_uom.id, condition=tab_templ.id == tab_prod.template,
).join(tab_cur, ).join(
condition=tab_asset.currency==tab_cur.id, tab_uom,
).join(tab_symb, condition=tab_templ.default_uom == tab_uom.id,
condition=tab_asset.uom==tab_symb.id, ).join(
tab_cur,
condition=tab_asset.currency == tab_cur.id,
).join(
tab_symb,
condition=tab_asset.uom == tab_symb.id,
).select( ).select(
tab_asset.id, tab_asset.id,
tab_templ.name, tab_templ.name,
@ -297,11 +316,11 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
cursor = Transaction().connection.cursor() cursor = Transaction().connection.cursor()
(query, tab_asset) = cls.get_name_symbol_sql() (query, tab_asset) = cls.get_name_symbol_sql()
query.where=tab_asset.id.in_([x.id for x in assets]) query.where = tab_asset.id.in_([x.id for x in assets])
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
result = {x:{y.id: None for y in assets} for x in names} result = {x: {y.id: None for y in assets} for x in names}
for record in records: for record in records:
values = { values = {
@ -321,8 +340,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" """
return ['OR', return ['OR',
(('uom.rec_name',) + tuple(clause[1:])), (('uom.rec_name',) + tuple(clause[1:])),
(('currency.rec_name',) + tuple(clause[1:])), (('currency.rec_name',) + tuple(clause[1:]))]
]
@classmethod @classmethod
def get_rate_data_sql(cls): def get_rate_data_sql(cls):
@ -334,8 +352,9 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
tab_asset = Asset.__table__() tab_asset = Asset.__table__()
tab_rate = Rate.__table__() tab_rate = Rate.__table__()
query = tab_asset.join(tab_rate, query = tab_asset.join(
condition=tab_asset.id==tab_rate.asset tab_rate,
condition=tab_asset.id == tab_rate.asset
).select( ).select(
tab_asset.id, tab_asset.id,
Round(tab_rate.rate, tab_asset.currency_digits).as_('rate'), Round(tab_rate.rate, tab_asset.currency_digits).as_('rate'),
@ -354,12 +373,12 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
cursor = Transaction().connection.cursor() cursor = Transaction().connection.cursor()
(query, tab_asset) = cls.get_rate_data_sql() (query, tab_asset) = cls.get_rate_data_sql()
query.where=tab_asset.id.in_([x.id for x in assets]) query.where = tab_asset.id.in_([x.id for x in assets])
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
result = {x:{y.id: None for y in assets} for x in names} result = {x: {y.id: None for y in assets} for x in names}
for record in records: for record in records:
(id1, rate1, date1, id_rate) = record (id1, rate1, date1, id_rate) = record
@ -413,7 +432,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query = tab_query.select( query = tab_query.select(
tab_query.date, tab_query.date,
where=tab_query.id==table.id, where=tab_query.id == table.id,
) )
return [query] return [query]
@ -426,7 +445,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query = tab_query.select( query = tab_query.select(
tab_query.rate, tab_query.rate,
where=tab_query.id==table.id, where=tab_query.id == table.id,
) )
return [query] return [query]
@ -449,8 +468,9 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
if isinstance(asset_ids, list): if isinstance(asset_ids, list):
where_asset &= tab_asset.id.in_(asset_ids) where_asset &= tab_asset.id.in_(asset_ids)
tab_today = tab_asset.join(tab_rate1, tab_today = tab_asset.join(
condition=tab_asset.id==tab_rate1.asset, tab_rate1,
condition=tab_asset.id == tab_rate1.asset,
).select( ).select(
tab_asset.id, tab_asset.id,
tab_rate1.date, tab_rate1.date,
@ -461,16 +481,18 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
) )
days_diff = days + 5 days_diff = days + 5
query = tab_today.join(tab_rate2, query = tab_today.join(
condition=(tab_today.id==tab_rate2.asset) & \ tab_rate2,
(tab_today.date > (tab_rate2.date + days)) & \ condition=(tab_today.id == tab_rate2.asset) &
(tab_today.date <= (tab_rate2.date + days_diff)), (tab_today.date > (tab_rate2.date + days)) &
type_ = 'LEFT OUTER', (tab_today.date <= (tab_rate2.date + days_diff)),
type_='LEFT OUTER',
).select( ).select(
tab_today.id, tab_today.id,
tab_today.date, tab_today.date,
tab_today.rate, tab_today.rate,
(tab_today.rate * 100.0 / NullIf(tab_rate2.rate, 0.00) - 100.0).as_('percent'), (tab_today.rate * 100.0 / NullIf(tab_rate2.rate, 0.00) -
100.0).as_('percent'),
distinct_on=[tab_today.id], distinct_on=[tab_today.id],
order_by=[tab_today.id, tab_rate2.date.desc] order_by=[tab_today.id, tab_rate2.date.desc]
) )
@ -480,13 +502,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
def order_change_day1(tables): def order_change_day1(tables):
""" order day1 """ order day1
""" """
Assert = Pool().get('investment.asset') Asset2 = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(days=0) tab_asset = Asset2.get_percentage_sql(days=0)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.percent, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id == table.id,
) )
return [query] return [query]
@ -494,13 +516,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
def order_change_month1(tables): def order_change_month1(tables):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Asset2 = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(days=30) tab_asset = Asset2.get_percentage_sql(days=30)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.percent, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id == table.id,
) )
return [query] return [query]
@ -508,13 +530,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
def order_change_month3(tables): def order_change_month3(tables):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Asset2 = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(days=90) tab_asset = Asset2.get_percentage_sql(days=90)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.percent, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id == table.id,
) )
return [query] return [query]
@ -522,13 +544,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
def order_change_month6(tables): def order_change_month6(tables):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Asset2 = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(days=180) tab_asset = Asset2.get_percentage_sql(days=180)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.percent, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id == table.id,
) )
return [query] return [query]
@ -536,13 +558,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
def order_change_month12(tables): def order_change_month12(tables):
""" order month1 """ order month1
""" """
Assert = Pool().get('investment.asset') Asset2 = Pool().get('investment.asset')
tab_asset = Asset.get_percentage_sql(days=365) tab_asset = Asset2.get_percentage_sql(days=365)
table, _ = tables[None] table, _ = tables[None]
query = tab_asset.select( query = tab_asset.select(
tab_asset.percent, tab_asset.percent,
where=tab_asset.id==table.id, where=tab_asset.id == table.id,
) )
return [query] return [query]
@ -560,9 +582,9 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
'month12': 365, 'month12': 365,
}[field_name]) }[field_name])
query = tab_percent.select(tab_percent.id, query = tab_percent.select(
where=Operator(Round(tab_percent.percent, 2), tab_percent.id,
clause[2])) where=Operator(Round(tab_percent.percent, 2), clause[2]))
return [('id', 'in', query)] return [('id', 'in', query)]
@classmethod @classmethod
@ -571,7 +593,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
""" """
cursor = Transaction().connection.cursor() cursor = Transaction().connection.cursor()
result = {x:{y.id: None for y in assets} for x in names} result = {x: {y.id: None for y in assets} for x in names}
exp = Decimal(Decimal(1) / 10 ** digits_percent) exp = Decimal(Decimal(1) / 10 ** digits_percent)
asset_id_lst = [x.id for x in assets] asset_id_lst = [x.id for x in assets]
@ -610,30 +632,34 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query_date = context.get('qdate', CurrentDate() - Literal(1)) query_date = context.get('qdate', CurrentDate() - Literal(1))
# get last date of rate # get last date of rate
tab_date = tab_asset.join(tab_rel, tab_date = tab_asset.join(
tab_rel,
# link to asset-source-relation to check if # link to asset-source-relation to check if
# there are online-sources set # there are online-sources set
condition=tab_rel.asset == tab_asset.id, condition=tab_rel.asset == tab_asset.id,
).join(tab_rate, ).join(
tab_rate,
condition=tab_asset.id == tab_rate.asset, condition=tab_asset.id == tab_rate.asset,
type_ = 'LEFT OUTER', type_='LEFT OUTER',
).select( ).select(
tab_asset.id, tab_asset.id,
(Coalesce(tab_rate.date, query_date) + Literal(1)).as_('date'), (Coalesce(tab_rate.date, query_date) + Literal(1)).as_('date'),
tab_asset.updtdays, tab_asset.updtdays,
tab_asset.updttime, tab_asset.updttime,
distinct_on = [tab_asset.id], distinct_on=[tab_asset.id],
order_by = [tab_asset.id, tab_rate.date.desc], order_by=[tab_asset.id, tab_rate.date.desc],
) )
query = tab_date.select( query = tab_date.select(
tab_date.id, tab_date.id,
(Case( (Case(
((tab_date.updtdays == 'work') & \ ((tab_date.updtdays == 'work') &
(Extract('dow', tab_date.date) == 0), tab_date.date + Literal(1)), (Extract('dow', tab_date.date) == 0),
((tab_date.updtdays == 'work') & \ tab_date.date + Literal(1)),
(Extract('dow', tab_date.date) == 6), tab_date.date + Literal(2)), ((tab_date.updtdays == 'work') &
else_ = tab_date.date, (Extract('dow', tab_date.date) == 6),
tab_date.date + Literal(2)),
else_=tab_date.date,
) + tab_date.updttime).as_('updttime'), ) + tab_date.updttime).as_('updttime'),
) )
return query return query
@ -654,7 +680,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
result = {x:{y.id: None for y in assets} for x in names} result = {x: {y.id: None for y in assets} for x in names}
for record in records: for record in records:
(id1, updt) = record (id1, updt) = record
@ -690,20 +716,24 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
tab_secsymb = Identifier.__table__() tab_secsymb = Identifier.__table__()
tab_isin = Identifier.__table__() tab_isin = Identifier.__table__()
query = tab_asset.join(tab_prod, query = tab_asset.join(
condition=tab_asset.product==tab_prod.id, tab_prod,
).join(tab_wkn, condition=tab_asset.product == tab_prod.id,
condition=(tab_prod.id==tab_wkn.product) & \ ).join(
(tab_wkn.type == 'wkn'), tab_wkn,
type_ = 'LEFT OUTER', condition=(tab_prod.id == tab_wkn.product) &
).join(tab_secsymb, (tab_wkn.type == 'wkn'),
condition=(tab_prod.id==tab_secsymb.product) & \ type_='LEFT OUTER',
(tab_secsymb.type == 'secsymb'), ).join(
type_ = 'LEFT OUTER', tab_secsymb,
).join(tab_isin, condition=(tab_prod.id == tab_secsymb.product) &
condition=(tab_prod.id==tab_isin.product) & \ (tab_secsymb.type == 'secsymb'),
(tab_isin.type == 'isin'), type_='LEFT OUTER',
type_ = 'LEFT OUTER', ).join(
tab_isin,
condition=(tab_prod.id == tab_isin.product) &
(tab_isin.type == 'isin'),
type_='LEFT OUTER',
).select( ).select(
tab_asset.id, tab_asset.id,
tab_wkn.code.as_('wkn'), tab_wkn.code.as_('wkn'),
@ -725,12 +755,15 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
tab_prod = Product.__table__() tab_prod = Product.__table__()
tab_templ = Templ.__table__() tab_templ = Templ.__table__()
query = tab_asset.join(tab_prod, query = tab_asset.join(
condition=tab_asset.product==tab_prod.id tab_prod,
).join(tab_templ, condition=tab_asset.product == tab_prod.id
condition=tab_templ.id==tab_prod.template ).join(
).select(tab_templ.name, tab_templ,
where=tab_asset.id==table.id condition=tab_templ.id == tab_prod.template
).select(
tab_templ.name,
where=tab_asset.id == table.id
) )
return [query] return [query]
@ -744,7 +777,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query = tab_ids.select( query = tab_ids.select(
getattr(tab_ids, 'wkn'), getattr(tab_ids, 'wkn'),
where=tab_ids.id==table.id, where=tab_ids.id == table.id,
) )
return [query] return [query]
@ -758,7 +791,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query = tab_ids.select( query = tab_ids.select(
getattr(tab_ids, 'isin'), getattr(tab_ids, 'isin'),
where=tab_ids.id==table.id, where=tab_ids.id == table.id,
) )
return [query] return [query]
@ -772,7 +805,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query = tab_ids.select( query = tab_ids.select(
getattr(tab_ids, 'secsymb'), getattr(tab_ids, 'secsymb'),
where=tab_ids.id==table.id, where=tab_ids.id == table.id,
) )
return [query] return [query]
@ -787,12 +820,13 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
tab_ids = cls.get_identifier_sql(tab_asset) tab_ids = cls.get_identifier_sql(tab_asset)
field_qu = getattr(tab_ids, names) field_qu = getattr(tab_ids, names)
query = tab_ids.join(tab_asset, query = tab_ids.join(
condition=tab_ids.id==tab_asset.id, tab_asset,
condition=tab_ids.id == tab_asset.id,
).select( ).select(
tab_asset.id, tab_asset.id,
where=Operator(field_qu, clause[2]) & \ where=Operator(field_qu, clause[2]) &
(field_qu != None), (field_qu != None),
) )
return [('id', 'in', query)] return [('id', 'in', query)]
@ -806,7 +840,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
tab_asset = Asset.__table__() tab_asset = Asset.__table__()
cursor = Transaction().connection.cursor() cursor = Transaction().connection.cursor()
result = {x:{y.id: None for y in assets} for x in names} result = {x: {y.id: None for y in assets} for x in names}
query = cls.get_identifier_sql(tab_asset) query = cls.get_identifier_sql(tab_asset)
query.where = tab_asset.id.in_([x.id for x in assets]) query.where = tab_asset.id.in_([x.id for x in assets])
@ -829,17 +863,18 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
return '%(prod)s | %(rate)s %(unit)s | %(date)s' % { return '%(prod)s | %(rate)s %(unit)s | %(date)s' % {
'prod': getattr(self.product, 'rec_name', '-'), 'prod': getattr(self.product, 'rec_name', '-'),
'unit': self.symbol, 'unit': self.symbol,
'rate': Report.format_number(self.rate, lang=None, 'rate': Report.format_number(
digits=self.currency_digits or 4) \ self.rate, lang=None, digits=self.currency_digits or 4)
if self.rate is not None else '-', if self.rate is not None else '-',
'date': Report.format_date(self.date) if self.date is not None else '-', 'date': Report.format_date(self.date)
} if self.date is not None else '-'}
@classmethod @classmethod
def search_rec_name(cls, name, clause): def search_rec_name(cls, name, clause):
""" search in rec_name """ search in rec_name
""" """
return ['OR', return [
'OR',
('product.rec_name',) + tuple(clause[1:]), ('product.rec_name',) + tuple(clause[1:]),
('product.identifiers.code',) + tuple(clause[1:]), ('product.identifiers.code',) + tuple(clause[1:]),
] ]
@ -862,8 +897,7 @@ class Asset(SymbolMixin, ModelSQL, ModelView):
query_time = context.get('qdatetime', CurrentTimestamp()) query_time = context.get('qdatetime', CurrentTimestamp())
to_run_activities = [] to_run_activities = []
for asset in Asset2.search([ for asset in Asset2.search([
('nextupdate', '<=', query_time), ('nextupdate', '<=', query_time)]):
]):
if OnlineSource.update_rate(asset): if OnlineSource.update_rate(asset):
to_run_activities.append(asset) to_run_activities.append(asset)
@ -877,10 +911,12 @@ class AssetSourceRel(ModelSQL):
'Asset Source Relation' 'Asset Source Relation'
__name__ = 'investment.asset_source_rel' __name__ = 'investment.asset_source_rel'
source = fields.Many2One(string='Online Source', select=True, source = fields.Many2One(
string='Online Source', select=True,
required=True, model_name='investment.source', required=True, model_name='investment.source',
ondelete='CASCADE') ondelete='CASCADE')
asset = fields.Many2One(string='Asset', select=True, asset = fields.Many2One(
string='Asset', select=True,
required=True, model_name='investment.asset', required=True, model_name='investment.asset',
ondelete='CASCADE') ondelete='CASCADE')

View file

@ -22,8 +22,8 @@ class Concat2(Function):
class GraphDef(metaclass=PoolMeta): class GraphDef(metaclass=PoolMeta):
__name__ = 'diagram.graphdef' __name__ = 'diagram.graphdef'
asset = fields.Many2One(string='Asset', asset = fields.Many2One(
model_name='investment.asset', string='Asset', model_name='investment.asset',
states={ states={
'invisible': Eval('dtype', '') != 'investment.asset', 'invisible': Eval('dtype', '') != 'investment.asset',
'required': Eval('dtype', '') == 'investment.asset', 'required': Eval('dtype', '') == 'investment.asset',
@ -70,7 +70,8 @@ class GraphDef(metaclass=PoolMeta):
elif self.scaling == 'six': elif self.scaling == 'six':
query = [ query = [
('asset.id', '=', self.asset.id), ('asset.id', '=', self.asset.id),
('date', '>=', self.chart.used_start_date() - timedelta(days=180)), ('date', '>=', self.chart.used_start_date() -
timedelta(days=180)),
('date', '<=', self.chart.used_end_date()), ('date', '<=', self.chart.used_end_date()),
] ]

View file

@ -4,7 +4,7 @@
# full copyright notices and license terms. # full copyright notices and license terms.
from io import StringIO from io import StringIO
from datetime import datetime, date from datetime import datetime, date
from decimal import Decimal from decimal import Decimal
import csv import csv
from trytond.pool import Pool from trytond.pool import Pool
@ -36,15 +36,15 @@ class ImportWizardStart(ModelView):
'Import CSV-File' 'Import CSV-File'
__name__ = 'investment.imp_wiz.start' __name__ = 'investment.imp_wiz.start'
asset = fields.Many2One(string='Asset', readonly=True, asset = fields.Many2One(
model_name='investment.asset') string='Asset', readonly=True, model_name='investment.asset')
file_ = fields.Binary(string="CSV-File", required=True) file_ = fields.Binary(string="CSV-File", required=True)
dec_divider = fields.Selection(string='Decimal divider', dec_divider = fields.Selection(
required=True, selection=sel_dec_divider) string='Decimal divider', required=True, selection=sel_dec_divider)
date_fmt = fields.Selection(string='Date format', date_fmt = fields.Selection(
required=True, selection=sel_date_fmt) string='Date format', required=True, selection=sel_date_fmt)
field_delimiter = fields.Selection(string='Field delimiter', field_delimiter = fields.Selection(
required=True, selection=sel_field_delimiter) string='Field delimiter', required=True, selection=sel_field_delimiter)
# end ImportWizardStart # end ImportWizardStart
@ -54,11 +54,14 @@ class ImportWizard(Wizard):
__name__ = 'investment.imp_wiz' __name__ = 'investment.imp_wiz'
start_state = 'start' start_state = 'start'
start = StateView(model_name='investment.imp_wiz.start', \ start = StateView(
view='investment.imp_wiz_start_form', \ model_name='investment.imp_wiz.start',
view='investment.imp_wiz_start_form',
buttons=[ buttons=[
Button(string='Cancel', state='end', icon='tryton-cancel'), Button(string='Cancel', state='end', icon='tryton-cancel'),
Button(string='Import File', state='importf', icon='tryton-import', default=True), Button(
string='Import File', state='importf',
icon='tryton-import', default=True),
]) ])
importf = StateTransition() importf = StateTransition()
@ -84,9 +87,9 @@ class ImportWizard(Wizard):
if self.start.file_ is not None: if self.start.file_ is not None:
(lines, max_date, min_date) = ImportWiz.read_csv_file( (lines, max_date, min_date) = ImportWiz.read_csv_file(
self.start.file_.decode('utf8'), self.start.file_.decode('utf8'),
dec_divider = self.start.dec_divider, dec_divider=self.start.dec_divider,
date_fmt = self.start.date_fmt, date_fmt=self.start.date_fmt,
delimiter = self.start.field_delimiter) delimiter=self.start.field_delimiter)
if len(lines) > 0: if len(lines) > 0:
ImportWiz.upload_rates( ImportWiz.upload_rates(
@ -140,33 +143,35 @@ class ImportWizard(Wizard):
max_rate = None max_rate = None
with StringIO(file_content) as fhdl: with StringIO(file_content) as fhdl:
csv_lines = csv.DictReader(fhdl, csv_lines = csv.DictReader(
fieldnames = ['date', 'rate'], fhdl,
dialect='excel', fieldnames=['date', 'rate'],
delimiter=delimiter) dialect='excel',
delimiter=delimiter)
for line in csv_lines: for line in csv_lines:
# skip first line # skip first line
if line.get('date', '') == 'date': if line.get('date', '') == 'date':
continue continue
try : try:
date_val = datetime.strptime(line.get('date', None).strip(), date_fmt).date() date_val = datetime.strptime(
except : line.get('date', None).strip(), date_fmt).date()
except Exception:
raise UserError(gettext( raise UserError(gettext(
'investment.msg_import_err_date', 'investment.msg_import_err_date',
datefmt = date_fmt, datefmt=date_fmt,
colnr = '1', colnr='1',
)) ))
try : try:
rate_val = line.get('rate', None).replace(del_chars[0], '').strip() rate_val = line.get('rate', None).replace(
del_chars[0], '').strip()
rate_val = Decimal(rate_val.replace(dec_divider, '.')) rate_val = Decimal(rate_val.replace(dec_divider, '.'))
except : except Exception:
raise UserError(gettext( raise UserError(gettext(
'investment.msg_import_err_date', 'investment.msg_import_err_date',
datefmt = 'dd%sdd' % dec_divider, datefmt='dd%sdd' % dec_divider,
colnr = '2', colnr='2'))
))
if isinstance(date_val, date) and isinstance(rate_val, Decimal): if isinstance(date_val, date) and isinstance(rate_val, Decimal):
result.append({'date': date_val, 'rate': rate_val}) result.append({'date': date_val, 'rate': rate_val})
@ -174,34 +179,32 @@ class ImportWizard(Wizard):
# date range # date range
if max_date is None: if max_date is None:
max_date = date_val max_date = date_val
else : else:
if max_date < date_val: if max_date < date_val:
max_date = date_val max_date = date_val
if min_date is None: if min_date is None:
min_date = date_val min_date = date_val
else : else:
if min_date > date_val: if min_date > date_val:
min_date = date_val min_date = date_val
# rate range # rate range
if max_rate is None: if max_rate is None:
max_rate = rate_val max_rate = rate_val
else : else:
if max_rate < rate_val: if max_rate < rate_val:
max_rate = rate_val max_rate = rate_val
if min_rate is None: if min_rate is None:
min_rate = rate_val min_rate = rate_val
else : else:
if min_rate > rate_val: if min_rate > rate_val:
min_rate = rate_val min_rate = rate_val
else : else:
raise UserError(gettext( raise UserError(gettext(
'investment.msg_err_unknown_content', 'investment.msg_err_unknown_content',
linetxt = line, linetxt=line))
))
return (result, max_date, min_date) return (result, max_date, min_date)
# end ImportWizard # end ImportWizard

View file

@ -309,7 +309,7 @@ class OnlineSource(ModelSQL, ModelView):
oname=self.rec_name, oname=self.rec_name,
)) ))
return url return url
else : else:
if self.url: if self.url:
return Template(self.url).substitute({ return Template(self.url).substitute({
'isin': isin if isin is not None else '', 'isin': isin if isin is not None else '',

39
rate.py
View file

@ -3,33 +3,35 @@
# The COPYRIGHT file at the top level of this repository contains the # The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms. # full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields, Unique, Check, SymbolMixin from trytond.model import (
ModelView, ModelSQL, fields, Unique, Check, SymbolMixin)
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.pyson import Eval, Bool from trytond.pyson import Eval
class Rate(SymbolMixin, ModelSQL, ModelView): class Rate(SymbolMixin, ModelSQL, ModelView):
'Rate' 'Rate'
__name__ = 'investment.rate' __name__ = 'investment.rate'
asset = fields.Many2One(string='Asset', required=True, asset = fields.Many2One(
select=True, ondelete='CASCADE', string='Asset', required=True, select=True, ondelete='CASCADE',
model_name='investment.asset') model_name='investment.asset')
date = fields.Date(string='Date', required=True, select=True) date = fields.Date(string='Date', required=True, select=True)
rate = fields.Numeric(string='Rate', required=True, select=True, rate = fields.Numeric(
digits=(16, Eval('asset_digits', 4)), string='Rate', required=True, select=True,
depends=['asset_digits']) digits=(16, Eval('asset_digits', 4)), depends=['asset_digits'])
asset_digits = fields.Function(fields.Integer(string='Digits', asset_digits = fields.Function(fields.Integer(
readonly=True), 'get_rate_data') string='Digits', readonly=True), 'get_rate_data')
currency = fields.Function(fields.Many2One(string='Currency', currency = fields.Function(fields.Many2One(
readonly=True, model_name='currency.currency'), string='Currency', readonly=True, model_name='currency.currency'),
'get_rate_data') 'get_rate_data')
uom = fields.Function(fields.Many2One(string='Uom', uom = fields.Function(fields.Many2One(
readonly=True, model_name='product.uom'), 'get_rate_data') string='Uom', readonly=True, model_name='product.uom'),
symbol = fields.Function(fields.Char(string='Symbol', 'get_rate_data')
readonly=True), 'get_rate_data') symbol = fields.Function(fields.Char(
string='Symbol', readonly=True), 'get_rate_data')
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
@ -62,8 +64,9 @@ class Rate(SymbolMixin, ModelSQL, ModelView):
tab_rate = cls.__table__() tab_rate = cls.__table__()
cursor = Transaction().connection.cursor() cursor = Transaction().connection.cursor()
query = tab_asset.join(tab_rate, query = tab_asset.join(
condition=tab_asset.id==tab_rate.asset, tab_rate,
condition=tab_asset.id == tab_rate.asset,
).select( ).select(
tab_rate.id, tab_rate.id,
tab_asset.uom, tab_asset.uom,
@ -74,7 +77,7 @@ class Rate(SymbolMixin, ModelSQL, ModelView):
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
result = {x:{y.id: None for y in rates} for x in names} result = {x: {y.id: None for y in rates} for x in names}
for record in records: for record in records:
r1 = { r1 = {
'symbol': '%', 'symbol': '%',

View file

@ -2,7 +2,7 @@
""" """
# Always prefer setuptools over distutils # Always prefer setuptools over distutils
from setuptools import setup, find_packages from setuptools import setup
# To use a consistent encoding # To use a consistent encoding
from codecs import open from codecs import open
from os import path from os import path
@ -36,7 +36,7 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f:
l2 = i.strip().split(';') l2 = i.strip().split(';')
if len(l2) < 4: if len(l2) < 4:
continue continue
modversion[l2[0]] = {'min':l2[1], 'max':l2[2], 'prefix':l2[3]} modversion[l2[0]] = {'min': l2[1], 'max': l2[2], 'prefix': l2[3]}
# tryton-version # tryton-version
major_version = 6 major_version = 6
@ -51,19 +51,21 @@ for dep in info.get('depends', []):
prefix = modversion[dep]['prefix'] prefix = modversion[dep]['prefix']
if len(modversion[dep]['max']) > 0: if len(modversion[dep]['max']) > 0:
requires.append('%s_%s >= %s, <= %s' % requires.append('%s_%s >= %s, <= %s' % (
(prefix, dep, modversion[dep]['min'], modversion[dep]['max'])) prefix, dep, modversion[dep]['min'],
else : modversion[dep]['max']))
requires.append('%s_%s >= %s' % else:
(prefix, dep, modversion[dep]['min'])) requires.append('%s_%s >= %s' % (
else : prefix, dep, modversion[dep]['min']))
requires.append('%s_%s >= %s.%s, < %s.%s' % else:
('trytond', dep, major_version, minor_version, requires.append('%s_%s >= %s.%s, < %s.%s' % (
'trytond', dep, major_version, minor_version,
major_version, minor_version + 1)) major_version, minor_version + 1))
requires.append('trytond >= %s.%s, < %s.%s' % requires.append('trytond >= %s.%s, < %s.%s' % (
(major_version, minor_version, major_version, minor_version + 1)) major_version, minor_version, major_version, minor_version + 1))
setup(name='%s_%s' % (PREFIX, MODULE), setup(
name='%s_%s' % (PREFIX, MODULE),
version=info.get('version', '0.0.1'), version=info.get('version', '0.0.1'),
description='Tryton module to add investment items.', description='Tryton module to add investment items.',
long_description=long_description, long_description=long_description,
@ -74,21 +76,21 @@ setup(name='%s_%s' % (PREFIX, MODULE),
author_email='service@m-ds.de', author_email='service@m-ds.de',
license='GPL-3', license='GPL-3',
classifiers=[ classifiers=[
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
'Environment :: Plugins', 'Environment :: Plugins',
'Framework :: Tryton', 'Framework :: Tryton',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'Intended Audience :: Customer Service', 'Intended Audience :: Customer Service',
'Intended Audience :: Information Technology', 'Intended Audience :: Information Technology',
'Intended Audience :: Financial and Insurance Industry', 'Intended Audience :: Financial and Insurance Industry',
'Topic :: Office/Business', 'Topic :: Office/Business',
'Topic :: Office/Business :: Financial :: Accounting', 'Topic :: Office/Business :: Financial :: Accounting',
'Natural Language :: German', 'Natural Language :: German',
'Natural Language :: English', 'Natural Language :: English',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'License :: OSI Approved :: GNU General Public License (GPL)', 'License :: OSI Approved :: GNU General Public License (GPL)',
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.8',
], ],
keywords='tryton investment shares commodities', keywords='tryton investment shares commodities',
@ -97,10 +99,10 @@ setup(name='%s_%s' % (PREFIX, MODULE),
'trytond.modules.%s' % MODULE, 'trytond.modules.%s' % MODULE,
], ],
package_data={ package_data={
'trytond.modules.%s' % MODULE: (info.get('xml', []) 'trytond.modules.%s' % MODULE: (info.get('xml', []) + [
+ ['tryton.cfg', 'locale/*.po', 'tests/*.py', 'tryton.cfg', 'locale/*.po', 'tests/*.py',
'view/*.xml', 'icon/*.svg', 'scripts/*.py', 'view/*.xml', 'icon/*.svg', 'scripts/*.py',
'versiondep.txt', 'README.rst']), 'versiondep.txt', 'README.rst']),
}, },
install_requires=requires, install_requires=requires,

View file

@ -4,27 +4,14 @@
import trytond.tests.test_tryton import trytond.tests.test_tryton
import unittest import unittest
from trytond.modules.investment.tests.test_asset import AssetTestCase from .test_module import InvestmentTestCase
from trytond.modules.investment.tests.test_rate import RateTestCase
from trytond.modules.investment.tests.test_source import SourceTestCase
from trytond.modules.investment.tests.test_wizard import WizardTestCase
__all__ = ['suite'] __all__ = ['suite']
class InvestmentTestCase(\
WizardTestCase, \
SourceTestCase, \
RateTestCase,\
AssetTestCase,\
):
'Test investment module'
module = 'investment'
# end InvestmentTestCase
def suite(): def suite():
suite = trytond.tests.test_tryton.suite() suite = trytond.tests.test_tryton.suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(InvestmentTestCase)) suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
InvestmentTestCase))
return suite return suite

View file

@ -3,7 +3,7 @@
# The COPYRIGHT file at the top level of this repository contains the # The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms. # full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.tests.test_tryton import with_transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.modules.company.tests import create_company from trytond.modules.company.tests import create_company
from trytond.transaction import Transaction from trytond.transaction import Transaction
@ -12,10 +12,9 @@ from decimal import Decimal
from datetime import time, date, datetime from datetime import time, date, datetime
class AssetTestCase(ModuleTestCase): class AssetTestCase(object):
'Test asset module' """ test asset
module = 'investment' """
def prep_asset_company(self): def prep_asset_company(self):
""" get/create company """ get/create company
""" """
@ -24,11 +23,13 @@ class AssetTestCase(ModuleTestCase):
company = Company.search([]) company = Company.search([])
if len(company) > 0: if len(company) > 0:
company = company[0] company = company[0]
else : else:
company = create_company(name='m-ds') company = create_company(name='m-ds')
return company return company
def prep_asset_product(self, name='Product 1', description=None, unit='u', unit_name='Units'): def prep_asset_product(
self, name='Product 1', description=None, unit='u',
unit_name='Units'):
""" create product """ create product
""" """
pool = Pool() pool = Pool()
@ -85,7 +86,7 @@ class AssetTestCase(ModuleTestCase):
asset = self.prep_asset_item( asset = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
self.assertEqual(asset.symbol, 'usd/u') self.assertEqual(asset.symbol, 'usd/u')
self.assertEqual(asset.asset_symbol.symbol, 'usd/u') self.assertEqual(asset.asset_symbol.symbol, 'usd/u')
@ -95,7 +96,8 @@ class AssetTestCase(ModuleTestCase):
{ {
'currency_digits': 1, 'currency_digits': 1,
}]) }])
self.assertRaisesRegex(UserError, self.assertRaisesRegex(
UserError,
'ss', 'ss',
Asset.write, Asset.write,
*[[asset], { *[[asset], {
@ -115,7 +117,7 @@ class AssetTestCase(ModuleTestCase):
asset = self.prep_asset_item( asset = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
self.assertEqual(asset.rec_name, 'Product 1 | - usd/u | -') self.assertEqual(asset.rec_name, 'Product 1 | - usd/u | -')
@ -127,7 +129,9 @@ class AssetTestCase(ModuleTestCase):
'rate': Decimal('2.45'), 'rate': Decimal('2.45'),
}])], }])],
}]) }])
self.assertEqual(asset.rec_name, 'Product 1 | 2.4500 usd/u | 05/15/2022') self.assertEqual(
asset.rec_name,
'Product 1 | 2.4500 usd/u | 05/15/2022')
self.assertEqual(Asset.search_count([('name', '=', 'Product 1')]), 1) self.assertEqual(Asset.search_count([('name', '=', 'Product 1')]), 1)
@with_transaction() @with_transaction()
@ -146,10 +150,10 @@ class AssetTestCase(ModuleTestCase):
asset1 = self.prep_asset_item( asset1 = self.prep_asset_item(
company=company, company=company,
product = product1) product=product1)
asset2 = self.prep_asset_item( asset2 = self.prep_asset_item(
company=company, company=company,
product = product2) product=product2)
Asset.write(*[ Asset.write(*[
[asset1], [asset1],
@ -173,8 +177,12 @@ class AssetTestCase(ModuleTestCase):
}])], }])],
}, },
]) ])
self.assertEqual(asset1.rec_name, 'Product 1 | 3.5000 usd/u | 05/18/2022') self.assertEqual(
self.assertEqual(asset2.rec_name, 'Product 2 | 2.6000 usd/u | 05/17/2022') asset1.rec_name,
'Product 1 | 3.5000 usd/u | 05/18/2022')
self.assertEqual(
asset2.rec_name,
'Product 2 | 2.6000 usd/u | 05/17/2022')
assets = Asset.search([], order=[('date', 'ASC')]) assets = Asset.search([], order=[('date', 'ASC')])
self.assertEqual(len(assets), 2) self.assertEqual(len(assets), 2)
@ -221,7 +229,7 @@ class AssetTestCase(ModuleTestCase):
asset1 = self.prep_asset_item( asset1 = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
self.assertEqual(asset1.rec_name, 'Product 1 | - usd/u | -') self.assertEqual(asset1.rec_name, 'Product 1 | - usd/u | -')
Asset.write(*[ Asset.write(*[
@ -242,7 +250,9 @@ class AssetTestCase(ModuleTestCase):
}])], }])],
}, },
]) ])
self.assertEqual(asset1.rec_name, 'Product 1 | 2.6000 usd/u | 05/16/2022') self.assertEqual(
asset1.rec_name,
'Product 1 | 2.6000 usd/u | 05/16/2022')
self.assertEqual(len(asset1.rates), 4) self.assertEqual(len(asset1.rates), 4)
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16)) self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 15)) self.assertEqual(asset1.rates[1].date, date(2022, 5, 15))
@ -252,13 +262,12 @@ class AssetTestCase(ModuleTestCase):
# query fixed date # query fixed date
tab_percent = Asset.get_percentage_sql(days=0) tab_percent = Asset.get_percentage_sql(days=0)
with Transaction().set_context({ with Transaction().set_context({
'qdate': date(2022, 5, 16), 'qdate': date(2022, 5, 16)}):
}):
query = tab_percent.select( query = tab_percent.select(
tab_percent.id, tab_percent.id,
tab_percent.date, tab_percent.date,
tab_percent.percent, tab_percent.percent,
where=tab_percent.id==asset1.id, where=tab_percent.id == asset1.id,
) )
cursor.execute(*query) cursor.execute(*query)
records = cursor.fetchall() records = cursor.fetchall()
@ -268,7 +277,9 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(len(records[0]), 3) self.assertEqual(len(records[0]), 3)
self.assertEqual(records[0][0], asset1.id) self.assertEqual(records[0][0], asset1.id)
self.assertEqual(records[0][1], date(2022, 5, 16)) self.assertEqual(records[0][1], date(2022, 5, 16))
self.assertEqual(records[0][2].quantize(Decimal('0.01')), Decimal('6.12')) self.assertEqual(
records[0][2].quantize(Decimal('0.01')),
Decimal('6.12'))
@with_transaction() @with_transaction()
def test_asset_percentages_daterange(self): def test_asset_percentages_daterange(self):
@ -284,10 +295,10 @@ class AssetTestCase(ModuleTestCase):
asset1 = self.prep_asset_item( asset1 = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
asset2 = self.prep_asset_item( asset2 = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
self.assertEqual(asset1.rec_name, 'Product 1 | - usd/u | -') self.assertEqual(asset1.rec_name, 'Product 1 | - usd/u | -')
self.assertEqual(asset2.rec_name, 'Product 1 | - usd/u | -') self.assertEqual(asset2.rec_name, 'Product 1 | - usd/u | -')
@ -314,8 +325,12 @@ class AssetTestCase(ModuleTestCase):
}])], }])],
}, },
]) ])
self.assertEqual(asset1.rec_name, 'Product 1 | 2.6000 usd/u | 05/16/2022') self.assertEqual(
self.assertEqual(asset2.rec_name, 'Product 1 | 5.2500 usd/u | 05/15/2022') asset1.rec_name,
'Product 1 | 2.6000 usd/u | 05/16/2022')
self.assertEqual(
asset2.rec_name,
'Product 1 | 5.2500 usd/u | 05/15/2022')
self.assertEqual(asset1.change_day1, Decimal('6.12')) self.assertEqual(asset1.change_day1, Decimal('6.12'))
self.assertEqual(asset2.change_day1, Decimal('-8.7')) self.assertEqual(asset2.change_day1, Decimal('-8.7'))
self.assertEqual(asset1.change_month1, None) self.assertEqual(asset1.change_month1, None)
@ -390,7 +405,7 @@ class AssetTestCase(ModuleTestCase):
asset1 = self.prep_asset_item( asset1 = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
self.assertEqual(asset1.rec_name, 'Product 1 | - usd/u | -') self.assertEqual(asset1.rec_name, 'Product 1 | - usd/u | -')
@ -411,7 +426,9 @@ class AssetTestCase(ModuleTestCase):
'rate': Decimal('2.8'), 'rate': Decimal('2.8'),
},])], },])],
}]) }])
self.assertEqual(asset1.rec_name, 'Product 1 | 2.6000 usd/u | 05/16/2022') self.assertEqual(
asset1.rec_name,
'Product 1 | 2.6000 usd/u | 05/16/2022')
self.assertEqual(len(asset1.rates), 4) self.assertEqual(len(asset1.rates), 4)
self.assertEqual(asset1.rates[0].date, date(2022, 5, 16)) self.assertEqual(asset1.rates[0].date, date(2022, 5, 16))
self.assertEqual(asset1.rates[1].date, date(2022, 5, 15)) self.assertEqual(asset1.rates[1].date, date(2022, 5, 15))
@ -465,7 +482,6 @@ class AssetTestCase(ModuleTestCase):
""" """
pool = Pool() pool = Pool()
OnlineSource = pool.get('investment.source') OnlineSource = pool.get('investment.source')
Asset = pool.get('investment.asset')
company = self.prep_asset_company() company = self.prep_asset_company()
product = self.prep_asset_product( product = self.prep_asset_product(
@ -474,14 +490,14 @@ class AssetTestCase(ModuleTestCase):
asset = self.prep_asset_item( asset = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
o_source, = OnlineSource.create([{ o_source, = OnlineSource.create([{
'name': 'Source 1', 'name': 'Source 1',
}]) }])
self.assertEqual(len(asset.updtsources), 0) self.assertEqual(len(asset.updtsources), 0)
self.assertEqual(asset.updttime, time(14,0)) self.assertEqual(asset.updttime, time(14, 0))
asset.updtsources = [o_source] asset.updtsources = [o_source]
asset.updttime = time(10, 45) asset.updttime = time(10, 45)
@ -511,7 +527,7 @@ class AssetTestCase(ModuleTestCase):
asset = self.prep_asset_item( asset = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
o_source, = OnlineSource.create([{ o_source, = OnlineSource.create([{
'name': 'Source 1', 'name': 'Source 1',
@ -524,8 +540,8 @@ class AssetTestCase(ModuleTestCase):
}]) }])
with Transaction().set_context({ with Transaction().set_context({
'qdate': date(2022, 10, 14), # friday
}): 'qdate': date(2022, 10, 14)}):
# re-read to make context work # re-read to make context work
asset2, = Asset.browse([asset.id]) asset2, = Asset.browse([asset.id])
@ -539,10 +555,12 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(asset2.nextupdate, datetime(2022, 10, 17, 10, 45)) self.assertEqual(asset2.nextupdate, datetime(2022, 10, 17, 10, 45))
self.assertEqual( self.assertEqual(
Asset.search_count([('nextupdate', '<', datetime(2022, 10, 17, 10, 45))]), Asset.search_count([
('nextupdate', '<', datetime(2022, 10, 17, 10, 45))]),
0) 0)
self.assertEqual( self.assertEqual(
Asset.search_count([('nextupdate', '>=', datetime(2022, 10, 17, 10, 45))]), Asset.search_count([
('nextupdate', '>=', datetime(2022, 10, 17, 10, 45))]),
1) 1)
# add rate at next monday # add rate at next monday
@ -550,7 +568,7 @@ class AssetTestCase(ModuleTestCase):
[asset], [asset],
{ {
'rates': [('create', [{ 'rates': [('create', [{
'date': date(2022, 10, 17), # monday 'date': date(2022, 10, 17), # monday
'rate': Decimal('1.5'), 'rate': Decimal('1.5'),
}])], }])],
}]) }])
@ -564,10 +582,12 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(asset.nextupdate, datetime(2022, 10, 18, 10, 45)) self.assertEqual(asset.nextupdate, datetime(2022, 10, 18, 10, 45))
self.assertEqual( self.assertEqual(
Asset.search_count([('nextupdate', '<', datetime(2022, 10, 18, 10, 45))]), Asset.search_count([
('nextupdate', '<', datetime(2022, 10, 18, 10, 45))]),
0) 0)
self.assertEqual( self.assertEqual(
Asset.search_count([('nextupdate', '>=', datetime(2022, 10, 18, 10, 45))]), Asset.search_count([
('nextupdate', '>=', datetime(2022, 10, 18, 10, 45))]),
1) 1)
# add rate at today # add rate at today
@ -589,10 +609,12 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(asset2.nextupdate, datetime(2022, 10, 19, 10, 45)) self.assertEqual(asset2.nextupdate, datetime(2022, 10, 19, 10, 45))
self.assertEqual( self.assertEqual(
Asset.search_count([('nextupdate', '<', datetime(2022, 10, 19, 10, 45))]), Asset.search_count([
('nextupdate', '<', datetime(2022, 10, 19, 10, 45))]),
0) 0)
self.assertEqual( self.assertEqual(
Asset.search_count([('nextupdate', '>=', datetime(2022, 10, 19, 10, 45))]), Asset.search_count([
('nextupdate', '>=', datetime(2022, 10, 19, 10, 45))]),
1) 1)
@with_transaction() @with_transaction()
@ -609,12 +631,8 @@ class AssetTestCase(ModuleTestCase):
product2 = self.prep_asset_product( product2 = self.prep_asset_product(
name='Product gram', unit='g') name='Product gram', unit='g')
asset1 = self.prep_asset_item( asset1 = self.prep_asset_item(company=company, product=product1)
company=company, asset2 = self.prep_asset_item(company=company, product=product2)
product = product1)
asset2 = self.prep_asset_item(
company=company,
product = product2)
Product.write(*[ Product.write(*[
[product1], [product1],
@ -653,9 +671,15 @@ class AssetTestCase(ModuleTestCase):
self.assertEqual(Asset.search_count([('isin', '=', 'XC0009655157')]), 1) self.assertEqual(Asset.search_count([('isin', '=', 'XC0009655157')]), 1)
self.assertEqual(Asset.search_count([('secsymb', '=', '1472977')]), 1) self.assertEqual(Asset.search_count([('secsymb', '=', '1472977')]), 1)
self.assertEqual(Asset.search_count([('rec_name', '=', '965515')]), 1) self.assertEqual(
self.assertEqual(Asset.search_count([('rec_name', '=', 'XC0009655157')]), 1) Asset.search_count([('rec_name', '=', '965515')]),
self.assertEqual(Asset.search_count([('rec_name', '=', '1472977')]), 1) 1)
self.assertEqual(
Asset.search_count([('rec_name', '=', 'XC0009655157')]),
1)
self.assertEqual(
Asset.search_count([('rec_name', '=', '1472977')]),
1)
self.assertEqual(Asset.search_count([('name', '=', '965515')]), 1) self.assertEqual(Asset.search_count([('name', '=', '965515')]), 1)
self.assertEqual(Asset.search_count([('name', '=', 'XC0009655157')]), 1) self.assertEqual(Asset.search_count([('name', '=', 'XC0009655157')]), 1)
@ -715,9 +739,7 @@ class AssetTestCase(ModuleTestCase):
name='Product gram', unit='g') name='Product gram', unit='g')
self.assertEqual(product2.default_uom.digits, 2) self.assertEqual(product2.default_uom.digits, 2)
asset = self.prep_asset_item( asset = self.prep_asset_item(company=company, product=product1)
company=company,
product = product1)
self.assertEqual(asset.product.rec_name, 'Product unit') self.assertEqual(asset.product.rec_name, 'Product unit')
self.assertEqual(asset.product.default_uom.rec_name, 'Unit') self.assertEqual(asset.product.default_uom.rec_name, 'Unit')

View file

@ -3,17 +3,15 @@
# The COPYRIGHT file at the top level of this repository contains the # The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms. # full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.tests.test_tryton import with_transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.modules.company.tests import create_company
from decimal import Decimal from decimal import Decimal
from datetime import date from datetime import date
class RateTestCase(ModuleTestCase): class RateTestCase(object):
'Test rate module' """ test rate
module = 'investment' """
@with_transaction() @with_transaction()
def test_rate_create(self): def test_rate_create(self):
""" create rate """ create rate
@ -27,7 +25,7 @@ class RateTestCase(ModuleTestCase):
asset = self.prep_asset_item( asset = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
Asset.write(*[ Asset.write(*[
[asset], [asset],

View file

@ -3,9 +3,8 @@
# The COPYRIGHT file at the top level of this repository contains the # The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms. # full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.tests.test_tryton import with_transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.modules.company.tests import create_company
from trytond.transaction import Transaction from trytond.transaction import Transaction
from decimal import Decimal from decimal import Decimal
from datetime import time, date, datetime from datetime import time, date, datetime
@ -14,10 +13,9 @@ from requests import Response
import requests import requests
class SourceTestCase(ModuleTestCase): class SourceTestCase(object):
'Test online source module' """ test online source
module = 'investment' """
@with_transaction() @with_transaction()
def test_waitlist_source_request(self): def test_waitlist_source_request(self):
""" create source, call server """ create source, call server
@ -59,7 +57,7 @@ class SourceTestCase(ModuleTestCase):
asset = self.prep_asset_item( asset = self.prep_asset_item(
company=company, company=company,
product = product) product=product)
Asset.write(*[ Asset.write(*[
[asset], [asset],
@ -68,9 +66,8 @@ class SourceTestCase(ModuleTestCase):
}]) }])
with Transaction().set_context({ with Transaction().set_context({
'qdate': date(2022, 10, 1), # saturday 'qdate': date(2022, 10, 1), # saturday
'qdatetime': datetime(2022, 10, 2, 10, 0, 0), 'qdatetime': datetime(2022, 10, 2, 10, 0, 0)}):
}):
asset2, = Asset.browse([asset]) asset2, = Asset.browse([asset])
self.assertEqual(asset2.wkn, '965515') self.assertEqual(asset2.wkn, '965515')
self.assertEqual(asset2.isin, 'XC0009655157') self.assertEqual(asset2.isin, 'XC0009655157')
@ -82,7 +79,6 @@ class SourceTestCase(ModuleTestCase):
self.assertEqual(asset2.nextupdate, datetime(2022, 10, 3, 14, 0)) self.assertEqual(asset2.nextupdate, datetime(2022, 10, 3, 14, 0))
self.assertEqual(len(asset.rates), 0) self.assertEqual(len(asset.rates), 0)
# fake server-response # fake server-response
resp1 = Response() resp1 = Response()
resp1._content = """<html><body>Response from finance-server resp1._content = """<html><body>Response from finance-server
@ -127,8 +123,8 @@ High 34,87 EUR
OSource.write(*[ OSource.write(*[
[osource], [osource],
{ {
'rgxdate': 'Course Date (\\d+-\\d+-\\d+) Today', 'rgxdate': 'Course Date (\\d+-\\d+-\\d+) Today',
'rgxdatefmt': '%Y-%m-%d', 'rgxdatefmt': '%Y-%m-%d',
}]) }])
self.assertEqual(osource.get_regex_result( self.assertEqual(osource.get_regex_result(
'The Course Date 2022-03-14 Today, High 13,43 EUR', 'The Course Date 2022-03-14 Today, High 13,43 EUR',

26
tests/test_module.py Normal file
View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds for Tryton.
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase
from .asset import AssetTestCase
from .rate import RateTestCase
from .source import SourceTestCase
from .wizard import WizardTestCase
class InvestmentTestCase(
WizardTestCase,
SourceTestCase,
RateTestCase,
AssetTestCase,
ModuleTestCase):
'Test investment module'
module = 'investment'
# end InvestmentTestCase
del ModuleTestCase

View file

@ -3,24 +3,21 @@
# The COPYRIGHT file at the top level of this repository contains the # The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms. # full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.tests.test_tryton import with_transaction
from trytond.pool import Pool from trytond.pool import Pool
from trytond.modules.company.tests import create_company
from trytond.transaction import Transaction from trytond.transaction import Transaction
from decimal import Decimal from decimal import Decimal
from datetime import date from datetime import date
class WizardTestCase(ModuleTestCase): class WizardTestCase(object):
'Test wizard module' """ test import wizard
module = 'investment' """
@with_transaction() @with_transaction()
def test_wiz_run_import(self): def test_wiz_run_import(self):
""" run import wizard """ run import wizard
""" """
pool = Pool() pool = Pool()
Asset = pool.get('investment.asset')
ImportWiz = pool.get('investment.imp_wiz', type='wizard') ImportWiz = pool.get('investment.imp_wiz', type='wizard')
company = self.prep_asset_company() company = self.prep_asset_company()
@ -28,15 +25,12 @@ class WizardTestCase(ModuleTestCase):
name='Product 1', name='Product 1',
description='some asset') description='some asset')
asset = self.prep_asset_item( asset = self.prep_asset_item(company=company, product=product)
company=company,
product = product)
self.assertEqual(len(asset.rates), 0) self.assertEqual(len(asset.rates), 0)
with Transaction().set_context({ with Transaction().set_context({
'active_id': asset.id, 'active_id': asset.id,
'active_model': 'investment.asset', 'active_model': 'investment.asset'}):
}):
(sess_id, start_state, end_state) = ImportWiz.create() (sess_id, start_state, end_state) = ImportWiz.create()
w_obj = ImportWiz(sess_id) w_obj = ImportWiz(sess_id)
self.assertEqual(start_state, 'start') self.assertEqual(start_state, 'start')
@ -61,7 +55,8 @@ class WizardTestCase(ModuleTestCase):
'dec_divider': ',', 'dec_divider': ',',
'date_fmt': '%d.%m.%Y', 'date_fmt': '%d.%m.%Y',
'field_delimiter': ';', 'field_delimiter': ';',
'file_': b'"date";"rate"\n"03.05.2022";"23,56"\n"05.05.2022";"24,22"\n"06.05.2022";"25,43"', 'file_': b'"date";"rate"\n"03.05.2022";"23,56"\n' +
b'"05.05.2022";"24,22"\n"06.05.2022";"25,43"',
}}, 'importf') }}, 'importf')
self.assertEqual(list(result.keys()), []) self.assertEqual(list(result.keys()), [])
# finish wizard # finish wizard

View file

@ -35,4 +35,3 @@ class UpdateSoureWizard(Wizard):
return 'end' return 'end'
# UpdateSoureWizard # UpdateSoureWizard