book: hierarchie + test
book: Feld 'start_balance' entfernt
This commit is contained in:
parent
e10616e847
commit
a2e7f192f8
16 changed files with 319 additions and 168 deletions
140
book.py
140
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,15 @@ 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,
|
||||
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=STATES, depends=DEPENDS)
|
||||
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 +70,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,41 +81,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,
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
states={
|
||||
'readonly': Or(
|
||||
STATES['readonly'],
|
||||
Bool(Eval('lines')),
|
||||
),
|
||||
}, depends=DEPENDS+['lines', 'currency_digits'])
|
||||
'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', required=True,
|
||||
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__()
|
||||
|
@ -131,16 +162,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
|
||||
|
@ -193,12 +226,15 @@ 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('currency')
|
||||
def on_change_with_currency_digits(self, name=None):
|
||||
|
@ -209,28 +245,36 @@ class Book(Workflow, ModelSQL, ModelView):
|
|||
else:
|
||||
return 2
|
||||
|
||||
@fields.depends('id', 'start_balance')
|
||||
@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
|
||||
|
@ -263,12 +307,6 @@ 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:
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_book_err_startamount_with_lines',
|
||||
bookname = book.rec_name,
|
||||
))
|
||||
if book.state != 'open':
|
||||
# allow state-update, if its the only action
|
||||
if not (('state' in values.keys()) and (len(values.keys()) == 1)):
|
||||
|
|
74
book.xml
74
book.xml
|
@ -12,6 +12,13 @@ full copyright notices and license terms. -->
|
|||
<field name="priority" eval="10"/>
|
||||
<field name="name">book_list</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="book_view_tree">
|
||||
<field name="model">cashbook.book</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="field_childs">childs</field>
|
||||
<field name="name">book_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="book_view_form">
|
||||
<field name="model">cashbook.book</field>
|
||||
<field name="type">form</field>
|
||||
|
@ -19,7 +26,7 @@ full copyright notices and license terms. -->
|
|||
<field name="name">book_form</field>
|
||||
</record>
|
||||
|
||||
<!-- action view-->
|
||||
<!-- action view - list -->
|
||||
<record model="ir.action.act_window" id="act_book_view">
|
||||
<field name="name">Cashbook</field>
|
||||
<field name="res_model">cashbook.book</field>
|
||||
|
@ -35,6 +42,23 @@ full copyright notices and license terms. -->
|
|||
<field name="act_window" ref="act_book_view"/>
|
||||
</record>
|
||||
|
||||
<!-- action view - tree -->
|
||||
<record model="ir.action.act_window" id="act_book_tree">
|
||||
<field name="name">Cashbook</field>
|
||||
<field name="res_model">cashbook.book</field>
|
||||
<field name="domain" eval="[('parent', '=', None)]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_book_tree-1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="book_view_tree"/>
|
||||
<field name="act_window" ref="act_book_tree"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_book_tree-2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="book_view_form"/>
|
||||
<field name="act_window" ref="act_book_tree"/>
|
||||
</record>
|
||||
|
||||
<!-- permission -->
|
||||
<!-- anon: deny all -->
|
||||
<record model="ir.model.access" id="access_book-anon">
|
||||
|
@ -251,18 +275,24 @@ full copyright notices and license terms. -->
|
|||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-start_balance-anon">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'start_balance')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-currency-anon">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-parent-anon">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'parent')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-childs-anon">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'childs')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- field-access - group_cashbook_admin -->
|
||||
<record model="ir.model.field.access" id="fa_book-company-group_cashbook_admin">
|
||||
|
@ -335,16 +365,23 @@ full copyright notices and license terms. -->
|
|||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-start_balance-group_cashbook_admin">
|
||||
<record model="ir.model.field.access" id="fa_book-currency-group_cashbook_admin">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'start_balance')]"/>
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
||||
<field name="group" ref="group_cashbook_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-currency-group_cashbook_admin">
|
||||
<record model="ir.model.field.access" id="fa_book-parent-group_cashbook_admin">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'parent')]"/>
|
||||
<field name="group" ref="group_cashbook_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-childs-group_cashbook_admin">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'childs')]"/>
|
||||
<field name="group" ref="group_cashbook_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
|
@ -421,16 +458,23 @@ full copyright notices and license terms. -->
|
|||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-start_balance-group_cashbook">
|
||||
<record model="ir.model.field.access" id="fa_book-currency-group_cashbook">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'start_balance')]"/>
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
||||
<field name="group" ref="group_cashbook"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-currency-group_cashbook">
|
||||
<record model="ir.model.field.access" id="fa_book-parent-group_cashbook">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'parent')]"/>
|
||||
<field name="group" ref="group_cashbook"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access" id="fa_book-childs-group_cashbook">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'childs')]"/>
|
||||
<field name="group" ref="group_cashbook"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
|
|
9
line.py
9
line.py
|
@ -51,7 +51,8 @@ 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),
|
||||
|
@ -607,8 +608,8 @@ 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,
|
||||
|
@ -646,7 +647,7 @@ class Line(Workflow, ModelSQL, ModelView):
|
|||
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
|
||||
|
|
40
locale/de.po
40
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."
|
||||
|
@ -258,6 +254,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"
|
||||
|
@ -286,6 +286,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"
|
||||
|
@ -418,6 +422,10 @@ 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"
|
||||
|
@ -434,6 +442,10 @@ 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"
|
||||
|
@ -482,10 +494,6 @@ msgctxt "field:cashbook.book,currency_digits:"
|
|||
msgid "Currency Digits"
|
||||
msgstr "Nachkommastellen Währung"
|
||||
|
||||
msgctxt "field:cashbook.book,start_balance:"
|
||||
msgid "Initial Amount"
|
||||
msgstr "Anfangsbetrag"
|
||||
|
||||
msgctxt "field:cashbook.book,start_date:"
|
||||
msgid "Initial Date"
|
||||
msgstr "Anfangsdatum"
|
||||
|
@ -518,6 +526,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 #
|
||||
|
|
40
locale/en.po
40
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'."
|
||||
|
@ -242,6 +238,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"
|
||||
|
@ -266,6 +266,10 @@ 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"
|
||||
|
@ -382,6 +386,10 @@ 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"
|
||||
|
@ -398,6 +406,10 @@ 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"
|
||||
|
@ -446,10 +458,6 @@ msgctxt "field:cashbook.book,currency_digits:"
|
|||
msgid "Currency Digits"
|
||||
msgstr "Currency Digits"
|
||||
|
||||
msgctxt "field:cashbook.book,start_balance:"
|
||||
msgid "Initial Amount"
|
||||
msgstr "Initial Amount"
|
||||
|
||||
msgctxt "field:cashbook.book,start_date:"
|
||||
msgid "Initial Date"
|
||||
msgstr "Initial Date"
|
||||
|
@ -482,6 +490,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"
|
||||
|
|
14
menu.xml
14
menu.xml
|
@ -83,9 +83,21 @@ full copyright notices and license terms. -->
|
|||
</record>
|
||||
|
||||
<!-- menu: /Cashbook/Cashbook -->
|
||||
<menuitem id="menu_booktree" action="act_book_tree"
|
||||
icon="tryton-tree"
|
||||
parent="menu_cashbook" sequence="40"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_booktree-group_cashbook">
|
||||
<field name="menu" ref="menu_booktree"/>
|
||||
<field name="group" ref="group_cashbook"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu-res.group" id="menu_booktree-group_cashbook_admin">
|
||||
<field name="menu" ref="menu_booktree"/>
|
||||
<field name="group" ref="group_cashbook_admin"/>
|
||||
</record>
|
||||
<!-- menu: /Cashbook/Cashbook/Cashbook -->
|
||||
<menuitem id="menu_booklist" action="act_book_view"
|
||||
icon="tryton-list"
|
||||
parent="menu_cashbook" sequence="40"/>
|
||||
parent="menu_booktree" sequence="10"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_booklist-group_cashbook">
|
||||
<field name="menu" ref="menu_booklist"/>
|
||||
<field name="group" ref="group_cashbook"/>
|
||||
|
|
|
@ -53,9 +53,6 @@ full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_category_type_not_like_parent">
|
||||
<field name="text">The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_book_err_startamount_with_lines">
|
||||
<field name="text">The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_line_deny_recon_by_state">
|
||||
<field name="text">For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'.</field>
|
||||
</record>
|
||||
|
|
|
@ -226,7 +226,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
|||
))
|
||||
values['start_amount'] = reconciliation.predecessor.end_amount
|
||||
else :
|
||||
values['start_amount'] = reconciliation.cashbook.start_balance
|
||||
values['start_amount'] = Decimal('0.0')
|
||||
values['end_amount'] = values['start_amount']
|
||||
|
||||
# add 'checked'-lines to reconciliation
|
||||
|
|
|
@ -51,10 +51,37 @@ class BookTestCase(ModuleTestCase):
|
|||
'number_sequ': self.prep_sequence().id,
|
||||
}])
|
||||
self.assertEqual(book.name, 'Book 1')
|
||||
self.assertEqual(book.rec_name, 'Book 1 | 0.00 usd | Open')
|
||||
self.assertEqual(book.btype.rec_name, 'CAS - Cash')
|
||||
self.assertEqual(book.state, 'open')
|
||||
self.assertEqual(book.state_string, 'Open')
|
||||
|
||||
@with_transaction()
|
||||
def test_book_create_hierarchy(self):
|
||||
""" create cashbook, hierarchical
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
|
||||
types = self.prep_type()
|
||||
company = self.prep_company()
|
||||
book, = Book.create([{
|
||||
'name': 'Level 1',
|
||||
'btype': None,
|
||||
'company': company.id,
|
||||
'childs': [('create', [{
|
||||
'name': 'Level 2',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
}])],
|
||||
}])
|
||||
self.assertEqual(book.name, 'Level 1')
|
||||
self.assertEqual(book.rec_name, 'Level 1')
|
||||
self.assertEqual(len(book.childs), 1)
|
||||
self.assertEqual(book.childs[0].rec_name, 'Level 1/Level 2 | 0.00 usd | Open')
|
||||
|
||||
@with_transaction()
|
||||
def test_book_deny_delete_open(self):
|
||||
""" create cashbook, add lines, try to delete in state 'open'
|
||||
|
@ -225,62 +252,6 @@ class BookTestCase(ModuleTestCase):
|
|||
},
|
||||
])
|
||||
|
||||
@with_transaction()
|
||||
def test_book_deny_update_start_amount(self):
|
||||
""" create cashbook, add lines, update start-amount
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
|
||||
types = self.prep_type()
|
||||
company = self.prep_company()
|
||||
category = self.prep_category(cattype='in')
|
||||
party = self.prep_party()
|
||||
book, = Book.create([{
|
||||
'name': 'Book 1',
|
||||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
}])
|
||||
self.assertEqual(book.name, 'Book 1')
|
||||
self.assertEqual(book.start_balance, Decimal('0.0'))
|
||||
self.assertEqual(book.rec_name, 'Book 1 | 0.00 usd | Open')
|
||||
|
||||
Book.write(*[
|
||||
[book],
|
||||
{
|
||||
'start_balance': Decimal('1.0'),
|
||||
}])
|
||||
self.assertEqual(book.start_balance, Decimal('1.0'))
|
||||
self.assertEqual(book.balance, Decimal('1.0'))
|
||||
|
||||
Book.write(*[
|
||||
[book],
|
||||
{
|
||||
'lines': [('create', [{
|
||||
'amount': Decimal('2.0'),
|
||||
'description': 'Test',
|
||||
'category': category.id,
|
||||
'bookingtype': 'in',
|
||||
'party': party.id,
|
||||
}])],
|
||||
}])
|
||||
self.assertEqual(book.start_balance, Decimal('1.0'))
|
||||
self.assertEqual(book.balance, Decimal('3.0'))
|
||||
self.assertEqual(len(book.lines), 1)
|
||||
self.assertEqual(book.lines[0].balance, Decimal('3.0'))
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The initial amount of the cash book 'Fridas book | 3.00 usd | Open' cannot be changed because it already contains bookings.",
|
||||
Book.write,
|
||||
*[
|
||||
[book],
|
||||
{
|
||||
'start_balance': Decimal('1.5'),
|
||||
},
|
||||
])
|
||||
|
||||
@with_transaction()
|
||||
def test_book_permission_owner(self):
|
||||
""" create book + 2x users, add users to group, check access
|
||||
|
|
|
@ -39,7 +39,6 @@ class BookingWizardTestCase(ModuleTestCase):
|
|||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2022, 1, 1),
|
||||
'start_balance': Decimal('0.0'),
|
||||
}])
|
||||
|
||||
party, = Party.create([{
|
||||
|
@ -114,7 +113,6 @@ class BookingWizardTestCase(ModuleTestCase):
|
|||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2022, 1, 1),
|
||||
'start_balance': Decimal('0.0'),
|
||||
}, {
|
||||
'name': 'Bank',
|
||||
'btype': types.id,
|
||||
|
@ -122,7 +120,6 @@ class BookingWizardTestCase(ModuleTestCase):
|
|||
'currency': company.currency.id,
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'start_date': date(2022, 1, 1),
|
||||
'start_balance': Decimal('0.0'),
|
||||
}])
|
||||
|
||||
party, = Party.create([{
|
||||
|
|
|
@ -574,6 +574,36 @@ class LineTestCase(ModuleTestCase):
|
|||
self.assertEqual(book.lines[2].rec_name, '05/01/2022|Rev/Sp|1.00 usd|Text 3 [-]')
|
||||
self.assertEqual(book.lines[2].state, 'edit')
|
||||
|
||||
@with_transaction()
|
||||
def test_line_to_non_type_book(self):
|
||||
""" create cashbook w/o type
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
Line = pool.get('cashbook.line')
|
||||
|
||||
category = self.prep_category(cattype='in')
|
||||
company = self.prep_company()
|
||||
party = self.prep_party()
|
||||
book, = Book.create([{
|
||||
'name': 'Book 1',
|
||||
'btype': None,
|
||||
'company': company.id,
|
||||
}])
|
||||
self.assertEqual(book.name, 'Book 1')
|
||||
self.assertEqual(book.state, 'open')
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
'The value for field "Cashbook" in "Cashbook Line" is not valid according to its domain.',
|
||||
Line.create,
|
||||
[{
|
||||
'cashbook': book.id,
|
||||
'date': date(2022, 5, 1),
|
||||
'category': category.id,
|
||||
'bookingtype': 'in',
|
||||
'amount': Decimal('0.0'),
|
||||
}])
|
||||
|
||||
@with_transaction()
|
||||
def test_line_create_check_deny_write(self):
|
||||
""" create cashbook + line, 'close' book, write to line
|
||||
|
|
|
@ -221,7 +221,6 @@ class ReconTestCase(ModuleTestCase):
|
|||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'start_balance': Decimal('12.50'),
|
||||
'start_date': date(2022, 5, 1),
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'reconciliations': [('create', [{
|
||||
|
@ -234,7 +233,7 @@ class ReconTestCase(ModuleTestCase):
|
|||
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
|
||||
|
||||
Reconciliation.wfcheck(list(book.reconciliations))
|
||||
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 12.50 usd - 12.50 usd [0]')
|
||||
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
|
||||
|
||||
@with_transaction()
|
||||
def test_recon_set_start_amount_by_predecessor(self):
|
||||
|
@ -254,7 +253,6 @@ class ReconTestCase(ModuleTestCase):
|
|||
'btype': types.id,
|
||||
'company': company.id,
|
||||
'currency': company.currency.id,
|
||||
'start_balance': Decimal('12.50'),
|
||||
'start_date': date(2022, 5, 1),
|
||||
'number_sequ': self.prep_sequence().id,
|
||||
'reconciliations': [('create', [{
|
||||
|
@ -287,7 +285,7 @@ class ReconTestCase(ModuleTestCase):
|
|||
Reconciliation.wfcheck(list(book.reconciliations))
|
||||
|
||||
self.assertEqual(book.reconciliations[0].state, 'check')
|
||||
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 12.50 usd - 24.50 usd [2]')
|
||||
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 12.00 usd [2]')
|
||||
Reconciliation.wfdone(list(book.reconciliations))
|
||||
self.assertEqual(book.reconciliations[0].state, 'done')
|
||||
|
||||
|
@ -298,7 +296,7 @@ class ReconTestCase(ModuleTestCase):
|
|||
}])
|
||||
self.assertEqual(recons[0].rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
|
||||
Reconciliation.wfcheck(recons)
|
||||
self.assertEqual(recons[0].rec_name, '05/31/2022 - 06/30/2022 | 24.50 usd - 24.50 usd [0]')
|
||||
self.assertEqual(recons[0].rec_name, '05/31/2022 - 06/30/2022 | 12.00 usd - 12.00 usd [0]')
|
||||
|
||||
@with_transaction()
|
||||
def test_recon_predecessor_done(self):
|
||||
|
|
|
@ -15,29 +15,32 @@ full copyright notices and license terms. -->
|
|||
</group>
|
||||
</group>
|
||||
|
||||
<label name="btype"/>
|
||||
<field name="btype"/>
|
||||
<label name="balance"/>
|
||||
<field name="balance"/>
|
||||
<newline/>
|
||||
|
||||
<notebook colspan="4">
|
||||
<page id="pgrecon" string="Reconciliations" col="1">
|
||||
<page name="reconciliations" string="Reconciliations" col="1">
|
||||
<field name="reconciliations"/>
|
||||
</page>
|
||||
<page id="pggeneral" string="General Information" col="4">
|
||||
<label name="company"/>
|
||||
<field name="company"/>
|
||||
<label name="parent"/>
|
||||
<field name="parent"/>
|
||||
<field name="childs" colspan="4"/>
|
||||
</page>
|
||||
<page name="number_sequ" string="Amount and Numbering" col="4">
|
||||
<label name="number_sequ"/>
|
||||
<field name="number_sequ"/>
|
||||
<label name="number_atcheck"/>
|
||||
<field name="number_atcheck"/>
|
||||
|
||||
<label name="btype"/>
|
||||
<field name="btype"/>
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
|
||||
<label name="start_balance"/>
|
||||
<field name="start_balance"/>
|
||||
<label name="start_date"/>
|
||||
<field name="start_date"/>
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
|
||||
<label id="phaccount" colspan="2" string=" "/>
|
||||
</page>
|
||||
|
|
|
@ -5,7 +5,6 @@ full copyright notices and license terms. -->
|
|||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="btype"/>
|
||||
<field name="start_balance"/>
|
||||
<field name="balance" sum="Balance"/>
|
||||
<field name="currency"/>
|
||||
<field name="owner"/>
|
||||
|
|
14
view/book_tree.xml
Normal file
14
view/book_tree.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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. -->
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="btype"/>
|
||||
<field name="balance" sum="Balance"/>
|
||||
<field name="currency"/>
|
||||
<field name="owner"/>
|
||||
<field name="state"/>
|
||||
<field name="parent" tree_invisible="1"/>
|
||||
<field name="childs" tree_invisible="1"/>
|
||||
</tree>
|
|
@ -13,13 +13,12 @@ full copyright notices and license terms. -->
|
|||
<field name="description" colspan="5"/>
|
||||
|
||||
<notebook colspan="6">
|
||||
<page string="General Information" id="general" col="6">
|
||||
<page string="General Information" id="general" col="4">
|
||||
<label name="company"/>
|
||||
<field name="company"/>
|
||||
<label name="parent"/>
|
||||
<field name="parent"/>
|
||||
<newline/>
|
||||
<field name="childs" colspan="6"/>
|
||||
<field name="childs" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
|
||||
|
|
Loading…
Reference in a new issue