book: view zeigt in listansicht bei unterkonten in fremdwährung
den korrekten wert, book-form: feld für saldo in unternehmens-währung
This commit is contained in:
parent
4a7ee23e2c
commit
59dfb94bee
7 changed files with 238 additions and 13 deletions
91
book.py
91
book.py
|
@ -11,8 +11,10 @@ from trytond.transaction import Transaction
|
|||
from trytond.pool import Pool
|
||||
from trytond.report import Report
|
||||
from decimal import Decimal
|
||||
from sql import Literal
|
||||
from sql.aggregate import Sum
|
||||
from sql.conditionals import Case
|
||||
from sql.conditionals import Case, Coalesce
|
||||
from sql.functions import CurrentDate
|
||||
from .model import order_name_hierarchical
|
||||
|
||||
|
||||
|
@ -103,15 +105,29 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
|
|||
balance = fields.Function(fields.Numeric(string='Balance', readonly=True,
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits']), 'on_change_with_balance')
|
||||
currency = fields.Many2One(string='Currency',
|
||||
model_name='currency.currency',
|
||||
|
||||
balance_ref = fields.Function(fields.Numeric(string='Balance (Ref.)',
|
||||
help='Balance in company currency',
|
||||
readonly=True, digits=(16, Eval('company_currency_digits', 2)),
|
||||
states={
|
||||
'invisible': ~Bool(Eval('company_currency')),
|
||||
}, depends=['company_currency_digits', 'company_currency']),
|
||||
'on_change_with_balance_ref')
|
||||
company_currency = fields.Function(fields.Many2One(readonly=True,
|
||||
string='Company Currency', states={'invisible': True},
|
||||
model_name='currency.currency'),
|
||||
'on_change_with_company_currency')
|
||||
company_currency_digits = fields.Function(fields.Integer(
|
||||
string='Currency Digits (Ref.)', readonly=True),
|
||||
'on_change_with_currency_digits')
|
||||
|
||||
currency = fields.Many2One(string='Currency', select=True,
|
||||
model_name='currency.currency', readonly=True,
|
||||
states={
|
||||
'readonly': Or(
|
||||
STATES2['readonly'],
|
||||
Bool(Eval('lines', [])),
|
||||
),
|
||||
'invisible': STATES2['invisible'],
|
||||
'required': ~STATES2['invisible'],
|
||||
}, depends=DEPENDS2+['lines'])
|
||||
currency_digits = fields.Function(fields.Integer(string='Currency Digits',
|
||||
readonly=True), 'on_change_with_currency_digits')
|
||||
|
@ -255,36 +271,95 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
|
|||
else:
|
||||
return 2
|
||||
|
||||
@fields.depends('company', 'currency', 'btype')
|
||||
def on_change_with_company_currency(self, name=None):
|
||||
""" get company-currency if its different from current
|
||||
cashbook-currency, disable if book is a view
|
||||
"""
|
||||
if self.company:
|
||||
if self.currency:
|
||||
if self.btype:
|
||||
if self.company.currency.id != self.currency.id:
|
||||
return self.company.currency.id
|
||||
|
||||
@fields.depends('id')
|
||||
def on_change_with_balance(self, name=None):
|
||||
""" compute balance
|
||||
"""
|
||||
pool = Pool()
|
||||
Book2 = pool.get('cashbook.book')
|
||||
Book3 = pool.get('cashbook.book')
|
||||
Line = pool.get('cashbook.line')
|
||||
Currency = pool.get('currency.currency')
|
||||
|
||||
tab_line = Line.__table__()
|
||||
tab_book = Book3.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
# select cashbook-lines from current cashbook and below
|
||||
line_query = Line.search([
|
||||
('cashbook.id', 'in', Book2.search([
|
||||
('parent', 'child_of', [self.id]),
|
||||
], query=True)),
|
||||
], query=True)
|
||||
|
||||
query = line_query.join(tab_line,
|
||||
# sum lines by currency
|
||||
bal_by_currency = line_query.join(tab_line,
|
||||
condition=tab_line.id==line_query.id,
|
||||
).join(tab_book,
|
||||
condition=tab_book.id==tab_line.cashbook,
|
||||
).select(
|
||||
Sum(tab_line.credit - tab_line.debit).as_('balance'),
|
||||
tab_book.currency,
|
||||
group_by=[tab_book.currency],
|
||||
)
|
||||
|
||||
if self.id:
|
||||
total = Decimal('0.0')
|
||||
|
||||
cursor.execute(*bal_by_currency)
|
||||
balance_lines = cursor.fetchall()
|
||||
|
||||
for line in balance_lines:
|
||||
(balance, id_currency) = line
|
||||
|
||||
total += Currency.compute(
|
||||
Currency(id_currency), # from
|
||||
balance,
|
||||
self.currency, # to
|
||||
)
|
||||
return total
|
||||
|
||||
@fields.depends('company', 'currency', 'id', 'btype')
|
||||
def on_change_with_balance_ref(self, name=None):
|
||||
""" balance converted to company-currency
|
||||
"""
|
||||
pool = Pool()
|
||||
Line = pool.get('cashbook.line')
|
||||
tab_line = Line.__table__()
|
||||
cursor = Transaction().connection.cursor()
|
||||
|
||||
if self.btype is None:
|
||||
return None
|
||||
|
||||
query = tab_line.select(
|
||||
Sum(tab_line.credit - tab_line.debit),
|
||||
where = tab_line.cashbook == self.id,
|
||||
)
|
||||
|
||||
if self.id:
|
||||
balance = Decimal('0.0')
|
||||
cursor.execute(*query)
|
||||
result = cursor.fetchone()
|
||||
balance = Decimal('0.0')
|
||||
if result:
|
||||
if result[0] is not None:
|
||||
balance += result[0]
|
||||
return balance
|
||||
if self.currency:
|
||||
return self.currency.compute(
|
||||
self.currency, # from
|
||||
balance,
|
||||
self.company.currency # to
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
|
|
16
locale/de.po
16
locale/de.po
|
@ -554,6 +554,22 @@ msgctxt "field:cashbook.book,right:"
|
|||
msgid "Right"
|
||||
msgstr "Rechts"
|
||||
|
||||
msgctxt "field:cashbook.book,balance_ref:"
|
||||
msgid "Balance (Ref.)"
|
||||
msgstr "Saldo (Ref.)"
|
||||
|
||||
msgctxt "help:cashbook.book,balance_ref:"
|
||||
msgid "Balance in company currency"
|
||||
msgstr "Saldo in der Unternehmenswährung"
|
||||
|
||||
msgctxt "field:cashbook.book,company_currency:"
|
||||
msgid "Company Currency"
|
||||
msgstr "Unternehmenswährung"
|
||||
|
||||
msgctxt "field:cashbook.book,company_currency_digits:"
|
||||
msgid "Currency Digits (Ref.)"
|
||||
msgstr "Nachkommastellen Währung (Ref.)"
|
||||
|
||||
|
||||
##################
|
||||
# cashbook.split #
|
||||
|
|
16
locale/en.po
16
locale/en.po
|
@ -518,6 +518,22 @@ msgctxt "field:cashbook.book,right:"
|
|||
msgid "Right"
|
||||
msgstr "Right"
|
||||
|
||||
msgctxt "field:cashbook.book,balance_ref:"
|
||||
msgid "Balance (Ref.)"
|
||||
msgstr "Balance (Ref.)"
|
||||
|
||||
msgctxt "help:cashbook.book,balance_ref:"
|
||||
msgid "Balance in company currency"
|
||||
msgstr "Balance in company currency"
|
||||
|
||||
msgctxt "field:cashbook.book,company_currency:"
|
||||
msgid "Company Currency"
|
||||
msgstr "Company Currency"
|
||||
|
||||
msgctxt "field:cashbook.book,company_currency_digits:"
|
||||
msgid "Currency Digits (Ref.)"
|
||||
msgstr "Currency Digits (Ref.)"
|
||||
|
||||
msgctxt "model:cashbook.split,name:"
|
||||
msgid "Split booking line"
|
||||
msgstr "Split booking line"
|
||||
|
|
|
@ -56,6 +56,110 @@ class BookTestCase(ModuleTestCase):
|
|||
self.assertEqual(book.state, 'open')
|
||||
self.assertEqual(book.state_string, 'Open')
|
||||
|
||||
@with_transaction()
|
||||
def test_book_create_2nd_currency(self):
|
||||
""" create cashbook, in 2nd currency, check balance-fields
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
|
||||
types = self.prep_type()
|
||||
company = self.prep_company()
|
||||
|
||||
# add EURO, set company-currency to EURO
|
||||
(usd, euro) = self.prep_2nd_currency(company)
|
||||
category = self.prep_category(cattype='in')
|
||||
self.assertEqual(company.currency.rec_name, 'Euro')
|
||||
|
||||
book, = Book.create([{
|
||||
'name': 'Book 1',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': usd.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2022, 5, 1),
|
||||
'lines': [('create', [{
|
||||
'date': date(2022, 5, 5),
|
||||
'description': 'Amount in USD',
|
||||
'bookingtype': 'in',
|
||||
'category': category.id,
|
||||
'amount': Decimal('10.0'),
|
||||
}])],
|
||||
}])
|
||||
|
||||
with Transaction().set_context({
|
||||
'date': date(2022, 5, 5),
|
||||
}):
|
||||
self.assertEqual(book.rec_name, 'Book 1 | 10.00 usd | Open')
|
||||
self.assertEqual(book.currency.rec_name, 'usd')
|
||||
self.assertEqual(book.currency.rate, Decimal('1.05'))
|
||||
self.assertEqual(book.company_currency.rec_name, 'Euro')
|
||||
self.assertEqual(book.company_currency.rate, Decimal('1.0'))
|
||||
|
||||
self.assertEqual(book.balance, Decimal('10.0'))
|
||||
self.assertEqual(book.balance_ref, Decimal('9.52'))
|
||||
|
||||
self.assertEqual(len(book.lines), 1)
|
||||
self.assertEqual(book.lines[0].rec_name,
|
||||
'05/05/2022|Rev|10.00 usd|Amount in USD [Cat1]')
|
||||
|
||||
@with_transaction()
|
||||
def test_book_create_2nd_currency_hierarchical(self):
|
||||
""" create cashbook-hierarchy, in 2nd currency,
|
||||
check balance-fields
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
|
||||
types = self.prep_type()
|
||||
company = self.prep_company()
|
||||
|
||||
# add EURO, set company-currency to EURO
|
||||
(usd, euro) = self.prep_2nd_currency(company)
|
||||
category = self.prep_category(cattype='in')
|
||||
self.assertEqual(company.currency.rec_name, 'Euro')
|
||||
|
||||
book, = Book.create([{
|
||||
'name': 'Book 1',
|
||||
'company': company.id,
|
||||
'currency': euro.id,
|
||||
'childs': [('create', [{
|
||||
'name': 'Book 2',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': usd.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2022, 5, 1),
|
||||
'lines': [('create', [{
|
||||
'date': date(2022, 5, 5),
|
||||
'description': 'Amount in USD',
|
||||
'bookingtype': 'in',
|
||||
'category': category.id,
|
||||
'amount': Decimal('10.0'),
|
||||
}])],
|
||||
}])],
|
||||
}])
|
||||
|
||||
with Transaction().set_context({
|
||||
'date': date(2022, 5, 5),
|
||||
}):
|
||||
self.assertEqual(book.rec_name, 'Book 1')
|
||||
self.assertEqual(book.currency.rec_name, 'Euro')
|
||||
self.assertEqual(book.currency.rate, Decimal('1.0'))
|
||||
self.assertEqual(book.company_currency, None)
|
||||
self.assertEqual(book.balance, Decimal('9.52'))
|
||||
self.assertEqual(book.balance_ref, None)
|
||||
self.assertEqual(len(book.lines), 0)
|
||||
self.assertEqual(len(book.childs), 1)
|
||||
|
||||
self.assertEqual(book.childs[0].rec_name, 'Book 1/Book 2 | 10.00 usd | Open')
|
||||
self.assertEqual(book.childs[0].currency.rec_name, 'usd')
|
||||
self.assertEqual(book.childs[0].currency.rate, Decimal('1.05'))
|
||||
self.assertEqual(book.childs[0].company_currency.rec_name, 'Euro')
|
||||
self.assertEqual(book.childs[0].balance, Decimal('10.0'))
|
||||
self.assertEqual(book.childs[0].balance_ref, Decimal('9.52'))
|
||||
self.assertEqual(len(book.childs[0].lines), 1)
|
||||
|
||||
@with_transaction()
|
||||
def test_book_create_hierarchy(self):
|
||||
""" create cashbook, hierarchical
|
||||
|
|
|
@ -98,6 +98,13 @@ class ConfigTestCase(ModuleTestCase):
|
|||
'rate': Decimal('1.05'),
|
||||
}])
|
||||
|
||||
# delete unwanted rates
|
||||
usd_1 = CurrencyRate.search([
|
||||
('currency.id', '=', usd.id),
|
||||
('date', '!=', date(2022, 5, 2)),
|
||||
])
|
||||
CurrencyRate.delete(usd_1)
|
||||
|
||||
return (usd, euro)
|
||||
|
||||
@with_transaction()
|
||||
|
|
|
@ -15,10 +15,14 @@ full copyright notices and license terms. -->
|
|||
</group>
|
||||
</group>
|
||||
|
||||
<label name="balance"/>
|
||||
<field name="balance" symbol="currency"/>
|
||||
<label name="btype"/>
|
||||
<field name="btype"/>
|
||||
<label name="balance"/>
|
||||
<field name="balance"/>
|
||||
|
||||
<label name="balance_ref"/>
|
||||
<field name="balance_ref" symbol="company_currency"/>
|
||||
<newline/>
|
||||
|
||||
<notebook colspan="4">
|
||||
<page name="reconciliations" string="Reconciliations" col="1">
|
||||
|
@ -32,6 +36,11 @@ full copyright notices and license terms. -->
|
|||
<field name="company"/>
|
||||
<label name="parent"/>
|
||||
<field name="parent"/>
|
||||
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
<newline/>
|
||||
|
||||
<field name="childs" colspan="4"/>
|
||||
</page>
|
||||
<page name="number_sequ" string="Amount and Numbering" col="4">
|
||||
|
@ -42,8 +51,6 @@ full copyright notices and license terms. -->
|
|||
|
||||
<label name="start_date"/>
|
||||
<field name="start_date"/>
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
</page>
|
||||
<page id="pgperm" string="Owner and Authorizeds" col="4">
|
||||
<label name="owner"/>
|
||||
|
|
|
@ -4,7 +4,7 @@ The COPYRIGHT file at the top level of this repository contains the
|
|||
full copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="balance" sum="Balance"/>
|
||||
<field name="balance"/>
|
||||
<field name="currency"/>
|
||||
<field name="state"/>
|
||||
<field name="parent" tree_invisible="1"/>
|
||||
|
|
Loading…
Reference in a new issue