Feld 'rate_2nd_currency' + 'amount_2nd_currency' ok + test

This commit is contained in:
Frederik Jaeckel 2022-10-03 08:47:55 +02:00
parent 59dfb94bee
commit 517e2c5ad3
5 changed files with 302 additions and 0 deletions

150
line.py
View file

@ -10,6 +10,7 @@ from trytond.transaction import Transaction
from trytond.report import Report from trytond.report import Report
from trytond.exceptions import UserError from trytond.exceptions import UserError
from trytond.i18n import gettext from trytond.i18n import gettext
from trytond.modules.currency.ir import rate_decimal
from decimal import Decimal from decimal import Decimal
from sql import Cast, Literal from sql import Cast, Literal
from sql.functions import DatePart from sql.functions import DatePart
@ -119,6 +120,23 @@ class Line(Workflow, ModelSQL, ModelView):
payee = fields.Function(fields.Reference(string='Payee', readonly=True, payee = fields.Function(fields.Reference(string='Payee', readonly=True,
selection=sel_payee), 'on_change_with_payee', searcher='search_payee') selection=sel_payee), 'on_change_with_payee', searcher='search_payee')
amount_2nd_currency = fields.Numeric(string='Amount Second Currency',
digits=(16, Eval('currency2nd_digits', 2)),
states={
'readonly': STATES['readonly'],
'required': Bool(Eval('currency2nd')),
'invisible': ~Bool(Eval('currency2nd')),
}, depends=DEPENDS+['currency2nd_digits', 'currency2nd'])
rate_2nd_currency = fields.Function(fields.Numeric(string='Rate',
help='Exchange rate between the currencies of the participating cashbooks.',
digits=(rate_decimal * 2, rate_decimal),
states={
'readonly': STATES['readonly'],
'required': Bool(Eval('currency2nd')),
'invisible': ~Bool(Eval('currency2nd')),
}, depends=DEPENDS+['currency2nd_digits', 'currency2nd']),
'on_change_with_rate_2nd_currency', setter='set_rate_2nd_currency')
# link to lines created by this record # link to lines created by this record
reference = fields.Many2One(string='Reference', readonly=True, select=True, reference = fields.Many2One(string='Reference', readonly=True, select=True,
states={ states={
@ -161,6 +179,10 @@ class Line(Workflow, ModelSQL, ModelView):
string="Currency", readonly=True), 'on_change_with_currency') string="Currency", readonly=True), 'on_change_with_currency')
currency_digits = fields.Function(fields.Integer(string='Currency Digits', currency_digits = fields.Function(fields.Integer(string='Currency Digits',
readonly=True), 'on_change_with_currency_digits') readonly=True), 'on_change_with_currency_digits')
currency2nd = fields.Function(fields.Many2One(model_name='currency.currency',
string="2nd Currency", readonly=True), 'on_change_with_currency2nd')
currency2nd_digits = fields.Function(fields.Integer(string='2nd Currency Digits',
readonly=True), 'on_change_with_currency2nd_digits')
state = fields.Selection(string='State', required=True, readonly=True, state = fields.Selection(string='State', required=True, readonly=True,
select=True, selection=sel_linetype) select=True, selection=sel_linetype)
@ -540,6 +562,88 @@ class Line(Workflow, ModelSQL, ModelView):
self.splitlines = [] self.splitlines = []
self.booktransf = None self.booktransf = None
@fields.depends('currency', 'booktransf', '_parent_booktransf.currency', \
'amount', 'amount_2nd_currency', 'rate_2nd_currency')
def on_change_amount(self):
""" update amount_2nd_currency
"""
self.on_change_rate_2nd_currency()
@fields.depends('booktransf', '_parent_booktransf.currency', \
'currency', 'amount', 'amount_2nd_currency', 'rate_2nd_currency')
def on_change_booktransf(self):
""" update amount_2nd_currency
"""
Currency = Pool().get('currency.currency')
if self.booktransf:
if self.currency:
if self.amount is not None:
if self.booktransf.currency.id != self.currency.id:
self.amount_2nd_currency = Currency.compute(
self.currency,
self.amount,
self.booktransf.currency
)
self.rate_2nd_currency = self.on_change_with_rate_2nd_currency()
return
self.amount_2nd_currency = None
@fields.depends('currency', 'booktransf', '_parent_booktransf.currency', \
'amount', 'amount_2nd_currency', 'rate_2nd_currency')
def on_change_rate_2nd_currency(self):
""" update amount_2nd_currency by rate
"""
if (self.amount is None) or (self.rate_2nd_currency is None):
return
if self.currency:
if self.booktransf:
if self.currency.id != self.booktransf.currency.id:
self.amount_2nd_currency = self.booktransf.currency.round(
self.amount * self.rate_2nd_currency
)
@classmethod
def set_rate_2nd_currency(cls, lines, name, value):
""" compute amount_2nd_currency, write to db
"""
Line2 = Pool().get('cashbook.line')
to_write = []
if not name == 'rate_2nd_currency':
return
for line in lines:
if line.booktransf is None:
continue
if line.cashbook.currency.id == line.booktransf.currency.id:
continue
to_write.extend([
[line],
{
'amount_2nd_currency': line.booktransf.currency.round(
line.amount * value),
}])
if len(to_write) > 0:
Line2.write(*to_write)
@fields.depends('amount', 'amount_2nd_currency', 'currency2nd')
def on_change_with_rate_2nd_currency(self, name=None):
""" get current rate from amount
"""
Rate = Pool().get('currency.currency.rate')
if (self.amount is not None) and \
(self.amount_2nd_currency is not None) and \
(self.currency2nd is not None):
if self.amount != Decimal('0.0'):
exp = Decimal(Decimal(1) / 10 ** Rate.rate.digits[1])
return (self.amount_2nd_currency / self.amount).quantize(exp)
@fields.depends('description') @fields.depends('description')
def on_change_with_descr_short(self, name=None): def on_change_with_descr_short(self, name=None):
""" to speed up list-view """ to speed up list-view
@ -613,6 +717,24 @@ class Line(Workflow, ModelSQL, ModelView):
else: else:
return 2 return 2
@fields.depends('currency', 'booktransf', '_parent_booktransf.currency')
def on_change_with_currency2nd(self, name=None):
""" currency of transfer-target
"""
if self.booktransf:
if self.currency:
if self.currency.id != self.booktransf.currency.id:
return self.booktransf.currency.id
@fields.depends('currency', 'booktransf', '_parent_booktransf.currency')
def on_change_with_currency2nd_digits(self, name=None):
""" currency of transfer-target
"""
if self.booktransf:
return self.booktransf.currency.digits
else:
return 2
@fields.depends('id', 'date', 'cashbook', \ @fields.depends('id', 'date', 'cashbook', \
'_parent_cashbook.id', 'reconciliation', \ '_parent_cashbook.id', 'reconciliation', \
'_parent_reconciliation.start_amount',\ '_parent_reconciliation.start_amount',\
@ -734,6 +856,33 @@ class Line(Workflow, ModelSQL, ModelView):
raise ValueError('invalid "bookingtype"') raise ValueError('invalid "bookingtype"')
return {} return {}
@classmethod
def add_2nd_currency(cls, values):
""" add second currency amount if missing
"""
pool = Pool()
Currency = pool.get('currency.currency')
Cashbook = pool.get('cashbook.book')
cashbook = values.get('cashbook', None)
booktransf = values.get('booktransf', None)
amount = values.get('amount', None)
amount_2nd_currency = values.get('amount_2nd_currency', None)
if cashbook:
if booktransf:
if amount is not None:
if amount_2nd_currency is None:
cashbook = Cashbook(cashbook)
booktransf = Cashbook(booktransf)
if cashbook.currency.id != booktransf.currency.id:
values['amount_2nd_currency'] = Currency.compute(
cashbook.currency,
amount,
booktransf.currency,
)
return values
@classmethod @classmethod
def update_amount_by_splitlines(cls, lines): def update_amount_by_splitlines(cls, lines):
""" update amounts from split-lines """ update amounts from split-lines
@ -862,6 +1011,7 @@ class Line(Workflow, ModelSQL, ModelView):
for values in vlist: for values in vlist:
values.update(cls.get_debit_credit(values)) values.update(cls.get_debit_credit(values))
values.update(cls.clear_by_bookingtype(values)) values.update(cls.clear_by_bookingtype(values))
values.update(cls.add_2nd_currency(values))
# deny add to reconciliation if state is not 'check' or 'done' # deny add to reconciliation if state is not 'check' or 'done'
if values.get('reconciliation', None): if values.get('reconciliation', None):

View file

@ -898,6 +898,26 @@ msgctxt "help:cashbook.line,splitlines:"
msgid "Rows with different categories form the total sum of the booking" msgid "Rows with different categories form the total sum of the booking"
msgstr "Zeilen mit unterschiedlichen Kategorien bilden die Gesamtsumme der Buchung" msgstr "Zeilen mit unterschiedlichen Kategorien bilden die Gesamtsumme der Buchung"
msgctxt "field:cashbook.line,currency2nd:"
msgid "2nd Currency"
msgstr "Fremdwährung"
msgctxt "field:cashbook.line,currency2nd_digits:"
msgid "2nd Currency Digits"
msgstr "Nachkommastellen Fremdwährung"
msgctxt "field:cashbook.line,amount_2nd_currency:"
msgid "Amount Second Currency"
msgstr "Fremdwährungsbetrag"
msgctxt "field:cashbook.line,rate_2nd_currency:"
msgid "Rate"
msgstr "Kurs"
msgctxt "help:cashbook.line,rate_2nd_currency:"
msgid "Exchange rate between the currencies of the participating cashbooks."
msgstr "Wechselkurs zwischen der Währungen der beteiligten Kassenbücher."
################# #################
# cashbook.type # # cashbook.type #

View file

@ -854,6 +854,26 @@ msgctxt "help:cashbook.line,splitlines:"
msgid "Rows with different categories form the total sum of the booking" msgid "Rows with different categories form the total sum of the booking"
msgstr "Rows with different categories form the total sum of the booking" msgstr "Rows with different categories form the total sum of the booking"
msgctxt "field:cashbook.line,currency2nd:"
msgid "2nd Currency"
msgstr "2nd Currency"
msgctxt "field:cashbook.line,currency2nd_digits:"
msgid "2nd Currency Digits"
msgstr "2nd Currency Digits"
msgctxt "field:cashbook.line,amount_2nd_currency:"
msgid "Amount Second Currency"
msgstr "Amount Second Currency"
msgctxt "field:cashbook.line,rate_2nd_currency:"
msgid "Rate"
msgstr "Rate"
msgctxt "help:cashbook.line,rate_2nd_currency:"
msgid "Exchange rate between the currencies of the participating cashbooks."
msgstr "Exchange rate between the currencies of the participating cashbooks."
msgctxt "model:cashbook.type,name:" msgctxt "model:cashbook.type,name:"
msgid "Cashbook Type" msgid "Cashbook Type"
msgstr "Cashbook Type" msgstr "Cashbook Type"

View file

@ -16,6 +16,111 @@ class LineTestCase(ModuleTestCase):
'Test cashbook line module' 'Test cashbook line module'
module = 'cashbook' module = 'cashbook'
@with_transaction()
def test_line_check_add_amount2nd_currency(self):
""" create cashbook, lines, add transfer without
amount_2nd_currency
"""
pool = Pool()
Book = pool.get('cashbook.book')
Lines = pool.get('cashbook.line')
types = self.prep_type()
company = self.prep_company()
# add EURO, set company-currency to EURO
(usd, euro) = self.prep_2nd_currency(company)
books = Book.create([{
'name': 'Book USD',
'btype': types.id,
'company': company.id,
'currency': usd.id,
'number_sequ': self.prep_sequence().id,
'start_date': date(2022, 5, 1),
}, {
'name': 'Book EURO',
'btype': types.id,
'company': company.id,
'currency': euro.id,
'number_sequ': self.prep_sequence().id,
'start_date': date(2022, 5, 1),
}])
self.assertEqual(len(books), 2)
self.assertEqual(books[0].rec_name, 'Book USD | 0.00 usd | Open')
self.assertEqual(books[1].rec_name, 'Book EURO | 0.00 € | Open')
Book.write(*[
[books[0]],
{
'lines': [('create', [{
'date': date(2022, 5, 5),
'description': 'Transfer USD --> EUR',
'bookingtype': 'mvout',
'amount': Decimal('10.0'),
'booktransf': books[1].id,
}])],
}])
self.assertEqual(len(books[0].lines), 1)
self.assertEqual(books[0].lines[0].rec_name,
'05/05/2022|to|-10.00 usd|Transfer USD --> EUR [Book EURO | 0.00 € | Open]')
self.assertEqual(books[0].lines[0].amount, Decimal('10.0'))
# auto-created
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('9.52'))
self.assertEqual(books[0].lines[0].rate_2nd_currency, Decimal('0.952'))
Lines.delete(books[0].lines)
Book.write(*[
[books[0]],
{
'lines': [('create', [{
'date': date(2022, 5, 5),
'description': 'Transfer USD --> EUR',
'bookingtype': 'mvout',
'amount': Decimal('10.0'),
'booktransf': books[1].id,
'amount_2nd_currency': Decimal('8.5'),
}])],
}])
self.assertEqual(len(books[0].lines), 1)
self.assertEqual(books[0].lines[0].rec_name,
'05/05/2022|to|-10.00 usd|Transfer USD --> EUR [Book EURO | 0.00 € | Open]')
self.assertEqual(books[0].lines[0].amount, Decimal('10.0'))
# manual set
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('8.5'))
self.assertEqual(books[0].lines[0].rate_2nd_currency, Decimal('0.85'))
# update rate to get new amount_2nd_currency
Lines.write(*[
[books[0].lines[0]],
{
'rate_2nd_currency': Decimal('0.9'),
}])
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('9.0'))
# update amount, rate, amount_2nd_currency
self.assertEqual(books[0].lines[0].rate_2nd_currency, Decimal('0.9'))
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('9.0'))
self.assertEqual(books[0].lines[0].amount, Decimal('10.0'))
books[0].lines[0].amount = Decimal('12.0')
books[0].lines[0].on_change_amount()
self.assertEqual(books[0].lines[0].rate_2nd_currency, Decimal('0.9'))
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('10.8'))
self.assertEqual(books[0].lines[0].amount, Decimal('12.0'))
books[0].lines[0].rate_2nd_currency = Decimal('0.95')
books[0].lines[0].on_change_rate_2nd_currency()
self.assertEqual(books[0].lines[0].rate_2nd_currency, Decimal('0.95'))
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('11.4'))
self.assertEqual(books[0].lines[0].amount, Decimal('12.0'))
books[0].lines[0].amount_2nd_currency = Decimal('10.5')
self.assertEqual(books[0].lines[0].on_change_with_rate_2nd_currency(), Decimal('0.875'))
self.assertEqual(books[0].lines[0].amount_2nd_currency, Decimal('10.5'))
self.assertEqual(books[0].lines[0].amount, Decimal('12.0'))
@with_transaction() @with_transaction()
def test_line_check_transfer_2nd_currency_out(self): def test_line_check_transfer_2nd_currency_out(self):
""" create cashbook, lines, transfer amount between """ create cashbook, lines, transfer amount between

View file

@ -34,10 +34,17 @@ full copyright notices and license terms. -->
<label name="category"/> <label name="category"/>
<field name="category"/> <field name="category"/>
<newline/> <newline/>
<label name="booktransf"/> <label name="booktransf"/>
<field name="booktransf"/> <field name="booktransf"/>
<newline/> <newline/>
<label name="amount_2nd_currency"/>
<field name="amount_2nd_currency" symbol="currency2nd"/>
<label name="rate_2nd_currency"/>
<field name="rate_2nd_currency"/>
<newline/>
<notebook colspan="6"> <notebook colspan="6">
<page name="splitlines" col="1" string="Split booking lines"> <page name="splitlines" col="1" string="Split booking lines">
<field name="splitlines"/> <field name="splitlines"/>