book: neues Feld 'description', sperrt btype-->None mit Zeilen + Test
line: verwendet nur kassenbücher mit typ
This commit is contained in:
parent
a2e7f192f8
commit
2acdc55efb
12 changed files with 107 additions and 11 deletions
11
book.py
11
book.py
|
@ -45,6 +45,8 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
|
|||
required=True, ondelete="RESTRICT")
|
||||
name = fields.Char(string='Name', required=True,
|
||||
states=STATES, depends=DEPENDS)
|
||||
description = fields.Text(string='Description',
|
||||
states=STATES, depends=DEPENDS)
|
||||
btype = fields.Many2One(string='Type',
|
||||
help='A cash book with type can contain postings. Without type is a view.',
|
||||
model_name='cashbook.type', ondelete='RESTRICT',
|
||||
|
@ -307,6 +309,15 @@ class Book(tree(separator='/'), Workflow, ModelSQL, ModelView):
|
|||
actions = iter(args)
|
||||
for books, values in zip(actions, actions):
|
||||
for book in books:
|
||||
# deny btype-->None if lines not empty
|
||||
if 'btype' in values.keys():
|
||||
if (values['btype'] is None) and (len(book.lines) > 0):
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_book_btype_with_lines',
|
||||
cbname = book.rec_name,
|
||||
numlines = len(book.lines),
|
||||
))
|
||||
|
||||
if book.state != 'open':
|
||||
# allow state-update, if its the only action
|
||||
if not (('state' in values.keys()) and (len(values.keys()) == 1)):
|
||||
|
|
|
@ -17,7 +17,8 @@ field_catnamelong = fields.Boolean(string='Category: Show long name',
|
|||
help='Shows the long name of the category in the Category field of a cash book line.')
|
||||
field_defbook = fields.Many2One(string='Default Cashbook',
|
||||
help='The default cashbook is selected when you open the booking wizard.',
|
||||
model_name='cashbook.book', ondelete='SET NULL')
|
||||
model_name='cashbook.book', ondelete='SET NULL',
|
||||
domain=[('btype', '!=', None)])
|
||||
|
||||
|
||||
class Configuration(ModelSingleton, ModelSQL, ModelView, UserMultiValueMixin):
|
||||
|
|
3
line.py
3
line.py
|
@ -931,6 +931,7 @@ class LineContext(ModelView):
|
|||
|
||||
cashbook = fields.Many2One(string='Cashbook', required=True,
|
||||
model_name='cashbook.book',
|
||||
domain=[('btype', '!=', None)],
|
||||
states={
|
||||
'readonly': Eval('num_cashbook', 0) < 2,
|
||||
}, depends=['num_cashbook'])
|
||||
|
@ -993,7 +994,7 @@ class LineContext(ModelView):
|
|||
with Transaction().set_context({
|
||||
'_check_access': True,
|
||||
}):
|
||||
return CashBook.search_count([])
|
||||
return CashBook.search_count([('btype', '!=', None)])
|
||||
|
||||
@classmethod
|
||||
def default_done(cls):
|
||||
|
|
12
locale/de.po
12
locale/de.po
|
@ -146,6 +146,10 @@ msgctxt "model:ir.message,text:msg_line_invalid_category"
|
|||
msgid "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
|
||||
msgstr "Die Kategorie der Buchungszeile '%(recname)s' paßt nicht zum Buchungstyp '%(booktype)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_book_btype_with_lines"
|
||||
msgid "The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines."
|
||||
msgstr "Der Typ kann am Kassenbuch '%(cbname)s' nicht gelöscht werden, da es noch %(numlines)s Zeilen enthält."
|
||||
|
||||
|
||||
#############
|
||||
# res.group #
|
||||
|
@ -434,10 +438,18 @@ msgctxt "view:cashbook.book:"
|
|||
msgid "Reconciliations"
|
||||
msgstr "Abstimmungen"
|
||||
|
||||
msgctxt "view:cashbook.book:"
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
msgctxt "field:cashbook.book,name:"
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
msgctxt "field:cashbook.book,description:"
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
msgctxt "field:cashbook.book,btype:"
|
||||
msgid "Type"
|
||||
msgstr "Typ"
|
||||
|
|
12
locale/en.po
12
locale/en.po
|
@ -142,6 +142,10 @@ msgctxt "model:ir.message,text:msg_line_invalid_category"
|
|||
msgid "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
|
||||
msgstr "The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_book_btype_with_lines"
|
||||
msgid "The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines."
|
||||
msgstr "The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines."
|
||||
|
||||
msgctxt "model:res.group,name:group_cashbook"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
@ -398,10 +402,18 @@ msgctxt "view:cashbook.book:"
|
|||
msgid "Reconciliations"
|
||||
msgstr "Reconciliations"
|
||||
|
||||
msgctxt "view:cashbook.book:"
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
msgctxt "field:cashbook.book,name:"
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
msgctxt "field:cashbook.book,description:"
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
msgctxt "field:cashbook.book,btype:"
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
|
|
@ -110,6 +110,9 @@ full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_line_invalid_category">
|
||||
<field name="text">The category of the booking line '%(recname)s' does not match the posting type '%(booktype)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_book_btype_with_lines">
|
||||
<field name="text">The type cannot be deleted on the cash book '%(cbname)s' because it still contains %(numlines)s lines.</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
|
@ -117,6 +117,62 @@ class BookTestCase(ModuleTestCase):
|
|||
Book.delete,
|
||||
[book])
|
||||
|
||||
@with_transaction()
|
||||
def test_book_deny_btype_set_none(self):
|
||||
""" create cashbook, add lines,
|
||||
try to set btype to None with lines
|
||||
"""
|
||||
pool = Pool()
|
||||
Book = pool.get('cashbook.book')
|
||||
|
||||
types = self.prep_type()
|
||||
category = self.prep_category(cattype='in')
|
||||
company = self.prep_company()
|
||||
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,
|
||||
'start_date': date(2022, 5, 1),
|
||||
'lines': [('create', [{
|
||||
'date': date(2022, 5, 1),
|
||||
'description': 'test 1',
|
||||
'category': category.id,
|
||||
'bookingtype': 'in',
|
||||
'amount': Decimal('1.0'),
|
||||
'party': party.id,
|
||||
}])],
|
||||
}])
|
||||
self.assertEqual(book.name, 'Book 1')
|
||||
self.assertEqual(book.btype.rec_name, 'CAS - Cash')
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The type cannot be deleted on the cash book 'Book 1 | 1.00 usd | Open' because it still contains 1 lines.",
|
||||
Book.write,
|
||||
*[
|
||||
[book],
|
||||
{
|
||||
'btype': None,
|
||||
},
|
||||
])
|
||||
|
||||
Book.write(*[
|
||||
[book],
|
||||
{
|
||||
'lines': [('delete', [book.lines[0].id])],
|
||||
}])
|
||||
self.assertEqual(len(book.lines), 0)
|
||||
self.assertEqual(book.btype.rec_name, 'CAS - Cash')
|
||||
|
||||
Book.write(*[
|
||||
[book],
|
||||
{
|
||||
'btype': None,
|
||||
}])
|
||||
self.assertEqual(book.btype, None)
|
||||
|
||||
@with_transaction()
|
||||
def test_book_deny_delete_closed(self):
|
||||
""" create cashbook, add lines, try to delete in state 'closed'
|
||||
|
|
|
@ -24,6 +24,9 @@ full copyright notices and license terms. -->
|
|||
<page name="reconciliations" string="Reconciliations" col="1">
|
||||
<field name="reconciliations"/>
|
||||
</page>
|
||||
<page name="description" string="Description" col="1">
|
||||
<field name="description"/>
|
||||
</page>
|
||||
<page id="pggeneral" string="General Information" col="4">
|
||||
<label name="company"/>
|
||||
<field name="company"/>
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
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="rec_name"/>
|
||||
<field name="balance" sum="Balance"/>
|
||||
<field name="currency"/>
|
||||
<field name="owner"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
|
|
|
@ -4,10 +4,8 @@ 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"/>
|
||||
|
|
|
@ -20,7 +20,7 @@ class EnterBookingStart(ModelView):
|
|||
__name__ = 'cashbook.enterbooking.start'
|
||||
|
||||
cashbook = fields.Many2One(string='Cashbook', model_name='cashbook.book',
|
||||
domain=[('id', 'in', Eval('cashbooks', []))],
|
||||
domain=[('id', 'in', Eval('cashbooks', [])), ('btype', '!=', None)],
|
||||
depends=['cashbooks'], required=True)
|
||||
cashbooks = fields.One2Many(string='Cashbooks', field=None,
|
||||
model_name='cashbook.book', readonly=True,
|
||||
|
@ -137,6 +137,7 @@ class EnterBookingWizard(Wizard):
|
|||
result = {
|
||||
'cashbooks': [x.id for x in Cashbook.search([
|
||||
('state', '=', 'open'),
|
||||
('btype', '!=', None),
|
||||
('owner.id', '=', Transaction().user),
|
||||
])],
|
||||
'bookingtype': getattr(self.start, 'bookingtype', 'out'),
|
||||
|
|
|
@ -16,7 +16,7 @@ class OpenCashBookStart(ModelView):
|
|||
__name__ = 'cashbook.open_lines.start'
|
||||
|
||||
cashbook = fields.Many2One(string='Cashbook', model_name='cashbook.book',
|
||||
required=True)
|
||||
required=True, domain=[('btype', '!=', None)])
|
||||
checked = fields.Boolean(string='Checked', help="Show cashbook lines in Checked-state.")
|
||||
done = fields.Boolean(string='Done', help="Show cashbook lines in Done-state")
|
||||
date_from = fields.Date(string='Start Date')
|
||||
|
@ -54,7 +54,7 @@ class OpenCashBook(Wizard):
|
|||
with Transaction().set_context({
|
||||
'_check_access': True,
|
||||
}):
|
||||
books = Book.search([])
|
||||
books = Book.search([('btype', '!=', None)])
|
||||
if len(books) == 1:
|
||||
return 'open_'
|
||||
return 'askuser'
|
||||
|
@ -90,7 +90,7 @@ class OpenCashBook(Wizard):
|
|||
with Transaction().set_context({
|
||||
'_check_access': True,
|
||||
}):
|
||||
books = Book.search([])
|
||||
books = Book.search([('btype', '!=', None)])
|
||||
if len(books) > 0:
|
||||
book = books[0]
|
||||
|
||||
|
|
Loading…
Reference in a new issue