# -*- 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.model import fields, SymbolMixin from trytond.exceptions import UserError from trytond.pool import PoolMeta, Pool from trytond.pyson import Eval, Or, Len from trytond.modules.cashbook.book import STATES2, DEPENDS2 from trytond.transaction import Transaction from decimal import Decimal from sql.functions import CurrentDate from sql.aggregate import Sum from sql.conditionals import Case, Coalesce class Book(SymbolMixin, metaclass=PoolMeta): __name__ = 'cashbook.book' asset = fields.Many2One(string='Asset', model_name='investment.asset', ondelete='RESTRICT', states={ 'required': Eval('feature', '') == 'asset', 'invisible': Eval('feature', '') != 'asset', 'readonly': Or( STATES2['readonly'], Len(Eval('lines')) > 0, ), }, depends=DEPENDS2+['feature', 'lines']) quantity_digits = fields.Integer(string='Digits', help='Quantity Digits', domain=[ ('quantity_digits', '>=', 0), ('quantity_digits', '<=', 6), ], states={ 'required': Eval('feature', '') == 'asset', 'invisible': Eval('feature', '') != 'asset', 'readonly': Or( STATES2['readonly'], Len(Eval('lines')) > 0, ), }, depends=DEPENDS2+['feature', 'lines']) asset_uomcat = fields.Function(fields.Many2One(string='UOM Category', readonly=True, model_name='product.uom.category', states={'invisible': True}), 'on_change_with_asset_uomcat') quantity_uom = fields.Many2One(string='UOM', model_name='product.uom', ondelete='RESTRICT', domain=[ ('category.id', '=', Eval('asset_uomcat', -1)), ], states={ 'required': Eval('feature', '') == 'asset', 'invisible': Eval('feature', '') != 'asset', 'readonly': Or( STATES2['readonly'], Len(Eval('lines')) > 0, ), }, depends=DEPENDS2+['feature', 'lines', 'asset_uomcat']) symbol = fields.Function(fields.Char(string='Symbol', readonly=True), 'on_change_with_symbol') quantity = fields.Function(fields.Numeric(string='Quantity', help='Quantity of assets until to date', readonly=True, digits=(16, Eval('quantity_digits', 4)), states={ 'invisible': Eval('feature', '') != 'asset', }, depends=['quantity_digits', 'feature']), 'get_asset_quantity') quantity_all = fields.Function(fields.Numeric(string='Total Quantity', help='Total quantity of all assets', readonly=True, digits=(16, Eval('quantity_digits', 4)), states={ 'invisible': Eval('feature', '') != 'asset', }, depends=['quantity_digits', 'feature']), 'get_asset_quantity') current_value = fields.Function(fields.Numeric(string='Value', 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.)', readonly=True, digits=(16, Eval('currency_digits', 2)), states={ 'invisible': Eval('feature', '') != 'asset', }, depends=['currency_digits', 'feature']), 'get_asset_quantity') @fields.depends('asset', 'quantity_uom') def on_change_asset(self): """ get uom from asset """ if self.asset: self.quantity_uom = self.asset.uom.id @classmethod def default_quantity_digits(cls): """ default: 4 """ return 4 @classmethod def get_asset_quantity(cls, cashbooks, names): """ get quantities """ pool = Pool() CBook = pool.get('cashbook.book') Line = pool.get('cashbook.line') Asset = pool.get('investment.asset') Currency = pool.get('currency.currency') Uom = pool.get('product.uom') tab_book = CBook.__table__() tab_line = Line.__table__() tab_cur = Currency.__table__() tab_asset = Asset.__table__() (tab_rate, tab2) = Asset.get_rate_data_sql() cursor = Transaction().connection.cursor() context = Transaction().context result = {x:{y.id: None for y in cashbooks} for x in names} query_date = context.get('qdate', CurrentDate()) company_currency = CBook.default_currency() query = tab_book.join(tab_line, condition=(tab_book.id==tab_line.cashbook), ).join(tab_cur, condition=tab_book.currency==tab_cur.id, ).join(tab_asset, condition=tab_book.asset==tab_asset.id, ).join(tab_rate, condition=tab_book.asset==tab_rate.id, type_ = 'LEFT OUTER', ).select( tab_book.id, # 0 Coalesce(Sum(Case( (tab_line.date <= query_date, tab_line.quantity), else_ = Decimal('0.0'), )), Decimal('0.0')).as_('quantity'), # 1 Sum(tab_line.quantity).as_('quantity_all'), # 2 Coalesce(tab_rate.rate, Decimal('0.0')).as_('rate'), # 3 tab_book.currency, # 4 tab_cur.digits.as_('currency_digits'), # 5 tab_asset.uom, # 6 tab_book.quantity_uom, # 7 tab_asset.currency.as_('asset_currency'), #8 group_by=[tab_book.id, tab_rate.rate, tab_book.currency, tab_cur.digits, tab_asset.uom, tab_book.quantity_uom, tab_asset.currency], ) cursor.execute(*query) records = cursor.fetchall() for record in records: # uom-factor if record[6] == record[7]: uom_factor = Decimal('1.0') else : uom_factor = Decimal( Uom.compute_qty(Uom(record[6]), 1.0, Uom(record[7]), round=False) ) values = { 'quantity': record[1], 'quantity_all': record[2], 'current_value': Currency.compute( record[8], record[3] * record[1] / uom_factor, record[4] ), 'current_value_ref': Currency.compute( record[8], record[3] * record[1] / uom_factor, company_currency if company_currency is not None else record[8], ), } for name in names: result[name][record[0]] = values[name] return result @fields.depends('quantity_uom', 'currency') def on_change_with_symbol(self, name=None): """ get symbol for asset """ return '%(currency)s/%(unit)s' % { 'currency': getattr(self.currency, 'symbol', '-'), 'unit': getattr(self.quantity_uom, 'symbol', '-'), } @fields.depends('asset', '_parent_asset.uom') def on_change_with_asset_uomcat(self, name=None): """ get uom-category of asset """ if self.asset: return self.asset.uom.category.id # end Book