From 353df93a9ea34b400af0a1a1f5d5c59630cc397f Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Fri, 11 Nov 2022 22:46:53 +0100 Subject: [PATCH] asset: Felder wkn, isin, symobl + suche + test --- __init__.py | 2 + asset.py | 93 ++++++++++++++++++++++++++++++++++++++++++++- identifier.py | 21 ++++++++++ locale/de.po | 39 +++++++++++++++++++ locale/en.po | 32 ++++++++++++++++ tests/test_asset.py | 70 +++++++++++++++++++++++++++++++++- view/asset_form.xml | 10 +++++ view/asset_list.xml | 3 ++ 8 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 identifier.py diff --git a/__init__.py b/__init__.py index 461ecbc..e4eea0f 100644 --- a/__init__.py +++ b/__init__.py @@ -5,8 +5,10 @@ from trytond.pool import Pool from .asset import Asset +from .identifier import Identifier def register(): Pool.register( Asset, + Identifier, module='investment', type_='model') diff --git a/asset.py b/asset.py index 9503311..c7d3c4c 100644 --- a/asset.py +++ b/asset.py @@ -4,8 +4,6 @@ # full copyright notices and license terms. from trytond.model import ModelView, ModelSQL, fields -from trytond.exceptions import UserError -from trytond.i18n import gettext from trytond.transaction import Transaction from trytond.pool import Pool from trytond.pyson import Eval, Bool @@ -46,6 +44,16 @@ class Asset(ModelSQL, ModelView): 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') + @classmethod def default_currency(cls): """ currency of company @@ -84,6 +92,87 @@ class Asset(ModelSQL, ModelView): if self.currency: self.currency_digits = self.currency.digits + @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 + @fields.depends('product') def on_change_with_product_uom(self, name=None): """ get category of product-uom diff --git a/identifier.py b/identifier.py new file mode 100644 index 0000000..ca5692d --- /dev/null +++ b/identifier.py @@ -0,0 +1,21 @@ +# -*- 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 fields +from trytond.pool import PoolMeta + + +class Identifier(metaclass=PoolMeta): + __name__ = 'product.identifier' + + @classmethod + def __setup__(cls): + super(Identifier, cls).__setup__() + cls.type.selection.extend([ + ('wkn', 'National Securities Identifying Number (NSIN)'), + ('secsymb', 'Stock market symbol'), + ]) + +# end Identifier diff --git a/locale/de.po b/locale/de.po index 5ecd515..6af7f3c 100644 --- a/locale/de.po +++ b/locale/de.po @@ -46,6 +46,10 @@ msgctxt "view:investment.asset:" msgid "Currency and Units" msgstr "Währung und Einheiten" +msgctxt "view:investment.asset:" +msgid "Identifiers" +msgstr "Bezeichner" + msgctxt "field:investment.asset,company:" msgid "Company" msgstr "Unternehmen" @@ -82,3 +86,38 @@ msgctxt "field:investment.asset,uom:" msgid "UOM" msgstr "Einheit" +msgctxt "field:investment.asset,wkn:" +msgid "NSIN" +msgstr "WKN" + +msgctxt "help:investment.asset,wkn:" +msgid "National Securities Identifying Number" +msgstr "Wertpapierkennnummer" + +msgctxt "field:investment.asset,isin:" +msgid "ISIN" +msgstr "ISIN" + +msgctxt "help:investment.asset,isin:" +msgid "International Securities Identification Number" +msgstr "Internationale Wertpapierkennnummer" + +msgctxt "field:investment.asset,secsymb:" +msgid "Symbol" +msgstr "Symbol" + +msgctxt "help:investment.asset,secsymb:" +msgid "Stock market symbol" +msgstr "Börsensymbol" + + +###################### +# product.identifier # +###################### +msgctxt "selection:product.identifier,type:" +msgid "National Securities Identifying Number (NSIN)" +msgstr "Wertpapierkennnummer (WKN)" + +msgctxt "selection:product.identifier,type:" +msgid "Stock market symbol" +msgstr "Börsensymbol" diff --git a/locale/en.po b/locale/en.po index 66fc058..36c4ac5 100644 --- a/locale/en.po +++ b/locale/en.po @@ -30,6 +30,10 @@ msgctxt "view:investment.asset:" msgid "Currency and Units" msgstr "Currency and Units" +msgctxt "view:investment.asset:" +msgid "Identifiers" +msgstr "Identifiers" + msgctxt "field:investment.asset,company:" msgid "Company" msgstr "Company" @@ -66,3 +70,31 @@ msgctxt "field:investment.asset,uom:" msgid "UOM" msgstr "UOM" +msgctxt "field:investment.asset,wkn:" +msgid "NSIN" +msgstr "NSIN" + +msgctxt "help:investment.asset,wkn:" +msgid "National Securities Identifying Number" +msgstr "National Securities Identifying Number" + +msgctxt "field:investment.asset,isin:" +msgid "ISIN" +msgstr "ISIN" + +msgctxt "help:investment.asset,isin:" +msgid "International Securities Identification Number" +msgstr "International Securities Identification Number" + +msgctxt "field:investment.asset,secsymb:" +msgid "Symbol" +msgstr "Symbol" + +msgctxt "help:investment.asset,secsymb:" +msgid "Stock market symbol" +msgstr "Stock market symbol" + +msgctxt "selection:product.identifier,type:" +msgid "National Securities Identifying Number (NSIN)" +msgstr "National Securities Identifying Number (NSIN)" + diff --git a/tests/test_asset.py b/tests/test_asset.py index fd46058..e64ea88 100644 --- a/tests/test_asset.py +++ b/tests/test_asset.py @@ -6,7 +6,6 @@ from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.pool import Pool from trytond.transaction import Transaction -from trytond.exceptions import UserError from trytond.modules.company.tests import create_company from datetime import date from decimal import Decimal @@ -82,6 +81,75 @@ class AssetTestCase(ModuleTestCase): company=company, product = product) + @with_transaction() + def test_asset_indentifiers(self): + """ create asset, add identifiers + """ + pool = Pool() + Product = pool.get('product.product') + Asset = pool.get('investment.asset') + + company = self.prep_asset_company() + product1 = self.prep_asset_product( + name='Product unit', unit='u') + product2 = self.prep_asset_product( + name='Product gram', unit='g') + + asset1 = self.prep_asset_item( + company=company, + product = product1) + asset2 = self.prep_asset_item( + company=company, + product = product2) + + Product.write(*[ + [product1], + { + 'identifiers': [('create', [{ + 'type': 'wkn', + 'code': '965515', + }, { + 'type': 'secsymb', + 'code': '1472977', + }, { + 'type': 'isin', + 'code': 'XC0009655157', + }, ])], + }, + [product2], + { + 'identifiers': [('create', [{ + 'type': 'wkn', + 'code': '965310', + }, { + 'type': 'secsymb', + 'code': '1431157', + }, { + 'type': 'isin', + 'code': 'XC0009653103', + }, ])], + }, + ]) + + self.assertEqual(asset1.wkn, '965515') + self.assertEqual(asset1.isin, 'XC0009655157') + self.assertEqual(asset1.secsymb, '1472977') + + self.assertEqual(Asset.search_count([('wkn', '=', '965515')]), 1) + self.assertEqual(Asset.search_count([('isin', '=', 'XC0009655157')]), 1) + self.assertEqual(Asset.search_count([('secsymb', '=', '1472977')]), 1) + + self.assertEqual(Asset.search_count([ + ('wkn', 'ilike', '9655%'), + ]), 1) + self.assertEqual(Asset.search_count([ + ('wkn', 'ilike', '965%'), + ]), 2) + + self.assertEqual(asset2.wkn, '965310') + self.assertEqual(asset2.isin, 'XC0009653103') + self.assertEqual(asset2.secsymb, '1431157') + @with_transaction() def test_asset_check_product_update(self): """ create asset diff --git a/view/asset_form.xml b/view/asset_form.xml index d53566b..7d279db 100644 --- a/view/asset_form.xml +++ b/view/asset_form.xml @@ -18,4 +18,14 @@ full copyright notices and license terms. -->