# -*- 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'), 'on_change_with_name', setter='set_name_data') name_line = fields.Char(string='Name', states={'invisible': True}) balance = fields.Function(fields.Numeric(string='Balance', readonly=True, digits=(16, Eval('currency_digits', 2)), depends=['currency_digits']), 'on_change_with_balance') @classmethod def set_name_data(cls, lines, name, value): """ store updated name """ print('\n## set_name_data', lines, name, value) cls.write(*[ lines, { 'name_line': value, }]) @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 @fields.depends('eval_dtype', 'cashbook', 'dtype', 'currency', 'name_line') def on_change_with_name(self, name=None): """ get name of Type """ # prefer to use local stored name of line if self.name_line: if len(self.name_line) > 0: return self.name_line # otherwise use rec_name of linked record if self.eval_dtype: return getattr( getattr(self, { 'cashbooks': 'cashbook', 'types': 'dtype', 'currencies': 'currency', }[self.eval_dtype], None), 'rec_name', None) @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'), )) 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