cashbook_investment/line.py

285 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
from trytond.pyson import Eval, Or, If, And
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
STATESQ1 = {
'invisible': And(
Eval('feature', '') != 'asset',
Eval('booktransf_feature', '') != 'asset',
),
'required': Or(
Eval('feature', '') == 'asset',
Eval('booktransf_feature', '') == 'asset',
),
'readonly': Or(
STATES['readonly'],
Eval('bookingtype', '').in_(['spin', 'spout']),
),
}
DEPENDSQ1 = ['feature', 'booktransf_feature', 'quantity_digits', 'bookingtype']
DEPENDSQ1.extend(DEPENDS)
STATESQ2 = {
'invisible': Eval('feature', '') != 'asset',
'required': Eval('feature', '') == 'asset',
}
DEPENDSQ2 = ['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=STATESQ1, depends=DEPENDSQ1)
quantity_credit = fields.Numeric(string='Quantity Credit',
digits=(16, Eval('quantity_digits', 4)), readonly=True,
states=STATESQ2, depends=DEPENDSQ2)
quantity_debit = fields.Numeric(string='Quantity Debit',
digits=(16, Eval('quantity_digits', 4)), readonly=True,
states=STATESQ2, depends=DEPENDSQ2)
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