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
|
# The COPYRIGHT file at the top level of this repository contains the
|
||||||
# full copyright notices and license terms.
|
# 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.pyson import Eval, Or, Bool, Id
|
||||||
from trytond.exceptions import UserError
|
from trytond.exceptions import UserError
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
@ -20,6 +20,16 @@ STATES = {
|
||||||
}
|
}
|
||||||
DEPENDS=['state']
|
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 = [
|
sel_state_book = [
|
||||||
('open', 'Open'),
|
('open', 'Open'),
|
||||||
('closed', 'Closed'),
|
('closed', 'Closed'),
|
||||||
|
@ -27,7 +37,7 @@ sel_state_book = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class Book(Workflow, ModelSQL, ModelView):
|
class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
|
||||||
'Cashbook'
|
'Cashbook'
|
||||||
__name__ = 'cashbook.book'
|
__name__ = 'cashbook.book'
|
||||||
|
|
||||||
|
@ -35,9 +45,15 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
required=True, ondelete="RESTRICT")
|
required=True, ondelete="RESTRICT")
|
||||||
name = fields.Char(string='Name', required=True,
|
name = fields.Char(string='Name', required=True,
|
||||||
states=STATES, depends=DEPENDS)
|
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',
|
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,
|
owner = fields.Many2One(string='Owner', required=True, select=True,
|
||||||
model_name='res.user', ondelete='SET NULL',
|
model_name='res.user', ondelete='SET NULL',
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
|
@ -54,8 +70,8 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
reconciliations = fields.One2Many(string='Reconciliations',
|
reconciliations = fields.One2Many(string='Reconciliations',
|
||||||
field='cashbook', model_name='cashbook.recon',
|
field='cashbook', model_name='cashbook.recon',
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES2, depends=DEPENDS2)
|
||||||
number_sequ = fields.Many2One(string='Line numbering', required=True,
|
number_sequ = fields.Many2One(string='Line numbering',
|
||||||
help='Number sequence for numbering of the cash book lines.',
|
help='Number sequence for numbering of the cash book lines.',
|
||||||
model_name='ir.sequence',
|
model_name='ir.sequence',
|
||||||
domain=[
|
domain=[
|
||||||
|
@ -65,41 +81,56 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
('company', '=', Eval('company', -1)),
|
('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'",
|
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.")
|
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,
|
states=STATES2, depends=DEPENDS2)
|
||||||
|
start_date = fields.Date(string='Initial Date',
|
||||||
states={
|
states={
|
||||||
'readonly': Or(
|
'readonly': Or(
|
||||||
STATES['readonly'],
|
STATES2['readonly'],
|
||||||
Bool(Eval('lines')),
|
Bool(Eval('lines')),
|
||||||
),
|
),
|
||||||
}, depends=DEPENDS+['lines'])
|
'invisible': STATES2['invisible'],
|
||||||
start_balance = fields.Numeric(string='Initial Amount', required=True,
|
'required': Bool(Eval('btype')),
|
||||||
digits=(16, Eval('currency_digits', 2)),
|
}, depends=DEPENDS2+['lines'])
|
||||||
states={
|
|
||||||
'readonly': Or(
|
|
||||||
STATES['readonly'],
|
|
||||||
Bool(Eval('lines')),
|
|
||||||
),
|
|
||||||
}, depends=DEPENDS+['lines', 'currency_digits'])
|
|
||||||
balance = fields.Function(fields.Numeric(string='Balance', readonly=True,
|
balance = fields.Function(fields.Numeric(string='Balance', readonly=True,
|
||||||
digits=(16, Eval('currency_digits', 2)),
|
digits=(16, Eval('currency_digits', 2)),
|
||||||
depends=['currency_digits']), 'on_change_with_balance')
|
depends=['currency_digits']), 'on_change_with_balance')
|
||||||
currency = fields.Many2One(string='Currency', required=True,
|
currency = fields.Many2One(string='Currency',
|
||||||
model_name='currency.currency',
|
model_name='currency.currency',
|
||||||
states={
|
states={
|
||||||
'readonly': Or(
|
'readonly': Or(
|
||||||
STATES['readonly'],
|
STATES2['readonly'],
|
||||||
Bool(Eval('lines', [])),
|
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',
|
currency_digits = fields.Function(fields.Integer(string='Currency Digits',
|
||||||
readonly=True), 'on_change_with_currency_digits')
|
readonly=True), 'on_change_with_currency_digits')
|
||||||
state = fields.Selection(string='State', required=True,
|
state = fields.Selection(string='State', required=True,
|
||||||
readonly=True, selection=sel_state_book)
|
readonly=True, selection=sel_state_book)
|
||||||
state_string = state.translated('state')
|
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
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(Book, cls).__setup__()
|
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
|
@classmethod
|
||||||
def default_number_atcheck(cls):
|
def default_number_atcheck(cls):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def default_start_balance(cls):
|
|
||||||
""" zero
|
|
||||||
"""
|
|
||||||
return Decimal('0.0')
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_currency(cls):
|
def default_currency(cls):
|
||||||
""" currency of company
|
""" currency of company
|
||||||
|
@ -193,12 +226,15 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
def get_rec_name(self, name):
|
def get_rec_name(self, name):
|
||||||
""" name, balance, state
|
""" name, balance, state
|
||||||
"""
|
"""
|
||||||
return '%(name)s | %(balance)s %(symbol)s | %(state)s' % {
|
recname = super(Book, self).get_rec_name(name)
|
||||||
'name': self.name or '-',
|
if self.btype:
|
||||||
'balance': Report.format_number(self.balance or 0.0, None),
|
return '%(name)s | %(balance)s %(symbol)s | %(state)s' % {
|
||||||
'symbol': getattr(self.currency, 'symbol', '-'),
|
'name': recname or '-',
|
||||||
'state': self.state_string,
|
'balance': Report.format_number(self.balance or 0.0, None),
|
||||||
}
|
'symbol': getattr(self.currency, 'symbol', '-'),
|
||||||
|
'state': self.state_string,
|
||||||
|
}
|
||||||
|
return recname
|
||||||
|
|
||||||
@fields.depends('currency')
|
@fields.depends('currency')
|
||||||
def on_change_with_currency_digits(self, name=None):
|
def on_change_with_currency_digits(self, name=None):
|
||||||
|
@ -209,28 +245,36 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
else:
|
else:
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
@fields.depends('id', 'start_balance')
|
@fields.depends('id')
|
||||||
def on_change_with_balance(self, name=None):
|
def on_change_with_balance(self, name=None):
|
||||||
""" compute balance
|
""" compute balance
|
||||||
"""
|
"""
|
||||||
Line = Pool().get('cashbook.line')
|
pool = Pool()
|
||||||
|
Book2 = pool.get('cashbook.book')
|
||||||
|
Line = pool.get('cashbook.line')
|
||||||
tab_line = Line.__table__()
|
tab_line = Line.__table__()
|
||||||
cursor = Transaction().connection.cursor()
|
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'),
|
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.id:
|
||||||
if self.start_balance is not None:
|
balance = Decimal('0.0')
|
||||||
balance = self.start_balance
|
cursor.execute(*query)
|
||||||
cursor.execute(*query)
|
result = cursor.fetchone()
|
||||||
result = cursor.fetchone()
|
if result:
|
||||||
if result:
|
if result[0] is not None:
|
||||||
balance += result[0]
|
balance += result[0]
|
||||||
return balance
|
return balance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ModelView.button
|
@ModelView.button
|
||||||
|
@ -263,12 +307,6 @@ class Book(Workflow, ModelSQL, ModelView):
|
||||||
actions = iter(args)
|
actions = iter(args)
|
||||||
for books, values in zip(actions, actions):
|
for books, values in zip(actions, actions):
|
||||||
for book in books:
|
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':
|
if book.state != 'open':
|
||||||
# allow state-update, if its the only action
|
# allow state-update, if its the only action
|
||||||
if not (('state' in values.keys()) and (len(values.keys()) == 1)):
|
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="priority" eval="10"/>
|
||||||
<field name="name">book_list</field>
|
<field name="name">book_list</field>
|
||||||
</record>
|
</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">
|
<record model="ir.ui.view" id="book_view_form">
|
||||||
<field name="model">cashbook.book</field>
|
<field name="model">cashbook.book</field>
|
||||||
<field name="type">form</field>
|
<field name="type">form</field>
|
||||||
|
@ -19,7 +26,7 @@ full copyright notices and license terms. -->
|
||||||
<field name="name">book_form</field>
|
<field name="name">book_form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- action view-->
|
<!-- action view - list -->
|
||||||
<record model="ir.action.act_window" id="act_book_view">
|
<record model="ir.action.act_window" id="act_book_view">
|
||||||
<field name="name">Cashbook</field>
|
<field name="name">Cashbook</field>
|
||||||
<field name="res_model">cashbook.book</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"/>
|
<field name="act_window" ref="act_book_view"/>
|
||||||
</record>
|
</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 -->
|
<!-- permission -->
|
||||||
<!-- anon: deny all -->
|
<!-- anon: deny all -->
|
||||||
<record model="ir.model.access" id="access_book-anon">
|
<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_read" eval="False"/>
|
||||||
<field name="perm_write" eval="False"/>
|
<field name="perm_write" eval="False"/>
|
||||||
</record>
|
</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">
|
<record model="ir.model.field.access" id="fa_book-currency-anon">
|
||||||
<field name="field"
|
<field name="field"
|
||||||
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
search="[('model.model', '=', 'cashbook.book'), ('name', '=', 'currency')]"/>
|
||||||
<field name="perm_read" eval="False"/>
|
<field name="perm_read" eval="False"/>
|
||||||
<field name="perm_write" eval="False"/>
|
<field name="perm_write" eval="False"/>
|
||||||
</record>
|
</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 -->
|
<!-- field-access - group_cashbook_admin -->
|
||||||
<record model="ir.model.field.access" id="fa_book-company-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_read" eval="True"/>
|
||||||
<field name="perm_write" eval="True"/>
|
<field name="perm_write" eval="True"/>
|
||||||
</record>
|
</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"
|
<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="group" ref="group_cashbook_admin"/>
|
||||||
<field name="perm_read" eval="True"/>
|
<field name="perm_read" eval="True"/>
|
||||||
<field name="perm_write" eval="True"/>
|
<field name="perm_write" eval="True"/>
|
||||||
</record>
|
</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"
|
<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="group" ref="group_cashbook_admin"/>
|
||||||
<field name="perm_read" eval="True"/>
|
<field name="perm_read" eval="True"/>
|
||||||
<field name="perm_write" 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_read" eval="True"/>
|
||||||
<field name="perm_write" eval="False"/>
|
<field name="perm_write" eval="False"/>
|
||||||
</record>
|
</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"
|
<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="group" ref="group_cashbook"/>
|
||||||
<field name="perm_read" eval="True"/>
|
<field name="perm_read" eval="True"/>
|
||||||
<field name="perm_write" eval="False"/>
|
<field name="perm_write" eval="False"/>
|
||||||
</record>
|
</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"
|
<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="group" ref="group_cashbook"/>
|
||||||
<field name="perm_read" eval="True"/>
|
<field name="perm_read" eval="True"/>
|
||||||
<field name="perm_write" eval="False"/>
|
<field name="perm_write" eval="False"/>
|
||||||
|
|
9
line.py
9
line.py
|
@ -51,7 +51,8 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
__name__ = 'cashbook.line'
|
__name__ = 'cashbook.line'
|
||||||
|
|
||||||
cashbook = fields.Many2One(string='Cashbook', required=True, select=True,
|
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,
|
date = fields.Date(string='Date', required=True, select=True,
|
||||||
states=STATES, depends=DEPENDS)
|
states=STATES, depends=DEPENDS)
|
||||||
month = fields.Function(fields.Integer(string='Month', readonly=True),
|
month = fields.Function(fields.Integer(string='Month', readonly=True),
|
||||||
|
@ -607,8 +608,8 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
@fields.depends('id', 'date', 'cashbook', \
|
@fields.depends('id', 'date', 'cashbook', \
|
||||||
'_parent_cashbook.start_balance', '_parent_cashbook.id',\
|
'_parent_cashbook.id', 'reconciliation', \
|
||||||
'reconciliation', '_parent_reconciliation.start_amount',
|
'_parent_reconciliation.start_amount',\
|
||||||
'_parent_reconciliation.state')
|
'_parent_reconciliation.state')
|
||||||
def on_change_with_balance(self, name=None):
|
def on_change_with_balance(self, name=None):
|
||||||
""" compute balance until current line, with current sort order,
|
""" compute balance until current line, with current sort order,
|
||||||
|
@ -646,7 +647,7 @@ class Line(Workflow, ModelSQL, ModelView):
|
||||||
query = [
|
query = [
|
||||||
('cashbook.id', '=', self.cashbook.id),
|
('cashbook.id', '=', self.cashbook.id),
|
||||||
]
|
]
|
||||||
balance = self.cashbook.start_balance
|
balance = Decimal('0.0')
|
||||||
|
|
||||||
# get existing reconciliation, starting before current line
|
# get existing reconciliation, starting before current line
|
||||||
# this will speed up calculation of by-line-balance
|
# 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'."
|
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."
|
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"
|
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'."
|
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."
|
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"
|
msgid "Cashbook"
|
||||||
msgstr "Kassenbuch"
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_booktree"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
msgctxt "model:ir.ui.menu,name:menu_open_lines"
|
msgctxt "model:ir.ui.menu,name:menu_open_lines"
|
||||||
msgid "Open Cashbook"
|
msgid "Open Cashbook"
|
||||||
msgstr "Kassenbuch öffnen"
|
msgstr "Kassenbuch öffnen"
|
||||||
|
@ -286,6 +286,10 @@ msgctxt "model:ir.action,name:act_book_view"
|
||||||
msgid "Cashbook"
|
msgid "Cashbook"
|
||||||
msgstr "Kassenbuch"
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:act_book_tree"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Kassenbuch"
|
||||||
|
|
||||||
msgctxt "model:ir.action,name:act_type_view"
|
msgctxt "model:ir.action,name:act_type_view"
|
||||||
msgid "Cashbook Type"
|
msgid "Cashbook Type"
|
||||||
msgstr "Kassenbuchtyp"
|
msgstr "Kassenbuchtyp"
|
||||||
|
@ -418,6 +422,10 @@ msgctxt "view:cashbook.book:"
|
||||||
msgid "General Information"
|
msgid "General Information"
|
||||||
msgstr "Allgemein"
|
msgstr "Allgemein"
|
||||||
|
|
||||||
|
msgctxt "view:cashbook.book:"
|
||||||
|
msgid "Amount and Numbering"
|
||||||
|
msgstr "Betrag und Nummerierung"
|
||||||
|
|
||||||
msgctxt "view:cashbook.book:"
|
msgctxt "view:cashbook.book:"
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr "Saldo"
|
msgstr "Saldo"
|
||||||
|
@ -434,6 +442,10 @@ msgctxt "field:cashbook.book,btype:"
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Typ"
|
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:"
|
msgctxt "field:cashbook.book,state:"
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Status"
|
msgstr "Status"
|
||||||
|
@ -482,10 +494,6 @@ msgctxt "field:cashbook.book,currency_digits:"
|
||||||
msgid "Currency Digits"
|
msgid "Currency Digits"
|
||||||
msgstr "Nachkommastellen Währung"
|
msgstr "Nachkommastellen Währung"
|
||||||
|
|
||||||
msgctxt "field:cashbook.book,start_balance:"
|
|
||||||
msgid "Initial Amount"
|
|
||||||
msgstr "Anfangsbetrag"
|
|
||||||
|
|
||||||
msgctxt "field:cashbook.book,start_date:"
|
msgctxt "field:cashbook.book,start_date:"
|
||||||
msgid "Initial Date"
|
msgid "Initial Date"
|
||||||
msgstr "Anfangsdatum"
|
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."
|
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'."
|
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 #
|
# 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'."
|
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'."
|
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"
|
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'."
|
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'."
|
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"
|
msgid "Cashbook"
|
||||||
msgstr "Cashbook"
|
msgstr "Cashbook"
|
||||||
|
|
||||||
|
msgctxt "model:ir.ui.menu,name:menu_booktree"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Cashbook"
|
||||||
|
|
||||||
msgctxt "model:ir.ui.menu,name:menu_open_lines"
|
msgctxt "model:ir.ui.menu,name:menu_open_lines"
|
||||||
msgid "Open Cashbook"
|
msgid "Open Cashbook"
|
||||||
msgstr "Open Cashbook"
|
msgstr "Open Cashbook"
|
||||||
|
@ -266,6 +266,10 @@ msgctxt "model:ir.action,name:act_book_view"
|
||||||
msgid "Cashbook"
|
msgid "Cashbook"
|
||||||
msgstr "Cashbook"
|
msgstr "Cashbook"
|
||||||
|
|
||||||
|
msgctxt "model:ir.action,name:act_book_tree"
|
||||||
|
msgid "Cashbook"
|
||||||
|
msgstr "Cashbook"
|
||||||
|
|
||||||
msgctxt "model:ir.action,name:act_type_view"
|
msgctxt "model:ir.action,name:act_type_view"
|
||||||
msgid "Cashbook Type"
|
msgid "Cashbook Type"
|
||||||
msgstr "Cashbook Type"
|
msgstr "Cashbook Type"
|
||||||
|
@ -382,6 +386,10 @@ msgctxt "view:cashbook.book:"
|
||||||
msgid "General Information"
|
msgid "General Information"
|
||||||
msgstr "General Information"
|
msgstr "General Information"
|
||||||
|
|
||||||
|
msgctxt "view:cashbook.book:"
|
||||||
|
msgid "Amount and Numbering"
|
||||||
|
msgstr "Amount and Numbering"
|
||||||
|
|
||||||
msgctxt "view:cashbook.book:"
|
msgctxt "view:cashbook.book:"
|
||||||
msgid "Balance"
|
msgid "Balance"
|
||||||
msgstr "Balance"
|
msgstr "Balance"
|
||||||
|
@ -398,6 +406,10 @@ msgctxt "field:cashbook.book,btype:"
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "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:"
|
msgctxt "field:cashbook.book,state:"
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "State"
|
msgstr "State"
|
||||||
|
@ -446,10 +458,6 @@ msgctxt "field:cashbook.book,currency_digits:"
|
||||||
msgid "Currency Digits"
|
msgid "Currency Digits"
|
||||||
msgstr "Currency Digits"
|
msgstr "Currency Digits"
|
||||||
|
|
||||||
msgctxt "field:cashbook.book,start_balance:"
|
|
||||||
msgid "Initial Amount"
|
|
||||||
msgstr "Initial Amount"
|
|
||||||
|
|
||||||
msgctxt "field:cashbook.book,start_date:"
|
msgctxt "field:cashbook.book,start_date:"
|
||||||
msgid "Initial Date"
|
msgid "Initial Date"
|
||||||
msgstr "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."
|
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."
|
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:"
|
msgctxt "model:cashbook.split,name:"
|
||||||
msgid "Split booking line"
|
msgid "Split booking line"
|
||||||
msgstr "Split booking line"
|
msgstr "Split booking line"
|
||||||
|
|
14
menu.xml
14
menu.xml
|
@ -83,9 +83,21 @@ full copyright notices and license terms. -->
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- menu: /Cashbook/Cashbook -->
|
<!-- 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"
|
<menuitem id="menu_booklist" action="act_book_view"
|
||||||
icon="tryton-list"
|
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">
|
<record model="ir.ui.menu-res.group" id="menu_booklist-group_cashbook">
|
||||||
<field name="menu" ref="menu_booklist"/>
|
<field name="menu" ref="menu_booklist"/>
|
||||||
<field name="group" ref="group_cashbook"/>
|
<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">
|
<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>
|
<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>
|
||||||
<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">
|
<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>
|
<field name="text">For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'.</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -226,7 +226,7 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
||||||
))
|
))
|
||||||
values['start_amount'] = reconciliation.predecessor.end_amount
|
values['start_amount'] = reconciliation.predecessor.end_amount
|
||||||
else :
|
else :
|
||||||
values['start_amount'] = reconciliation.cashbook.start_balance
|
values['start_amount'] = Decimal('0.0')
|
||||||
values['end_amount'] = values['start_amount']
|
values['end_amount'] = values['start_amount']
|
||||||
|
|
||||||
# add 'checked'-lines to reconciliation
|
# add 'checked'-lines to reconciliation
|
||||||
|
|
|
@ -51,10 +51,37 @@ class BookTestCase(ModuleTestCase):
|
||||||
'number_sequ': self.prep_sequence().id,
|
'number_sequ': self.prep_sequence().id,
|
||||||
}])
|
}])
|
||||||
self.assertEqual(book.name, 'Book 1')
|
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.btype.rec_name, 'CAS - Cash')
|
||||||
self.assertEqual(book.state, 'open')
|
self.assertEqual(book.state, 'open')
|
||||||
self.assertEqual(book.state_string, '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()
|
@with_transaction()
|
||||||
def test_book_deny_delete_open(self):
|
def test_book_deny_delete_open(self):
|
||||||
""" create cashbook, add lines, try to delete in state 'open'
|
""" 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()
|
@with_transaction()
|
||||||
def test_book_permission_owner(self):
|
def test_book_permission_owner(self):
|
||||||
""" create book + 2x users, add users to group, check access
|
""" create book + 2x users, add users to group, check access
|
||||||
|
|
|
@ -39,7 +39,6 @@ class BookingWizardTestCase(ModuleTestCase):
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'number_sequ': self.prep_sequence().id,
|
'number_sequ': self.prep_sequence().id,
|
||||||
'start_date': date(2022, 1, 1),
|
'start_date': date(2022, 1, 1),
|
||||||
'start_balance': Decimal('0.0'),
|
|
||||||
}])
|
}])
|
||||||
|
|
||||||
party, = Party.create([{
|
party, = Party.create([{
|
||||||
|
@ -114,7 +113,6 @@ class BookingWizardTestCase(ModuleTestCase):
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'number_sequ': self.prep_sequence().id,
|
'number_sequ': self.prep_sequence().id,
|
||||||
'start_date': date(2022, 1, 1),
|
'start_date': date(2022, 1, 1),
|
||||||
'start_balance': Decimal('0.0'),
|
|
||||||
}, {
|
}, {
|
||||||
'name': 'Bank',
|
'name': 'Bank',
|
||||||
'btype': types.id,
|
'btype': types.id,
|
||||||
|
@ -122,7 +120,6 @@ class BookingWizardTestCase(ModuleTestCase):
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'number_sequ': self.prep_sequence().id,
|
'number_sequ': self.prep_sequence().id,
|
||||||
'start_date': date(2022, 1, 1),
|
'start_date': date(2022, 1, 1),
|
||||||
'start_balance': Decimal('0.0'),
|
|
||||||
}])
|
}])
|
||||||
|
|
||||||
party, = Party.create([{
|
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].rec_name, '05/01/2022|Rev/Sp|1.00 usd|Text 3 [-]')
|
||||||
self.assertEqual(book.lines[2].state, 'edit')
|
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()
|
@with_transaction()
|
||||||
def test_line_create_check_deny_write(self):
|
def test_line_create_check_deny_write(self):
|
||||||
""" create cashbook + line, 'close' book, write to line
|
""" create cashbook + line, 'close' book, write to line
|
||||||
|
|
|
@ -221,7 +221,6 @@ class ReconTestCase(ModuleTestCase):
|
||||||
'btype': types.id,
|
'btype': types.id,
|
||||||
'company': company.id,
|
'company': company.id,
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'start_balance': Decimal('12.50'),
|
|
||||||
'start_date': date(2022, 5, 1),
|
'start_date': date(2022, 5, 1),
|
||||||
'number_sequ': self.prep_sequence().id,
|
'number_sequ': self.prep_sequence().id,
|
||||||
'reconciliations': [('create', [{
|
'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]')
|
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))
|
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()
|
@with_transaction()
|
||||||
def test_recon_set_start_amount_by_predecessor(self):
|
def test_recon_set_start_amount_by_predecessor(self):
|
||||||
|
@ -254,7 +253,6 @@ class ReconTestCase(ModuleTestCase):
|
||||||
'btype': types.id,
|
'btype': types.id,
|
||||||
'company': company.id,
|
'company': company.id,
|
||||||
'currency': company.currency.id,
|
'currency': company.currency.id,
|
||||||
'start_balance': Decimal('12.50'),
|
|
||||||
'start_date': date(2022, 5, 1),
|
'start_date': date(2022, 5, 1),
|
||||||
'number_sequ': self.prep_sequence().id,
|
'number_sequ': self.prep_sequence().id,
|
||||||
'reconciliations': [('create', [{
|
'reconciliations': [('create', [{
|
||||||
|
@ -287,7 +285,7 @@ class ReconTestCase(ModuleTestCase):
|
||||||
Reconciliation.wfcheck(list(book.reconciliations))
|
Reconciliation.wfcheck(list(book.reconciliations))
|
||||||
|
|
||||||
self.assertEqual(book.reconciliations[0].state, 'check')
|
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))
|
Reconciliation.wfdone(list(book.reconciliations))
|
||||||
self.assertEqual(book.reconciliations[0].state, 'done')
|
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]')
|
self.assertEqual(recons[0].rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
|
||||||
Reconciliation.wfcheck(recons)
|
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()
|
@with_transaction()
|
||||||
def test_recon_predecessor_done(self):
|
def test_recon_predecessor_done(self):
|
||||||
|
|
|
@ -15,29 +15,32 @@ full copyright notices and license terms. -->
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<label name="btype"/>
|
||||||
|
<field name="btype"/>
|
||||||
<label name="balance"/>
|
<label name="balance"/>
|
||||||
<field name="balance"/>
|
<field name="balance"/>
|
||||||
<newline/>
|
|
||||||
|
|
||||||
<notebook colspan="4">
|
<notebook colspan="4">
|
||||||
<page id="pgrecon" string="Reconciliations" col="1">
|
<page name="reconciliations" string="Reconciliations" col="1">
|
||||||
<field name="reconciliations"/>
|
<field name="reconciliations"/>
|
||||||
</page>
|
</page>
|
||||||
<page id="pggeneral" string="General Information" col="4">
|
<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"/>
|
<label name="number_sequ"/>
|
||||||
<field name="number_sequ"/>
|
<field name="number_sequ"/>
|
||||||
<label name="number_atcheck"/>
|
<label name="number_atcheck"/>
|
||||||
<field 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"/>
|
<label name="start_date"/>
|
||||||
<field name="start_date"/>
|
<field name="start_date"/>
|
||||||
|
<label name="currency"/>
|
||||||
|
<field name="currency"/>
|
||||||
|
|
||||||
<label id="phaccount" colspan="2" string=" "/>
|
<label id="phaccount" colspan="2" string=" "/>
|
||||||
</page>
|
</page>
|
||||||
|
|
|
@ -5,7 +5,6 @@ full copyright notices and license terms. -->
|
||||||
<tree>
|
<tree>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="btype"/>
|
<field name="btype"/>
|
||||||
<field name="start_balance"/>
|
|
||||||
<field name="balance" sum="Balance"/>
|
<field name="balance" sum="Balance"/>
|
||||||
<field name="currency"/>
|
<field name="currency"/>
|
||||||
<field name="owner"/>
|
<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"/>
|
<field name="description" colspan="5"/>
|
||||||
|
|
||||||
<notebook colspan="6">
|
<notebook colspan="6">
|
||||||
<page string="General Information" id="general" col="6">
|
<page string="General Information" id="general" col="4">
|
||||||
<label name="company"/>
|
<label name="company"/>
|
||||||
<field name="company"/>
|
<field name="company"/>
|
||||||
<label name="parent"/>
|
<label name="parent"/>
|
||||||
<field name="parent"/>
|
<field name="parent"/>
|
||||||
<newline/>
|
<field name="childs" colspan="4"/>
|
||||||
<field name="childs" colspan="6"/>
|
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue