book: start-saldo + sperre bei lines>0, saldo, rec_name + tests
This commit is contained in:
parent
8fd6e0d339
commit
ae5303658e
9 changed files with 218 additions and 40 deletions
75
book.py
75
book.py
|
@ -9,6 +9,10 @@ from trytond.exceptions import UserError
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
|
from trytond.report import Report
|
||||||
|
from decimal import Decimal
|
||||||
|
from sql.aggregate import Sum
|
||||||
|
from sql.conditionals import Case
|
||||||
|
|
||||||
|
|
||||||
STATES = {
|
STATES = {
|
||||||
|
@ -48,6 +52,15 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
account = fields.Many2One(string='Account', select=True,
|
account = fields.Many2One(string='Account', select=True,
|
||||||
model_name='account.account', ondelete='RESTRICT',
|
model_name='account.account', ondelete='RESTRICT',
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
|
start_balance = fields.Numeric(string='Initial Amount', required=True,
|
||||||
|
states={
|
||||||
|
'readonly': Or(
|
||||||
|
STATES['readonly'],
|
||||||
|
Bool(Eval('lines')),
|
||||||
|
),
|
||||||
|
}, depends=DEPENDS+['lines'])
|
||||||
|
balance = fields.Function(fields.Numeric(string='Balance', readonly=True),
|
||||||
|
'on_change_with_balance')
|
||||||
currency = fields.Many2One(string='Currency', required=True,
|
currency = fields.Many2One(string='Currency', required=True,
|
||||||
model_name='currency.currency',
|
model_name='currency.currency',
|
||||||
states={
|
states={
|
||||||
|
@ -64,6 +77,7 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Book, cls).__setup__()
|
super(Book, cls).__setup__()
|
||||||
cls._order.insert(0, ('name', 'ASC'))
|
cls._order.insert(0, ('name', 'ASC'))
|
||||||
|
cls._order.insert(0, ('state', 'ASC'))
|
||||||
t = cls.__table__()
|
t = cls.__table__()
|
||||||
cls._sql_constraints.extend([
|
cls._sql_constraints.extend([
|
||||||
('state_val',
|
('state_val',
|
||||||
|
@ -90,6 +104,12 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def default_start_balance(cls):
|
||||||
|
""" zero
|
||||||
|
"""
|
||||||
|
return Decimal('0.0')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_currency(cls):
|
def default_currency(cls):
|
||||||
""" currency of company
|
""" currency of company
|
||||||
|
@ -116,6 +136,55 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
"""
|
"""
|
||||||
return Transaction().user
|
return Transaction().user
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def order_state(tables):
|
||||||
|
""" edit = 0, check/done = 1
|
||||||
|
"""
|
||||||
|
Book2 = Pool().get('cashbook.book')
|
||||||
|
tab_book = Book2.__table__()
|
||||||
|
table, _ = tables[None]
|
||||||
|
|
||||||
|
query = tab_book.select(
|
||||||
|
Case(
|
||||||
|
(tab_book.state == 'open', 0),
|
||||||
|
else_ = 1),
|
||||||
|
where=tab_book.id==table.id
|
||||||
|
)
|
||||||
|
return [query]
|
||||||
|
|
||||||
|
def get_rec_name(self, name):
|
||||||
|
""" name, balance, state
|
||||||
|
"""
|
||||||
|
return '%(name)s | %(balance)s %(symbol)s | %(state)s' % {
|
||||||
|
'name': self.name or '-',
|
||||||
|
'balance': Report.format_number(self.balance or 0.0, None),
|
||||||
|
'symbol': getattr(self.currency, 'symbol', '-'),
|
||||||
|
'state': self.state_string,
|
||||||
|
}
|
||||||
|
|
||||||
|
@fields.depends('id', 'start_balance')
|
||||||
|
def on_change_with_balance(self, name=None):
|
||||||
|
""" compute balance
|
||||||
|
"""
|
||||||
|
Line = Pool().get('cashbook.line')
|
||||||
|
tab_line = Line.__table__()
|
||||||
|
cursor = Transaction().connection.cursor()
|
||||||
|
|
||||||
|
query = tab_line.select(
|
||||||
|
Sum(tab_line.credit - tab_line.debit).as_('balance'),
|
||||||
|
group_by=[tab_line.cashbook],
|
||||||
|
where=tab_line.cashbook == self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.id:
|
||||||
|
if self.start_balance is not None:
|
||||||
|
balance = self.start_balance
|
||||||
|
cursor.execute(*query)
|
||||||
|
result = cursor.fetchone()
|
||||||
|
if result:
|
||||||
|
balance += result[0]
|
||||||
|
return balance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ModelView.button
|
@ModelView.button
|
||||||
@Workflow.transition('open')
|
@Workflow.transition('open')
|
||||||
|
@ -147,6 +216,12 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
actions = iter(args)
|
actions = iter(args)
|
||||||
for books, values in zip(actions, actions):
|
for books, values in zip(actions, actions):
|
||||||
for book in books:
|
for book in books:
|
||||||
|
if 'start_balance' in values.keys():
|
||||||
|
if len(book.lines) > 0:
|
||||||
|
raise UserError(gettext(
|
||||||
|
'cashbook.msg_book_err_startamount_with_lines',
|
||||||
|
bookname = book.rec_name,
|
||||||
|
))
|
||||||
if book.state != 'open':
|
if book.state != 'open':
|
||||||
# allow state-update, if its the only action
|
# allow state-update, if its the only action
|
||||||
if not (('state' in values.keys()) and (len(values.keys()) == 1)):
|
if not (('state' in values.keys()) and (len(values.keys()) == 1)):
|
||||||
|
|
73
line.py
73
line.py
|
@ -77,6 +77,13 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
required=True, readonly=True, depends=['currency_digits'])
|
required=True, readonly=True, depends=['currency_digits'])
|
||||||
credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)),
|
credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)),
|
||||||
required=True, readonly=True, depends=['currency_digits'])
|
required=True, readonly=True, depends=['currency_digits'])
|
||||||
|
|
||||||
|
balance = fields.Function(fields.Numeric(string='Balance',
|
||||||
|
digits=(16, Eval('currency_digits', 2)),
|
||||||
|
help='Balance of the cash book up to the current line, if the default sorting applies.',
|
||||||
|
readonly=True, depends=['currency_digits']),
|
||||||
|
'on_change_with_balance')
|
||||||
|
|
||||||
currency = fields.Function(fields.Many2One(model_name='currency.currency',
|
currency = fields.Function(fields.Many2One(model_name='currency.currency',
|
||||||
string="Currency"), 'on_change_with_currency')
|
string="Currency"), 'on_change_with_currency')
|
||||||
currency_digits = fields.Function(fields.Integer(string='Currency Digits'),
|
currency_digits = fields.Function(fields.Integer(string='Currency Digits'),
|
||||||
|
@ -94,8 +101,8 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Line, cls).__setup__()
|
super(Line, cls).__setup__()
|
||||||
cls._order.insert(0, ('state', 'ASC'))
|
|
||||||
cls._order.insert(0, ('date', 'ASC'))
|
cls._order.insert(0, ('date', 'ASC'))
|
||||||
|
cls._order.insert(0, ('state', 'ASC'))
|
||||||
t = cls.__table__()
|
t = cls.__table__()
|
||||||
cls._sql_constraints.extend([
|
cls._sql_constraints.extend([
|
||||||
('state_val',
|
('state_val',
|
||||||
|
@ -146,20 +153,6 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@fields.depends('bookingtype', 'category')
|
|
||||||
def on_change_bookingtype(self):
|
|
||||||
""" clear category if not valid type
|
|
||||||
"""
|
|
||||||
types = {
|
|
||||||
'in': ['in', 'mvin'],
|
|
||||||
'out': ['out', 'mvout'],
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.bookingtype:
|
|
||||||
if self.category:
|
|
||||||
if not self.bookingtype in types.get(self.category.cattype, ''):
|
|
||||||
self.category = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_state(cls):
|
def default_state(cls):
|
||||||
""" default: edit
|
""" default: edit
|
||||||
|
@ -180,6 +173,12 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
context = Transaction().context
|
context = Transaction().context
|
||||||
return context.get('cashbook', None)
|
return context.get('cashbook', None)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def search_rec_name(cls, name, clause):
|
||||||
|
""" search in description +...
|
||||||
|
"""
|
||||||
|
return [('description',) + tuple(clause[1:])]
|
||||||
|
|
||||||
def get_rec_name(self, name):
|
def get_rec_name(self, name):
|
||||||
""" short + name
|
""" short + name
|
||||||
"""
|
"""
|
||||||
|
@ -219,12 +218,6 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
|
|
||||||
return [tab2]
|
return [tab2]
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def search_category_view(cls, name, clause):
|
|
||||||
""" search in category
|
|
||||||
"""
|
|
||||||
return [('category.rec_name',) + tuple(clause[1:])]
|
|
||||||
|
|
||||||
@fields.depends('category')
|
@fields.depends('category')
|
||||||
def on_change_with_category_view(self, name=None):
|
def on_change_with_category_view(self, name=None):
|
||||||
""" show optimizef form of category for list-view
|
""" show optimizef form of category for list-view
|
||||||
|
@ -239,10 +232,10 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
return self.category.get_long_recname(self.category.name)
|
return self.category.get_long_recname(self.category.name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def search_rec_name(cls, name, clause):
|
def search_category_view(cls, name, clause):
|
||||||
""" search in description +...
|
""" search in category
|
||||||
"""
|
"""
|
||||||
return [('description',) + tuple(clause[1:])]
|
return [('category.rec_name',) + tuple(clause[1:])]
|
||||||
|
|
||||||
@fields.depends('date')
|
@fields.depends('date')
|
||||||
def on_change_with_month(self, name=None):
|
def on_change_with_month(self, name=None):
|
||||||
|
@ -286,6 +279,20 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
"""
|
"""
|
||||||
return [('cashbook.state',) + tuple(clause[1:])]
|
return [('cashbook.state',) + tuple(clause[1:])]
|
||||||
|
|
||||||
|
@fields.depends('bookingtype', 'category')
|
||||||
|
def on_change_bookingtype(self):
|
||||||
|
""" clear category if not valid type
|
||||||
|
"""
|
||||||
|
types = {
|
||||||
|
'in': ['in', 'mvin'],
|
||||||
|
'out': ['out', 'mvout'],
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.bookingtype:
|
||||||
|
if self.category:
|
||||||
|
if not self.bookingtype in types.get(self.category.cattype, ''):
|
||||||
|
self.category = None
|
||||||
|
|
||||||
@fields.depends('cashbook', '_parent_cashbook.currency')
|
@fields.depends('cashbook', '_parent_cashbook.currency')
|
||||||
def on_change_with_currency(self, name=None):
|
def on_change_with_currency(self, name=None):
|
||||||
""" currency of cashbook
|
""" currency of cashbook
|
||||||
|
@ -302,6 +309,23 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
else:
|
else:
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
|
@fields.depends('id', 'cashbook', '_parent_cashbook.start_balance', '_parent_cashbook.id')
|
||||||
|
def on_change_with_balance(self, name=None):
|
||||||
|
""" compute balance until current line, with current sort order
|
||||||
|
"""
|
||||||
|
Line = Pool().get('cashbook.line')
|
||||||
|
|
||||||
|
if self.cashbook:
|
||||||
|
balance = self.cashbook.start_balance
|
||||||
|
lines = Line.search([
|
||||||
|
('cashbook.id', '=', self.cashbook.id),
|
||||||
|
])
|
||||||
|
for line in lines:
|
||||||
|
balance += line.credit - line.debit
|
||||||
|
if line.id == self.id:
|
||||||
|
break
|
||||||
|
return balance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_debit_credit(cls, values):
|
def get_debit_credit(cls, values):
|
||||||
""" compute debit/credit from amount
|
""" compute debit/credit from amount
|
||||||
|
@ -470,6 +494,7 @@ class LineContext(ModelView):
|
||||||
""" get number of accessible cashbooks,
|
""" get number of accessible cashbooks,
|
||||||
depends on user-permissions
|
depends on user-permissions
|
||||||
"""
|
"""
|
||||||
|
print('-- on_change_with_num_cashbook:', Transaction().context)
|
||||||
LineContext = Pool().get('cashbook.line.context')
|
LineContext = Pool().get('cashbook.line.context')
|
||||||
return LineContext.default_num_cashbook()
|
return LineContext.default_num_cashbook()
|
||||||
|
|
||||||
|
|
16
locale/de.po
16
locale/de.po
|
@ -54,6 +54,10 @@ msgctxt "model:ir.message,text:msg_category_type_not_like_parent"
|
||||||
msgid "The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'."
|
msgid "The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'."
|
||||||
msgstr "Der Typ der aktuellen Kategorie '%(catname)s' muß gleich dem Typ der übergeordneten Kategorie '%(parentname)s' sein."
|
msgstr "Der Typ der aktuellen Kategorie '%(catname)s' muß gleich dem Typ der übergeordneten Kategorie '%(parentname)s' sein."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_book_err_startamount_with_lines"
|
||||||
|
msgid "The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings."
|
||||||
|
msgstr "Der Anfangsbetrag des Kassenbuchs '%(bookname)s' kann nicht geändert werden, da es bereits Buchungen enthält."
|
||||||
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# res.group #
|
# res.group #
|
||||||
|
@ -274,6 +278,10 @@ msgctxt "field:cashbook.book,currency:"
|
||||||
msgid "Currency"
|
msgid "Currency"
|
||||||
msgstr "Währung"
|
msgstr "Währung"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook.book,start_balance:"
|
||||||
|
msgid "Initial Amount"
|
||||||
|
msgstr "Anfangsbetrag"
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# cashbook.line #
|
# cashbook.line #
|
||||||
|
@ -390,6 +398,14 @@ msgctxt "field:cashbook.line,currency_digits:"
|
||||||
msgid "Currency Digits"
|
msgid "Currency Digits"
|
||||||
msgstr "Nachkommastellen Währung"
|
msgstr "Nachkommastellen Währung"
|
||||||
|
|
||||||
|
msgctxt "field:cashbook.line,balance:"
|
||||||
|
msgid "Balance"
|
||||||
|
msgstr "Saldo"
|
||||||
|
|
||||||
|
msgctxt "help:cashbook.line,balance:"
|
||||||
|
msgid "Balance of the cash book up to the current line, if the default sorting applies."
|
||||||
|
msgstr "Saldo des Kassenbuchs bis zur aktuellen Zeile, sofern die Standardsortierung gilt."
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# cashbook.type #
|
# cashbook.type #
|
||||||
|
|
|
@ -41,6 +41,9 @@ full copyright notices and license terms. -->
|
||||||
<record model="ir.message" id="msg_category_type_not_like_parent">
|
<record model="ir.message" id="msg_category_type_not_like_parent">
|
||||||
<field name="text">The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'.</field>
|
<field name="text">The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'.</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record model="ir.message" id="msg_book_err_startamount_with_lines">
|
||||||
|
<field name="text">The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings.</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -62,7 +62,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
self.assertEqual(book.state, 'open')
|
self.assertEqual(book.state, 'open')
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
"The cashbook 'Book 1' cannot be deleted because it contains 1 lines and is not in the status 'Archive'.",
|
"The cashbook 'Book 1 | 1.00 usd | Open' cannot be deleted because it contains 1 lines and is not in the status 'Archive'.",
|
||||||
Book.delete,
|
Book.delete,
|
||||||
[book])
|
[book])
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
self.assertEqual(book.state, 'closed')
|
self.assertEqual(book.state, 'closed')
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
"The cashbook 'Book 1' cannot be deleted because it contains 1 lines and is not in the status 'Archive'.",
|
"The cashbook 'Book 1 | 1.00 usd | Closed' cannot be deleted because it contains 1 lines and is not in the status 'Archive'.",
|
||||||
Book.delete,
|
Book.delete,
|
||||||
[book])
|
[book])
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
self.assertEqual(book.state, 'closed')
|
self.assertEqual(book.state, 'closed')
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
"The cash book 'Book 1a' is 'Closed' and cannot be changed.",
|
"The cash book 'Book 1a | 1.00 usd | Closed' is 'Closed' and cannot be changed.",
|
||||||
Book.write,
|
Book.write,
|
||||||
*[
|
*[
|
||||||
[book],
|
[book],
|
||||||
|
@ -183,7 +183,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
Book.wfarchive([book])
|
Book.wfarchive([book])
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
"The cash book 'Book 1c' is 'Archive' and cannot be changed.",
|
"The cash book 'Book 1c | 0.00 usd | Archive' is 'Archive' and cannot be changed.",
|
||||||
Book.write,
|
Book.write,
|
||||||
*[
|
*[
|
||||||
[book],
|
[book],
|
||||||
|
@ -192,6 +192,59 @@ class BookTestCase(ModuleTestCase):
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_book_deny_update_start_amount(self):
|
||||||
|
""" create cashbook, add lines, update start-amount
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Book = pool.get('cashbook.book')
|
||||||
|
|
||||||
|
types = self.prep_type()
|
||||||
|
company = self.prep_company()
|
||||||
|
category = self.prep_category(cattype='in')
|
||||||
|
book, = Book.create([{
|
||||||
|
'name': 'Book 1',
|
||||||
|
'btype': types.id,
|
||||||
|
'company': company.id,
|
||||||
|
'currency': company.currency.id,
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.name, 'Book 1')
|
||||||
|
self.assertEqual(book.start_balance, Decimal('0.0'))
|
||||||
|
self.assertEqual(book.rec_name, 'Book 1 | 0.00 usd | Open')
|
||||||
|
|
||||||
|
Book.write(*[
|
||||||
|
[book],
|
||||||
|
{
|
||||||
|
'start_balance': Decimal('1.0'),
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.start_balance, Decimal('1.0'))
|
||||||
|
self.assertEqual(book.balance, Decimal('1.0'))
|
||||||
|
|
||||||
|
Book.write(*[
|
||||||
|
[book],
|
||||||
|
{
|
||||||
|
'lines': [('create', [{
|
||||||
|
'amount': Decimal('2.0'),
|
||||||
|
'description': 'Test',
|
||||||
|
'category': category.id,
|
||||||
|
'bookingtype': 'in',
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
self.assertEqual(book.start_balance, Decimal('1.0'))
|
||||||
|
self.assertEqual(book.balance, Decimal('3.0'))
|
||||||
|
self.assertEqual(len(book.lines), 1)
|
||||||
|
self.assertEqual(book.lines[0].balance, Decimal('3.0'))
|
||||||
|
|
||||||
|
self.assertRaisesRegex(UserError,
|
||||||
|
"The initial amount of the cash book 'Fridas book | 3.00 usd | Open' cannot be changed because it already contains bookings.",
|
||||||
|
Book.write,
|
||||||
|
*[
|
||||||
|
[book],
|
||||||
|
{
|
||||||
|
'start_balance': Decimal('1.5'),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_book_permission_owner(self):
|
def test_book_permission_owner(self):
|
||||||
""" create book + 2x users, add users to group, check access
|
""" create book + 2x users, add users to group, check access
|
||||||
|
@ -228,7 +281,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
'company': company.id,
|
'company': company.id,
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.rec_name, 'Fridas book'),
|
self.assertEqual(book.rec_name, 'Fridas book | 0.00 usd | Open'),
|
||||||
self.assertEqual(book.owner.rec_name, 'Frida'),
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
@ -243,7 +296,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
with Transaction().set_user(usr_lst[0].id):
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
books = Book.search([])
|
books = Book.search([])
|
||||||
self.assertEqual(len(books), 1)
|
self.assertEqual(len(books), 1)
|
||||||
self.assertEqual(books[0].rec_name, 'Fridas book')
|
self.assertEqual(books[0].rec_name, 'Fridas book | 0.00 usd | Open')
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
'You are not allowed to access "Cashbook".',
|
'You are not allowed to access "Cashbook".',
|
||||||
|
@ -298,7 +351,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'btype': types.id,
|
'btype': types.id,
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.rec_name, 'Fridas book'),
|
self.assertEqual(book.rec_name, 'Fridas book | 0.00 usd | Open'),
|
||||||
self.assertEqual(book.owner.rec_name, 'Frida'),
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
@ -315,7 +368,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
with Transaction().set_user(usr_lst[0].id):
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
books = Book.search([])
|
books = Book.search([])
|
||||||
self.assertEqual(len(books), 1)
|
self.assertEqual(len(books), 1)
|
||||||
self.assertEqual(books[0].rec_name, 'Fridas book')
|
self.assertEqual(books[0].rec_name, 'Fridas book | 0.00 usd | Open')
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_book_permission_observer(self):
|
def test_book_permission_observer(self):
|
||||||
|
@ -360,7 +413,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'btype': types.id,
|
'btype': types.id,
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.rec_name, 'Fridas book'),
|
self.assertEqual(book.rec_name, 'Fridas book | 0.00 usd | Open'),
|
||||||
self.assertEqual(book.owner.rec_name, 'Frida'),
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
@ -377,6 +430,6 @@ class BookTestCase(ModuleTestCase):
|
||||||
with Transaction().set_user(usr_lst[0].id):
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
books = Book.search([])
|
books = Book.search([])
|
||||||
self.assertEqual(len(books), 1)
|
self.assertEqual(len(books), 1)
|
||||||
self.assertEqual(books[0].rec_name, 'Fridas book')
|
self.assertEqual(books[0].rec_name, 'Fridas book | 0.00 usd | Open')
|
||||||
|
|
||||||
# end BookTestCase
|
# end BookTestCase
|
||||||
|
|
|
@ -131,7 +131,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
self.assertEqual(book.state, 'closed')
|
self.assertEqual(book.state, 'closed')
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
"The cash book 'Book 1' is 'Closed' and cannot be changed.",
|
"The cash book 'Book | 2.00 usd | Closed' is 'Closed' and cannot be changed.",
|
||||||
Line.write,
|
Line.write,
|
||||||
*[
|
*[
|
||||||
[book.lines[0]],
|
[book.lines[0]],
|
||||||
|
@ -478,7 +478,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
self.assertEqual(book.state, 'closed')
|
self.assertEqual(book.state, 'closed')
|
||||||
|
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(UserError,
|
||||||
"The cashbook line '05/01/2022 Text 1' cannot be deleted because the Cashbook 'Book 1' is in state 'Closed'.",
|
"The cashbook line '05/01/2022 Text 1' cannot be deleted because the Cashbook 'Book | 2.00 usd | Closed' is in state 'Closed'.",
|
||||||
Lines.delete,
|
Lines.delete,
|
||||||
[book.lines[0]])
|
[book.lines[0]])
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}])],
|
}])],
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.rec_name, 'Fridas book'),
|
self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'),
|
||||||
self.assertEqual(book.owner.rec_name, 'Frida'),
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
@ -585,7 +585,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
with Transaction().set_user(usr_lst[0].id):
|
with Transaction().set_user(usr_lst[0].id):
|
||||||
lines = Line.search([])
|
lines = Line.search([])
|
||||||
self.assertEqual(len(lines), 1)
|
self.assertEqual(len(lines), 1)
|
||||||
self.assertEqual(lines[0].cashbook.rec_name, 'Fridas book')
|
self.assertEqual(lines[0].cashbook.rec_name, 'Fridas book | 1.00 usd | Open')
|
||||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||||
|
|
||||||
Line.write(*[
|
Line.write(*[
|
||||||
|
@ -647,7 +647,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}])],
|
}])],
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.rec_name, 'Fridas book'),
|
self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'),
|
||||||
self.assertEqual(book.owner.rec_name, 'Frida'),
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
@ -731,7 +731,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}])],
|
}])],
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.rec_name, 'Fridas book'),
|
self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'),
|
||||||
self.assertEqual(book.owner.rec_name, 'Frida'),
|
self.assertEqual(book.owner.rec_name, 'Frida'),
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
|
|
@ -13,6 +13,10 @@ full copyright notices and license terms. -->
|
||||||
<label name="account"/>
|
<label name="account"/>
|
||||||
<field name="account"/>
|
<field name="account"/>
|
||||||
|
|
||||||
|
<label name="start_balance"/>
|
||||||
|
<field name="start_balance"/>
|
||||||
|
<newline/>
|
||||||
|
|
||||||
<label name="state"/>
|
<label name="state"/>
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
<group id="grpstate" col="3" colspan="2">
|
<group id="grpstate" col="3" colspan="2">
|
||||||
|
|
|
@ -5,6 +5,7 @@ full copyright notices and license terms. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="btype"/>
|
<field name="btype"/>
|
||||||
|
<field name="start_balance"/>
|
||||||
<field name="currency"/>
|
<field name="currency"/>
|
||||||
<field name="account"/>
|
<field name="account"/>
|
||||||
<field name="owner"/>
|
<field name="owner"/>
|
||||||
|
|
|
@ -9,6 +9,7 @@ full copyright notices and license terms. -->
|
||||||
<field name="description" expand="1"/>
|
<field name="description" expand="1"/>
|
||||||
<field name="credit" sum="Credit"/>
|
<field name="credit" sum="Credit"/>
|
||||||
<field name="debit" sum="Debit"/>
|
<field name="debit" sum="Debit"/>
|
||||||
|
<field name="balance"/>
|
||||||
<field name="currency"/>
|
<field name="currency"/>
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
<button name="wfedit"/>
|
<button name="wfedit"/>
|
||||||
|
|
Loading…
Reference in a new issue