kategorie: sperrt 'Typ' wenn parent existiert, korrekte Anpassung
der sub-kategorien bei Änderung + test Line: Kategoriefeld prüft Inhalt + tests
This commit is contained in:
parent
52ffa0536e
commit
8fd6e0d339
7 changed files with 137 additions and 46 deletions
68
category.py
68
category.py
|
@ -6,6 +6,7 @@
|
||||||
from trytond.model import ModelView, ModelSQL, fields, Unique, tree, sequence_ordered
|
from trytond.model import ModelView, ModelSQL, fields, Unique, tree, sequence_ordered
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
|
from trytond.pyson import Eval, If, Bool
|
||||||
from trytond.exceptions import UserError
|
from trytond.exceptions import UserError
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
|
||||||
|
@ -23,7 +24,15 @@ class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
|
||||||
name = fields.Char(string='Name', required=True, translate=True)
|
name = fields.Char(string='Name', required=True, translate=True)
|
||||||
description = fields.Char(string='Description', translate=True)
|
description = fields.Char(string='Description', translate=True)
|
||||||
cattype = fields.Selection(string='Type', required=True,
|
cattype = fields.Selection(string='Type', required=True,
|
||||||
help='Type of Category', selection=sel_categorytype)
|
help='Type of Category', selection=sel_categorytype,
|
||||||
|
states={'readonly': Bool(Eval('parent_cattype'))},
|
||||||
|
domain=[If(Bool(Eval('parent_cattype')),
|
||||||
|
('cattype', '=', Eval('parent_cattype', '')),
|
||||||
|
())],
|
||||||
|
depends=['parent_cattype'])
|
||||||
|
parent_cattype = fields.Function(fields.Char(string='Parent Category Type',
|
||||||
|
readonly=True, states={'invisible': True}),
|
||||||
|
'on_change_with_parent_cattype')
|
||||||
|
|
||||||
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')
|
||||||
|
@ -98,6 +107,13 @@ class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
|
||||||
('account.code',) + tuple(clause[1:]),
|
('account.code',) + tuple(clause[1:]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@fields.depends('parent', '_parent_parent.cattype')
|
||||||
|
def on_change_with_parent_cattype(self, name=None):
|
||||||
|
""" get type of parent category or None
|
||||||
|
"""
|
||||||
|
if self.parent:
|
||||||
|
return self.parent.cattype
|
||||||
|
|
||||||
@fields.depends('account')
|
@fields.depends('account')
|
||||||
def on_change_with_account_code(self, name=None):
|
def on_change_with_account_code(self, name=None):
|
||||||
""" get code of account
|
""" get code of account
|
||||||
|
@ -111,34 +127,56 @@ class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
|
||||||
"""
|
"""
|
||||||
return [('account.code',) + tuple(clause[1:])]
|
return [('account.code',) + tuple(clause[1:])]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def check_category_hierarchy(cls, categories):
|
||||||
|
""" check if current category-type is equal to parent
|
||||||
|
"""
|
||||||
|
for category in categories:
|
||||||
|
if category.parent:
|
||||||
|
if category.parent.cattype != category.cattype:
|
||||||
|
raise UserError(gettext(
|
||||||
|
'cashbook.msg_category_type_not_like_parent',
|
||||||
|
parentname = category.parent.rec_name,
|
||||||
|
catname = category.rec_name,
|
||||||
|
))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, vlist):
|
||||||
|
""" add debit/credit
|
||||||
|
"""
|
||||||
|
records = super(Category, cls).create(vlist)
|
||||||
|
cls.check_category_hierarchy(records)
|
||||||
|
return records
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def write(cls, *args):
|
def write(cls, *args):
|
||||||
""" parent.cattape == cattype,
|
""" parent.cattape == cattype,
|
||||||
update sub-categories
|
update sub-categories
|
||||||
"""
|
"""
|
||||||
to_write = []
|
|
||||||
actions = iter(args)
|
actions = iter(args)
|
||||||
|
to_check = []
|
||||||
|
to_write = []
|
||||||
|
to_write2 = []
|
||||||
for categories, values in zip(actions, actions):
|
for categories, values in zip(actions, actions):
|
||||||
|
to_write2.extend([categories, values])
|
||||||
|
|
||||||
if 'cattype' in values.keys():
|
if 'cattype' in values.keys():
|
||||||
for category in categories:
|
# update sub-categories
|
||||||
if category.parent:
|
cats = Category.search([
|
||||||
if category.parent.cattype != values['cattype']:
|
('parent', 'child_of', [x.id for x in categories])
|
||||||
raise UserError(gettext(
|
])
|
||||||
'cashbook.msg_category_type_not_like_parent',
|
|
||||||
parentname = category.parent.rec_name,
|
|
||||||
catname = category.rec_name,
|
|
||||||
))
|
|
||||||
cats = Category.search([('parent', 'child_of', [x.id for x in categories])])
|
|
||||||
if len(cats) > 0:
|
if len(cats) > 0:
|
||||||
to_write.extend([
|
to_write.extend([
|
||||||
cats,
|
cats,
|
||||||
{
|
{
|
||||||
'cattype': values['cattype'],
|
'cattype': values['cattype'],
|
||||||
}])
|
}])
|
||||||
|
to_check.extend(categories)
|
||||||
|
to_check.extend(cats)
|
||||||
|
|
||||||
super(Category, cls).write(*args)
|
# add category-updates after regulary writes
|
||||||
if len(to_write) > 0:
|
to_write2.extend(to_write)
|
||||||
print('\n## to_write:',to_write)
|
super(Category, cls).write(*to_write2)
|
||||||
Category.write(*to_write)
|
cls.check_category_hierarchy(to_check)
|
||||||
|
|
||||||
# end Category
|
# end Category
|
||||||
|
|
9
line.py
9
line.py
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
from trytond.model import ModelView, ModelSQL, Workflow, fields, Check
|
from trytond.model import ModelView, ModelSQL, Workflow, fields, Check
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.pyson import Eval, If, Or
|
from trytond.pyson import Eval, If, Or, Bool
|
||||||
from trytond.transaction import Transaction
|
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
|
||||||
|
@ -53,7 +53,12 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
category = fields.Many2One(string='Category', required=True,
|
category = fields.Many2One(string='Category', required=True,
|
||||||
model_name='cashbook.category', ondelete='RESTRICT',
|
model_name='cashbook.category', ondelete='RESTRICT',
|
||||||
states=STATES, depends=DEPENDS+['bookingtype'],
|
states={
|
||||||
|
'readonly': Or(
|
||||||
|
STATES['readonly'],
|
||||||
|
Bool(Eval('bookingtype')) == False,
|
||||||
|
),
|
||||||
|
}, depends=DEPENDS+['bookingtype'],
|
||||||
domain=[
|
domain=[
|
||||||
If(
|
If(
|
||||||
Eval('bookingtype', '').in_(['in', 'mvin']),
|
Eval('bookingtype', '').in_(['in', 'mvin']),
|
||||||
|
|
|
@ -43,7 +43,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
Book = pool.get('cashbook.book')
|
Book = pool.get('cashbook.book')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -74,7 +74,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
Book = pool.get('cashbook.book')
|
Book = pool.get('cashbook.book')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -107,7 +107,7 @@ class BookTestCase(ModuleTestCase):
|
||||||
Book = pool.get('cashbook.book')
|
Book = pool.get('cashbook.book')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
|
|
@ -13,7 +13,7 @@ class CategoryTestCase(ModuleTestCase):
|
||||||
'Test cashbook categoy module'
|
'Test cashbook categoy module'
|
||||||
module = 'cashbook'
|
module = 'cashbook'
|
||||||
|
|
||||||
def prep_category(self, name='Cat1'):
|
def prep_category(self, name='Cat1', cattype='out'):
|
||||||
""" create category
|
""" create category
|
||||||
"""
|
"""
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
|
@ -24,9 +24,57 @@ class CategoryTestCase(ModuleTestCase):
|
||||||
category, = Category.create([{
|
category, = Category.create([{
|
||||||
'company': company.id,
|
'company': company.id,
|
||||||
'name': name,
|
'name': name,
|
||||||
|
'cattype': cattype,
|
||||||
}])
|
}])
|
||||||
return category
|
return category
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_category_create_check_category_type(self):
|
||||||
|
""" create category, update type of category
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Category = pool.get('cashbook.category')
|
||||||
|
company = self.prep_company()
|
||||||
|
|
||||||
|
category, = Category.create([{
|
||||||
|
'company': company.id,
|
||||||
|
'name': 'Level 1',
|
||||||
|
'cattype': 'in',
|
||||||
|
'childs': [('create', [{
|
||||||
|
'company': company.id,
|
||||||
|
'name': 'Level 2',
|
||||||
|
'cattype': 'in',
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
|
||||||
|
self.assertEqual(category.rec_name, 'Level 1')
|
||||||
|
self.assertEqual(category.cattype, 'in')
|
||||||
|
self.assertEqual(len(category.childs), 1)
|
||||||
|
self.assertEqual(category.childs[0].rec_name, 'Level 1/Level 2')
|
||||||
|
self.assertEqual(category.childs[0].cattype, 'in')
|
||||||
|
|
||||||
|
self.assertRaisesRegex(UserError,
|
||||||
|
'The value for field "Type" in "Category" is not valid according to its domain.',
|
||||||
|
Category.write,
|
||||||
|
*[
|
||||||
|
[category.childs[0]],
|
||||||
|
{
|
||||||
|
'cattype': 'out',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
Category.write(*[
|
||||||
|
[category],
|
||||||
|
{
|
||||||
|
'cattype': 'out',
|
||||||
|
}])
|
||||||
|
self.assertEqual(category.rec_name, 'Level 1')
|
||||||
|
self.assertEqual(category.cattype, 'out')
|
||||||
|
self.assertEqual(len(category.childs), 1)
|
||||||
|
self.assertEqual(category.childs[0].rec_name, 'Level 1/Level 2')
|
||||||
|
self.assertEqual(category.childs[0].cattype, 'out')
|
||||||
|
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_category_create_nodupl_at_root(self):
|
def test_category_create_nodupl_at_root(self):
|
||||||
""" create category, duplicates are allowed at root-level
|
""" create category, duplicates are allowed at root-level
|
||||||
|
|
|
@ -25,7 +25,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Lines = pool.get('cashbook.line')
|
Lines = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -102,7 +102,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Line = pool.get('cashbook.line')
|
Line = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -150,7 +150,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
IrDate = pool.get('ir.date')
|
IrDate = pool.get('ir.date')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
IrDate.today = MagicMock(return_value=date(2022, 6, 1))
|
IrDate.today = MagicMock(return_value=date(2022, 6, 1))
|
||||||
|
|
||||||
|
@ -214,14 +214,10 @@ class LineTestCase(ModuleTestCase):
|
||||||
Category = pool.get('cashbook.category')
|
Category = pool.get('cashbook.category')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category_in = self.prep_category(cattype='in')
|
||||||
|
category_out = self.prep_category(name='Out Category', cattype='out')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
|
|
||||||
category2, = Category.create([{
|
|
||||||
'company': company.id,
|
|
||||||
'name': 'Category',
|
|
||||||
}])
|
|
||||||
|
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
'btype': types.id,
|
'btype': types.id,
|
||||||
|
@ -230,25 +226,25 @@ class LineTestCase(ModuleTestCase):
|
||||||
'lines': [('create', [{
|
'lines': [('create', [{
|
||||||
'date': date(2022, 5, 1),
|
'date': date(2022, 5, 1),
|
||||||
'description': 'Revenue',
|
'description': 'Revenue',
|
||||||
'category': category2.id,
|
'category': category_in.id,
|
||||||
'bookingtype': 'in',
|
'bookingtype': 'in',
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}, {
|
}, {
|
||||||
'date': date(2022, 6, 1),
|
'date': date(2022, 6, 1),
|
||||||
'description': 'Expense',
|
'description': 'Expense',
|
||||||
'category': category2.id,
|
'category': category_out.id,
|
||||||
'bookingtype': 'out',
|
'bookingtype': 'out',
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}, {
|
}, {
|
||||||
'date': date(2022, 6, 1),
|
'date': date(2022, 6, 1),
|
||||||
'description': 'Transfer from',
|
'description': 'Transfer from',
|
||||||
'category': category2.id,
|
'category': category_in.id,
|
||||||
'bookingtype': 'mvin',
|
'bookingtype': 'mvin',
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}, {
|
}, {
|
||||||
'date': date(2022, 6, 1),
|
'date': date(2022, 6, 1),
|
||||||
'description': 'Transfer to',
|
'description': 'Transfer to',
|
||||||
'category': category2.id,
|
'category': category_out.id,
|
||||||
'bookingtype': 'mvout',
|
'bookingtype': 'mvout',
|
||||||
'amount': Decimal('1.0'),
|
'amount': Decimal('1.0'),
|
||||||
}])],
|
}])],
|
||||||
|
@ -291,6 +287,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
[book.lines[0]],
|
[book.lines[0]],
|
||||||
{
|
{
|
||||||
'bookingtype': 'out',
|
'bookingtype': 'out',
|
||||||
|
'category': category_out.id,
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.lines[0].amount, Decimal('2.0'))
|
self.assertEqual(book.lines[0].amount, Decimal('2.0'))
|
||||||
self.assertEqual(book.lines[0].bookingtype, 'out')
|
self.assertEqual(book.lines[0].bookingtype, 'out')
|
||||||
|
@ -300,6 +297,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Line.write(*[
|
Line.write(*[
|
||||||
[book.lines[0]],
|
[book.lines[0]],
|
||||||
{
|
{
|
||||||
|
'category': category_in.id,
|
||||||
'bookingtype': 'mvin',
|
'bookingtype': 'mvin',
|
||||||
'amount': Decimal('3.0'),
|
'amount': Decimal('3.0'),
|
||||||
}])
|
}])
|
||||||
|
@ -320,7 +318,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Account = pool.get('account.account')
|
Account = pool.get('account.account')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
|
|
||||||
with Transaction().set_context({
|
with Transaction().set_context({
|
||||||
|
@ -340,10 +338,12 @@ class LineTestCase(ModuleTestCase):
|
||||||
'company': company.id,
|
'company': company.id,
|
||||||
'name': 'Level1',
|
'name': 'Level1',
|
||||||
'account': accounts[0].id,
|
'account': accounts[0].id,
|
||||||
|
'cattype': 'in',
|
||||||
'childs': [('create', [{
|
'childs': [('create', [{
|
||||||
'company': company.id,
|
'company': company.id,
|
||||||
'name': 'Level2',
|
'name': 'Level2',
|
||||||
'account': accounts[1].id,
|
'account': accounts[1].id,
|
||||||
|
'cattype': 'in',
|
||||||
}])],
|
}])],
|
||||||
}])
|
}])
|
||||||
self.assertEqual(category2.rec_name, 'Level1 [0123]')
|
self.assertEqual(category2.rec_name, 'Level1 [0123]')
|
||||||
|
@ -414,7 +414,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Lines = pool.get('cashbook.line')
|
Lines = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -450,7 +450,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Lines = pool.get('cashbook.line')
|
Lines = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -491,7 +491,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Lines = pool.get('cashbook.line')
|
Lines = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
book, = Book.create([{
|
book, = Book.create([{
|
||||||
'name': 'Book 1',
|
'name': 'Book 1',
|
||||||
|
@ -536,7 +536,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Line = pool.get('cashbook.line')
|
Line = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
usr_lst = ResUser.create([{
|
usr_lst = ResUser.create([{
|
||||||
|
@ -606,7 +606,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Line = pool.get('cashbook.line')
|
Line = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
grp_reviewer, = ResGroup.create([{
|
grp_reviewer, = ResGroup.create([{
|
||||||
|
@ -690,7 +690,7 @@ class LineTestCase(ModuleTestCase):
|
||||||
Line = pool.get('cashbook.line')
|
Line = pool.get('cashbook.line')
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category()
|
category = self.prep_category(cattype='in')
|
||||||
company = self.prep_company()
|
company = self.prep_company()
|
||||||
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
|
||||||
grp_observer, = ResGroup.create([{
|
grp_observer, = ResGroup.create([{
|
||||||
|
|
|
@ -23,7 +23,7 @@ full copyright notices and license terms. -->
|
||||||
<field name="parent"/>
|
<field name="parent"/>
|
||||||
<label name="sequence"/>
|
<label name="sequence"/>
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="childs" colspan="4"/>
|
<field name="childs" colspan="6"/>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,12 @@ full copyright notices and license terms. -->
|
||||||
|
|
||||||
<label name="date"/>
|
<label name="date"/>
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<label name="category"/>
|
|
||||||
<field name="category"/>
|
|
||||||
<newline/>
|
|
||||||
|
|
||||||
<label name="bookingtype"/>
|
<label name="bookingtype"/>
|
||||||
<field name="bookingtype"/>
|
<field name="bookingtype"/>
|
||||||
|
<newline/>
|
||||||
|
|
||||||
|
<label name="category"/>
|
||||||
|
<field name="category"/>
|
||||||
<label name="amount"/>
|
<label name="amount"/>
|
||||||
<field name="amount" symbol="currency"/>
|
<field name="amount" symbol="currency"/>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue