diff --git a/README.rst b/README.rst
index 97408f7..2572ae2 100644
--- a/README.rst
+++ b/README.rst
@@ -14,6 +14,52 @@ Requires
Changes
=======
+*6.0.11 - 16.09.2022*
+
+- add: hierarchy for cashbooks
+
+*6.0.10 - 13.09.2022*
+
+- add: split-booking with transfer
+
+*6.0.9 - 08.09.2022*
+
+- updt: allow negative amounts
+
+*6.0.8 - 07.09.2022*
+
+- updt: enter-booking form optimized
+
+*6.0.7 - 07.09.2022*
+
+- add: enter-booking-wizard
+
+*6.0.6 - 06.09.2022*
+
+- updt: optimized form - line, line-context
+- updt: extended search in cashbook-lines
+
+*6.0.5 - 05.09.2022*
+
+- updt: view of book + line optimized
+
+*6.0.4 - 05.09.2022*
+
+- fix: write number at state-change 'check' -> 'done'
+- updt: speedup transaction view
+
+*6.0.3 - 31.08.2022*
+
+- updt: checks, sorting
+
+*6.0.2 - 25.08.2022*
+
+- add: split-booking
+
+*6.0.1 - 23.08.2022*
+
+- works
+
*6.0.0 - 05.08.2022*
- init
diff --git a/__init__.py b/__init__.py
index cb57d15..6115d74 100644
--- a/__init__.py
+++ b/__init__.py
@@ -10,6 +10,7 @@ from .line import Line, LineContext
from .splitline import SplitLine
from .wizard_openline import OpenCashBook, OpenCashBookStart
from .wizard_runreport import RunCbReport, RunCbReportStart
+from .wizard_booking import EnterBookingWizard, EnterBookingStart
from .configuration import Configuration, UserConfiguration
from .category import Category
from .reconciliation import Reconciliation
@@ -28,6 +29,7 @@ def register():
Reconciliation,
OpenCashBookStart,
RunCbReportStart,
+ EnterBookingStart,
module='cashbook', type_='model')
Pool.register(
ReconciliationReport,
@@ -35,4 +37,5 @@ def register():
Pool.register(
OpenCashBook,
RunCbReport,
+ EnterBookingWizard,
module='cashbook', type_='wizard')
diff --git a/book.py b/book.py
index dd92f35..38fa020 100644
--- a/book.py
+++ b/book.py
@@ -3,7 +3,7 @@
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
-from trytond.model import Workflow, ModelView, ModelSQL, fields, Check
+from trytond.model import Workflow, ModelView, ModelSQL, fields, Check, tree
from trytond.pyson import Eval, Or, Bool, Id
from trytond.exceptions import UserError
from trytond.i18n import gettext
@@ -20,6 +20,16 @@ STATES = {
}
DEPENDS=['state']
+# states in case of 'btype'!=None
+STATES2 = {
+ 'readonly': Or(
+ Eval('state', '') != 'open',
+ ~Bool(Eval('btype')),
+ ),
+ 'invisible': ~Bool(Eval('btype')),
+ }
+DEPENDS2 = ['state', 'btype']
+
sel_state_book = [
('open', 'Open'),
('closed', 'Closed'),
@@ -27,7 +37,7 @@ sel_state_book = [
]
-class Book(Workflow, ModelSQL, ModelView):
+class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
'Cashbook'
__name__ = 'cashbook.book'
@@ -35,9 +45,17 @@ class Book(Workflow, ModelSQL, ModelView):
required=True, ondelete="RESTRICT")
name = fields.Char(string='Name', required=True,
states=STATES, depends=DEPENDS)
- btype = fields.Many2One(string='Type', required=True,
- model_name='cashbook.type', ondelete='RESTRICT',
+ description = fields.Text(string='Description',
states=STATES, depends=DEPENDS)
+ btype = fields.Many2One(string='Type',
+ help='A cash book with type can contain postings. Without type is a view.',
+ model_name='cashbook.type', ondelete='RESTRICT',
+ states={
+ 'readonly': Or(
+ STATES['readonly'],
+ Bool(Eval('lines')),
+ ),
+ }, depends=DEPENDS+['lines'])
owner = fields.Many2One(string='Owner', required=True, select=True,
model_name='res.user', ondelete='SET NULL',
states=STATES, depends=DEPENDS)
@@ -54,8 +72,8 @@ class Book(Workflow, ModelSQL, ModelView):
states=STATES, depends=DEPENDS)
reconciliations = fields.One2Many(string='Reconciliations',
field='cashbook', model_name='cashbook.recon',
- states=STATES, depends=DEPENDS)
- number_sequ = fields.Many2One(string='Line numbering', required=True,
+ states=STATES2, depends=DEPENDS2)
+ number_sequ = fields.Many2One(string='Line numbering',
help='Number sequence for numbering of the cash book lines.',
model_name='ir.sequence',
domain=[
@@ -65,37 +83,56 @@ class Book(Workflow, ModelSQL, ModelView):
('company', '=', Eval('company', -1)),
],
],
- states=STATES, depends=DEPENDS+['company'])
+ states={
+ 'readonly': STATES2['readonly'],
+ 'required': Bool(Eval('btype')),
+ }, depends=DEPENDS2+['company'])
number_atcheck = fields.Boolean(string="number when 'Checking'",
- help="The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done.")
- start_date = fields.Date(string='Initial Date', required=True,
+ help="The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done.",
+ states=STATES2, depends=DEPENDS2)
+ start_date = fields.Date(string='Initial Date',
states={
'readonly': Or(
- STATES['readonly'],
+ STATES2['readonly'],
Bool(Eval('lines')),
),
- }, depends=DEPENDS+['lines'])
- 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,
+ 'invisible': STATES2['invisible'],
+ 'required': Bool(Eval('btype')),
+ }, depends=DEPENDS2+['lines'])
+ 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',
states={
'readonly': Or(
- STATES['readonly'],
+ STATES2['readonly'],
Bool(Eval('lines', [])),
),
- }, depends=DEPENDS+['lines'])
+ 'invisible': STATES2['invisible'],
+ 'required': Bool(Eval('btype')),
+ }, depends=DEPENDS2+['lines'])
+ currency_digits = fields.Function(fields.Integer(string='Currency Digits',
+ readonly=True), 'on_change_with_currency_digits')
state = fields.Selection(string='State', required=True,
readonly=True, selection=sel_state_book)
state_string = state.translated('state')
+ parent = fields.Many2One(string="Parent",
+ model_name='cashbook.book', ondelete='RESTRICT',
+ left='left', right='right')
+ childs = fields.One2Many(string='Children', field='parent',
+ model_name='cashbook.book')
+ left = fields.Integer(string='Left', required=True, select=True)
+ right = fields.Integer(string='Right', required=True, select=True)
+
+ @classmethod
+ def __register__(cls, module_name):
+ super(Book, cls).__register__(module_name)
+
+ table = cls.__table_handler__(module_name)
+ table.drop_column('start_balance')
+
@classmethod
def __setup__(cls):
super(Book, cls).__setup__()
@@ -127,16 +164,18 @@ class Book(Workflow, ModelSQL, ModelView):
},
})
+ @staticmethod
+ def default_left():
+ return 0
+
+ @staticmethod
+ def default_right():
+ return 0
+
@classmethod
def default_number_atcheck(cls):
return True
- @classmethod
- def default_start_balance(cls):
- """ zero
- """
- return Decimal('0.0')
-
@classmethod
def default_currency(cls):
""" currency of company
@@ -189,35 +228,55 @@ class Book(Workflow, ModelSQL, ModelView):
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,
- }
+ recname = super(Book, self).get_rec_name(name)
+ if self.btype:
+ return '%(name)s | %(balance)s %(symbol)s | %(state)s' % {
+ 'name': recname or '-',
+ 'balance': Report.format_number(self.balance or 0.0, None),
+ 'symbol': getattr(self.currency, 'symbol', '-'),
+ 'state': self.state_string,
+ }
+ return recname
- @fields.depends('id', 'start_balance')
+ @fields.depends('currency')
+ def on_change_with_currency_digits(self, name=None):
+ """ currency of cashbook
+ """
+ if self.currency:
+ return self.currency.digits
+ else:
+ return 2
+
+ @fields.depends('id')
def on_change_with_balance(self, name=None):
""" compute balance
"""
- Line = Pool().get('cashbook.line')
+ pool = Pool()
+ Book2 = pool.get('cashbook.book')
+ Line = pool.get('cashbook.line')
tab_line = Line.__table__()
cursor = Transaction().connection.cursor()
- query = tab_line.select(
+ line_query = Line.search([
+ ('cashbook.id', 'in', Book2.search([
+ ('parent', 'child_of', [self.id]),
+ ], query=True)),
+ ], query=True)
+
+ query = line_query.join(tab_line,
+ condition=tab_line.id==line_query.id,
+ ).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 = Decimal('0.0')
+ cursor.execute(*query)
+ result = cursor.fetchone()
+ if result:
+ if result[0] is not None:
balance += result[0]
- return balance
+ return balance
@classmethod
@ModelView.button
@@ -250,12 +309,15 @@ class Book(Workflow, ModelSQL, ModelView):
actions = iter(args)
for books, values in zip(actions, actions):
for book in books:
- if 'start_balance' in values.keys():
- if len(book.lines) > 0:
+ # deny btype-->None if lines not empty
+ if 'btype' in values.keys():
+ if (values['btype'] is None) and (len(book.lines) > 0):
raise UserError(gettext(
- 'cashbook.msg_book_err_startamount_with_lines',
- bookname = book.rec_name,
+ 'cashbook.msg_book_btype_with_lines',
+ cbname = book.rec_name,
+ numlines = len(book.lines),
))
+
if book.state != 'open':
# allow state-update, if its the only action
if not (('state' in values.keys()) and (len(values.keys()) == 1)):
diff --git a/book.xml b/book.xml
index 465bcaf..810cf96 100644
--- a/book.xml
+++ b/book.xml
@@ -12,6 +12,13 @@ full copyright notices and license terms. -->
book_list
+
+ cashbook.book
+ tree
+
+ childs
+ book_tree
+
cashbook.book
form
@@ -19,7 +26,7 @@ full copyright notices and license terms. -->
book_form
-
+
Cashbook
cashbook.book
@@ -35,6 +42,23 @@ full copyright notices and license terms. -->
+
+
+ Cashbook
+ cashbook.book
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -251,18 +275,24 @@ full copyright notices and license terms. -->
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -335,16 +365,23 @@ full copyright notices and license terms. -->
-
+
+ search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
-
+
+ search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'parent')]"/>
+
+
+
+
+
+
@@ -421,16 +458,23 @@ full copyright notices and license terms. -->
-
+
+ search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
-
+
+ search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'parent')]"/>
+
+
+
+
+
+
diff --git a/category.py b/category.py
index 0d23eb8..477016c 100644
--- a/category.py
+++ b/category.py
@@ -3,12 +3,46 @@
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
-from trytond.model import ModelView, ModelSQL, fields, Unique, tree, sequence_ordered
+from trytond.model import ModelView, ModelSQL, fields, Unique, Exclude, tree
from trytond.transaction import Transaction
from trytond.pool import Pool
from trytond.pyson import Eval, If, Bool
from trytond.exceptions import UserError
from trytond.i18n import gettext
+from sql.operators import Equal
+from sql.functions import Function
+from sql import With, Literal
+
+
+class ArrayApppend(Function):
+ """ sql: array_append
+ """
+ __slots__ = ()
+ _function = 'ARRAY_APPEND'
+
+# end ArrayApppend
+
+
+class ArrayToString(Function):
+ """ sql: array_to_string
+ """
+ __slots__ = ()
+ _function = 'ARRAY_TO_STRING'
+
+# end ArrayToString
+
+
+class Array(Function):
+ """ sql: array-type
+ """
+ __slots__ = ()
+ _function = 'ARRAY'
+
+ def __str__(self):
+ return self._function + '[' + ', '.join(
+ map(self._format, self.args)) + ']'
+
+# end Array
sel_categorytype = [
@@ -17,7 +51,7 @@ sel_categorytype = [
]
-class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
+class Category(tree(separator='/'), ModelSQL, ModelView):
'Category'
__name__ = 'cashbook.category'
@@ -36,7 +70,6 @@ class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
company = fields.Many2One(string='Company', model_name='company.company',
required=True, ondelete="RESTRICT")
- sequence = fields.Integer(string='Sequence', select=True)
parent = fields.Many2One(string="Parent",
model_name='cashbook.category', ondelete='RESTRICT',
left='left', right='right')
@@ -45,15 +78,35 @@ class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
left = fields.Integer(string='Left', required=True, select=True)
right = fields.Integer(string='Right', required=True, select=True)
+ @classmethod
+ def __register__(cls, module_name):
+ super(Category, cls).__register__(module_name)
+ cls.migrate_sequence(module_name)
+
@classmethod
def __setup__(cls):
super(Category, cls).__setup__()
- cls._order.insert(0, ('name', 'ASC'))
+ cls._order.insert(0, ('rec_name', 'ASC'))
t = cls.__table__()
cls._sql_constraints.extend([
- ('name_uniq', Unique(t, t.name, t.company, t.parent), 'cashbook.msg_category_name_unique'),
+ ('name_uniq',
+ Unique(t, t.name, t.company, t.parent),
+ 'cashbook.msg_category_name_unique'),
+ ('name2_uniq',
+ Exclude(t,
+ (t.name, Equal),
+ (t.cattype, Equal),
+ where=(t.parent == None)),
+ 'cashbook.msg_category_name_unique'),
])
+ @classmethod
+ def migrate_sequence(cls, module_name):
+ """ remove colum 'sequence'
+ """
+ table = cls.__table_handler__(module_name)
+ table.drop_column('sequence')
+
@classmethod
def default_cattype(cls):
return 'out'
@@ -70,6 +123,34 @@ class Category(tree(separator='/'), sequence_ordered(), ModelSQL, ModelView):
def default_right():
return 0
+ @staticmethod
+ def order_rec_name(tables):
+ """ order by pos
+ a recursive sorting
+ """
+ Category2 = Pool().get('cashbook.category')
+ tab_cat = Category2.__table__()
+ tab_cat2 = Category2.__table__()
+ table, _ = tables[None]
+
+ categories = With('id', 'name', 'name_path', recursive=True)
+ categories.query = tab_cat.select(
+ tab_cat.id, tab_cat.name, Array(tab_cat.name),
+ where = tab_cat.parent==None,
+ )
+ categories.query |= tab_cat2.join(categories,
+ condition=categories.id==tab_cat2.parent,
+ ).select(
+ tab_cat2.id, tab_cat2.name, ArrayApppend(categories.name_path, tab_cat2.name),
+ )
+ categories.query.all_ = True
+
+ query = categories.select(
+ ArrayToString(categories.name_path, '/').as_('rec_name'),
+ where = table.id==categories.id,
+ with_ = [categories])
+ return [query]
+
@fields.depends('parent', '_parent_parent.cattype')
def on_change_with_parent_cattype(self, name=None):
""" get type of parent category or None
diff --git a/category.xml b/category.xml
index a5dcc66..516e4c7 100644
--- a/category.xml
+++ b/category.xml
@@ -42,6 +42,20 @@ full copyright notices and license terms. -->
+
+
+ Revenue
+
+
+
+
+
+ Expense
+
+
+
+
+
Category
@@ -59,6 +73,21 @@ full copyright notices and license terms. -->
+
+
+ Revenue
+
+
+
+
+
+ Expense
+
+
+
+
+
+
diff --git a/configuration.py b/configuration.py
index e0e460f..2dc986e 100644
--- a/configuration.py
+++ b/configuration.py
@@ -15,6 +15,10 @@ field_done = fields.Boolean(string='Done',
help='Show cashbook lines in Done-state.')
field_catnamelong = fields.Boolean(string='Category: Show long name',
help='Shows the long name of the category in the Category field of a cash book line.')
+field_defbook = fields.Many2One(string='Default Cashbook',
+ help='The default cashbook is selected when you open the booking wizard.',
+ model_name='cashbook.book', ondelete='SET NULL',
+ domain=[('btype', '!=', None)])
class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin):
@@ -36,6 +40,7 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin):
checked = fields.MultiValue(field_checked)
done = fields.MultiValue(field_done)
catnamelong = fields.MultiValue(field_catnamelong)
+ defbook = fields.MultiValue(field_defbook)
@classmethod
def multivalue_model(cls, field):
@@ -44,7 +49,7 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin):
pool = Pool()
if field in ['date_from', 'date_to', 'checked', 'done',
- 'catnamelong']:
+ 'catnamelong', 'defbook']:
return pool.get('cashbook.configuration_user')
return super(Configuration, cls).multivalue_model(field)
@@ -82,6 +87,7 @@ class UserConfiguration(ModelSQL, UserValueMixin):
checked = field_checked
done = field_done
catnamelong = field_catnamelong
+ defbook = field_defbook
@classmethod
def default_checked(cls):
diff --git a/line.py b/line.py
index a8ccda4..db402e9 100644
--- a/line.py
+++ b/line.py
@@ -51,14 +51,17 @@ class Line(Workflow, ModelSQL, ModelView):
__name__ = 'cashbook.line'
cashbook = fields.Many2One(string='Cashbook', required=True, select=True,
- model_name='cashbook.book', ondelete='CASCADE', readonly=True)
+ model_name='cashbook.book', ondelete='CASCADE', readonly=True,
+ domain=[('btype', '!=', None)])
date = fields.Date(string='Date', required=True, select=True,
states=STATES, depends=DEPENDS)
month = fields.Function(fields.Integer(string='Month', readonly=True),
'on_change_with_month', searcher='search_month')
number = fields.Char(string='Number', readonly=True)
- description = fields.Text(string='Description',
+ description = fields.Text(string='Description', select=True,
states=STATES, depends=DEPENDS)
+ descr_short = fields.Function(fields.Char(string='Description', readonly=True),
+ 'on_change_with_descr_short', searcher='search_descr_short')
category = fields.Many2One(string='Category',
model_name='cashbook.category', ondelete='RESTRICT',
states={
@@ -171,6 +174,13 @@ class Line(Workflow, ModelSQL, ModelView):
#image = fields.Binary...
+ @classmethod
+ def __register__(cls, module_name):
+ super(Line, cls).__register__(module_name)
+
+ table = cls.__table_handler__(module_name)
+ table.drop_constraint('amount_val')
+
@classmethod
def __setup__(cls):
super(Line, cls).__setup__()
@@ -270,19 +280,44 @@ class Line(Workflow, ModelSQL, ModelView):
'cashbook.msg_line_err_write_to_reconciled',
datetxt = Report.format_date(line.date),
))
- # in case of 'mvin' or 'mvout' - create counterpart
- if (line.bookingtype in ['mvout', 'mvin']) and (line.reference is None):
- values = {
- 'cashbook': line.booktransf.id,
- 'bookingtype': 'mvin' if line.bookingtype == 'mvout' else 'mvout',
- 'date': line.date,
- 'description': line.description,
- 'booktransf': line.cashbook.id,
- 'reference': line.id,
- }
- values.update(line.get_amount_by_second_currency(line.booktransf.currency))
- values.update(cls.get_debit_credit(values))
- to_create_line.append(values)
+
+ if line.reference is None:
+ if line.bookingtype in ['mvout', 'mvin']:
+ # in case of 'mvin' or 'mvout' - add counterpart
+ values = {
+ 'cashbook': line.booktransf.id,
+ 'bookingtype': 'mvin' if line.bookingtype == 'mvout' else 'mvout',
+ 'date': line.date,
+ 'description': line.description,
+ 'booktransf': line.cashbook.id,
+ 'reference': line.id,
+ }
+ values.update(line.get_amount_by_second_currency(line.booktransf.currency))
+ values.update(cls.get_debit_credit(values))
+ to_create_line.append(values)
+ elif line.bookingtype in ['spout', 'spin']:
+ # splitbooking can have a transfer - add counterpart
+ for sp_line in line.splitlines:
+ if sp_line.splittype != 'tr':
+ continue
+
+ values = {
+ 'cashbook': sp_line.booktransf.id,
+ 'date': line.date,
+ 'description': sp_line.description,
+ 'booktransf': line.cashbook.id,
+ 'reference': line.id,
+ }
+ if line.bookingtype.endswith('out'):
+ values['bookingtype'] = 'mvin'
+ else :
+ values['bookingtype'] = 'mvout'
+ values.update(line.get_amount_by_second_currency(
+ sp_line.booktransf.currency,
+ amount = sp_line.amount,
+ ))
+ values.update(cls.get_debit_credit(values))
+ to_create_line.append(values)
# add number to line
if line.cashbook.number_atcheck == True:
@@ -345,7 +380,12 @@ class Line(Workflow, ModelSQL, ModelView):
def search_rec_name(cls, name, clause):
""" search in description +...
"""
- return [('description',) + tuple(clause[1:])]
+ return cls.search_payee(name, clause) + [
+ ('description',) + tuple(clause[1:]),
+ ('category.rec_name',) + tuple(clause[1:]),
+ ('splitlines.description',) + tuple(clause[1:]),
+ ('splitlines.category.rec_name',) + tuple(clause[1:]),
+ ]
def get_rec_name(self, name):
""" short + name
@@ -379,7 +419,7 @@ class Line(Workflow, ModelSQL, ModelView):
}):
values['amount'] = Currency.compute(
self.cashbook.currency,
- self.amount,
+ values['amount'],
to_currency)
return values
@@ -414,6 +454,13 @@ class Line(Workflow, ModelSQL, ModelView):
return [tab2]
+ @staticmethod
+ def order_descr_short(tables):
+ """ order by 'description'
+ """
+ table, _ = tables[None]
+ return [table.description]
+
@classmethod
def search_payee(cls, names, clause):
""" search in payee for party or cashbook
@@ -454,6 +501,12 @@ class Line(Workflow, ModelSQL, ModelView):
"""
return [('cashbook.state',) + tuple(clause[1:])]
+ @classmethod
+ def search_descr_short(cls, names, clause):
+ """ search in description
+ """
+ return [('description',) + tuple(clause[1:])]
+
@fields.depends('amount', 'splitlines')
def on_change_splitlines(self):
""" update amount if splitlines change
@@ -481,6 +534,13 @@ class Line(Workflow, ModelSQL, ModelView):
else :
self.splitlines = []
+ @fields.depends('description')
+ def on_change_with_descr_short(self, name=None):
+ """ to speed up list-view
+ """
+ if self.description:
+ return self.description[:50].replace('\n', '; ')
+
@fields.depends('party', 'booktransf', 'bookingtype')
def on_change_with_payee(self, name=None):
""" get party or cashbook
@@ -548,8 +608,9 @@ class Line(Workflow, ModelSQL, ModelView):
return 2
@fields.depends('id', 'date', 'cashbook', \
- '_parent_cashbook.start_balance', '_parent_cashbook.id',\
- 'reconciliation', '_parent_reconciliation.start_amount')
+ '_parent_cashbook.id', 'reconciliation', \
+ '_parent_reconciliation.start_amount',\
+ '_parent_reconciliation.state')
def on_change_with_balance(self, name=None):
""" compute balance until current line, with current sort order,
try to use a reconciliation as start to speed up calculation
@@ -558,31 +619,55 @@ class Line(Workflow, ModelSQL, ModelView):
Reconciliation = pool.get('cashbook.recon')
Line = pool.get('cashbook.line')
+ def get_from_last_recon(line2):
+ """ search last reconciliation in state 'done',
+ generate query
+ """
+ query2 = []
+ end_amount = None
+
+ recons = Reconciliation.search([
+ ('cashbook.id', '=', self.cashbook.id),
+ ('date_to', '<=', line2.date),
+ ('state', '=', 'done'),
+ ], order=[('date_from', 'DESC')], limit=1)
+ if len(recons) > 0:
+ query2.append([
+ ('date', '>=', recons[0].date_to),
+ ('date', '<=', line2.date),
+ ['OR',
+ ('reconciliation', '=', None),
+ ('reconciliation.id', '!=', recons[0]),
+ ],
+ ])
+ end_amount = recons[0].end_amount
+ return (query2, end_amount)
+
if self.cashbook:
query = [
('cashbook.id', '=', self.cashbook.id),
]
- balance = self.cashbook.start_balance
+ balance = Decimal('0.0')
# get existing reconciliation, starting before current line
# this will speed up calculation of by-line-balance
if self.date is not None:
- recons = Reconciliation.search([
- ('cashbook.id', '=', self.cashbook.id),
- ('date_from', '<=', self.date),
- ('state', '=', 'done'),
- ], order=[('date_from', 'DESC')], limit=1)
- if len(recons) > 0:
- query.extend([
- ['OR',
- ('date', '>', recons[0].date_from),
- [
- ('date', '=', recons[0].date_from),
- ('reconciliation.id', '=',recons[0].id),
- ],
- ]
- ])
- balance = recons[0].start_amount
+ if self.reconciliation:
+ if self.reconciliation.state == 'done':
+ query.append(
+ ('reconciliation.id', '=', self.reconciliation.id),
+ )
+ balance = self.reconciliation.start_amount
+ else :
+ (query2, balance2) = get_from_last_recon(self)
+ query.extend(query2)
+ if balance2 is not None:
+ balance = balance2
+ else :
+ (query2, balance2) = get_from_last_recon(self)
+ query.extend(query2)
+ if balance2 is not None:
+ balance = balance2
lines = Line.search(query)
for line in lines:
@@ -689,6 +774,8 @@ class Line(Workflow, ModelSQL, ModelView):
# splitline: category <--> bookingtype?
for spline in line.splitlines:
+ if spline.splittype != 'cat':
+ continue
if not line.bookingtype in types[spline.category.cattype]:
raise UserError(gettext(
'cashbook.msg_line_split_invalid_category',
@@ -722,7 +809,7 @@ class Line(Workflow, ModelSQL, ModelView):
# deny write if line is not 'Edit'
if line.state != 'edit':
# allow state-update, if its the only action
- if not ((len(set({'state', 'reconciliation'}).intersection(values.keys())) > 0) \
+ if not ((len(set({'state', 'reconciliation', 'number'}).intersection(values.keys())) > 0) \
and (len(values.keys()) == 1)):
raise UserError(gettext(
'cashbook.msg_line_deny_write',
@@ -844,16 +931,19 @@ class LineContext(ModelView):
cashbook = fields.Many2One(string='Cashbook', required=True,
model_name='cashbook.book',
+ domain=[('btype', '!=', None)],
states={
'readonly': Eval('num_cashbook', 0) < 2,
}, depends=['num_cashbook'])
date_from = fields.Date(string='Start Date', depends=['date_to'],
+ help='Limits the date range for the displayed entries.',
domain=[
If(Eval('date_to') & Eval('date_from'),
('date_from', '<=', Eval('date_to')),
()),
])
date_to = fields.Date(string='End Date', depends=['date_from'],
+ help='Limits the date range for the displayed entries.',
domain=[
If(Eval('date_to') & Eval('date_from'),
('date_from', '<=', Eval('date_to')),
@@ -904,7 +994,7 @@ class LineContext(ModelView):
with Transaction().set_context({
'_check_access': True,
}):
- return CashBook.search_count([])
+ return CashBook.search_count([('btype', '!=', None)])
@classmethod
def default_done(cls):
diff --git a/locale/de.po b/locale/de.po
index 073d916..ba68660 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -70,10 +70,6 @@ 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'."
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."
-
msgctxt "model:ir.message,text:msg_line_deny_recon_by_state"
msgid "For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'."
msgstr "Für die Abstimmung muss die Zeile '%(recname)s' im Status 'Prüfen' oder 'Fertig' sein."
@@ -150,6 +146,10 @@ msgctxt "model:ir.message,text:msg_line_invalid_category"
msgid "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
msgstr "Die Kategorie der Buchungszeile '%(recname)s' paßt nicht zum Buchungstyp '%(booktype)s'."
+msgctxt "model:ir.message,text:msg_book_btype_with_lines"
+msgid "The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines."
+msgstr "Der Typ kann am Kassenbuch '%(cbname)s' nicht gelöscht werden, da es noch %(numlines)s Zeilen enthält."
+
#############
# res.group #
@@ -258,6 +258,10 @@ msgctxt "model:ir.ui.menu,name:menu_booklist"
msgid "Cashbook"
msgstr "Kassenbuch"
+msgctxt "model:ir.ui.menu,name:menu_booktree"
+msgid "Cashbook"
+msgstr "Kassenbuch"
+
msgctxt "model:ir.ui.menu,name:menu_open_lines"
msgid "Open Cashbook"
msgstr "Kassenbuch öffnen"
@@ -274,6 +278,10 @@ msgctxt "model:ir.ui.menu,name:act_category_view"
msgid "Category"
msgstr "Kategorie"
+msgctxt "model:ir.ui.menu,name:menu_enter_booking"
+msgid "Enter Booking"
+msgstr "Buchung eingeben"
+
#############
# ir.action #
@@ -282,6 +290,10 @@ msgctxt "model:ir.action,name:act_book_view"
msgid "Cashbook"
msgstr "Kassenbuch"
+msgctxt "model:ir.action,name:act_book_tree"
+msgid "Cashbook"
+msgstr "Kassenbuch"
+
msgctxt "model:ir.action,name:act_type_view"
msgid "Cashbook Type"
msgstr "Kassenbuchtyp"
@@ -302,6 +314,10 @@ msgctxt "model:ir.action,name:act_wizard_report"
msgid "Cashbook Report"
msgstr "Kassenbuch Bericht"
+msgctxt "model:ir.action,name:act_enterbooking_wiz"
+msgid "Enter Booking"
+msgstr "Buchung eingeben"
+
###############################
# ir.action.act_window.domain #
@@ -318,6 +334,22 @@ msgctxt "model:ir.action.act_window.domain,name:act_line_domain_all"
msgid "All"
msgstr "Alle"
+msgctxt "model:ir.action.act_window.domain,name:act_category_tree_domain_in"
+msgid "Revenue"
+msgstr "Einnahmen"
+
+msgctxt "model:ir.action.act_window.domain,name:act_category_tree_domain_out"
+msgid "Expense"
+msgstr "Ausgaben"
+
+msgctxt "model:ir.action.act_window.domain,name:act_category_list_domain_in"
+msgid "Revenue"
+msgstr "Einnahmen"
+
+msgctxt "model:ir.action.act_window.domain,name:act_category_list_domain_out"
+msgid "Expense"
+msgstr "Ausgaben"
+
###################
# ir.model.button #
@@ -390,18 +422,42 @@ msgctxt "view:cashbook.book:"
msgid "Owner and Authorizeds"
msgstr "Eigentümer und Autorisierte"
+msgctxt "view:cashbook.book:"
+msgid "General Information"
+msgstr "Allgemein"
+
+msgctxt "view:cashbook.book:"
+msgid "Amount and Numbering"
+msgstr "Betrag und Nummerierung"
+
+msgctxt "view:cashbook.book:"
+msgid "Balance"
+msgstr "Saldo"
+
msgctxt "view:cashbook.book:"
msgid "Reconciliations"
msgstr "Abstimmungen"
+msgctxt "view:cashbook.book:"
+msgid "Description"
+msgstr "Beschreibung"
+
msgctxt "field:cashbook.book,name:"
msgid "Name"
msgstr "Name"
+msgctxt "field:cashbook.book,description:"
+msgid "Description"
+msgstr "Beschreibung"
+
msgctxt "field:cashbook.book,btype:"
msgid "Type"
msgstr "Typ"
+msgctxt "help:cashbook.book,btype:"
+msgid "A cash book with type can contain postings. Without type is a view."
+msgstr "Ein Kassenbuch mit Typ kann Buchungen enthalten. Ohne Typ ist eine Sicht."
+
msgctxt "field:cashbook.book,state:"
msgid "State"
msgstr "Status"
@@ -446,9 +502,9 @@ msgctxt "field:cashbook.book,currency:"
msgid "Currency"
msgstr "Währung"
-msgctxt "field:cashbook.book,start_balance:"
-msgid "Initial Amount"
-msgstr "Anfangsbetrag"
+msgctxt "field:cashbook.book,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
msgctxt "field:cashbook.book,start_date:"
msgid "Initial Date"
@@ -482,6 +538,22 @@ msgctxt "help:cashbook.book,number_atcheck:"
msgid "The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done."
msgstr "Die Nummerierung der Zeilen wird beim Schritt 'Prüfen' erledigt. Bei inaktivem Häkchen passiert dies erst bei 'Fertig'."
+msgctxt "field:cashbook.book,parent:"
+msgid "Parent"
+msgstr "Übergeordnet"
+
+msgctxt "field:cashbook.book,childs:"
+msgid "Children"
+msgstr "Untergeordnet"
+
+msgctxt "field:cashbook.book,left:"
+msgid "Left"
+msgstr "Links"
+
+msgctxt "field:cashbook.book,right:"
+msgid "Right"
+msgstr "Rechts"
+
##################
# cashbook.split #
@@ -570,6 +642,46 @@ msgctxt "field:cashbook.split,state_cashbook:"
msgid "State of Cashbook"
msgstr "Kassenbuchstatus"
+msgctxt "field:cashbook.split,splittype:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "help:cashbook.split,splittype:"
+msgid "Type of split booking line"
+msgstr "Typ der Splitbuchungszeile"
+
+msgctxt "selection:cashbook.split,splittype:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "selection:cashbook.split,splittype:"
+msgid "Transfer"
+msgstr "Umbuchung"
+
+msgctxt "field:cashbook.split,target:"
+msgid "Target"
+msgstr "Ziel"
+
+msgctxt "selection:cashbook.split,target:"
+msgid "Cashbook"
+msgstr "Kassenbuch"
+
+msgctxt "selection:cashbook.split,target:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:cashbook.split,cashbook:"
+msgid "Cashbook"
+msgstr "Kassenbuch"
+
+msgctxt "field:cashbook.split,owner_cashbook:"
+msgid "Owner"
+msgstr "Eigentümer"
+
+msgctxt "field:cashbook.split,booktransf:"
+msgid "Source/Dest"
+msgstr "Quelle/Ziel"
+
#################
# cashbook.line #
@@ -618,6 +730,10 @@ msgctxt "field:cashbook.line,description:"
msgid "Description"
msgstr "Beschreibung"
+msgctxt "field:cashbook.line,descr_short:"
+msgid "Description"
+msgstr "Beschreibung"
+
msgctxt "field:cashbook.line,state:"
msgid "State"
msgstr "Status"
@@ -934,10 +1050,18 @@ msgctxt "field:cashbook.line.context,date_from:"
msgid "Start Date"
msgstr "Beginndatum"
+msgctxt "help:cashbook.line.context,date_from:"
+msgid "Limits the date range for the displayed entries."
+msgstr "Begrenzt den Datumsbereich für die angezeigten Einträge."
+
msgctxt "field:cashbook.line.context,date_to:"
msgid "End Date"
msgstr "Endedatum"
+msgctxt "help:cashbook.line.context,date_to:"
+msgid "Limits the date range for the displayed entries."
+msgstr "Begrenzt den Datumsbereich für die angezeigten Einträge."
+
##########################
# cashbook.configuration #
@@ -946,6 +1070,10 @@ msgctxt "model:cashbook.configuration,name:"
msgid "Configuration"
msgstr "Konfiguration"
+msgctxt "view:cashbook.configuration:"
+msgid "Enter Booking Wizard"
+msgstr "Dialog: Buchung eingeben"
+
msgctxt "view:cashbook.configuration:"
msgid "Open Cashbook Wizard"
msgstr "Dialog: Kassenbuch öffnen"
@@ -954,6 +1082,14 @@ msgctxt "view:cashbook.configuration:"
msgid "Cashbook"
msgstr "Kassenbuch"
+msgctxt "field:cashbook.configuration,defbook:"
+msgid "Default Cashbook"
+msgstr "Standardkassenbuch"
+
+msgctxt "help:cashbook.configuration,defbook:"
+msgid "The default cashbook is selected when you open the booking wizard."
+msgstr "Das Standardkassenbuch wird beim Öffnen des Buchungswizards ausgewählt."
+
msgctxt "field:cashbook.configuration,date_from:"
msgid "Start Date"
msgstr "Beginndatum"
@@ -1026,6 +1162,14 @@ msgctxt "help:cashbook.configuration_user,catnamelong:"
msgid "Shows the long name of the category in the Category field of a cash book line."
msgstr "Zeigt im Feld 'Kategorie' einer Kassenbuchzeile den langen Namen der Kategorie."
+msgctxt "field:cashbook.configuration_user,defbook:"
+msgid "Default Cashbook"
+msgstr "Standardkassenbuch"
+
+msgctxt "help:cashbook.configuration_user,defbook:"
+msgid "The default cashbook is selected when you open the booking wizard."
+msgstr "Das Standardkassenbuch wird beim Öffnen des Buchungswizards ausgewählt."
+
##################
# cashbook.recon #
@@ -1209,3 +1353,103 @@ msgstr "Gesamt"
msgctxt "report:cashbook.reprecon:"
msgid "Payee"
msgstr "Empfänger"
+
+
+###############################
+# cashbook.enterbooking.start #
+###############################
+msgctxt "model:cashbook.enterbooking.start,name:"
+msgid "Enter Booking"
+msgstr "Buchung eingeben"
+
+msgctxt "view:cashbook.enterbooking.start:"
+msgid "Description"
+msgstr "Beschreibung"
+
+msgctxt "view:cashbook.enterbooking.start:"
+msgid "Booking"
+msgstr "Buchung"
+
+msgctxt "field:cashbook.enterbooking.start,cashbook:"
+msgid "Cashbook"
+msgstr "Kassenbuch"
+
+msgctxt "field:cashbook.enterbooking.start,cashbooks:"
+msgid "Cashbooks"
+msgstr "Kassenbücher"
+
+msgctxt "field:cashbook.enterbooking.start,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
+msgctxt "field:cashbook.enterbooking.start,currency:"
+msgid "Currency"
+msgstr "Währung"
+
+msgctxt "field:cashbook.enterbooking.start,bookingtype:"
+msgid "Type"
+msgstr "Typ"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Revenue"
+msgstr "Einnahme"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Revenue Splitbooking"
+msgstr "Einnahme Splitbuchung"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Expense"
+msgstr "Ausgabe"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Expense Splitbooking"
+msgstr "Ausgabe Splitbuchung"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Transfer from"
+msgstr "Umbuchung von"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Transfer to"
+msgstr "Umbuchung nach"
+
+msgctxt "field:cashbook.enterbooking.start,amount:"
+msgid "Amount"
+msgstr "Betrag"
+
+msgctxt "field:cashbook.enterbooking.start,owner_cashbook:"
+msgid "Owner"
+msgstr "Eigentümer"
+
+msgctxt "field:cashbook.enterbooking.start,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:cashbook.enterbooking.start,booktransf:"
+msgid "Source/Dest"
+msgstr "Quelle/Ziel"
+
+msgctxt "field:cashbook.enterbooking.start,party:"
+msgid "Party"
+msgstr "Partei"
+
+
+#########################
+# cashbook.enterbooking #
+#########################
+msgctxt "model:cashbook.enterbooking,name:"
+msgid "Enter Booking"
+msgstr "Buchung eingeben"
+
+msgctxt "wizard_button:cashbook.enterbooking,start,end:"
+msgid "Cancel"
+msgstr "Abbruch"
+
+msgctxt "wizard_button:cashbook.enterbooking,start,save_:"
+msgid "Save"
+msgstr "Speichern"
+
+msgctxt "wizard_button:cashbook.enterbooking,start,savenext_:"
+msgid "Save & Next"
+msgstr "Speichern & Weiter"
diff --git a/locale/en.po b/locale/en.po
index c6f7965..5d58001 100644
--- a/locale/en.po
+++ b/locale/en.po
@@ -66,10 +66,6 @@ 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'."
msgstr "The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'."
-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 "The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings."
-
msgctxt "model:ir.message,text:msg_line_deny_recon_by_state"
msgid "For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'."
msgstr "For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'."
@@ -146,6 +142,10 @@ msgctxt "model:ir.message,text:msg_line_invalid_category"
msgid "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
msgstr "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
+msgctxt "model:ir.message,text:msg_book_btype_with_lines"
+msgid "The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines."
+msgstr "The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines."
+
msgctxt "model:res.group,name:group_cashbook"
msgid "Cashbook"
msgstr "Cashbook"
@@ -242,6 +242,10 @@ msgctxt "model:ir.ui.menu,name:menu_booklist"
msgid "Cashbook"
msgstr "Cashbook"
+msgctxt "model:ir.ui.menu,name:menu_booktree"
+msgid "Cashbook"
+msgstr "Cashbook"
+
msgctxt "model:ir.ui.menu,name:menu_open_lines"
msgid "Open Cashbook"
msgstr "Open Cashbook"
@@ -258,10 +262,18 @@ msgctxt "model:ir.ui.menu,name:act_category_view"
msgid "Category"
msgstr "Category"
+msgctxt "model:ir.ui.menu,name:menu_enter_booking"
+msgid "Enter Booking"
+msgstr "Enter Booking"
+
msgctxt "model:ir.action,name:act_book_view"
msgid "Cashbook"
msgstr "Cashbook"
+msgctxt "model:ir.action,name:act_book_tree"
+msgid "Cashbook"
+msgstr "Cashbook"
+
msgctxt "model:ir.action,name:act_type_view"
msgid "Cashbook Type"
msgstr "Cashbook Type"
@@ -282,6 +294,10 @@ msgctxt "model:ir.action,name:act_wizard_report"
msgid "Cashbook Report"
msgstr "Cashbook Report"
+msgctxt "model:ir.action,name:act_enterbooking_wiz"
+msgid "Enter Booking"
+msgstr "Enter Booking"
+
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_current"
msgid "Current Month"
msgstr "Current Month"
@@ -294,6 +310,22 @@ msgctxt "model:ir.action.act_window.domain,name:act_line_domain_all"
msgid "All"
msgstr "All"
+msgctxt "model:ir.action.act_window.domain,name:act_category_tree_domain_in"
+msgid "Revenue"
+msgstr "Revenue"
+
+msgctxt "model:ir.action.act_window.domain,name:act_category_tree_domain_out"
+msgid "Expense"
+msgstr "Expense"
+
+msgctxt "model:ir.action.act_window.domain,name:act_category_list_domain_in"
+msgid "Revenue"
+msgstr "Revenue"
+
+msgctxt "model:ir.action.act_window.domain,name:act_category_list_domain_out"
+msgid "Expense"
+msgstr "Expense"
+
msgctxt "model:ir.model.button,string:line_wfedit_button"
msgid "Edit"
msgstr "Edit"
@@ -354,18 +386,42 @@ msgctxt "view:cashbook.book:"
msgid "Owner and Authorizeds"
msgstr "Owner and Authorizeds"
+msgctxt "view:cashbook.book:"
+msgid "General Information"
+msgstr "General Information"
+
+msgctxt "view:cashbook.book:"
+msgid "Amount and Numbering"
+msgstr "Amount and Numbering"
+
+msgctxt "view:cashbook.book:"
+msgid "Balance"
+msgstr "Balance"
+
msgctxt "view:cashbook.book:"
msgid "Reconciliations"
msgstr "Reconciliations"
+msgctxt "view:cashbook.book:"
+msgid "Description"
+msgstr "Description"
+
msgctxt "field:cashbook.book,name:"
msgid "Name"
msgstr "Name"
+msgctxt "field:cashbook.book,description:"
+msgid "Description"
+msgstr "Description"
+
msgctxt "field:cashbook.book,btype:"
msgid "Type"
msgstr "Type"
+msgctxt "help:cashbook.book,btype:"
+msgid "A cash book with type can contain postings. Without type is a view."
+msgstr "A cash book with type can contain postings. Without type is a view."
+
msgctxt "field:cashbook.book,state:"
msgid "State"
msgstr "State"
@@ -410,9 +466,9 @@ msgctxt "field:cashbook.book,currency:"
msgid "Currency"
msgstr "Currency"
-msgctxt "field:cashbook.book,start_balance:"
-msgid "Initial Amount"
-msgstr "Initial Amount"
+msgctxt "field:cashbook.book,currency_digits:"
+msgid "Currency Digits"
+msgstr "Currency Digits"
msgctxt "field:cashbook.book,start_date:"
msgid "Initial Date"
@@ -446,6 +502,22 @@ msgctxt "help:cashbook.book,number_atcheck:"
msgid "The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done."
msgstr "The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done."
+msgctxt "field:cashbook.book,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:cashbook.book,childs:"
+msgid "Children"
+msgstr "Children"
+
+msgctxt "field:cashbook.book,left:"
+msgid "Left"
+msgstr "Left"
+
+msgctxt "field:cashbook.book,right:"
+msgid "Right"
+msgstr "Right"
+
msgctxt "model:cashbook.split,name:"
msgid "Split booking line"
msgstr "Split booking line"
@@ -530,6 +602,46 @@ msgctxt "field:cashbook.split,state_cashbook:"
msgid "State of Cashbook"
msgstr "State of Cashbook"
+msgctxt "field:cashbook.split,splittype:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "help:cashbook.split,splittype:"
+msgid "Type of split booking line"
+msgstr "Type of split booking line"
+
+msgctxt "selection:cashbook.split,splittype:"
+msgid "Category"
+msgstr "Category"
+
+msgctxt "selection:cashbook.split,splittype:"
+msgid "Transfer"
+msgstr "Transfer"
+
+msgctxt "field:cashbook.split,target:"
+msgid "Target"
+msgstr "Target"
+
+msgctxt "selection:cashbook.split,target:"
+msgid "Cashbook"
+msgstr "Cashbook"
+
+msgctxt "selection:cashbook.split,target:"
+msgid "Category"
+msgstr "Category"
+
+msgctxt "field:cashbook.split,cashbook:"
+msgid "Cashbook"
+msgstr "Cashbook"
+
+msgctxt "field:cashbook.split,owner_cashbook:"
+msgid "Owner"
+msgstr "Owner"
+
+msgctxt "field:cashbook.split,booktransf:"
+msgid "Source/Dest"
+msgstr "Source/Dest"
+
msgctxt "model:cashbook.line,name:"
msgid "Cashbook Line"
msgstr "Cashbook Line"
@@ -574,6 +686,10 @@ msgctxt "field:cashbook.line,description:"
msgid "Description"
msgstr "Description"
+msgctxt "field:cashbook.line,descr_short:"
+msgid "Description"
+msgstr "Description"
+
msgctxt "field:cashbook.line,state:"
msgid "State"
msgstr "State"
@@ -870,14 +986,26 @@ msgctxt "field:cashbook.line.context,date_from:"
msgid "Start Date"
msgstr "Start Date"
+msgctxt "help:cashbook.line.context,date_from:"
+msgid "Limits the date range for the displayed entries."
+msgstr "Limits the date range for the displayed entries."
+
msgctxt "field:cashbook.line.context,date_to:"
msgid "End Date"
msgstr "End Date"
+msgctxt "help:cashbook.line.context,date_to:"
+msgid "Limits the date range for the displayed entries."
+msgstr "Limits the date range for the displayed entries."
+
msgctxt "model:cashbook.configuration,name:"
msgid "Configuration"
msgstr "Configuration"
+msgctxt "view:cashbook.configuration:"
+msgid "Enter Booking Wizard"
+msgstr "Enter Booking Wizard"
+
msgctxt "view:cashbook.configuration:"
msgid "Open Cashbook Wizard"
msgstr "Open Cashbook Wizard"
@@ -886,6 +1014,14 @@ msgctxt "view:cashbook.configuration:"
msgid "Cashbook"
msgstr "Cashbook"
+msgctxt "field:cashbook.configuration,defbook:"
+msgid "Default Cashbook"
+msgstr "Default Cashbook"
+
+msgctxt "help:cashbook.configuration,defbook:"
+msgid "The default cashbook is selected when you open the booking wizard."
+msgstr "The default cashbook is selected when you open the booking wizard."
+
msgctxt "field:cashbook.configuration,date_from:"
msgid "Start Date"
msgstr "Start Date"
@@ -954,6 +1090,14 @@ msgctxt "help:cashbook.configuration_user,catnamelong:"
msgid "Shows the long name of the category in the Category field of a cash book line."
msgstr "Shows the long name of the category in the Category field of a cash book line."
+msgctxt "field:cashbook.configuration_user,defbook:"
+msgid "Default Cashbook"
+msgstr "Default Cashbook"
+
+msgctxt "help:cashbook.configuration_user,defbook:"
+msgid "The default cashbook is selected when you open the booking wizard."
+msgstr "The default cashbook is selected when you open the booking wizard."
+
msgctxt "model:cashbook.recon,name:"
msgid "Cashbook Reconciliation"
msgstr "Cashbook Reconciliation"
@@ -1122,3 +1266,95 @@ msgctxt "report:cashbook.reprecon:"
msgid "Total"
msgstr "Total"
+msgctxt "report:cashbook.reprecon:"
+msgid "Payee"
+msgstr "Payee"
+
+msgctxt "model:cashbook.enterbooking.start,name:"
+msgid "Enter Booking"
+msgstr "Enter Booking"
+
+msgctxt "view:cashbook.enterbooking.start:"
+msgid "Description"
+msgstr "Description"
+
+msgctxt "view:cashbook.enterbooking.start:"
+msgid "Booking"
+msgstr "Booking"
+
+msgctxt "field:cashbook.enterbooking.start,cashbook:"
+msgid "Cashbook"
+msgstr "Cashbook"
+
+msgctxt "field:cashbook.enterbooking.start,cashbooks:"
+msgid "Cashbooks"
+msgstr "Cashbooks"
+
+msgctxt "field:cashbook.enterbooking.start,currency_digits:"
+msgid "Currency Digits"
+msgstr "Currency Digits"
+
+msgctxt "field:cashbook.enterbooking.start,currency:"
+msgid "Currency"
+msgstr "Currency"
+
+msgctxt "field:cashbook.enterbooking.start,bookingtype:"
+msgid "Type"
+msgstr "Type"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Revenue"
+msgstr "Revenue"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Revenue Splitbooking"
+msgstr "Revenue Splitbooking"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Expense"
+msgstr "Expense"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Expense Splitbooking"
+msgstr "Expense Splitbooking"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Transfer from"
+msgstr "Transfer from"
+
+msgctxt "selection:cashbook.enterbooking.start,bookingtype:"
+msgid "Transfer to"
+msgstr "Transfer to"
+
+msgctxt "field:cashbook.enterbooking.start,amount:"
+msgid "Amount"
+msgstr "Amount"
+
+msgctxt "field:cashbook.enterbooking.start,owner_cashbook:"
+msgid "Owner"
+msgstr "Owner"
+
+msgctxt "field:cashbook.enterbooking.start,category:"
+msgid "Category"
+msgstr "Category"
+
+msgctxt "field:cashbook.enterbooking.start,booktransf:"
+msgid "Source/Dest"
+msgstr "Source/Dest"
+
+msgctxt "field:cashbook.enterbooking.start,party:"
+msgid "Party"
+msgstr "Party"
+
+msgctxt "model:cashbook.enterbooking,name:"
+msgid "Enter Booking"
+msgstr "Enter Booking"
+
+msgctxt "wizard_button:cashbook.enterbooking,start,end:"
+msgid "Cancel"
+msgstr "Cancel"
+
+msgctxt "wizard_button:cashbook.enterbooking,start,save_:"
+msgid "Save"
+msgstr "Save"
+
diff --git a/menu.xml b/menu.xml
index c37eb13..f05d611 100644
--- a/menu.xml
+++ b/menu.xml
@@ -56,10 +56,23 @@ full copyright notices and license terms. -->
+
+
+
+
+
+ parent="menu_cashbook" sequence="30"/>
+
+
+
+
+ parent="menu_booktree" sequence="10"/>