cashbook_investment/line.py

277 lines
10 KiB
Python
Raw Normal View History

2022-12-21 23:32:26 +00:00
# -*- coding: utf-8 -*-
2023-01-15 22:06:47 +00:00
# This file is part of the cashbook-module from m-ds.de for Tryton.
2022-12-21 23:32:26 +00:00
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
from decimal import Decimal
from trytond.model import fields
from trytond.pool import PoolMeta, Pool
2022-12-21 23:32:26 +00:00
from trytond.pyson import Eval, Or, If
from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.report import Report
2022-12-21 23:32:26 +00:00
from trytond.modules.cashbook.line import STATES, DEPENDS
2023-01-12 22:37:20 +00:00
from .mixin import SecondUomMixin
2022-12-21 23:32:26 +00:00
STATESQ = {
2023-01-14 23:36:02 +00:00
'required': Eval('feature', '') == 'asset',
'invisible': Eval('feature', '') != 'asset',
'readonly': Or(
STATES['readonly'],
Eval('bookingtype', '').in_(['spin', 'spout']),
),
}
2023-01-14 23:36:02 +00:00
DEPENDSQ = DEPENDS+['feature', 'quantity_digits', 'bookingtype']
2022-12-21 23:32:26 +00:00
2023-01-12 22:37:20 +00:00
class Line(SecondUomMixin, metaclass=PoolMeta):
2022-12-21 23:32:26 +00:00
__name__ = 'cashbook.line'
quantity = fields.Numeric(string='Quantity',
digits=(16, Eval('quantity_digits', 4)),
states=STATESQ, depends=DEPENDSQ)
quantity_credit = fields.Numeric(string='Quantity Credit',
digits=(16, Eval('quantity_digits', 4)), readonly=True,
states={
'invisible': STATESQ['invisible'],
'required': STATESQ['required'],
}, depends=DEPENDSQ)
quantity_debit = fields.Numeric(string='Quantity Debit',
digits=(16, Eval('quantity_digits', 4)), readonly=True,
states={
'invisible': STATESQ['invisible'],
'required': STATESQ['required'],
}, depends=DEPENDSQ)
2022-12-21 23:32:26 +00:00
quantity_digits = fields.Function(fields.Integer(string='Digits',
readonly=True, states={'invisible': True}),
'on_change_with_quantity_digits')
quantity_uom = fields.Function(fields.Many2One(string='Symbol',
readonly=True, model_name='product.uom'),
'on_change_with_quantity_uom')
2022-12-21 23:32:26 +00:00
asset_rate = fields.Function(fields.Numeric(string='Rate',
readonly=True,
digits=(16, If(
Eval('currency_digits', 2) > Eval('quantity_digits', 2),
Eval('currency_digits', 2), Eval('quantity_digits', 2))),
2022-12-25 10:36:12 +00:00
states={
'invisible': Eval('feature', '') != 'asset',
}, depends=['currency_digits', 'quantity_digits', 'feature']),
2022-12-21 23:32:26 +00:00
'on_change_with_asset_rate')
quantity_balance = fields.Function(fields.Numeric(string='Quantity',
digits=(16, Eval('quantity_digits', 4)), readonly=True,
help='Number of shares in the cashbook up to the current row if the default sort applies.',
states={
'invisible': Eval('feature', '') != 'asset',
}, depends=['quantity_digits', 'feature']),
'on_change_with_quantity_balance')
2022-12-21 23:32:26 +00:00
def get_rec_name(self, name):
""" add quantities - if its a asset-cashbook
"""
recname = super(Line, self).get_rec_name(name)
if self.cashbook.feature == 'asset':
recname += '|%(quantity)s %(uom_symbol)s' % {
'quantity': Report.format_number(self.quantity or 0.0, None,
digits=self.quantity_digits),
'uom_symbol': self.quantity_uom.symbol,
}
return recname
2023-01-15 22:06:47 +00:00
@classmethod
def get_fields_write_update(cls):
""" add 'quantity' to updatefields
"""
result = super(Line, cls).get_fields_write_update()
result.append('quantity')
return result
@classmethod
2023-01-14 23:36:02 +00:00
def get_debit_credit(cls, values, line=None):
""" compute quantity_debit/quantity_credit from quantity
"""
2023-01-14 23:36:02 +00:00
Cashbook = Pool().get('cashbook.book')
result = super(Line, cls).get_debit_credit(values, line)
if line:
cashbook = line.cashbook
else:
id_cashbook = values.get('cashbook', None)
cashbook = None
if id_cashbook:
cashbook = Cashbook.browse([id_cashbook])[0]
if isinstance(values, dict):
type_ = values.get('bookingtype', None)
quantity = values.get('quantity', None)
else :
type_ = getattr(values, 'bookingtype', None)
quantity = getattr(values, 'quantity', None)
2023-01-14 23:36:02 +00:00
if (type_ is not None) and (cashbook.feature == 'asset'):
if quantity is not None:
if type_ in ['in', 'mvin', 'spin']:
2023-01-14 23:36:02 +00:00
result.update({
'quantity_debit': Decimal('0.0'),
'quantity_credit': quantity,
})
elif type_ in ['out', 'mvout', 'spout']:
2023-01-14 23:36:02 +00:00
result.update({
'quantity_debit': quantity,
'quantity_credit': Decimal('0.0'),
})
else :
raise ValueError('invalid "bookingtype"')
2023-01-14 23:36:02 +00:00
return result
@classmethod
def get_counterpart_values(cls, line, values={}):
""" add quantity to counterpart
"""
result = super(Line, cls).get_counterpart_values(line, values)
2023-01-14 23:36:02 +00:00
line_uom = getattr(line.quantity_uom, 'id', None)
booktransf_uom = getattr(getattr(line.booktransf, 'quantity_uom', {}), 'id', None)
if booktransf_uom is None:
# counterpart-cashbook has no uom -> no quantity
result.update({
'quantity': None,
'quantity_2nd_uom': None,
})
else :
if line_uom is None:
result.update({
'quantity': line.quantity,
'quantity_2nd_uom': None,
})
elif line_uom == booktransf_uom:
result.update({
'quantity': line.quantity,
'quantity_2nd_uom': None,
})
else :
result.update({
'quantity': line.quantity_2nd_uom,
'quantity_2nd_uom': line.quantity,
})
return result
@fields.depends('id', 'date', 'cashbook', 'feature',\
'_parent_cashbook.id', 'reconciliation', \
'_parent_reconciliation.start_quantity',\
'_parent_reconciliation.state')
def on_change_with_quantity_balance(self, name=None):
""" get quantity-balance
"""
Line2 = Pool().get('cashbook.line')
if self.feature == 'asset':
return Line2.get_balance_of_line(self,
field_name='quantity',
credit_name='quantity_credit',
debit_name='quantity_debit')
2022-12-21 23:32:26 +00:00
@fields.depends('quantity', 'amount', 'currency_digits', 'quantity_digits')
def on_change_with_asset_rate(self, name=None):
""" get rate
"""
if (self.quantity is None) or (self.amount is None):
return
digit = max(
self.currency_digits if self.currency_digits is not None else 2,
self.quantity_digits if self.quantity_digits is not None else 4)
if self.quantity != Decimal('0.0'):
return (
self.amount / self.quantity
2023-01-14 23:36:02 +00:00
).quantize(Decimal(Decimal(1) / 10**digit))
2022-12-21 23:32:26 +00:00
@fields.depends('cashbook', '_parent_cashbook.quantity_uom')
def on_change_with_quantity_uom(self, name=None):
""" get quantity-unit of asset
2022-12-21 23:32:26 +00:00
"""
if self.cashbook:
2022-12-25 10:36:12 +00:00
if self.cashbook.quantity_uom:
return self.cashbook.quantity_uom.id
2022-12-21 23:32:26 +00:00
@fields.depends('cashbook', '_parent_cashbook.quantity_digits')
def on_change_with_quantity_digits(self, name=None):
""" get digits from cashbook
"""
if self.cashbook:
return self.cashbook.quantity_digits
return 4
@classmethod
def validate(cls, lines):
""" deny pos/neg mismatch
"""
super(Line, cls).validate(lines)
for line in lines:
# ignore non-asset-lines
if line.cashbook.feature != 'asset':
continue
# quantity must be set
if (line.quantity is None) or \
(line.quantity_credit is None) or \
(line.quantity_debit is None):
raise UserError(gettext(
'cashbook_investment.msg_line_quantity_not_set',
linetxt = line.rec_name,
))
# quantity and amount must with same sign
(amount_sign, a_dig, a_exp) = line.amount.as_tuple()
(quantity_sign, q_dig, q_exp) = line.quantity.as_tuple()
if amount_sign != quantity_sign:
raise UserError(gettext(
'cashbook_investment.msg_line_sign_mismatch',
linetxt = line.rec_name,
))
2023-01-15 22:06:47 +00:00
@classmethod
def update_values_by_splitlines(cls, lines):
""" add quantity to line
"""
to_write = super(Line, cls).update_values_by_splitlines(lines)
for line in lines:
cnt1 = sum([1 for x in line.splitlines if x.quantity is not None])
quantity = sum([x.quantity or Decimal('0.0') for x in line.splitlines])
if (cnt1 > 0) and (quantity != line.quantity):
to_write.extend([ [line], {'quantity': quantity,} ])
return to_write
@classmethod
def add_values_from_splitlines(cls, values):
""" add values for create to line by settings on splitlines
"""
values = super(Line, cls).add_values_from_splitlines(values)
if ('splitlines' in values.keys()) and ('quantity' not in values.keys()):
for action in values['splitlines']:
quantity = None
if action[0] == 'create':
cnt1 = sum([1 for x in action[1] if x.get('quantity', None) is not None])
quantity = sum([x.get('quantity', Decimal('0.0')) for x in action[1]])
if cnt1 > 0:
values['quantity'] = quantity
return values
2023-01-14 23:36:02 +00:00
@classmethod
def add_2nd_unit_values(cls, values):
""" extend create-values
"""
Cashbook = Pool().get('cashbook.book')
values = super(Line, cls).add_2nd_unit_values(values)
cashbook = values.get('cashbook', None)
if cashbook:
values.update(cls.add_2nd_quantity(values, Cashbook(cashbook).quantity_uom))
return values
2023-01-12 22:37:20 +00:00
# end Line