extend evaluation for cashbook-profit/loss amount/percent/diff - todo

This commit is contained in:
Frederik Jaeckel 2023-02-02 23:35:58 +01:00
parent 6ee40e8cff
commit 9774f183ad
11 changed files with 265 additions and 21 deletions

View file

@ -9,6 +9,8 @@ from .line import EvaluationLine
from .currency import Currency
from .evaluation_context import EvaluationContext
from .evaluation_wizard import OpenChartWizard
from .investment import InvestmentEvaluation, InvestmentLine
def register():
Pool.register(
@ -20,3 +22,7 @@ def register():
Pool.register(
OpenChartWizard,
module='cashbook_report', type_='wizard')
Pool.register(
InvestmentEvaluation,
InvestmentLine,
module='cashbook_report', type_='model', depends=['cashbook_investment'])

View file

@ -7,17 +7,11 @@ from trytond.model import ModelView, ModelSQL, fields, sequence_ordered
from trytond.pyson import Eval
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.i18n import gettext
from .colors import sel_color as sel_bgcolor
from .templates import template_view_graph, template_view_line
from .templates import template_view_graph, template_view_line, cashbook_types
sel_etype = [
('cashbooks', 'Cashbooks'),
('types', 'Types of Cashbooks'),
('currencies', 'Currencys'),
('categories', 'Categories'),
]
sel_chart = [
('vbar', 'Vertical Bars'),
('hbar', 'Horizontal Bars'),
@ -44,7 +38,7 @@ class Evaluation(sequence_ordered(), ModelSQL, ModelView):
required=True, ondelete="RESTRICT")
name = fields.Char(string='Name', required=True)
dtype = fields.Selection(string='Data type', required=True,
sort=False, selection=sel_etype,
sort=True, selection='get_sel_etype',
help='Type of data displayed')
dtype_string = dtype.translated('dtype')
chart = fields.Selection(string='Chart type', required=True,
@ -64,7 +58,7 @@ class Evaluation(sequence_ordered(), ModelSQL, ModelView):
relation_name='cashbook_report.eval_line',
origin='evaluation', target='cashbook',
states={
'invisible': Eval('dtype', '') != 'cashbooks',
'invisible': ~Eval('dtype', '').in_(cashbook_types),
}, depends=['dtype'])
types = fields.Many2Many(string='Types',
relation_name='cashbook_report.eval_line',
@ -143,6 +137,17 @@ class Evaluation(sequence_ordered(), ModelSQL, ModelView):
"""
return 'pie'
@classmethod
def get_sel_etype(cls):
""" get list of evaluation-types
"""
return [
('cashbooks', gettext('cashbook_report.msg_dtype_cashbook')),
('types', gettext('cashbook_report.msg_dtype_type')),
('currencies', gettext('cashbook_report.msg_dtype_currency')),
('categories', gettext('cashbook_report.msg_dtype_category')),
]
@classmethod
def get_create_view_data(cls, evaluation):
""" generate dictionary to create view-xml
@ -285,7 +290,7 @@ class Evaluation(sequence_ordered(), ModelSQL, ModelView):
continue
for dt in ['cashbooks', 'types', 'currencies', 'categories']:
if (values['dtype'] != dt) and \
if (not values['dtype'].startswith(dt)) and \
(len(getattr(evaluation, dt)) > 0):
to_write.extend([
[evaluation],

67
investment.py Normal file
View file

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# 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.
from trytond.pool import PoolMeta, Pool
from trytond.i18n import gettext
from decimal import Decimal
class InvestmentEvaluation(metaclass=PoolMeta):
__name__ = 'cashbook_report.evaluation'
@classmethod
def get_sel_etype(cls):
""" get list of evaluation-types
"""
result = super(InvestmentEvaluation, cls).get_sel_etype()
result.extend([
('cashbooks_gldiff', gettext('cashbook_report.msg_dtype_cashbook_gldiff')),
('cashbooks_glperc', gettext('cashbook_report.msg_dtype_cashbook_glperc')),
('cashbooks_glvalue', gettext('cashbook_report.msg_dtype_cashbooks_glvalue'))
])
return result
# end InvestmentEvaluation
class InvestmentLine(metaclass=PoolMeta):
__name__ = 'cashbook_report.eval_line'
def get_value_cashbooks_gldiff(self):
""" amount of profit/loss of cashbooks
"""
Currency = Pool().get('currency.currency')
if self.cashbook:
if self.cashbook.feature == 'asset':
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return Currency.compute(
self.cashbook.currency,
self.cashbook.diff_amount,
self.eval_currency,
).quantize(exp)
def get_value_cashbooks_glvalue(self):
""" current value of cashbooks
"""
Currency = Pool().get('currency.currency')
if self.cashbook:
if self.cashbook.feature == 'asset':
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return Currency.compute(
self.cashbook.currency,
self.cashbook.current_value,
self.eval_currency,
).quantize(exp)
def get_value_cashbooks_glperc(self):
""" percent of profit/loss of cashbooks
"""
if self.cashbook:
if self.cashbook.feature == 'asset':
return self.cashbook.diff_percent
# end InvestmentLine

14
line.py
View file

@ -11,6 +11,7 @@ from trytond.transaction import Transaction
from trytond.i18n import gettext
from trytond.exceptions import UserError
from trytond.pool import Pool
from .templates import cashbook_types
class EvaluationLine(ModelSQL, ModelView):
@ -23,7 +24,7 @@ class EvaluationLine(ModelSQL, ModelView):
cashbook = fields.Many2One(string='Cashbook', select=True, ondelete='CASCADE',
model_name='cashbook.book',
states={
'required': Eval('eval_dtype', '') == 'cashbooks',
'required': Eval('eval_dtype', '').in_(cashbook_types),
}, depends=['eval_dtype'])
dtype = fields.Many2One(string='Type', select=True, ondelete='CASCADE',
model_name='cashbook.type',
@ -130,6 +131,9 @@ class EvaluationLine(ModelSQL, ModelView):
return getattr(
getattr(self, {
'cashbooks': 'cashbook',
'cashbooks_gldiff': 'cashbook',
'cashbooks_glperc': 'cashbook',
'cashbooks_glvalue': 'cashbook',
'categories': 'category',
'types': 'dtype',
'currencies': 'currency',
@ -142,7 +146,7 @@ class EvaluationLine(ModelSQL, ModelView):
"""
super(EvaluationLine, cls).validate(records)
for record in records:
if (record.evaluation.dtype != 'cashbooks') and \
if (record.evaluation.dtype not in cashbook_types) and \
(record.cashbook is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
@ -160,6 +164,12 @@ class EvaluationLine(ModelSQL, ModelView):
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_currency'),
))
if (record.evaluation.dtype != 'categories') and \
(record.category is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_category'),
))
def get_balance_by_query(self, query):
""" run 'query' on Lines, convert used

View file

@ -11,8 +11,20 @@ msgid "Type of evaluation must be '%(typename)s'."
msgstr "Typ der Auswertung mus '%(typename)s' sein."
msgctxt "model:ir.message,text:msg_dtype_cashbook"
msgid "Cashbooks"
msgstr "Kassenbücher"
msgid "Cashbooks [Amount]"
msgstr "Kassenbücher [Betrag]"
msgctxt "model:ir.message,text:msg_dtype_cashbook_gldiff"
msgid "Cashbooks [Amount of Profit/Loss]"
msgstr "Kassenbücher [Betrag Gewinn/Verlust]"
msgctxt "model:ir.message,text:msg_dtype_cashbook_glperc"
msgid "Cashbooks [Percent of Profit/Loss]"
msgstr "Kassenbücher [Prozent Gewinn/Verlust]"
msgctxt "model:ir.message,text:msg_dtype_cashbooks_glvalue"
msgid "Cashbooks [Current Value]"
msgstr "Kassenbücher [aktueller Wert]"
msgctxt "model:ir.message,text:msg_dtype_type"
msgid "Types of Cashbooks"
@ -22,6 +34,10 @@ msgctxt "model:ir.message,text:msg_dtype_currency"
msgid "Currencies"
msgstr "Währungen"
msgctxt "model:ir.message,text:msg_dtype_category"
msgid "Categories"
msgstr "Kategorien"
msgctxt "model:ir.message,text:msg_name_graph"
msgid "Graph: %(gname)s"
msgstr "Diagramm: %(gname)s"

View file

@ -7,8 +7,20 @@ msgid "Type of evaluation must be '%(typename)s'."
msgstr "Type of evaluation must be '%(typename)s'."
msgctxt "model:ir.message,text:msg_dtype_cashbook"
msgid "Cashbooks"
msgstr "Cashbooks"
msgid "Cashbooks [Amount]"
msgstr "Cashbooks [Amount]"
msgctxt "model:ir.message,text:msg_dtype_cashbook_gldiff"
msgid "Cashbooks [Amount of Profit/Loss]"
msgstr "Cashbooks [Amount of Profit/Loss]"
msgctxt "model:ir.message,text:msg_dtype_cashbook_glperc"
msgid "Cashbooks [Percent of Profit/Loss]"
msgstr "Cashbooks [Percent of Profit/Loss]"
msgctxt "model:ir.message,text:msg_dtype_cashbooks_glvalue"
msgid "Cashbooks [Current Value]"
msgstr "Cashbooks [Current Value]"
msgctxt "model:ir.message,text:msg_dtype_type"
msgid "Types of Cashbooks"
@ -18,6 +30,10 @@ msgctxt "model:ir.message,text:msg_dtype_currency"
msgid "Currencies"
msgstr "Currencies"
msgctxt "model:ir.message,text:msg_dtype_category"
msgid "Categories"
msgstr "Categories"
msgctxt "model:ir.message,text:msg_name_graph"
msgid "Graph: %(gname)s"
msgstr "Graph: %(gname)s"

View file

@ -9,7 +9,16 @@ full copyright notices and license terms. -->
<field name="text">Type of evaluation must be '%(typename)s'.</field>
</record>
<record model="ir.message" id="msg_dtype_cashbook">
<field name="text">Cashbooks</field>
<field name="text">Cashbooks [Amount]</field>
</record>
<record model="ir.message" id="msg_dtype_cashbook_gldiff">
<field name="text">Cashbooks [Amount of Profit/Loss]</field>
</record>
<record model="ir.message" id="msg_dtype_cashbook_glperc">
<field name="text">Cashbooks [Percent of Profit/Loss]</field>
</record>
<record model="ir.message" id="msg_dtype_cashbooks_glvalue">
<field name="text">Cashbooks [Current Value]</field>
</record>
<record model="ir.message" id="msg_dtype_type">
<field name="text">Types of Cashbooks</field>
@ -17,6 +26,9 @@ full copyright notices and license terms. -->
<record model="ir.message" id="msg_dtype_currency">
<field name="text">Currencies</field>
</record>
<record model="ir.message" id="msg_dtype_category">
<field name="text">Categories</field>
</record>
<record model="ir.message" id="msg_name_graph">
<field name="text">Graph: %(gname)s</field>
</record>

View file

@ -22,7 +22,7 @@ with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
# tryton.cfg einlesen
config = ConfigParser()
config.readfp(open('tryton.cfg'))
config.read_file(open('tryton.cfg'))
info = dict(config.items('tryton'))
for key in ('depends', 'extras_depend', 'xml'):
if key in info:
@ -68,6 +68,7 @@ setup(name='%s_%s' % (PREFIX, MODULE),
description='Tryton module to add reports to cashbook.',
long_description=long_description,
url='https://www.m-ds.de/',
download_url='https://scmdev.m-ds.de/Tryton/Extra/cashbook_report',
author='martin-data services',
author_email='service@m-ds.de',
license='GPL-3',

View file

@ -3,6 +3,7 @@
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
cashbook_types = ['cashbooks', 'cashbooks_gldiff', 'cashbooks_glperc', 'cashbooks_glvalue']
template_view_line = '<field name="balance" fill="%(fill)s" empty="0" string="%(string)s"/>'

View file

@ -510,6 +510,31 @@ class ReportTestCase(CashbookTestCase):
self.assertEqual(len(evaluation.currencies), 0)
self.assertEqual(len(evaluation.categories), 0)
# investment - profit/loss amount
if 'cashbooks_gldiff' in [x[0] for x in Evaluation.get_sel_etype()]:
# no change if switch between cashbook-types
Evaluation.write(*[
[evaluation],
{
'dtype': 'cashbooks_gldiff',
}])
self.assertEqual(len(evaluation.cashbooks), 3)
self.assertEqual(len(evaluation.types), 0)
self.assertEqual(len(evaluation.currencies), 0)
self.assertEqual(len(evaluation.categories), 0)
Evaluation.write(*[
[evaluation],
{
'dtype': 'cashbooks_glperc',
}])
self.assertEqual(len(evaluation.cashbooks), 3)
self.assertEqual(len(evaluation.types), 0)
self.assertEqual(len(evaluation.currencies), 0)
self.assertEqual(len(evaluation.categories), 0)
else :
print('\n--== Module "cashbook_investment" not installed ==--')
Evaluation.write(*[
[evaluation],
{
@ -684,6 +709,90 @@ class ReportTestCase(CashbookTestCase):
if DashboardAction is not None:
self.assertEqual(DashboardAction.search_count([]), 1)
@with_transaction()
def test_report_chart_hbar_book_investment(self):
""" create 3x cashbooks, add bookings, rates
create report with cashbooks, check
"""
pool = Pool()
Evaluation = pool.get('cashbook_report.evaluation')
Book = pool.get('cashbook.book')
company = self.prep_company()
with Transaction().set_context({
'company': company.id,
}):
if 'cashbooks_gldiff' not in [x[0] for x in Evaluation.get_sel_etype()]:
print('\n--== Module "cashbook_investment" not installed ==--')
return
AccType = pool.get('cashbook.type')
Asset = pool.get('investment.asset')
Product = pool.get('product.template')
Uom = pool.get('product.uom')
at, = AccType.create([{
'name': 'depot',
'short': 'D',
'feature': 'asset',
'company': company.id,
}])
prod_templ, = Product.create([{
'name': 'Aurum',
'type': 'assets',
'list_price': Decimal('1.0'),
'default_uom': Uom.search([('symbol', '=', 'u')])[0].id,
'products': [('create', [{
'description': 'Au',
}])],
}])
asset, = Asset.create([{
'company': company.id,
'product': prod_templ.products[0].id,
'currency': company.currency.id,
'currency_digits': 4,
'uom': prod_templ.default_uom.id,
'rates': [('create', [{
'date': date(2022, 5, 1),
'rate': Decimal('1750.0'),
}, ])],
}])
AccType.write(*[
[books[0].btype],
{
'feature': 'asset',
}])
books = self.prep_report_3books()
Book.write(*[
books,
{
'asset': asset.id,
'quantity_uom': asset.uom.id,
'quantity_digits': 3,
}])
self.assertEqual(books[0].rec_name, 'ss')
evaluation, = Evaluation.create([{
'name': 'Evaluation 1',
'dtype': 'cashbooks_gldiff',
'chart': 'hbar',
'cashbooks': [('add', [x.id for x in books])],
}])
self.assertEqual(evaluation.dtype, 'cashbooks_gldiff')
self.assertEqual(evaluation.chart, 'hbar')
self.assertEqual(evaluation.legend, True)
self.assertEqual(evaluation.maincolor, 'default')
self.assertEqual(evaluation.bgcolor, '#ffffc0')
self.assertEqual(evaluation.currency.code, 'EUR')
self.assertEqual(evaluation.line_values[0].balance, Decimal('23.81'))
self.assertEqual(evaluation.line_values[1].balance, Decimal('11.90'))
self.assertEqual(evaluation.line_values[2].balance, Decimal('23.00'))
@with_transaction()
def test_report_chart_pie_book_red(self):
""" create 3x cashbooks, add bookings,
@ -719,7 +828,7 @@ class ReportTestCase(CashbookTestCase):
<field name="name"/>
</x>
<y>
<field name="balance" fill="1" empty="0" string="Cashbooks"/>
<field name="balance" fill="1" empty="0" string="Cashbooks [Amount]"/>
</y>
</graph>
""")

View file

@ -4,8 +4,9 @@ depends:
res
cashbook
cashbook_bookcategory
extras_depend:
#extras_depend:
dashboard
cashbook_investment
xml:
icon.xml
message.xml