diff --git a/.hgignore b/.hgignore
index b6818de..e2b39b0 100644
--- a/.hgignore
+++ b/.hgignore
@@ -2,3 +2,5 @@ syntax: glob
build/*
mds_cashbook_bookcategory.egg-info/*
dist/*
+__pycache__/*
+locale/convert_de2en.py
diff --git a/__init__.py b/__init__.py
index e6e1377..11bfdee 100644
--- a/__init__.py
+++ b/__init__.py
@@ -4,7 +4,12 @@
# full copyright notices and license terms.
from trytond.pool import Pool
+from .category import Category
+from .book import CategoryCashbookRel, Cashbook
def register():
Pool.register(
+ Category,
+ Cashbook,
+ CategoryCashbookRel,
module='cashbook_bookcategory', type_='model')
diff --git a/book.py b/book.py
new file mode 100644
index 0000000..65f0839
--- /dev/null
+++ b/book.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+from trytond.model import ModelSQL, fields
+from trytond.transaction import Transaction
+from trytond.pool import Pool, PoolMeta
+
+
+class Cashbook(metaclass=PoolMeta):
+ __name__ = 'cashbook.book'
+
+ categories = fields.Many2Many(string='Categories',
+ relation_name='cashbook.bookcategory-rel',
+ origin='cashbook', target='category')
+
+# end Cashbook
+
+
+class CategoryCashbookRel(ModelSQL):
+ 'Category Cashbook Relation'
+ __name__ = 'cashbook.bookcategory-rel'
+
+ category = fields.Many2One(string='Category', required=True, select=True,
+ model_name='cashbook.bookcategory', ondelete='CASCADE')
+ cashbook = fields.Many2One(string='Cashbook', required=True, select=True,
+ model_name='cashbook.book', ondelete='CASCADE')
+
+# end CategoryCashbookRel
diff --git a/book.xml b/book.xml
new file mode 100644
index 0000000..12806b1
--- /dev/null
+++ b/book.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ cashbook.book
+
+ book_form
+
+
+
+
diff --git a/category.py b/category.py
new file mode 100644
index 0000000..06160cc
--- /dev/null
+++ b/category.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# This file is part of Tryton. 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, tree
+from trytond.modules.cashbook.model import order_name_hierarchical
+from trytond.transaction import Transaction
+
+
+class Category(tree(separator=' / '), ModelSQL, ModelView):
+ "Cashbook Category"
+ __name__ = "cashbook.bookcategory"
+
+ company = fields.Many2One(string='Company', model_name='company.company',
+ required=True, ondelete="RESTRICT")
+ name = fields.Char(string='Name', required=True, translate=True)
+
+ parent = fields.Many2One(string='Parent', select=True,
+ model_name='cashbook.bookcategory', ondelete='CASCADE',
+ left='left', right='right')
+ childs = fields.One2Many(string='Children', field='parent',
+ model_name='cashbook.bookcategory')
+ left = fields.Integer(string='Left', required=True, select=True)
+ right = fields.Integer(string='Right', required=True, select=True)
+
+ @classmethod
+ def __setup__(cls):
+ super(Category, cls).__setup__()
+ cls._order.insert(0, ('rec_name', 'ASC'))
+
+ @staticmethod
+ def default_left():
+ return 0
+
+ @staticmethod
+ def default_right():
+ return 0
+
+ @staticmethod
+ def default_company():
+ return Transaction().context.get('company') or None
+
+ @staticmethod
+ def order_rec_name(tables):
+ """ order by pos
+ a recursive sorting
+ """
+ return order_name_hierarchical('cashbook.bookcategory', tables)
+
+# ende Category
diff --git a/category.xml b/category.xml
new file mode 100644
index 0000000..eab3ea6
--- /dev/null
+++ b/category.xml
@@ -0,0 +1,143 @@
+
+
+
+
+ cashbook.bookcategory
+ tree
+
+ category_list
+
+
+ cashbook.bookcategory
+ tree
+
+ childs
+ category_tree
+
+
+ cashbook.bookcategory
+ form
+ category_form
+
+
+
+
+ Cashbook Category
+ cashbook.bookcategory
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Cashbook Category (List)
+ cashbook.bookcategory
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Administrators: Category read/write
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Owners: Category read/write
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ User in companies
+
+
+
+
+
+
+
+
+
+
diff --git a/locale/de.po b/locale/de.po
new file mode 100644
index 0000000..2372d4e
--- /dev/null
+++ b/locale/de.po
@@ -0,0 +1,107 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+
+#################
+# ir.rule.group #
+#################
+msgctxt "model:ir.rule.group,name:rg_category_write_adm"
+msgid "Administrators: Category read/write"
+msgstr "Administrators: Kategorie schreiben"
+
+msgctxt "model:ir.rule.group,name:rg_category_rw_owner"
+msgid "Owners: Category read/write"
+msgstr "Eigentümer: Kategorie schreiben"
+
+msgctxt "model:ir.rule.group,name:rg_category_companies"
+msgid "User in companies"
+msgstr "Benutzer im Unternehmen"
+
+
+##############
+# ir.ui.menu #
+##############
+msgctxt "model:ir.ui.menu,name:menu_category_tree"
+msgid "Cashbook Category"
+msgstr "Kassenbuchkategorie"
+
+msgctxt "model:ir.ui.menu,name:menu_category_list"
+msgid "Cashbook Category (List)"
+msgstr "Kassenbuchkategorie (Liste)"
+
+
+#############
+# ir.action #
+#############
+msgctxt "model:ir.action,name:tree_category_view"
+msgid "Cashbook Category"
+msgstr "Kassenbuchkategorie"
+
+msgctxt "model:ir.action,name:list_category_view"
+msgid "Cashbook Category (List)"
+msgstr "Kassenbuchkategorie (Liste)"
+
+
+#########################
+# cashbook.bookcategory #
+#########################
+msgctxt "model:cashbook.bookcategory,name:"
+msgid "Cashbook Category"
+msgstr "Kassenbuchkategorie"
+
+msgctxt "view:cashbook.bookcategory:"
+msgid "General Information"
+msgstr "Allgemein"
+
+msgctxt "field:cashbook.bookcategory,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:cashbook.bookcategory,company:"
+msgid "Company"
+msgstr "Unternehmen"
+
+msgctxt "field:cashbook.bookcategory,parent:"
+msgid "Parent"
+msgstr "Übergeordnet"
+
+msgctxt "field:cashbook.bookcategory,childs:"
+msgid "Children"
+msgstr "Untergeordnet"
+
+msgctxt "field:cashbook.bookcategory,left:"
+msgid "Left"
+msgstr "Links"
+
+msgctxt "field:cashbook.bookcategory,right:"
+msgid "Right"
+msgstr "Rechts"
+
+
+#################
+# cashbook.book #
+#################
+msgctxt "view:cashbook.book:"
+msgid "Categories"
+msgstr "Kategorien"
+
+msgctxt "field:cashbook.book,categories:"
+msgid "Categories"
+msgstr "Kategorien"
+
+
+#############################
+# cashbook.bookcategory-rel #
+#############################
+msgctxt "model:cashbook.bookcategory-rel,name:"
+msgid "Category Cashbook Relation"
+msgstr "Kategorie Kassenbuch Verknüpfung"
+
+msgctxt "field:cashbook.bookcategory-rel,category:"
+msgid "Category"
+msgstr "Kategorie"
+
+msgctxt "field:cashbook.bookcategory-rel,cashbook:"
+msgid "Cashbook"
+msgstr "Kassenbuch"
diff --git a/locale/en.po b/locale/en.po
new file mode 100644
index 0000000..97cfcf1
--- /dev/null
+++ b/locale/en.po
@@ -0,0 +1,80 @@
+#
+msgid ""
+msgstr "Content-Type: text/plain; charset=utf-8\n"
+
+msgctxt "model:ir.rule.group,name:rg_category_write_adm"
+msgid "Administrators: Category read/write"
+msgstr "Administrators: Category read/write"
+
+msgctxt "model:ir.rule.group,name:rg_category_rw_owner"
+msgid "Owners: Category read/write"
+msgstr "Owners: Category read/write"
+
+msgctxt "model:ir.rule.group,name:rg_category_companies"
+msgid "User in companies"
+msgstr "User in companies"
+
+msgctxt "model:ir.ui.menu,name:menu_category_tree"
+msgid "Cashbook Category"
+msgstr "Cashbook Category"
+
+msgctxt "model:ir.ui.menu,name:menu_category_list"
+msgid "Cashbook Category (List)"
+msgstr "Cashbook Category (List)"
+
+msgctxt "model:ir.action,name:tree_category_view"
+msgid "Cashbook Category"
+msgstr "Cashbook Category"
+
+msgctxt "model:ir.action,name:list_category_view"
+msgid "Cashbook Category (List)"
+msgstr "Cashbook Category (List)"
+
+msgctxt "model:cashbook.bookcategory,name:"
+msgid "Cashbook Category"
+msgstr "Cashbook Category"
+
+msgctxt "view:cashbook.bookcategory:"
+msgid "General Information"
+msgstr "General Information"
+
+msgctxt "field:cashbook.bookcategory,name:"
+msgid "Name"
+msgstr "Name"
+
+msgctxt "field:cashbook.bookcategory,company:"
+msgid "Company"
+msgstr "Company"
+
+msgctxt "field:cashbook.bookcategory,parent:"
+msgid "Parent"
+msgstr "Parent"
+
+msgctxt "field:cashbook.bookcategory,childs:"
+msgid "Children"
+msgstr "Children"
+
+msgctxt "field:cashbook.bookcategory,left:"
+msgid "Left"
+msgstr "Left"
+
+msgctxt "field:cashbook.bookcategory,right:"
+msgid "Right"
+msgstr "Right"
+
+msgctxt "view:cashbook.book:"
+msgid "Categories"
+msgstr "Categories"
+
+msgctxt "field:cashbook.book,categories:"
+msgid "Categories"
+msgstr "Categories"
+
+msgctxt "model:cashbook.bookcategory-rel,name:"
+msgid "Category Cashbook Relation"
+msgstr "Category Cashbook Relation"
+
+msgctxt "field:cashbook.bookcategory-rel,category:"
+msgid "Category"
+msgstr "Category"
+
diff --git a/menu.xml b/menu.xml
new file mode 100644
index 0000000..436cc5e
--- /dev/null
+++ b/menu.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..ead6f2c
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,24 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
+
+import trytond.tests.test_tryton
+import unittest
+
+from trytond.modules.cashbook_bookcategory.tests.test_category import CategoryTestCase
+
+
+__all__ = ['suite']
+
+
+class CashbookCategoryTestCase(\
+ CategoryTestCase,\
+ ):
+ 'Test cashbook module'
+ module = 'cashbook_bookcategory'
+
+# end CashbookCategoryTestCase
+
+def suite():
+ suite = trytond.tests.test_tryton.suite()
+ suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CashbookCategoryTestCase))
+ return suite
diff --git a/tests/test_category.py b/tests/test_category.py
new file mode 100644
index 0000000..8a197fc
--- /dev/null
+++ b/tests/test_category.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# This file is part of the cashbook-module from m-ds for Tryton.
+# The COPYRIGHT file at the top level of this repository contains the
+# full copyright notices and license terms.
+
+from trytond.tests.test_tryton import ModuleTestCase, with_transaction
+from trytond.pool import Pool
+from trytond.transaction import Transaction
+from trytond.exceptions import UserError
+from trytond.modules.cashbook.tests import CashbookTestCase
+
+
+class CategoryTestCase(CashbookTestCase):
+ 'Test cashbook category module'
+ module = 'cashbook_bookcategory'
+
+# end CategoryTestCase
diff --git a/tryton.cfg b/tryton.cfg
index fceac5a..ba1dc2c 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -3,3 +3,6 @@ version=6.0.0
depends:
cashbook
xml:
+ category.xml
+ book.xml
+ menu.xml
diff --git a/view/book_form.xml b/view/book_form.xml
new file mode 100644
index 0000000..c6bde97
--- /dev/null
+++ b/view/book_form.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/view/category_form.xml b/view/category_form.xml
new file mode 100644
index 0000000..5366dfc
--- /dev/null
+++ b/view/category_form.xml
@@ -0,0 +1,18 @@
+
+
+
diff --git a/view/category_list.xml b/view/category_list.xml
new file mode 100644
index 0000000..9e613dd
--- /dev/null
+++ b/view/category_list.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/view/category_tree.xml b/view/category_tree.xml
new file mode 100644
index 0000000..5cf645d
--- /dev/null
+++ b/view/category_tree.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+