evaluation/graph: anzeige läuft

This commit is contained in:
Frederik Jaeckel 2022-11-04 10:17:31 +01:00
parent 26d16a7297
commit 71ad546b21
13 changed files with 366 additions and 296 deletions

View file

@ -4,7 +4,8 @@
# full copyright notices and license terms.
from trytond.pool import Pool
from .evaluation import Evaluation, EvaluationLineRel
from .evaluation import Evaluation
from .line import EvaluationLine
from .currency import Currency
from .evaluation_context import EvaluationContext
from .evaluation_wizard import OpenChartWizard
@ -13,7 +14,7 @@ def register():
Pool.register(
Currency,
Evaluation,
EvaluationLineRel,
EvaluationLine,
EvaluationContext,
module='cashbook_report', type_='model')
Pool.register(

View file

@ -3,13 +3,9 @@
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
from decimal import Decimal
from sql.aggregate import Sum
from trytond.model import ModelView, ModelSQL, fields, Check
from trytond.pyson import Eval, Or, Bool, Id, Len
from trytond.model import ModelView, ModelSQL, fields
from trytond.pyson import Eval
from trytond.transaction import Transaction
from trytond.i18n import gettext
from trytond.exceptions import UserError
from trytond.pool import Pool
from .colors import sel_color as sel_bgcolor
from .templates import template_view_graph, template_view_line
@ -172,15 +168,11 @@ class Evaluation(ModelSQL, ModelView):
for evaluation in evaluations:
if evaluation.dtype:
# skip if no data to show
if len(getattr(evaluation, evaluation.dtype, [])) == 0:
if len(evaluation.line_values) == 0:
continue
view_graph, = UiView.create([{
'model': 'cashbook_report.%s' % {
'cashbooks': 'eval_book',
'types': 'eval_type',
'currencies': 'eval_currency',
}[evaluation.dtype],
'model': 'cashbook_report.eval_line',
'module': 'cashbook_report',
'priority': 10,
'type': 'graph',
@ -220,15 +212,16 @@ class Evaluation(ModelSQL, ModelView):
""" unlink records if dtype changes
"""
to_write = []
actions = iter(args)
to_update_uiview = []
for evaluations, values in zip(actions, actions):
actions = iter(args)
for evaluations, values in zip(actions, actions):
# update ui-view if related fields change
if len(set({'name', 'dtype', 'bgcolor', 'maincolor',
'legend', 'chart'}).intersection(values.keys())) > 0:
to_update_uiview.extend(evaluations)
# unlink records if dtype changes
if 'dtype' in values.keys():
for evaluation in evaluations:
if evaluation.dtype == values['dtype']:
@ -278,235 +271,3 @@ class Evaluation(ModelSQL, ModelView):
# end Evaluation
class EvaluationLineRel(ModelSQL):
'Evaluation Line Relation'
__name__ = 'cashbook_report.eval_line'
evaluation = fields.Many2One(string='Evaluation', required=True,
select=True, ondelete='CASCADE',
model_name='cashbook_report.evaluation')
cashbook = fields.Many2One(string='Cashbook', select=True, ondelete='CASCADE',
model_name='cashbook.book',
states={
'required': Eval('eval_dtype', '') == 'cashbooks',
}, depends=['eval_dtype'])
dtype = fields.Many2One(string='Type', select=True, ondelete='CASCADE',
model_name='cashbook.type',
states={
'required': Eval('eval_dtype', '') == 'types',
}, depends=['eval_dtype'])
currency = fields.Many2One(string='Currency', select=True, ondelete='CASCADE',
model_name='currency.currency',
states={
'required': Eval('eval_dtype', '') == 'currencies',
}, depends=['eval_dtype'])
# currency of evaluation
eval_currency = fields.Function(fields.Many2One(model_name='currency.currency',
string="Currency", readonly=True), 'on_change_with_eval_currency')
currency_digits = fields.Function(fields.Integer(string='Currency Digits',
readonly=True), 'on_change_with_currency_digits')
eval_dtype = fields.Function(fields.Char(string='Data type', readonly=True),
'on_change_with_eval_dtype')
name = fields.Function(fields.Char(string='Name', readonly=True),
'on_change_with_name')
balance = fields.Function(fields.Numeric(string='Balance',
readonly=True, digits=(16, Eval('currency_digits', 2)),
depends=['currency_digits']),
'on_change_with_balance')
@classmethod
def fields_view_get(cls, view_id, view_type='form'):
""" replace form-view-id
"""
pool = Pool()
ModelData = pool.get('ir.model.data')
Evaluation = pool.get('cashbook_report.evaluation')
context = Transaction().context
# get id of origin chart-form
form_id = ModelData.get_id('cashbook_report', 'point_view_graph')
# active_chart was added by tree_open-action
active_evaluation = context.get('active_evaluation', None)
# check if we are requested for our default form...
if (view_type == 'graph') and (view_id == form_id) and \
(active_evaluation is not None):
evaluation, = Evaluation.browse([active_evaluation])
if evaluation.ui_view_point:
# ... switch to view, created by evaluation-config
view_id = evaluation.ui_view_point.id
return super(EvaluationLineRel, cls).fields_view_get(
view_id=view_id, view_type=view_type)
@fields.depends('evaluation', '_parent_evaluation.dtype')
def on_change_with_eval_dtype(self, name=None):
""" get dtape from parent
"""
if self.evaluation:
return self.evaluation.dtype
@fields.depends('evaluation', '_parent_evaluation.currency')
def on_change_with_eval_currency(self, name=None):
""" currency of evaluation
"""
if self.evaluation:
return self.evaluation.currency.id
@fields.depends('evaluation', '_parent_evaluation.currency')
def on_change_with_currency_digits(self, name=None):
""" currency-digits of evaluation
"""
if self.evaluation:
return self.evaluation.currency.digits
else:
return 2
@classmethod
def validate(cls, records):
""" check parent record
"""
super(EvaluationLineRel, cls).validate(records)
for record in records:
if (record.evaluation.dtype != 'cashbooks') and \
(record.cashbook is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_cashbook'),
))
if (record.evaluation.dtype != 'types') and \
(record.dtype is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_type'),
))
if (record.evaluation.dtype != 'currencies') and \
(record.currency is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_currency'),
))
@fields.depends('eval_dtype', 'cashbook', 'dtype', 'currency')
def on_change_with_name(self, name=None):
""" get name of Type
"""
if self.eval_dtype:
return getattr(
getattr(self, {
'cashbooks': 'cashbook',
'types': 'dtype',
'currencies': 'currency',
}[self.eval_dtype], None),
'rec_name', None)
def get_value_cashbooks(self):
""" balance of cashbooks
"""
Currency = Pool().get('currency.currency')
if self.cashbook:
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return Currency.compute(
self.cashbook.currency,
self.cashbook.balance,
self.eval_currency,
).quantize(exp)
def get_value_types(self):
""" get balance of bookings in cashbooks by 'type',
converted to currency of evaluation
"""
pool = Pool()
Lines = pool.get('cashbook.line')
Cashbook = pool.get('cashbook.book')
Currency = pool.get('currency.currency')
tab_line = Lines.__table__()
tab_book = Cashbook.__table__()
cursor = Transaction().connection.cursor()
if (self.evaluation is None) or (self.dtype is None) or \
(self.eval_currency is None) or (self.currency_digits is None):
return None
lines = Lines.search([
('cashbook.btype.id', '=', self.dtype.id),
('cashbook.state', '=', 'open'),
('cashbook.owner.id', '=', Transaction().user),
], query=True)
query = lines.join(tab_line, condition=lines.id==tab_line.id,
).join(tab_book, condition=tab_book.id==tab_line.cashbook,
).select(
tab_book.currency,
Sum(tab_line.credit - tab_line.debit).as_('balance'),
group_by=[tab_book.currency],
)
cursor.execute(*query)
balances = cursor.fetchall()
total_amount = Decimal('0.0')
for balance in balances:
(id_currency, bal1) = balance
total_amount += Currency.compute(
Currency(id_currency),
bal1,
self.eval_currency,
)
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return total_amount.quantize(exp)
def get_value_currencies(self):
""" get balance of bookings in cashbooks by 'currency',
converted to currency of evaluation
"""
pool = Pool()
Lines = pool.get('cashbook.line')
Currency = pool.get('currency.currency')
tab_line = Lines.__table__()
cursor = Transaction().connection.cursor()
if (self.evaluation is None) or (self.currency is None) or \
(self.eval_currency is None) or (self.currency_digits is None):
return None
lines = Lines.search([
('cashbook.currency.id', '=', self.currency.id),
('cashbook.state', '=', 'open'),
('cashbook.owner.id', '=', Transaction().user),
], query=True)
query = lines.join(tab_line, condition=lines.id==tab_line.id,
).select(
Sum(tab_line.credit - tab_line.debit).as_('balance'),
)
cursor.execute(*query)
balances = cursor.fetchall()
total_amount = Decimal('0.0')
for balance in balances:
(bal1,) = balance
total_amount += Currency.compute(
self.currency,
bal1,
self.eval_currency,
)
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return total_amount.quantize(exp)
@fields.depends('eval_dtype', 'eval_currency', 'currency_digits', \
'cashbook', '_parent_cashbook.currency', '_parent_cashbook.balance',\
'evaluation', 'dtype', 'currency')
def on_change_with_balance(self, name=None):
""" balance of cashbook
"""
if self.eval_dtype:
return getattr(self, 'get_value_%s' % self.eval_dtype)()
# end EvaluationLineRel

View file

@ -12,8 +12,7 @@ class EvaluationContext(ModelView):
__name__ = 'cashbook_report.evaluation.context'
evaluation = fields.Many2One(string='Evaluation', readonly=True,
model_name='cashbook_report.evaluation',
states={'invisible': True})
model_name='cashbook_report.evaluation')
@classmethod
def default_evaluation(cls):

View file

@ -23,7 +23,7 @@ full copyright notices and license terms. -->
</record>
<record model="ir.action.act_window.view" id="act_evaluation_graph_view-1">
<field name="sequence" eval="10"/>
<field name="view" ref="book_view_graph"/>
<field name="view" ref="evalline_view_graph"/>
<field name="act_window" ref="act_evaluation_graph_view"/>
</record>

View file

@ -1,17 +0,0 @@
<?xml version="1.0"?>
<!-- This file is part of the diagram-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<tryton>
<data>
<!-- views -->
<record model="ir.ui.view" id="book_view_graph">
<field name="model">cashbook.book</field>
<field name="type">graph</field>
<field name="priority" eval="10"/>
<field name="name">book_graph</field>
</record>
</data>
</tryton>

79
ir.xml Normal file
View file

@ -0,0 +1,79 @@
<?xml version="1.0"?>
<!-- This file is part of the diagram-module from m-ds for Tryton.
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.model.access" id="access_iruiview-group_cashbook">
<field name="model" search="[('model', '=', 'ir.ui.view')]"/>
<field name="group" ref="cashbook.group_cashbook"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<!-- permission by rule - anon -->
<record model="ir.rule.group" id="rg_iruiview_anon">
<field name="model" search="[('model', '=', 'ir.ui.view')]"/>
<field name="name">Anon: IR UI View read</field>
<field name="global_p" eval="False"/>
<field name="default_p" eval="True"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.rule" id="rg_iruiview_anon-1">
<field name="domain" eval="[]" pyson="1"/>
<field name="rule_group" ref="rg_iruiview_anon"/>
</record>
<!-- permission by rule - group_cashbook - edit -->
<record model="ir.rule.group" id="rg_iruiview_group_cashbook">
<field name="model" search="[('model', '=', 'ir.ui.view')]"/>
<field name="name">Owner: IR UI View edit</field>
<field name="global_p" eval="False"/>
<field name="default_p" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.rule" id="rg_iruiview_group_cashbook-2">
<field name="domain" eval="[
('model', '=', 'cashbook_report.eval_line'),
('type', '=', 'graph'),
('module', '=', 'cashbook_report'),
('create_uid', '=', Eval('user', {}).get('id', -1)),
]" pyson="1"/>
<field name="rule_group" ref="rg_iruiview_group_cashbook"/>
</record>
<record model="ir.rule.group-res.group" id="rg_iruiview_group_cashbook-group_cashbook">
<field name="rule_group" ref="rg_iruiview_group_cashbook"/>
<field name="group" ref="cashbook.group_cashbook"/>
</record>
<!-- permission by rule - group_admin -->
<record model="ir.rule.group" id="rg_iruiview_group_admin">
<field name="model" search="[('model', '=', 'ir.ui.view')]"/>
<field name="name">Administrator: IR UI View edit</field>
<field name="global_p" eval="False"/>
<field name="default_p" eval="False"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.rule" id="rg_iruiview_group_admin-1">
<field name="domain" eval="[]" pyson="1"/>
<field name="rule_group" ref="rg_iruiview_group_admin"/>
</record>
<record model="ir.rule.group-res.group" id="rg_iruiview_group_admin-group_admin">
<field name="rule_group" ref="rg_iruiview_group_admin"/>
<field name="group" ref="res.group_admin"/>
</record>
</data>
</tryton>

246
line.py Normal file
View file

@ -0,0 +1,246 @@
# -*- 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 decimal import Decimal
from sql.aggregate import Sum
from trytond.model import ModelView, ModelSQL, fields
from trytond.pyson import Eval
from trytond.transaction import Transaction
from trytond.i18n import gettext
from trytond.exceptions import UserError
from trytond.pool import Pool
class EvaluationLine(ModelSQL, ModelView):
'Evaluation Line Relation'
__name__ = 'cashbook_report.eval_line'
evaluation = fields.Many2One(string='Evaluation', required=True,
select=True, ondelete='CASCADE',
model_name='cashbook_report.evaluation')
cashbook = fields.Many2One(string='Cashbook', select=True, ondelete='CASCADE',
model_name='cashbook.book',
states={
'required': Eval('eval_dtype', '') == 'cashbooks',
}, depends=['eval_dtype'])
dtype = fields.Many2One(string='Type', select=True, ondelete='CASCADE',
model_name='cashbook.type',
states={
'required': Eval('eval_dtype', '') == 'types',
}, depends=['eval_dtype'])
currency = fields.Many2One(string='Currency', select=True, ondelete='CASCADE',
model_name='currency.currency',
states={
'required': Eval('eval_dtype', '') == 'currencies',
}, depends=['eval_dtype'])
# dtype + currency of evaluation
eval_dtype = fields.Function(fields.Char(string='Data type', readonly=True),
'on_change_with_eval_dtype')
eval_currency = fields.Function(fields.Many2One(model_name='currency.currency',
string="Currency", readonly=True), 'on_change_with_eval_currency')
currency_digits = fields.Function(fields.Integer(string='Currency Digits',
readonly=True), 'on_change_with_currency_digits')
name = fields.Function(fields.Char(string='Name', readonly=True),
'on_change_with_name')
balance = fields.Function(fields.Numeric(string='Balance',
readonly=True, digits=(16, Eval('currency_digits', 2)),
depends=['currency_digits']),
'on_change_with_balance')
@classmethod
def fields_view_get(cls, view_id, view_type='form'):
""" replace form-view-id
"""
pool = Pool()
ModelData = pool.get('ir.model.data')
Evaluation = pool.get('cashbook_report.evaluation')
context = Transaction().context
# get id of origin chart-form
form_id = ModelData.get_id('cashbook_report', 'evalline_view_graph')
# active_chart was added by tree_open-action
active_evaluation = context.get('active_evaluation', None)
# check if we are requested for our default form...
if (view_type == 'graph') and (view_id == form_id) and \
(active_evaluation is not None):
evaluation, = Evaluation.browse([active_evaluation])
if evaluation.ui_view_chart:
# ... switch to view, created by evaluation-config
view_id = evaluation.ui_view_chart.id
return super(EvaluationLine, cls).fields_view_get(
view_id=view_id, view_type=view_type)
@fields.depends('evaluation', '_parent_evaluation.dtype')
def on_change_with_eval_dtype(self, name=None):
""" get dtape from parent
"""
if self.evaluation:
return self.evaluation.dtype
@fields.depends('evaluation', '_parent_evaluation.currency')
def on_change_with_eval_currency(self, name=None):
""" currency of evaluation
"""
if self.evaluation:
return self.evaluation.currency.id
@fields.depends('evaluation', '_parent_evaluation.currency')
def on_change_with_currency_digits(self, name=None):
""" currency-digits of evaluation
"""
if self.evaluation:
return self.evaluation.currency.digits
else:
return 2
@classmethod
def validate(cls, records):
""" check parent record
"""
super(EvaluationLine, cls).validate(records)
for record in records:
if (record.evaluation.dtype != 'cashbooks') and \
(record.cashbook is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_cashbook'),
))
if (record.evaluation.dtype != 'types') and \
(record.dtype is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_type'),
))
if (record.evaluation.dtype != 'currencies') and \
(record.currency is not None):
raise UserError(gettext(
'cashbook_report.msg_invalid_dtype',
typename = gettext('cashbook_report.msg_dtype_currency'),
))
@fields.depends('eval_dtype', 'cashbook', 'dtype', 'currency')
def on_change_with_name(self, name=None):
""" get name of Type
"""
if self.eval_dtype:
return getattr(
getattr(self, {
'cashbooks': 'cashbook',
'types': 'dtype',
'currencies': 'currency',
}[self.eval_dtype], None),
'rec_name', None)
def get_value_cashbooks(self):
""" balance of cashbooks
"""
Currency = Pool().get('currency.currency')
if self.cashbook:
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return Currency.compute(
self.cashbook.currency,
self.cashbook.balance,
self.eval_currency,
).quantize(exp)
def get_value_types(self):
""" get balance of bookings in cashbooks by 'type',
converted to currency of evaluation
"""
pool = Pool()
Lines = pool.get('cashbook.line')
Cashbook = pool.get('cashbook.book')
Currency = pool.get('currency.currency')
tab_line = Lines.__table__()
tab_book = Cashbook.__table__()
cursor = Transaction().connection.cursor()
if (self.evaluation is None) or (self.dtype is None) or \
(self.eval_currency is None) or (self.currency_digits is None):
return None
lines = Lines.search([
('cashbook.btype.id', '=', self.dtype.id),
('cashbook.state', '=', 'open'),
('cashbook.owner.id', '=', Transaction().user),
], query=True)
query = lines.join(tab_line, condition=lines.id==tab_line.id,
).join(tab_book, condition=tab_book.id==tab_line.cashbook,
).select(
tab_book.currency,
Sum(tab_line.credit - tab_line.debit).as_('balance'),
group_by=[tab_book.currency],
)
cursor.execute(*query)
balances = cursor.fetchall()
total_amount = Decimal('0.0')
for balance in balances:
(id_currency, bal1) = balance
total_amount += Currency.compute(
Currency(id_currency),
bal1,
self.eval_currency,
)
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return total_amount.quantize(exp)
def get_value_currencies(self):
""" get balance of bookings in cashbooks by 'currency',
converted to currency of evaluation
"""
pool = Pool()
Lines = pool.get('cashbook.line')
Currency = pool.get('currency.currency')
tab_line = Lines.__table__()
cursor = Transaction().connection.cursor()
if (self.evaluation is None) or (self.currency is None) or \
(self.eval_currency is None) or (self.currency_digits is None):
return None
lines = Lines.search([
('cashbook.currency.id', '=', self.currency.id),
('cashbook.state', '=', 'open'),
('cashbook.owner.id', '=', Transaction().user),
], query=True)
query = lines.join(tab_line, condition=lines.id==tab_line.id,
).select(
Sum(tab_line.credit - tab_line.debit).as_('balance'),
)
cursor.execute(*query)
balances = cursor.fetchall()
total_amount = Decimal('0.0')
for balance in balances:
(bal1,) = balance
total_amount += Currency.compute(
self.currency,
bal1,
self.eval_currency,
)
exp = Decimal(Decimal(1) / 10 ** self.currency_digits)
return total_amount.quantize(exp)
@fields.depends('eval_dtype', 'eval_currency', 'currency_digits', \
'cashbook', '_parent_cashbook.currency', '_parent_cashbook.balance',\
'evaluation', '_parent_evaluation.id', 'dtype', 'currency')
def on_change_with_balance(self, name=None):
""" balance of cashbook
"""
if self.eval_dtype:
return getattr(self, 'get_value_%s' % self.eval_dtype)()
# end EvaluationLine

View file

@ -307,7 +307,7 @@ class ReportTestCase(CashbookTestCase):
self.assertEqual(evaluation.currency.code, 'EUR')
# check uiview
self.assertEqual(evaluation.ui_view_chart.model, 'cashbook_report.eval_book')
self.assertEqual(evaluation.ui_view_chart.model, 'cashbook_report.eval_line')
self.assertEqual(evaluation.ui_view_chart.module, 'cashbook_report')
self.assertEqual(evaluation.ui_view_chart.priority, 10)
self.assertEqual(evaluation.ui_view_chart.type, 'graph')

View file

@ -1,13 +1,14 @@
[tryton]
version=6.0.0
depends:
ir
cashbook
xml:
icon.xml
message.xml
graph.xml
ir.xml
evaluation.xml
line_value.xml
line.xml
evaluation_context.xml
evaluation_wizard.xml
menu.xml

8
view/evalline_list.xml Normal file
View file

@ -0,0 +1,8 @@
<?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. -->
<tree >
<field name="name"/>
<field name="balance"/>
</tree>

View file

@ -2,13 +2,7 @@
<!-- 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. -->
<form col="1">
<notebook>
<page id="chart" col="1" string="Chart">
<field name="cashbooks" view_ids="cashbook_report.book_view_graph" readonly="1"/>
<!-- <field name="types" view_ids="cashbook_report.book_view_graph" readonly="1"/> -->
</page>
<page id="config" col="6" string="Settings">
<form col="6">
<label name="name"/>
<field name="name"/>
<label name="dtype"/>
@ -27,6 +21,4 @@ full copyright notices and license terms. -->
<field name="cashbooks" colspan="6"/>
<field name="types" colspan="6"/>
<field name="currencies" colspan="6"/>
</page>
</notebook>
</form>