diff --git a/README.rst b/README.rst
index 97408f7..2b72d75 100644
--- a/README.rst
+++ b/README.rst
@@ -14,6 +14,36 @@ Requires
Changes
=======
+*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..2adfb4f 100644
--- a/book.py
+++ b/book.py
@@ -76,14 +76,16 @@ class Book(Workflow, ModelSQL, ModelView):
),
}, depends=DEPENDS+['lines'])
start_balance = fields.Numeric(string='Initial Amount', required=True,
+ digits=(16, Eval('currency_digits', 2)),
states={
'readonly': Or(
STATES['readonly'],
Bool(Eval('lines')),
),
- }, depends=DEPENDS+['lines'])
- balance = fields.Function(fields.Numeric(string='Balance', readonly=True),
- 'on_change_with_balance')
+ }, depends=DEPENDS+['lines', 'currency_digits'])
+ 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', required=True,
model_name='currency.currency',
states={
@@ -92,6 +94,8 @@ class Book(Workflow, ModelSQL, ModelView):
Bool(Eval('lines', [])),
),
}, depends=DEPENDS+['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')
@@ -196,6 +200,15 @@ class Book(Workflow, ModelSQL, ModelView):
'state': self.state_string,
}
+ @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', 'start_balance')
def on_change_with_balance(self, name=None):
""" compute balance
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..e8de3b6 100644
--- a/configuration.py
+++ b/configuration.py
@@ -15,6 +15,9 @@ 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')
class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin):
@@ -36,6 +39,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 +48,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 +86,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..8e0f17f 100644
--- a/line.py
+++ b/line.py
@@ -57,8 +57,10 @@ class Line(Workflow, ModelSQL, ModelView):
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={
@@ -89,7 +91,8 @@ class Line(Workflow, ModelSQL, ModelView):
STATES['readonly'],
Eval('bookingtype', '').in_(['spin', 'spout']),
),
- }, depends=DEPENDS+['currency_digits', 'bookingtype'])
+ }, depends=DEPENDS+['currency_digits', 'bookingtype'],
+ domain=[('amount', '>=', Decimal('0.0'))])
debit = fields.Numeric(string='Debit', digits=(16, Eval('currency_digits', 2)),
required=True, readonly=True, depends=['currency_digits'])
credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)),
@@ -181,6 +184,9 @@ class Line(Workflow, ModelSQL, ModelView):
('state_val',
Check(t, t.state.in_(['edit', 'check', 'done'])),
'cashbook.msg_line_wrong_state_value'),
+ ('amount_val',
+ Check(t, t.amount >= Decimal('0.0')),
+ 'cashbook.msg_line_must_positive'),
])
cls._transitions |= set((
('edit', 'check'),
@@ -345,7 +351,11 @@ class Line(Workflow, ModelSQL, ModelView):
def search_rec_name(cls, name, clause):
""" search in description +...
"""
- return [('description',) + tuple(clause[1:])]
+ l1 = cls.search_payee(name, clause) + [
+ ('description',) + tuple(clause[1:]),
+ ('category.rec_name',) + tuple(clause[1:]),
+ ]
+ return l1
def get_rec_name(self, name):
""" short + name
@@ -414,6 +424,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 +471,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 +504,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]
+
@fields.depends('party', 'booktransf', 'bookingtype')
def on_change_with_payee(self, name=None):
""" get party or cashbook
@@ -549,7 +579,8 @@ class Line(Workflow, ModelSQL, ModelView):
@fields.depends('id', 'date', 'cashbook', \
'_parent_cashbook.start_balance', '_parent_cashbook.id',\
- 'reconciliation', '_parent_reconciliation.start_amount')
+ '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,6 +589,30 @@ 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),
@@ -567,22 +622,22 @@ class Line(Workflow, ModelSQL, ModelView):
# 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:
@@ -722,7 +777,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',
@@ -848,12 +903,14 @@ class LineContext(ModelView):
'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')),
diff --git a/locale/de.po b/locale/de.po
index 073d916..71403b9 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -150,6 +150,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_line_must_positive"
+msgid "The amount must be positive."
+msgstr "Der Betrag muß positiv sein."
+
#############
# res.group #
@@ -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 #
@@ -302,6 +310,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 +330,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,6 +418,14 @@ 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 "Balance"
+msgstr "Saldo"
+
msgctxt "view:cashbook.book:"
msgid "Reconciliations"
msgstr "Abstimmungen"
@@ -446,6 +482,10 @@ msgctxt "field:cashbook.book,currency:"
msgid "Currency"
msgstr "Währung"
+msgctxt "field:cashbook.book,currency_digits:"
+msgid "Currency Digits"
+msgstr "Nachkommastellen Währung"
+
msgctxt "field:cashbook.book,start_balance:"
msgid "Initial Amount"
msgstr "Anfangsbetrag"
@@ -618,6 +658,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 +978,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 +998,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 +1010,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 +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 "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 +1281,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 "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,balance:"
+msgid "Balance"
+msgstr "Saldo"
+
+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..49684f9 100644
--- a/locale/en.po
+++ b/locale/en.po
@@ -146,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 "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
+msgctxt "model:ir.message,text:msg_line_must_positive"
+msgid "The amount must be positive."
+msgstr "The amount must be positive."
+
msgctxt "model:res.group,name:group_cashbook"
msgid "Cashbook"
msgstr "Cashbook"
@@ -294,6 +298,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,6 +374,14 @@ 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 "Balance"
+msgstr "Balance"
+
msgctxt "view:cashbook.book:"
msgid "Reconciliations"
msgstr "Reconciliations"
@@ -410,6 +438,10 @@ msgctxt "field:cashbook.book,currency:"
msgid "Currency"
msgstr "Currency"
+msgctxt "field:cashbook.book,currency_digits:"
+msgid "Currency Digits"
+msgstr "Currency Digits"
+
msgctxt "field:cashbook.book,start_balance:"
msgid "Initial Amount"
msgstr "Initial Amount"
@@ -574,6 +606,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,10 +906,18 @@ 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"
diff --git a/menu.xml b/menu.xml
index c37eb13..d4c8a1b 100644
--- a/menu.xml
+++ b/menu.xml
@@ -56,10 +56,23 @@ full copyright notices and license terms. -->
+
+
+
+
+
+ parent="menu_cashbook" sequence="30"/>