345 lines
12 KiB
Python
345 lines
12 KiB
Python
# -*- 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.model import ModelView, ModelSQL, fields
|
|
from trytond.transaction import Transaction
|
|
from trytond.pool import Pool
|
|
from trytond.pyson import Eval, Bool, And
|
|
from decimal import Decimal
|
|
from datetime import time
|
|
from sql.functions import CurrentTime
|
|
from sql.conditionals import Case
|
|
|
|
|
|
class Asset(ModelSQL, ModelView):
|
|
'Asset'
|
|
__name__ = 'investment.asset'
|
|
|
|
company = fields.Many2One(string='Company', model_name='company.company',
|
|
required=True, ondelete="RESTRICT")
|
|
product = fields.Many2One(string='Product', required=True,
|
|
model_name='product.product', ondelete='RESTRICT',
|
|
domain=[('type', '=', 'assets')])
|
|
product_uom = fields.Function(fields.Many2One(string='UOM Category',
|
|
readonly=True, model_name='product.uom.category',
|
|
help='Category of unit on the product.'),
|
|
'on_change_with_product_uom')
|
|
uom = fields.Many2One(string='UOM', required=True,
|
|
model_name='product.uom', ondelete='RESTRICT',
|
|
states={
|
|
'readonly': ~Bool(Eval('product')),
|
|
},
|
|
domain=[
|
|
('category', '=', Eval('product_uom')),
|
|
], depends=['product_uom', 'product'])
|
|
rates = fields.One2Many(string='Rates', field='asset',
|
|
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')
|
|
|
|
company_currency = fields.Function(fields.Many2One(readonly=True,
|
|
string='Company Currency', states={'invisible': True},
|
|
model_name='currency.currency'),
|
|
'on_change_with_company_currency')
|
|
company_currency_digits = fields.Function(fields.Integer(
|
|
string='Currency Digits (Ref.)', readonly=True),
|
|
'on_change_with_currency_digits')
|
|
|
|
currency = fields.Many2One(string='Currency', select=True,
|
|
required=True, model_name='currency.currency', ondelete='RESTRICT')
|
|
currency_digits = fields.Integer(string='Currency Digits',
|
|
required=True)
|
|
|
|
wkn = fields.Function(fields.Char(string='NSIN', readonly=True,
|
|
help='National Securities Identifying Number'),
|
|
'get_identifiers', searcher='search_identifier')
|
|
isin = fields.Function(fields.Char(string='ISIN', readonly=True,
|
|
help='International Securities Identification Number'),
|
|
'get_identifiers', searcher='search_identifier')
|
|
secsymb = fields.Function(fields.Char(string='Symbol', readonly=True,
|
|
help='Stock market symbol'),
|
|
'get_identifiers', searcher='search_identifier')
|
|
|
|
updtsource = fields.Many2One(string='Update Source',
|
|
help='Select a source for the course update.',
|
|
ondelete='SET NULL', model_name='investment.source')
|
|
updttime = fields.Time(string='Time',
|
|
states={
|
|
'readonly': ~Bool(Eval('updtsource')),
|
|
}, depends=['updtsource'])
|
|
updtneeded = fields.Function(fields.Boolean(string='Course update needed',
|
|
readonly=True),
|
|
'on_change_with_updtneeded', searcher='search_updtneeded')
|
|
|
|
@classmethod
|
|
def default_currency(cls):
|
|
""" currency of company
|
|
"""
|
|
Company = Pool().get('company.company')
|
|
|
|
company = cls.default_company()
|
|
if company:
|
|
company = Company(company)
|
|
if company.currency:
|
|
return company.currency.id
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company') or None
|
|
|
|
@classmethod
|
|
def default_currency_digits(cls):
|
|
""" default: 4
|
|
"""
|
|
return 4
|
|
|
|
@fields.depends('updtsource', 'updttime')
|
|
def on_change_updtsource(self):
|
|
""" clear time-fields
|
|
"""
|
|
if self.updtsource is None:
|
|
self.updttime = None
|
|
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
|
|
"""
|
|
if self.product:
|
|
self.uom = self.product.default_uom
|
|
return
|
|
self.uom = None
|
|
|
|
@fields.depends('currency', 'currency_digits')
|
|
def on_change_currency(self):
|
|
""" update currency_digits by value on currency
|
|
"""
|
|
if self.currency:
|
|
self.currency_digits = self.currency.digits
|
|
|
|
@fields.depends('product')
|
|
def on_change_with_product_uom(self, name=None):
|
|
""" get category of product-uom
|
|
"""
|
|
if self.product:
|
|
return self.product.default_uom.category.id
|
|
|
|
@fields.depends('currency')
|
|
def on_change_with_currency_digits(self, name=None):
|
|
""" currency of cashbook
|
|
"""
|
|
if self.currency:
|
|
return self.currency.digits
|
|
else:
|
|
return 2
|
|
|
|
@fields.depends('company', 'currency')
|
|
def on_change_with_company_currency(self, name=None):
|
|
""" get company-currency if its different from current
|
|
asset-currency
|
|
"""
|
|
if self.company:
|
|
if self.currency:
|
|
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
|
|
"""
|
|
pool = Pool()
|
|
Asset2 = pool.get('investment.asset')
|
|
Rate = pool.get('investment.rate')
|
|
IrDate = pool.get('ir.date')
|
|
tab_asset = Asset2.__table__()
|
|
tab_rate = Rate.__table__()
|
|
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]),
|
|
)
|
|
return [('id', '=', query)]
|
|
|
|
@classmethod
|
|
def get_identifier_sql(cls, tab_asset):
|
|
""" sql-query for identifiers
|
|
"""
|
|
pool = Pool()
|
|
Product = pool.get('product.product')
|
|
Identifier = pool.get('product.identifier')
|
|
tab_prod = Product.__table__()
|
|
tab_wkn = Identifier.__table__()
|
|
tab_secsymb = Identifier.__table__()
|
|
tab_isin = Identifier.__table__()
|
|
|
|
query = tab_asset.join(tab_prod,
|
|
condition=tab_asset.product==tab_prod.id,
|
|
).join(tab_wkn,
|
|
condition=(tab_prod.id==tab_wkn.product) & \
|
|
(tab_wkn.type == 'wkn'),
|
|
type_ = 'LEFT OUTER',
|
|
).join(tab_secsymb,
|
|
condition=(tab_prod.id==tab_secsymb.product) & \
|
|
(tab_secsymb.type == 'secsymb'),
|
|
type_ = 'LEFT OUTER',
|
|
).join(tab_isin,
|
|
condition=(tab_prod.id==tab_isin.product) & \
|
|
(tab_isin.type == 'isin'),
|
|
type_ = 'LEFT OUTER',
|
|
).select(
|
|
tab_asset.id,
|
|
tab_wkn.code.as_('wkn'),
|
|
tab_secsymb.code.as_('secsymb'),
|
|
tab_isin.code.as_('isin'),
|
|
)
|
|
return query
|
|
|
|
@classmethod
|
|
def search_identifier(cls, names, clause):
|
|
""" search in identifier
|
|
"""
|
|
pool = Pool()
|
|
Asset = pool.get('investment.asset')
|
|
tab_asset = Asset.__table__()
|
|
Operator = fields.SQL_OPERATORS[clause[1]]
|
|
tab_ids = cls.get_identifier_sql(tab_asset)
|
|
|
|
field_qu = getattr(tab_ids, names)
|
|
query = tab_ids.join(tab_asset,
|
|
condition=tab_ids.id==tab_asset.id,
|
|
).select(
|
|
tab_asset.id,
|
|
where=Operator(field_qu, clause[2]) & \
|
|
(field_qu != None),
|
|
)
|
|
|
|
return [('id', 'in', query)]
|
|
|
|
@classmethod
|
|
def get_identifiers(cls, assets, names):
|
|
""" get identifiers of assets
|
|
"""
|
|
pool = Pool()
|
|
Asset = pool.get('investment.asset')
|
|
tab_asset = Asset.__table__()
|
|
cursor = Transaction().connection.cursor()
|
|
|
|
result = {x:{y.id: None for y in assets} for x in names}
|
|
|
|
query = cls.get_identifier_sql(tab_asset)
|
|
query.where = tab_asset.id.in_([x.id for x in assets])
|
|
|
|
cursor.execute(*query)
|
|
l1 = cursor.fetchall()
|
|
|
|
for x in l1:
|
|
(id1, wkn, secsymb, isin) = x
|
|
r1 = {'wkn': wkn, 'secsymb': secsymb, 'isin': isin}
|
|
|
|
for n in names:
|
|
result[n][id1] = r1[n]
|
|
|
|
return result
|
|
|
|
def get_rec_name(self, name):
|
|
if self.product:
|
|
return self.product.rec_name
|
|
else:
|
|
return self.id
|
|
|
|
@classmethod
|
|
def search_rec_name(cls, name, clause):
|
|
""" search in rec_name
|
|
"""
|
|
return [('product.rec_name',) + tuple(clause[1:])]
|
|
|
|
@classmethod
|
|
def cron_update(cls):
|
|
""" update asset-rates
|
|
"""
|
|
pool = Pool()
|
|
Asset2 = pool.get('investment.asset')
|
|
|
|
for asset in Asset2.search([
|
|
('updtneeded', '=', True),
|
|
]):
|
|
pass
|
|
|
|
@classmethod
|
|
def create(cls, vlist):
|
|
""" add debit/credit
|
|
"""
|
|
vlist = [x.copy() for x in vlist]
|
|
for values in vlist:
|
|
if 'updtsource' in values.keys():
|
|
if values['updtsource'] is None:
|
|
values['updttime1'] = None
|
|
values['updttime2'] = None
|
|
values['updttime3'] = None
|
|
return super(Asset, cls).create(vlist)
|
|
|
|
@classmethod
|
|
def write(cls, *args):
|
|
""" deny update if cashbook.line!='open',
|
|
add or update debit/credit
|
|
"""
|
|
actions = iter(args)
|
|
for lines, values in zip(actions, actions):
|
|
if 'updtsource' in values.keys():
|
|
if values['updtsource'] is None:
|
|
values['updttime1'] = None
|
|
values['updttime2'] = None
|
|
values['updttime3'] = None
|
|
super(Asset, cls).write(*args)
|
|
|
|
# end Asset
|