2022-12-21 23:32:26 +00:00
|
|
|
# -*- 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 trytond.model import fields
|
2023-01-01 19:34:51 +00:00
|
|
|
from trytond.pool import PoolMeta, Pool
|
2022-12-21 23:32:26 +00:00
|
|
|
from trytond.pyson import Eval, Or, If
|
2022-12-31 15:15:23 +00:00
|
|
|
from trytond.exceptions import UserError
|
|
|
|
from trytond.i18n import gettext
|
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
|
|
|
|
2022-12-30 22:55:00 +00:00
|
|
|
STATESQ = {
|
|
|
|
'required': Or(
|
|
|
|
Eval('feature', '') == 'asset',
|
|
|
|
Eval('booktransf_feature', '') == 'asset',
|
|
|
|
),
|
|
|
|
'invisible': ~Or(
|
|
|
|
Eval('feature', '') == 'asset',
|
|
|
|
Eval('booktransf_feature', '') == 'asset',
|
|
|
|
),
|
|
|
|
'readonly': Or(
|
|
|
|
STATES['readonly'],
|
|
|
|
Eval('bookingtype', '').in_(['spin', 'spout']),
|
|
|
|
),
|
|
|
|
}
|
|
|
|
DEPENDSQ = DEPENDS+['feature', 'booktransf_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)),
|
2022-12-30 22:55:00 +00:00
|
|
|
states=STATESQ, depends=DEPENDSQ)
|
|
|
|
quantity_credit = fields.Numeric(string='Quantity Credit',
|
2022-12-31 15:15:23 +00:00
|
|
|
digits=(16, Eval('quantity_digits', 4)), readonly=True,
|
|
|
|
states={
|
|
|
|
'invisible': STATESQ['invisible'],
|
|
|
|
'required': STATESQ['required'],
|
|
|
|
}, depends=DEPENDSQ)
|
2022-12-30 22:55:00 +00:00
|
|
|
quantity_debit = fields.Numeric(string='Quantity Debit',
|
2022-12-31 15:15:23 +00:00
|
|
|
digits=(16, Eval('quantity_digits', 4)), readonly=True,
|
|
|
|
states={
|
|
|
|
'invisible': STATESQ['invisible'],
|
|
|
|
'required': STATESQ['required'],
|
|
|
|
}, depends=DEPENDSQ)
|
2022-12-30 22:55:00 +00:00
|
|
|
|
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'),
|
2022-12-22 15:01:10 +00:00
|
|
|
'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),
|
2022-12-22 15:01:10 +00:00
|
|
|
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')
|
2022-12-31 15:15:23 +00:00
|
|
|
quantity_balance = fields.Function(fields.Numeric(string='Quantity',
|
|
|
|
digits=(16, Eval('quantity_digits', 4)),
|
|
|
|
help='Number of shares in the cashbook up to the current row if the default sort applies.',
|
|
|
|
readonly=True, depends=['quantity_digits']),
|
|
|
|
'on_change_with_quantity_balance')
|
2022-12-21 23:32:26 +00:00
|
|
|
|
2022-12-30 22:55:00 +00:00
|
|
|
@classmethod
|
|
|
|
def get_debit_credit(cls, values):
|
|
|
|
""" compute quantity_debit/quantity_credit from quantity
|
|
|
|
"""
|
|
|
|
values2 = super(Line, cls).get_debit_credit(values)
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
if type_:
|
|
|
|
if quantity is not None:
|
|
|
|
if type_ in ['in', 'mvin', 'spin']:
|
|
|
|
values2.update({
|
|
|
|
'quantity_debit': Decimal('0.0'),
|
|
|
|
'quantity_credit': quantity,
|
|
|
|
})
|
|
|
|
elif type_ in ['out', 'mvout', 'spout']:
|
|
|
|
values2.update({
|
|
|
|
'quantity_debit': quantity,
|
|
|
|
'quantity_credit': Decimal('0.0'),
|
|
|
|
})
|
|
|
|
else :
|
|
|
|
raise ValueError('invalid "bookingtype"')
|
|
|
|
return values2
|
|
|
|
|
2022-12-25 12:37:17 +00:00
|
|
|
@classmethod
|
|
|
|
def get_counterpart_values(cls, line, values={}):
|
|
|
|
""" add quantity to counterpart
|
|
|
|
"""
|
|
|
|
result = super(Line, cls).get_counterpart_values(line, values)
|
|
|
|
result['quantity'] = line.quantity
|
|
|
|
return result
|
|
|
|
|
2023-01-01 19:34:51 +00:00
|
|
|
@fields.depends('id', 'date', 'cashbook', \
|
|
|
|
'_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')
|
|
|
|
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
|
|
|
|
).quantize(Decimal(str(1/10**digit)))
|
|
|
|
|
|
|
|
@fields.depends('cashbook', '_parent_cashbook.quantity_uom')
|
2022-12-22 15:01:10 +00:00
|
|
|
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
|
|
|
|
|
2022-12-31 15:15:23 +00:00
|
|
|
@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,
|
|
|
|
))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def write(cls, *args):
|
|
|
|
""" add or update quanity_debit/credit
|
|
|
|
"""
|
|
|
|
actions = iter(args)
|
|
|
|
to_write = []
|
|
|
|
for lines, values in zip(actions, actions):
|
|
|
|
# update debit / credit
|
|
|
|
if len(set(values.keys()).intersection(set({'quantity', 'bookingtype'}))) > 0:
|
|
|
|
for line in lines:
|
|
|
|
values2 = {}
|
|
|
|
values2.update(values)
|
|
|
|
values2.update(cls.get_debit_credit({
|
|
|
|
x:values.get(x, getattr(line, x)) for x in ['quantity', 'bookingtype']
|
|
|
|
}))
|
|
|
|
to_write.extend([lines, values2])
|
|
|
|
else :
|
|
|
|
to_write.extend([lines, values])
|
|
|
|
super(Line, cls).write(*to_write)
|
|
|
|
|
2023-01-12 22:37:20 +00:00
|
|
|
# end Line
|