line: spalte 'empfänger', Feld 'reference' + tests

This commit is contained in:
Frederik Jaeckel 2022-08-16 14:16:14 +02:00
parent 30b91cf518
commit 5fdbb0ce89
10 changed files with 510 additions and 42 deletions

119
line.py
View file

@ -17,6 +17,11 @@ from sql.conditionals import Case
from .book import sel_state_book from .book import sel_state_book
sel_payee = [
('cashbook.book', 'Cashbook'),
('party.party', 'Party')
]
sel_linetype = [ sel_linetype = [
('edit', 'Edit'), ('edit', 'Edit'),
('check', 'Checked'), ('check', 'Checked'),
@ -51,13 +56,15 @@ class Line(Workflow, ModelSQL, ModelView):
'on_change_with_month', searcher='search_month') 'on_change_with_month', searcher='search_month')
description = fields.Text(string='Description', description = fields.Text(string='Description',
states=STATES, depends=DEPENDS) states=STATES, depends=DEPENDS)
category = fields.Many2One(string='Category', required=True, category = fields.Many2One(string='Category',
model_name='cashbook.category', ondelete='RESTRICT', model_name='cashbook.category', ondelete='RESTRICT',
states={ states={
'readonly': Or( 'readonly': Or(
STATES['readonly'], STATES['readonly'],
Bool(Eval('bookingtype')) == False, Bool(Eval('bookingtype')) == False,
), ),
'required': Eval('bookingtype', '').in_(['in', 'out']),
'invisible': ~Eval('bookingtype', '').in_(['in', 'out']),
}, depends=DEPENDS+['bookingtype'], }, depends=DEPENDS+['bookingtype'],
domain=[ domain=[
If( If(
@ -78,14 +85,18 @@ class Line(Workflow, ModelSQL, ModelView):
credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)), credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)),
required=True, readonly=True, depends=['currency_digits']) required=True, readonly=True, depends=['currency_digits'])
booktransf = fields.Many2One(string='Transfer Cashbook', # party or cashbook as counterpart
booktransf = fields.Many2One(string='Source/Dest',
ondelete='RESTRICT', model_name='cashbook.book', ondelete='RESTRICT', model_name='cashbook.book',
domain=[('cashbook.owner.id', '=', Eval('context',{}).get('user', -1))], domain=[
('owner.id', '=', Eval('owner_cashbook', -1)),
('id', '!=', Eval('cashbook', -1)),
],
states={ states={
'readonly': STATES['readonly'], 'readonly': STATES['readonly'],
'invisible': ~Eval('bookingtype', '').in_(['mvin', 'mvout']), 'invisible': ~Eval('bookingtype', '').in_(['mvin', 'mvout']),
'required': Eval('bookingtype', '').in_(['mvin', 'mvout']), 'required': Eval('bookingtype', '').in_(['mvin', 'mvout']),
}, depends=DEPENDS+['bookingtype']) }, depends=DEPENDS+['bookingtype', 'owner_cashbook', 'cashbook'])
party = fields.Many2One(string='Party', model_name='party.party', party = fields.Many2One(string='Party', model_name='party.party',
ondelete='RESTRICT', ondelete='RESTRICT',
states={ states={
@ -93,6 +104,20 @@ class Line(Workflow, ModelSQL, ModelView):
'invisible': ~Eval('bookingtype', '').in_(['in', 'out']), 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']),
'required': Eval('bookingtype', '').in_(['in', 'out']), 'required': Eval('bookingtype', '').in_(['in', 'out']),
}, depends=DEPENDS+['bookingtype']) }, depends=DEPENDS+['bookingtype'])
payee = fields.Function(fields.Reference(string='Payee', readonly=True,
selection=sel_payee), 'on_change_with_payee', searcher='search_payee')
# link to lines created by this record
reference = fields.Many2One(string='Reference', readonly=True, select=True,
states={
'invisible': ~Bool(Eval('reference')),
}, model_name='cashbook.line', ondelete='CASCADE',
help='The current row was created by and is controlled by the reference row.')
references = fields.One2Many(string='References', model_name='cashbook.line',
help='The rows are created and managed by the current record.',
states={
'invisible': ~Bool(Eval('references')),
}, field='reference', readonly=True)
reconciliation = fields.Many2One(string='Reconciliation', readonly=True, reconciliation = fields.Many2One(string='Reconciliation', readonly=True,
model_name='cashbook.recon', ondelete='SET NULL', model_name='cashbook.recon', ondelete='SET NULL',
@ -116,6 +141,9 @@ class Line(Workflow, ModelSQL, ModelView):
state_cashbook = fields.Function(fields.Selection(string='State of Cashbook', state_cashbook = fields.Function(fields.Selection(string='State of Cashbook',
readonly=True, states={'invisible': True}, selection=sel_state_book), readonly=True, states={'invisible': True}, selection=sel_state_book),
'on_change_with_state_cashbook', searcher='search_state_cashbook') 'on_change_with_state_cashbook', searcher='search_state_cashbook')
owner_cashbook = fields.Function(fields.Many2One(string='Owner', readonly=True,
states={'invisible': True}, model_name='res.user'),
'on_change_with_owner_cashbook')
#image = fields.Binary... #image = fields.Binary...
@ -138,7 +166,8 @@ class Line(Workflow, ModelSQL, ModelView):
cls._buttons.update({ cls._buttons.update({
'wfedit': { 'wfedit': {
'invisible': Eval('state', '') != 'check', 'invisible': Eval('state', '') != 'check',
'depends': ['state'], 'readonly': Bool(Eval('reference')),
'depends': ['state', 'reference'],
}, },
'wfcheck': { 'wfcheck': {
'invisible': Eval('state') != 'edit', 'invisible': Eval('state') != 'edit',
@ -156,7 +185,27 @@ class Line(Workflow, ModelSQL, ModelView):
def wfedit(cls, lines): def wfedit(cls, lines):
""" edit line """ edit line
""" """
pass pool = Pool()
Line2 = pool.get('cashbook.line')
to_delete_line = []
for line in lines:
if line.reference:
if Transaction().context.get('line.allow.wfedit', False) == False:
raise UserError(gettext(
'cashbook.msg_line_denywf_by_reference',
recname = line.reference.rec_name,
cbook = line.reference.cashbook.rec_name,
))
# delete references
to_delete_line.extend(list(line.references))
if len(to_delete_line) > 0:
with Transaction().set_context({
'line.allow.wfedit': True,
}):
Line2.wfedit(to_delete_line)
Line2.delete(to_delete_line)
@classmethod @classmethod
@ModelView.button @ModelView.button
@ -166,7 +215,9 @@ class Line(Workflow, ModelSQL, ModelView):
""" """
pool = Pool() pool = Pool()
Recon = pool.get('cashbook.recon') Recon = pool.get('cashbook.recon')
Line2 = pool.get('cashbook.line')
to_create_line = []
for line in lines: for line in lines:
# deny if date is in range of existing reconciliation # deny if date is in range of existing reconciliation
# allow cashbook-line at range-limits # allow cashbook-line at range-limits
@ -194,6 +245,23 @@ class Line(Workflow, ModelSQL, ModelView):
'cashbook.msg_line_err_write_to_reconciled', 'cashbook.msg_line_err_write_to_reconciled',
datetxt = Report.format_date(line.date), datetxt = Report.format_date(line.date),
)) ))
# in case of 'mvin' or 'mvout' - create counterpart
if (line.bookingtype in ['mvout', 'mvin']) and (line.reference is None):
to_create_line.append({
'cashbook': line.booktransf.id,
'bookingtype': 'mvin' if line.bookingtype == 'mvout' else 'mvout',
'date': line.date,
'description': line.description,
'amount': line.amount,
'credit': line.debit,
'debit': line.credit,
'booktransf': line.cashbook.id,
'reference': line.id,
})
if len(to_create_line) > 0:
new_lines = Line2.create(to_create_line)
Line2.wfcheck(new_lines)
@classmethod @classmethod
@ModelView.button @ModelView.button
@ -232,12 +300,17 @@ class Line(Workflow, ModelSQL, ModelView):
def get_rec_name(self, name): def get_rec_name(self, name):
""" short + name """ short + name
""" """
return '%(date)s|%(amount)s %(symbol)s|%(desc)s [%(category)s]' % { credit = self.credit if self.credit is not None else Decimal('0.0')
debit = self.debit if self.debit is not None else Decimal('0.0')
return '%(date)s|%(type)s|%(amount)s %(symbol)s|%(desc)s [%(category)s]' % {
'date': Report.format_date(self.date), 'date': Report.format_date(self.date),
'desc': (self.description or '-')[:40], 'desc': (self.description or '-')[:40],
'amount': Report.format_number(self.amount or 0.0, None), 'amount': Report.format_number(credit - debit, None),
'symbol': getattr(self.currency, 'symbol', '-'), 'symbol': getattr(self.currency, 'symbol', '-'),
'category': self.category_view, 'category': self.category_view \
if self.bookingtype in ['in', 'out'] \
else getattr(self.booktransf, 'rec_name', '-'),
'type': gettext('cashbook.msg_line_bookingtype_%s' % self.bookingtype),
} }
@staticmethod @staticmethod
@ -271,6 +344,27 @@ class Line(Workflow, ModelSQL, ModelView):
return [tab2] return [tab2]
@fields.depends('party', 'booktransf', 'bookingtype')
def on_change_with_payee(self, name=None):
""" get party or cashbook
"""
if self.bookingtype:
if self.bookingtype in ['in', 'out']:
if self.party:
return 'party.party,%d' % self.party.id
elif self.bookingtype in ['mvin', 'mvout']:
if self.booktransf:
return 'cashbook.book,%d' % self.booktransf.id
@classmethod
def search_payee(cls, names, clause):
""" search in payee for party or cashbook
"""
return ['OR',
('party.rec_name',) + tuple(clause[1:]),
('booktransf.rec_name',) + tuple(clause[1:]),
]
@fields.depends('category') @fields.depends('category')
def on_change_with_category_view(self, name=None): def on_change_with_category_view(self, name=None):
""" show optimizef form of category for list-view """ show optimizef form of category for list-view
@ -320,6 +414,13 @@ class Line(Workflow, ModelSQL, ModelView):
) )
return [('id', 'in', query)] return [('id', 'in', query)]
@fields.depends('cashbook', '_parent_cashbook.owner')
def on_change_with_owner_cashbook(self, name=None):
""" get current owner
"""
if self.cashbook:
return self.cashbook.owner.id
@fields.depends('cashbook', '_parent_cashbook.state') @fields.depends('cashbook', '_parent_cashbook.state')
def on_change_with_state_cashbook(self, name=None): def on_change_with_state_cashbook(self, name=None):
""" get state of cashbook """ get state of cashbook

View file

@ -102,6 +102,26 @@ msgctxt "model:ir.message,text:msg_recon_predecessor_not_done"
msgid "The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'." msgid "The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'."
msgstr "Der Vorgänger '%(recname_p)s' muss sich im Status 'Fertig' befinden, bevor Sie den aktuellen Abgleich '%(recname_c)s' prüfen können." msgstr "Der Vorgänger '%(recname_p)s' muss sich im Status 'Fertig' befinden, bevor Sie den aktuellen Abgleich '%(recname_c)s' prüfen können."
msgctxt "model:ir.message,text:msg_line_bookingtype_in"
msgid "Rev"
msgstr "Einn."
msgctxt "model:ir.message,text:msg_line_bookingtype_out"
msgid "Exp"
msgstr "Ausg."
msgctxt "model:ir.message,text:msg_line_bookingtype_mvin"
msgid "from"
msgstr "von"
msgctxt "model:ir.message,text:msg_line_bookingtype_mvout"
msgid "to"
msgstr "nach"
msgctxt "model:ir.message,text:msg_line_denywf_by_reference"
msgid "The current line is managed by the cashbook line '%(recname)s', cashbook: '%(cbook)s'."
msgstr "Die aktuelle Zeile wird durch die Kassenbuchzeile '%(recname)s' verwaltet, Kassenbuch: '%(cbook)s'."
############# #############
# res.group # # res.group #
@ -494,6 +514,42 @@ msgctxt "field:cashbook.line,party:"
msgid "Party" msgid "Party"
msgstr "Partei" msgstr "Partei"
msgctxt "field:cashbook.line,booktransf:"
msgid "Source/Dest"
msgstr "Quelle/Ziel"
msgctxt "field:cashbook.line,owner_cashbook:"
msgid "Owner"
msgstr "Eigentümer"
msgctxt "field:cashbook.line,reference:"
msgid "Reference"
msgstr "Referenz"
msgctxt "help:cashbook.line,reference:"
msgid "The current row was created by and is controlled by the reference row."
msgstr "Die aktuelle Zeile wurde durch die Referenzzeile erstellt und wird von dieser gesteuert."
msgctxt "field:cashbook.line,references:"
msgid "References"
msgstr "Referenzen"
msgctxt "help:cashbook.line,references:"
msgid "The rows are created and managed by the current record."
msgstr "Die Zeilen werden durch den aktuellen Datensatz erstellt und verwaltet."
msgctxt "field:cashbook.line,payee:"
msgid "Payee"
msgstr "Empfänger"
msgctxt "selection:cashbook.line,payee:"
msgid "Cashbook"
msgstr "Kassenbuch"
msgctxt "selection:cashbook.line,payee:"
msgid "Party"
msgstr "Partei"
################# #################
# cashbook.type # # cashbook.type #

View file

@ -35,8 +35,8 @@ msgid "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linest
msgstr "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linestate)s'." msgstr "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linestate)s'."
msgctxt "model:ir.message,text:msg_line_deny_stateedit_with_recon" msgctxt "model:ir.message,text:msg_line_deny_stateedit_with_recon"
msgid "The status cannot be changed to 'Edit' as long as the line '%(recname)s' is associated with a reconciliation." msgid "The status cannot be changed to 'Edit' while the line '%(recname)s' is associated with a reconciliation."
msgstr "The status cannot be changed to 'Edit' as long as the line '%(recname)s' is associated with a reconciliation." msgstr "The status cannot be changed to 'Edit' while the line '%(recname)s' is associated with a reconciliation."
msgctxt "model:ir.message,text:msg_line_deny_write" msgctxt "model:ir.message,text:msg_line_deny_write"
msgid "The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed." msgid "The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed."
@ -82,6 +82,42 @@ msgctxt "model:ir.message,text:msg_recon_err_overlap"
msgid "The date range overlaps with another reconciliation." msgid "The date range overlaps with another reconciliation."
msgstr "The date range overlaps with another reconciliation." msgstr "The date range overlaps with another reconciliation."
msgctxt "model:ir.message,text:msg_line_err_write_to_reconciled"
msgid "For the date '%(datetxt)s' there is already a completed reconciliation. Use a different date."
msgstr "For the date '%(datetxt)s' there is already a completed reconciliation. Use a different date."
msgctxt "model:ir.message,text:msg_recon_lines_no_linked"
msgid "In the date range from %(date_from)s to %(date_to)s, there are still cashbook lines that do not belong to any reconciliation."
msgstr "In the date range from %(date_from)s to %(date_to)s, there are still cashbook lines that do not belong to any reconciliation."
msgctxt "model:ir.message,text:msg_recon_date_from_to_mismatch"
msgid "The start date '%(datefrom)s' of the current reconciliation '%(recname)s' must correspond to the end date '%(dateto)s' of the predecessor."
msgstr "The start date '%(datefrom)s' of the current reconciliation '%(recname)s' must correspond to the end date '%(dateto)s' of the predecessor."
msgctxt "model:ir.message,text:msg_recon_predecessor_not_done"
msgid "The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'."
msgstr "The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'."
msgctxt "model:ir.message,text:msg_line_bookingtype_in"
msgid "Rev"
msgstr "Rev"
msgctxt "model:ir.message,text:msg_line_bookingtype_out"
msgid "Exp"
msgstr "Exp"
msgctxt "model:ir.message,text:msg_line_bookingtype_mvin"
msgid "from"
msgstr "from"
msgctxt "model:ir.message,text:msg_line_bookingtype_mvout"
msgid "to"
msgstr "to"
msgctxt "model:ir.message,text:msg_line_denywf_by_reference"
msgid "The current line is managed by the cashbook line '%(recname)s', cashbook: '%(cbook)s'."
msgstr "The current line is managed by the cashbook line '%(recname)s', cashbook: '%(cbook)s'."
msgctxt "model:res.group,name:group_cashbook" msgctxt "model:res.group,name:group_cashbook"
msgid "Cashbook" msgid "Cashbook"
msgstr "Cashbook" msgstr "Cashbook"
@ -438,6 +474,46 @@ msgctxt "field:cashbook.line,reconciliation:"
msgid "Reconciliation" msgid "Reconciliation"
msgstr "Reconciliation" msgstr "Reconciliation"
msgctxt "field:cashbook.line,party:"
msgid "Party"
msgstr "Party"
msgctxt "field:cashbook.line,booktransf:"
msgid "Source/Dest"
msgstr "Source/Dest"
msgctxt "field:cashbook.line,owner_cashbook:"
msgid "Owner"
msgstr "Owner"
msgctxt "field:cashbook.line,reference:"
msgid "Reference"
msgstr "Reference"
msgctxt "help:cashbook.line,reference:"
msgid "The current row was created by and is controlled by the reference row."
msgstr "The current row was created by and is controlled by the reference row."
msgctxt "field:cashbook.line,references:"
msgid "References"
msgstr "References"
msgctxt "help:cashbook.line,references:"
msgid "The rows are created and managed by the current record."
msgstr "The rows are created and managed by the current record."
msgctxt "field:cashbook.line,payee:"
msgid "Payee"
msgstr "Payee"
msgctxt "selection:cashbook.line,payee:"
msgid "Cashbook"
msgstr "Cashbook"
msgctxt "selection:cashbook.line,payee:"
msgid "Party"
msgstr "Party"
msgctxt "model:cashbook.type,name:" msgctxt "model:cashbook.type,name:"
msgid "Cashbook Type" msgid "Cashbook Type"
msgstr "Cashbook Type" msgstr "Cashbook Type"
@ -738,3 +814,7 @@ msgctxt "field:cashbook.recon,start_amount:"
msgid "Start Amount" msgid "Start Amount"
msgstr "Start Amount" msgstr "Start Amount"
msgctxt "field:cashbook.recon,end_amount:"
msgid "End Amount"
msgstr "End Amount"

View file

@ -77,6 +77,22 @@ full copyright notices and license terms. -->
<record model="ir.message" id="msg_recon_predecessor_not_done"> <record model="ir.message" id="msg_recon_predecessor_not_done">
<field name="text">The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'.</field> <field name="text">The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'.</field>
</record> </record>
<record model="ir.message" id="msg_line_bookingtype_in">
<field name="text">Rev</field>
</record>
<record model="ir.message" id="msg_line_bookingtype_out">
<field name="text">Exp</field>
</record>
<record model="ir.message" id="msg_line_bookingtype_mvin">
<field name="text">from</field>
</record>
<record model="ir.message" id="msg_line_bookingtype_mvout">
<field name="text">to</field>
</record>
<record model="ir.message" id="msg_line_denywf_by_reference">
<field name="text">The current line is managed by the cashbook line '%(recname)s', cashbook: '%(cbook)s'.</field>
</record>
</data> </data>
</tryton> </tryton>

View file

@ -45,6 +45,7 @@ class BookTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -56,6 +57,7 @@ class BookTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -76,6 +78,7 @@ class BookTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -87,6 +90,7 @@ class BookTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -109,6 +113,7 @@ class BookTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -120,6 +125,7 @@ class BookTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -202,6 +208,7 @@ class BookTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
company = self.prep_company() company = self.prep_company()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -228,6 +235,7 @@ class BookTestCase(ModuleTestCase):
'description': 'Test', 'description': 'Test',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.start_balance, Decimal('1.0')) self.assertEqual(book.start_balance, Decimal('1.0'))

View file

@ -43,6 +43,16 @@ class ConfigTestCase(ModuleTestCase):
self.assertEqual(cfg2.catnamelong, True) self.assertEqual(cfg2.catnamelong, True)
return cfg2 return cfg2
def prep_party(self, name='Party'):
""" new party
"""
Party = Pool().get('party.party')
party, = Party.create([{
'name': name,
'addresses': [('create', [{}])],
}])
return party
@with_transaction() @with_transaction()
def test_config_create(self): def test_config_create(self):
""" create config """ create config

View file

@ -27,6 +27,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -38,12 +39,14 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 2), 'date': date(2022, 5, 2),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -51,10 +54,10 @@ class LineTestCase(ModuleTestCase):
self.assertEqual(book.state, 'open') self.assertEqual(book.state, 'open')
self.assertEqual(len(book.lines), 2) self.assertEqual(len(book.lines), 2)
self.assertEqual(book.lines[0].date, date(2022, 5, 1)) self.assertEqual(book.lines[0].date, date(2022, 5, 1))
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[0].state_cashbook, 'open') self.assertEqual(book.lines[0].state_cashbook, 'open')
self.assertEqual(book.lines[1].date, date(2022, 5, 2)) self.assertEqual(book.lines[1].date, date(2022, 5, 2))
self.assertEqual(book.lines[1].rec_name, '05/02/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]')
self.assertEqual(Lines.search_count([('rec_name', '=', 'Text 1')]), 1) self.assertEqual(Lines.search_count([('rec_name', '=', 'Text 1')]), 1)
self.assertEqual(Lines.search_count([('rec_name', '=', 'Text 1a')]), 0) self.assertEqual(Lines.search_count([('rec_name', '=', 'Text 1a')]), 0)
@ -67,9 +70,9 @@ class LineTestCase(ModuleTestCase):
# sorting: date -> state -> id # sorting: date -> state -> id
self.assertEqual(len(book.lines), 2) self.assertEqual(len(book.lines), 2)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[0].state, 'edit') self.assertEqual(book.lines[0].state, 'edit')
self.assertEqual(book.lines[1].rec_name, '05/02/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]')
self.assertEqual(book.lines[1].state, 'edit') self.assertEqual(book.lines[1].state, 'edit')
# set to same date # set to same date
@ -80,17 +83,17 @@ class LineTestCase(ModuleTestCase):
}]) }])
# check again # check again
book, = Book.search([]) book, = Book.search([])
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[0].state, 'edit') self.assertEqual(book.lines[0].state, 'edit')
self.assertEqual(book.lines[1].rec_name, '05/01/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '05/01/2022|Rev|1.00 usd|Text 2 [Cat1]')
self.assertEqual(book.lines[1].state, 'edit') self.assertEqual(book.lines[1].state, 'edit')
# set to 'check', will sort first # set to 'check', will sort first
Lines.wfcheck([book.lines[1]]) Lines.wfcheck([book.lines[1]])
book, = Book.search([]) book, = Book.search([])
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 2 [Cat1]')
self.assertEqual(book.lines[0].state, 'check') self.assertEqual(book.lines[0].state, 'check')
self.assertEqual(book.lines[1].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[1].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[1].state, 'edit') self.assertEqual(book.lines[1].state, 'edit')
@with_transaction() @with_transaction()
@ -104,6 +107,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -115,12 +119,14 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 6, 1), 'date': date(2022, 6, 1),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -170,6 +176,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
IrDate.today = MagicMock(return_value=date(2022, 6, 1)) IrDate.today = MagicMock(return_value=date(2022, 6, 1))
book, = Book.create([{ book, = Book.create([{
@ -183,12 +190,14 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 6, 1), 'date': date(2022, 6, 1),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -221,6 +230,135 @@ class LineTestCase(ModuleTestCase):
IrDate.today = MagicMock(return_value=date.today()) IrDate.today = MagicMock(return_value=date.today())
@with_transaction()
def test_line_check_bookingtype_mvout(self):
""" create cashbook + line, bookingtype 'mvout'
"""
pool = Pool()
Book = pool.get('cashbook.book')
Line = pool.get('cashbook.line')
Category = pool.get('cashbook.category')
types = self.prep_type()
category_in = self.prep_category(cattype='in')
category_out = self.prep_category(name='Out Category', cattype='out')
company = self.prep_company()
party = self.prep_party()
book2, = Book.create([{
'name': 'Book 2',
'btype': types.id,
'company': company.id,
'currency': company.currency.id,
}])
book, = Book.create([{
'name': 'Book 1',
'btype': types.id,
'company': company.id,
'currency': company.currency.id,
'lines': [('create', [{
'date': date(2022, 5, 1),
'description': 'Transfer Out',
'category': category_out.id,
'bookingtype': 'mvout',
'amount': Decimal('1.0'),
'booktransf': book2.id,
}])],
}])
self.assertEqual(book.rec_name, 'Book 1 | -1.00 usd | Open')
self.assertEqual(len(book.lines), 1)
self.assertEqual(len(book2.lines), 0)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|to|-1.00 usd|Transfer Out [Book 2 | 0.00 usd | Open]')
self.assertEqual(len(book.lines[0].references), 0)
# check payee
self.assertEqual(book.lines[0].payee.rec_name, 'Book 2 | 0.00 usd | Open')
self.assertEqual(Line.search_count([('payee', 'ilike', 'book 2%')]), 1)
# set line to 'checked', this creates the counterpart
Line.wfcheck(list(book.lines))
self.assertEqual(len(book.lines), 1)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|to|-1.00 usd|Transfer Out [Book 2 | 1.00 usd | Open]')
self.assertEqual(book.lines[0].state, 'check')
self.assertEqual(len(book.lines[0].references), 1)
self.assertEqual(book.lines[0].reference, None)
self.assertEqual(book.lines[0].references[0].id, book2.lines[0].id)
self.assertEqual(len(book2.lines), 1)
self.assertEqual(book2.lines[0].rec_name, '05/01/2022|from|1.00 usd|Transfer Out [Book 1 | -1.00 usd | Open]')
self.assertEqual(book2.lines[0].state, 'check')
self.assertEqual(book2.lines[0].reference.rec_name, '05/01/2022|to|-1.00 usd|Transfer Out [Book 2 | 1.00 usd | Open]')
self.assertEqual(len(book2.lines[0].references), 0)
@with_transaction()
def test_line_check_bookingtype_mvin(self):
""" create cashbook + line, bookingtype 'mvin'
"""
pool = Pool()
Book = pool.get('cashbook.book')
Line = pool.get('cashbook.line')
Category = pool.get('cashbook.category')
types = self.prep_type()
category_in = self.prep_category(cattype='in')
category_out = self.prep_category(name='Out Category', cattype='out')
company = self.prep_company()
party = self.prep_party()
book2, = Book.create([{
'name': 'Book 2',
'btype': types.id,
'company': company.id,
'currency': company.currency.id,
}])
book, = Book.create([{
'name': 'Book 1',
'btype': types.id,
'company': company.id,
'currency': company.currency.id,
'lines': [('create', [{
'date': date(2022, 5, 1),
'description': 'Transfer In',
'category': category_in.id,
'bookingtype': 'mvin',
'amount': Decimal('1.0'),
'booktransf': book2.id,
}])],
}])
self.assertEqual(book.rec_name, 'Book 1 | 1.00 usd | Open')
self.assertEqual(len(book.lines), 1)
self.assertEqual(len(book2.lines), 0)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|from|1.00 usd|Transfer In [Book 2 | 0.00 usd | Open]')
self.assertEqual(len(book.lines[0].references), 0)
# set line to 'checked', this creates the counterpart
Line.wfcheck(list(book.lines))
self.assertEqual(len(book.lines), 1)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|from|1.00 usd|Transfer In [Book 2 | -1.00 usd | Open]')
self.assertEqual(book.lines[0].state, 'check')
self.assertEqual(len(book.lines[0].references), 1)
self.assertEqual(book.lines[0].reference, None)
self.assertEqual(book.lines[0].references[0].id, book2.lines[0].id)
self.assertEqual(len(book2.lines), 1)
self.assertEqual(book2.lines[0].rec_name, '05/01/2022|to|-1.00 usd|Transfer In [Book 1 | 1.00 usd | Open]')
self.assertEqual(book2.lines[0].state, 'check')
self.assertEqual(book2.lines[0].reference.rec_name, '05/01/2022|from|1.00 usd|Transfer In [Book 2 | -1.00 usd | Open]')
self.assertEqual(len(book2.lines[0].references), 0)
# tryt wfedit to 'book2.lines[0]'
self.assertRaisesRegex(UserError,
"The current line is managed by the cashbook line '05/01/2022|from|1.00 usd|Transfer In [Book 2 | -1.00 usd | Open]', cashbook: 'Book 1 | 1.00 usd | Open'.",
Line.wfedit,
[book2.lines[0]])
Line.wfedit([book.lines[0]])
self.assertEqual(len(book2.lines), 0)
@with_transaction() @with_transaction()
def test_line_create_check_debit_credit(self): def test_line_create_check_debit_credit(self):
""" create cashbook + line, check calculation of debit/credit """ create cashbook + line, check calculation of debit/credit
@ -235,6 +373,14 @@ class LineTestCase(ModuleTestCase):
category_in = self.prep_category(cattype='in') category_in = self.prep_category(cattype='in')
category_out = self.prep_category(name='Out Category', cattype='out') category_out = self.prep_category(name='Out Category', cattype='out')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book2, = Book.create([{
'name': 'Book 2',
'btype': types.id,
'company': company.id,
'currency': company.currency.id,
}])
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
@ -247,24 +393,28 @@ class LineTestCase(ModuleTestCase):
'category': category_in.id, 'category': category_in.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 6, 1), 'date': date(2022, 6, 1),
'description': 'Expense', 'description': 'Expense',
'category': category_out.id, 'category': category_out.id,
'bookingtype': 'out', 'bookingtype': 'out',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 6, 1), 'date': date(2022, 6, 1),
'description': 'Transfer from', 'description': 'Transfer from',
'category': category_in.id, 'category': category_in.id,
'bookingtype': 'mvin', 'bookingtype': 'mvin',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'booktransf': book2.id,
}, { }, {
'date': date(2022, 6, 1), 'date': date(2022, 6, 1),
'description': 'Transfer to', 'description': 'Transfer to',
'category': category_out.id, 'category': category_out.id,
'bookingtype': 'mvout', 'bookingtype': 'mvout',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'booktransf': book2.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -276,6 +426,11 @@ class LineTestCase(ModuleTestCase):
self.assertEqual(book.lines[0].credit, Decimal('1.0')) self.assertEqual(book.lines[0].credit, Decimal('1.0'))
self.assertEqual(book.lines[0].debit, Decimal('0.0')) self.assertEqual(book.lines[0].debit, Decimal('0.0'))
# check payee
self.assertEqual(book.lines[0].payee.rec_name, 'Party')
self.assertEqual(Line.search_count([('payee', 'ilike', 'party%')]), 2)
self.assertEqual(Line.search_count([('payee', 'ilike', 'book%')]), 2)
self.assertEqual(book.lines[1].amount, Decimal('1.0')) self.assertEqual(book.lines[1].amount, Decimal('1.0'))
self.assertEqual(book.lines[1].bookingtype, 'out') self.assertEqual(book.lines[1].bookingtype, 'out')
self.assertEqual(book.lines[1].credit, Decimal('0.0')) self.assertEqual(book.lines[1].credit, Decimal('0.0'))
@ -318,6 +473,7 @@ class LineTestCase(ModuleTestCase):
'category': category_in.id, 'category': category_in.id,
'bookingtype': 'mvin', 'bookingtype': 'mvin',
'amount': Decimal('3.0'), 'amount': Decimal('3.0'),
'booktransf': book2.id,
}]) }])
self.assertEqual(book.lines[0].amount, Decimal('3.0')) self.assertEqual(book.lines[0].amount, Decimal('3.0'))
self.assertEqual(book.lines[0].bookingtype, 'mvin') self.assertEqual(book.lines[0].bookingtype, 'mvin')
@ -337,6 +493,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
with Transaction().set_context({ with Transaction().set_context({
'company': company.id, 'company': company.id,
@ -370,12 +527,14 @@ class LineTestCase(ModuleTestCase):
'category': category2.id, 'category': category2.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 6, 1), 'date': date(2022, 6, 1),
'description': 'Text 2', 'description': 'Text 2',
'category': category2.childs[0].id, 'category': category2.childs[0].id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -407,6 +566,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -418,12 +578,14 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 2), 'date': date(2022, 5, 2),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -443,6 +605,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -454,12 +617,14 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 2), 'date': date(2022, 5, 2),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -484,6 +649,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -495,12 +661,14 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 2), 'date': date(2022, 5, 2),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -529,6 +697,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')]) grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
usr_lst = ResUser.create([{ usr_lst = ResUser.create([{
'login': 'frida', 'login': 'frida',
@ -559,6 +728,7 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'), self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'),
@ -577,14 +747,15 @@ class LineTestCase(ModuleTestCase):
lines = Line.search([]) lines = Line.search([])
self.assertEqual(len(lines), 1) self.assertEqual(len(lines), 1)
self.assertEqual(lines[0].cashbook.rec_name, 'Fridas book | 1.00 usd | Open') self.assertEqual(lines[0].cashbook.rec_name, 'Fridas book | 1.00 usd | Open')
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 1 [Cat1]')
Line.write(*[ Line.write(*[
lines, lines,
{ {
'description': 'Test 2', 'description': 'Test 2',
}]) }])
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 2 [Cat1]')
self.assertEqual(lines[0].owner_cashbook.rec_name, 'Frida')
@with_transaction() @with_transaction()
def test_line_permission_reviewer(self): def test_line_permission_reviewer(self):
@ -599,6 +770,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')]) grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
grp_reviewer, = ResGroup.create([{ grp_reviewer, = ResGroup.create([{
'name': 'Cashbook Reviewer', 'name': 'Cashbook Reviewer',
@ -636,6 +808,7 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'), self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'),
@ -650,25 +823,25 @@ class LineTestCase(ModuleTestCase):
self.assertEqual(len(lines), 1) self.assertEqual(len(lines), 1)
self.assertEqual(len(lines[0].cashbook.reviewer.users), 1) self.assertEqual(len(lines[0].cashbook.reviewer.users), 1)
self.assertEqual(lines[0].cashbook.reviewer.users[0].rec_name, 'Diego') self.assertEqual(lines[0].cashbook.reviewer.users[0].rec_name, 'Diego')
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 1 [Cat1]')
Line.write(*[ Line.write(*[
lines, lines,
{ {
'description': 'Test 2', 'description': 'Test 2',
}]) }])
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 2 [Cat1]')
# change to user 'frida' read/write line # change to user 'frida' read/write line
with Transaction().set_user(usr_lst[0].id): with Transaction().set_user(usr_lst[0].id):
lines = Line.search([]) lines = Line.search([])
self.assertEqual(len(lines), 1) self.assertEqual(len(lines), 1)
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 2 [Cat1]')
Line.write(*[ Line.write(*[
lines, lines,
{ {
'description': 'Test 3', 'description': 'Test 3',
}]) }])
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 3 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 3 [Cat1]')
@with_transaction() @with_transaction()
def test_line_permission_observer(self): def test_line_permission_observer(self):
@ -683,6 +856,7 @@ class LineTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')]) grp_cashbook, = ResGroup.search([('name', '=', 'Cashbook')])
grp_observer, = ResGroup.create([{ grp_observer, = ResGroup.create([{
'name': 'Cashbook Observer', 'name': 'Cashbook Observer',
@ -720,6 +894,7 @@ class LineTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
}]) }])
self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'), self.assertEqual(book.rec_name, 'Fridas book | 1.00 usd | Open'),
@ -734,7 +909,7 @@ class LineTestCase(ModuleTestCase):
self.assertEqual(len(lines), 1) self.assertEqual(len(lines), 1)
self.assertEqual(len(lines[0].cashbook.observer.users), 1) self.assertEqual(len(lines[0].cashbook.observer.users), 1)
self.assertEqual(lines[0].cashbook.observer.users[0].rec_name, 'Diego') self.assertEqual(lines[0].cashbook.observer.users[0].rec_name, 'Diego')
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 1 [Cat1]')
self.assertRaisesRegex(UserError, self.assertRaisesRegex(UserError,
'You are not allowed to write to records "[0-9]{1,}" of "Cashbook Line" because of at least one of these rules:\nOwners and reviewers: Cashbook line write - ', 'You are not allowed to write to records "[0-9]{1,}" of "Cashbook Line" because of at least one of these rules:\nOwners and reviewers: Cashbook line write - ',
@ -750,12 +925,12 @@ class LineTestCase(ModuleTestCase):
with Transaction().set_user(usr_lst[0].id): with Transaction().set_user(usr_lst[0].id):
lines = Line.search([]) lines = Line.search([])
self.assertEqual(len(lines), 1) self.assertEqual(len(lines), 1)
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 1 [Cat1]')
Line.write(*[ Line.write(*[
lines, lines,
{ {
'description': 'Test 2', 'description': 'Test 2',
}]) }])
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]') self.assertEqual(lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Test 2 [Cat1]')
# end LineTestCase # end LineTestCase

View file

@ -202,6 +202,7 @@ class ReconTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
company = self.prep_company() company = self.prep_company()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -219,12 +220,14 @@ class ReconTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'description': 'Line 1', 'description': 'Line 1',
'amount': Decimal('5.0'), 'amount': Decimal('5.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 5), 'date': date(2022, 5, 5),
'bookingtype': 'in', 'bookingtype': 'in',
'category': category.id, 'category': category.id,
'description': 'Line 2', 'description': 'Line 2',
'amount': Decimal('7.0'), 'party': party.id,
'amount': Decimal('7.0'),
},])], },])],
}]) }])
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
@ -344,6 +347,7 @@ class ReconTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -355,12 +359,14 @@ class ReconTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 5), 'date': date(2022, 5, 5),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
'reconciliations': [('create', [{ 'reconciliations': [('create', [{
'date': date(2022, 5, 28), 'date': date(2022, 5, 28),
@ -371,14 +377,14 @@ class ReconTestCase(ModuleTestCase):
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
self.assertEqual(book.state, 'open') self.assertEqual(book.state, 'open')
self.assertEqual(len(book.lines), 2) self.assertEqual(len(book.lines), 2)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[1].rec_name, '05/05/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '05/05/2022|Rev|1.00 usd|Text 2 [Cat1]')
self.assertEqual(len(book.reconciliations), 1) self.assertEqual(len(book.reconciliations), 1)
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]')
self.assertEqual(len(book.reconciliations[0].lines), 0) self.assertEqual(len(book.reconciliations[0].lines), 0)
self.assertRaisesRegex(UserError, self.assertRaisesRegex(UserError,
"For reconciliation, the line '05/01/2022|1.00 usd|Text 1 [Cat1]' must be in the status 'Check' or 'Done'.", "For reconciliation, the line '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]' must be in the status 'Check' or 'Done'.",
Lines.write, Lines.write,
*[ *[
[book.lines[0]], [book.lines[0]],
@ -420,9 +426,9 @@ 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(len(book.reconciliations[0].lines), 1) self.assertEqual(len(book.reconciliations[0].lines), 1)
self.assertEqual(book.reconciliations[0].lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.reconciliations[0].lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[1].rec_name, '06/01/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '06/01/2022|Rev|1.00 usd|Text 2 [Cat1]')
# move 2nd line into date-range of checked-reconciliation, wf-check # move 2nd line into date-range of checked-reconciliation, wf-check
Lines.write(*[ Lines.write(*[
@ -481,6 +487,7 @@ class ReconTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -492,12 +499,14 @@ class ReconTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 6, 5), 'date': date(2022, 6, 5),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
'reconciliations': [('create', [{ 'reconciliations': [('create', [{
'date': date(2022, 5, 28), 'date': date(2022, 5, 28),
@ -508,13 +517,13 @@ class ReconTestCase(ModuleTestCase):
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
self.assertEqual(book.state, 'open') self.assertEqual(book.state, 'open')
self.assertEqual(len(book.lines), 2) self.assertEqual(len(book.lines), 2)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[1].rec_name, '06/05/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '06/05/2022|Rev|1.00 usd|Text 2 [Cat1]')
Lines.wfcheck([book.lines[0]]) Lines.wfcheck([book.lines[0]])
Reconciliation.wfcheck([book.reconciliations[0]]) Reconciliation.wfcheck([book.reconciliations[0]])
self.assertEqual(len(book.reconciliations[0].lines), 1) self.assertEqual(len(book.reconciliations[0].lines), 1)
self.assertEqual(book.reconciliations[0].lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.reconciliations[0].lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
Lines.write(*[ Lines.write(*[
[book.lines[1]], [book.lines[1]],
@ -539,6 +548,7 @@ class ReconTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -550,6 +560,7 @@ class ReconTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
'reconciliations': [('create', [{ 'reconciliations': [('create', [{
'date': date(2022, 5, 28), 'date': date(2022, 5, 28),
@ -599,6 +610,7 @@ class ReconTestCase(ModuleTestCase):
types = self.prep_type() types = self.prep_type()
category = self.prep_category(cattype='in') category = self.prep_category(cattype='in')
company = self.prep_company() company = self.prep_company()
party = self.prep_party()
book, = Book.create([{ book, = Book.create([{
'name': 'Book 1', 'name': 'Book 1',
'btype': types.id, 'btype': types.id,
@ -610,12 +622,14 @@ class ReconTestCase(ModuleTestCase):
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}, { }, {
'date': date(2022, 5, 5), 'date': date(2022, 5, 5),
'description': 'Text 2', 'description': 'Text 2',
'category': category.id, 'category': category.id,
'bookingtype': 'in', 'bookingtype': 'in',
'amount': Decimal('1.0'), 'amount': Decimal('1.0'),
'party': party.id,
}])], }])],
'reconciliations': [('create', [{ 'reconciliations': [('create', [{
'date': date(2022, 5, 28), 'date': date(2022, 5, 28),
@ -626,8 +640,8 @@ class ReconTestCase(ModuleTestCase):
self.assertEqual(book.name, 'Book 1') self.assertEqual(book.name, 'Book 1')
self.assertEqual(book.state, 'open') self.assertEqual(book.state, 'open')
self.assertEqual(len(book.lines), 2) self.assertEqual(len(book.lines), 2)
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]') self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]')
self.assertEqual(book.lines[1].rec_name, '05/05/2022|1.00 usd|Text 2 [Cat1]') self.assertEqual(book.lines[1].rec_name, '05/05/2022|Rev|1.00 usd|Text 2 [Cat1]')
self.assertEqual(book.lines[0].reconciliation, None) self.assertEqual(book.lines[0].reconciliation, None)
self.assertEqual(book.lines[1].reconciliation, None) self.assertEqual(book.lines[1].reconciliation, None)
self.assertEqual(len(book.reconciliations), 1) self.assertEqual(len(book.reconciliations), 1)

View file

@ -35,4 +35,13 @@ full copyright notices and license terms. -->
<group name="description" colspan="4" col="1" string="Description"> <group name="description" colspan="4" col="1" string="Description">
<field name="description"/> <field name="description"/>
</group> </group>
<newline/>
<label name="reference"/>
<field name="reference"/>
<newline/>
<field name="references" colspan="4"/>
<newline/>
<field name="owner_cashbook"/>
</form> </form>

View file

@ -5,8 +5,7 @@ full copyright notices and license terms. -->
<tree> <tree>
<field name="cashbook" tree_invisible="1"/> <field name="cashbook" tree_invisible="1"/>
<field name="date"/> <field name="date"/>
<field name="party"/> <field name="payee"/>
<field name="booktransf"/>
<field name="category_view"/> <field name="category_view"/>
<field name="description" expand="1"/> <field name="description" expand="1"/>
<field name="credit" sum="Credit"/> <field name="credit" sum="Credit"/>