book: list-view - farbige asset-zeilen,

book: Felder diff-prozent/amount + tests
This commit is contained in:
Frederik Jaeckel 2022-12-23 19:15:20 +01:00
parent 8f8da805d4
commit d501bd1700
8 changed files with 249 additions and 31 deletions

59
book.py
View file

@ -4,9 +4,8 @@
# full copyright notices and license terms.
from trytond.model import fields, SymbolMixin
from trytond.exceptions import UserError
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval, Or, Len
from trytond.pyson import Eval, Or, Len, Bool, If
from trytond.modules.cashbook.book import STATES2, DEPENDS2
from trytond.transaction import Transaction
from decimal import Decimal
@ -75,18 +74,44 @@ class Book(SymbolMixin, metaclass=PoolMeta):
}, depends=['quantity_digits', 'feature']),
'get_asset_quantity')
current_value = fields.Function(fields.Numeric(string='Value',
help='Valuation of the investment based on the current stock market price.',
readonly=True, digits=(16, Eval('currency_digits', 2)),
states={
'invisible': Eval('feature', '') != 'asset',
}, depends=['currency_digits', 'feature']),
'get_asset_quantity')
current_value_ref = fields.Function(fields.Numeric(string='Value (Ref.)',
help='Valuation of the investment based on the current stock exchange price, converted into the company currency.',
readonly=True, digits=(16, Eval('currency_digits', 2)),
states={
'invisible': Eval('feature', '') != 'asset',
}, depends=['currency_digits', 'feature']),
'invisible': Or(
Eval('feature', '') != 'asset',
~Bool(Eval('company_currency', -1)),
),
}, depends=['currency_digits', 'feature', 'company_currency']),
'get_asset_quantity')
# performance
diff_amount = fields.Function(fields.Numeric(string='Difference',
help='Difference between acquisition value and current value',
readonly=True, digits=(16, Eval('currency_digits', 2)),
depends=['currency_digits']), 'get_asset_quantity')
diff_percent = fields.Function(fields.Numeric(string='Percent',
help='percentage performance since acquisition',
readonly=True, digits=(16, Eval('currency_digits', 2)),
depends=['currency_digits']), 'get_asset_quantity')
@classmethod
def view_attributes(cls):
return super(Book, cls).view_attributes() + [
('/tree', 'visual',
If(Eval('feature', '') == 'asset',
If(Eval('diff_percent', 0) < 0, 'danger',
If(Eval('diff_percent', 0) > 0, 'success', '')
), '')
),
]
@fields.depends('asset', 'quantity_uom')
def on_change_asset(self):
""" get uom from asset
@ -115,6 +140,7 @@ class Book(SymbolMixin, metaclass=PoolMeta):
tab_cur = Currency.__table__()
tab_asset = Asset.__table__()
(tab_rate, tab2) = Asset.get_rate_data_sql()
(tab_balance, tab2) = CBook.get_balance_of_cashbook_sql()
cursor = Transaction().connection.cursor()
context = Transaction().context
@ -128,6 +154,9 @@ class Book(SymbolMixin, metaclass=PoolMeta):
condition=tab_book.currency==tab_cur.id,
).join(tab_asset,
condition=tab_book.asset==tab_asset.id,
).join(tab_balance,
condition=tab_book.id==tab_balance.cashbook,
type_ = 'LEFT OUTER',
).join(tab_rate,
condition=tab_book.asset==tab_rate.id,
type_ = 'LEFT OUTER',
@ -144,9 +173,11 @@ class Book(SymbolMixin, metaclass=PoolMeta):
tab_asset.uom, # 6
tab_book.quantity_uom, # 7
tab_asset.currency.as_('asset_currency'), #8
Coalesce(tab_balance.balance, Decimal('0.0')).as_('balance'), #9
group_by=[tab_book.id, tab_rate.rate,
tab_book.currency, tab_cur.digits, tab_asset.uom,
tab_book.quantity_uom, tab_asset.currency],
tab_book.quantity_uom, tab_asset.currency,
tab_balance.balance],
)
cursor.execute(*query)
records = cursor.fetchall()
@ -160,19 +191,27 @@ class Book(SymbolMixin, metaclass=PoolMeta):
Uom.compute_qty(Uom(record[6]), 1.0, Uom(record[7]), round=False)
)
current_value = Currency.compute(
record[8],
record[3] * record[1] / uom_factor,
record[4]
)
values = {
'quantity': record[1],
'quantity_all': record[2],
'current_value': Currency.compute(
record[8],
record[3] * record[1] / uom_factor,
record[4]
),
'current_value': current_value,
'current_value_ref': Currency.compute(
record[8],
record[3] * record[1] / uom_factor,
company_currency if company_currency is not None else record[8],
),
'diff_amount': current_value - record[9],
'diff_percent': (
Decimal('100.0') * current_value / \
record[9] - Decimal('100.0')
).quantize(Decimal(str(1/10**record[5]))) \
if record[9] != Decimal('0.0') else None,
}
for name in names:

View file

@ -11,5 +11,17 @@ full copyright notices and license terms. -->
<field name="name">book_form</field>
</record>
<record model="ir.ui.view" id="book_view_list">
<field name="model">cashbook.book</field>
<field name="inherit" ref="cashbook.book_view_list"/>
<field name="name">book_list</field>
</record>
<record model="ir.ui.view" id="book_view_tree">
<field name="model">cashbook.book</field>
<field name="inherit" ref="cashbook.book_view_tree"/>
<field name="name">book_tree</field>
</record>
</data>
</tryton>

View file

@ -23,8 +23,8 @@ msgid "Quantity"
msgstr "Anzahl"
msgctxt "view:cashbook.book:"
msgid "Current value of the asset"
msgstr "aktueller Wert des Vermögenswertes"
msgid "Current valuation of the investment"
msgstr "aktuelle Bewertung der Vermögensanlage"
msgctxt "field:cashbook.book,asset:"
msgid "Asset"
@ -71,16 +71,32 @@ msgid "Value"
msgstr "Wert"
msgctxt "help:cashbook.book,current_value:"
msgid "Current Value in cashbook currency"
msgstr "aktueller Wert in der Kassenbuchwährung"
msgid "Valuation of the investment based on the current stock market price."
msgstr "Bewertung der Vermögensanlage anhand des aktuellen Börsenkurses."
msgctxt "field:cashbook.book,current_value_ref:"
msgid "Value (Ref)"
msgstr "Wert (Ref)"
msgid "Value (Ref.)"
msgstr "Wert (Ref.)"
msgctxt "help:cashbook.book,current_value:"
msgid "Current Value in company currency"
msgstr "aktueller Wert in der Unternehmenswährung"
msgctxt "help:cashbook.book,current_value_ref:"
msgid "Valuation of the investment based on the current stock exchange price, converted into the company currency."
msgstr "Bewertung der Vermögensanlage anhand des aktuellen Börsenkurses, umgerechnet in die Unternehmenswährung."
msgctxt "field:cashbook.book,diff_amount:"
msgid "Difference"
msgstr "Differenz"
msgctxt "help:cashbook.book,diff_amount:"
msgid "Difference between acquisition value and current value"
msgstr "Differenz zwischen Anschaffungswert und aktuellem Wert"
msgctxt "field:cashbook.book,diff_percent:"
msgid "Percent"
msgstr "Prozent"
msgctxt "help:cashbook.book,diff_percent:"
msgid "percentage performance since acquisition"
msgstr "prozentuale Wertentwicklung seit Anschaffung"
#################

View file

@ -15,8 +15,8 @@ msgid "Quantity"
msgstr "Quantity"
msgctxt "view:cashbook.book:"
msgid "Value of the asset"
msgstr "Value of the asset"
msgid "Current value of the asset"
msgstr "Current value of the asset"
msgctxt "field:cashbook.book,asset:"
msgid "Asset"
@ -63,16 +63,16 @@ msgid "Value"
msgstr "Value"
msgctxt "help:cashbook.book,current_value:"
msgid "Current Value in cashbook currency"
msgstr "Current Value in cashbook currency"
msgid "Valuation of the investment based on the current stock market price."
msgstr "Valuation of the investment based on the current stock market price."
msgctxt "field:cashbook.book,current_value_ref:"
msgid "Value (Ref)"
msgstr "Value (Ref)"
msgid "Value (Ref.)"
msgstr "Value (Ref.)"
msgctxt "help:cashbook.book,current_value:"
msgid "Current Value in company currency"
msgstr "Current Value in company currency"
msgctxt "help:cashbook.book,current_value_ref:"
msgid "Valuation of the investment based on the current stock exchange price, converted into the company currency."
msgstr "Valuation of the investment based on the current stock exchange price, converted into the company currency."
msgctxt "field:cashbook.line,quantity_digits:"
msgid "Digits"

View file

@ -257,11 +257,127 @@ class CbInvTestCase(CashbookTestCase, InvestmentTestCase):
self.assertEqual(book.asset.rate, Decimal('1750.0')) # usd
self.assertEqual(book2.quantity, Decimal('20.0'))
self.assertEqual(book2.quantity_all, Decimal('20.0'))
# usd --> eur: 1750 / 1.05 = 1666.666
# 1 ounce --> 20 gram: 1666.666 * 20 / 28.3495 = 1175.7996
# usd --> eur: 1750 US$ / 1.05 = 1666.666
# 1 ounce --> 20 gram: 1666.666 * 20 / 28.3495 = 1175.7996
# bette we use 'Troy Ounce': 1 oz.tr. = 31.1034768 gram
self.assertEqual(book2.current_value, Decimal('1175.80'))
self.assertEqual(book2.current_value_ref, Decimal('1175.80'))
self.assertEqual(book2.diff_amount, Decimal('-74.20'))
self.assertEqual(book2.diff_percent, Decimal('-5.94'))
@with_transaction()
def test_assetbook_check_uom_and_currency_convert2(self):
""" asset in US$/Ounce, cashbook in CHF/Gram,
company-currency EUR
"""
pool = Pool()
Book = pool.get('cashbook.book')
BType = pool.get('cashbook.type')
Asset = pool.get('investment.asset')
ProdTempl = pool.get('product.template')
Uom = pool.get('product.uom')
Currency = pool.get('currency.currency')
types = self.prep_type()
BType.write(*[
[types],
{
'feature': 'asset',
}])
category = self.prep_category(cattype='in')
company = self.prep_company()
party = self.prep_party()
asset = self.prep_asset_item(
company=company,
product = self.prep_asset_product(name='Product 1'))
# set product to ounce
ounce, = Uom.search([('symbol', '=', 'oz')])
gram, = Uom.search([('symbol', '=', 'g')])
ProdTempl.write(*[
[asset.product.template],
{
'default_uom': ounce.id,
'name': 'Aurum',
}])
Asset.write(*[
[asset],
{
'uom': ounce.id,
'rates': [('create', [{
'date': date(2022, 5, 1),
'rate': Decimal('1750.0'),
}, ])],
}])
self.assertEqual(asset.rec_name, 'Aurum | 1,750.0000 usd/oz | 05/01/2022')
(usd, euro) = self.prep_2nd_currency(company)
self.assertEqual(company.currency.rec_name, 'Euro')
self.assertEqual(asset.symbol, 'usd/oz')
chf, = Currency.create([{
'name': 'Swiss Franc',
'code': 'CHF',
'numeric_code': '756',
'symbol': 'CHF',
'rounding': Decimal('0.01'),
'digits': 2,
'rates': [('create', [{
'date': date(2022, 5, 1),
'rate': Decimal('0.95'),
}])],
}])
book, = Book.create([{
'start_date': date(2022, 4, 1),
'name': 'Aurum-Storage',
'btype': types.id,
'company': company.id,
'currency': chf.id,
'number_sequ': self.prep_sequence().id,
'asset': asset.id,
'quantity_uom': gram.id,
'quantity_digits': 3,
'lines': [('create', [{
'date': date(2022, 5, 1),
'description': 'store some metal',
'category': category.id,
'bookingtype': 'in',
'amount': Decimal('1250.0'),
'party': party.id,
'quantity': Decimal('20.0'),
}],
)],
}])
self.assertEqual(book.rec_name, 'Aurum-Storage | 1,250.00 CHF | Open')
self.assertEqual(book.balance_all, Decimal('1250.0'))
self.assertEqual(len(book.lines), 1)
self.assertEqual(book.lines[0].amount, Decimal('1250.0'))
self.assertEqual(book.lines[0].quantity, Decimal('20.0'))
self.assertEqual(book.lines[0].quantity_uom.symbol, 'g')
self.assertEqual(book.symbol, 'CHF/g')
self.assertEqual(book.asset.rec_name, 'Aurum | 1,750.0000 usd/oz | 05/01/2022')
# check quantities at cashbook
with Transaction().set_context({
'qdate': date(2022, 5, 1),
'company': company.id,
}):
book2, = Book.browse([book])
self.assertEqual(book.asset.rate, Decimal('1750.0')) # usd
self.assertEqual(book2.quantity, Decimal('20.0'))
self.assertEqual(book2.quantity_all, Decimal('20.0'))
# usd --> chf: 1750 US$ * 0.95 / 1.05 = 1583.333 €
# 1 ounce --> 20 gram: 1583.333 CHF * 20 / 28.3495 = 1117.0097 CHF
self.assertEqual(book2.current_value, Decimal('1117.01')) # CHF
self.assertEqual(book2.current_value_ref, Decimal('1175.80')) # EUR
self.assertEqual(book2.diff_amount, Decimal('-132.99'))
self.assertEqual(book2.diff_percent, Decimal('-10.64'))
@with_transaction()
def test_assetbook_book_uom(self):

View file

@ -12,11 +12,20 @@ full copyright notices and license terms. -->
<label name="quantity_all"/>
<field name="quantity_all" symbol="quantity_uom"/>
<separator colspan="4" name="current_value" string="Current value of the asset"/>
<separator colspan="4" name="current_value" string="Current valuation of the investment"/>
<label name="current_value"/>
<field name="current_value" symbol="currency"/>
<label name="current_value_ref"/>
<field name="current_value_ref" symbol="company_currency"/>
<label name="diff_amount"/>
<field name="diff_amount" symbol="currency"/>
<label name="diff_percent"/>
<group id="diff_percent" col="2">
<field name="diff_percent" xexpand="0"/>
<label name="diff_percent" xalign="0.0" string="%" xexpand="1"/>
</group>
</xpath>
<xpath expr="/form/notebook/page[@id='pggeneral']" position="after">

14
view/book_list.xml Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<!-- This file is part of the cashbook-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<data>
<xpath expr="/tree/field[@name='balance']" position="after">
<field name="current_value"/>
<field name="diff_amount"/>
<field name="diff_percent"/>
<field name="quantity"/>
</xpath>
</data>

12
view/book_tree.xml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<!-- This file is part of the cashbook-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<data>
<xpath expr="/tree/field[@name='balance']" position="after">
<field name="diff_amount"/>
<field name="diff_percent"/>
</xpath>
</data>