From 91a34e216b188349c12be795e084094e451aac5a Mon Sep 17 00:00:00 2001 From: Frederik Jaeckel Date: Thu, 18 Aug 2022 11:58:05 +0200 Subject: [PATCH] book: Feld 'start_date' + test, line: balance-berechnung mit abstimmung gekoppelt + test, abstimmung: start/enddatum automatisch --- book.py | 14 ++++ book.xml | 3 + line.py | 59 ++++++++++++-- locale/de.po | 36 +++++++++ locale/en.po | 90 ++++++++++++++++++++- message.xml | 3 + reconciliation.py | 39 +++++++++- tests/test_book.py | 5 +- tests/test_line.py | 134 ++++++++++++++++++++++++++++++++ tests/test_reconciliation.py | 65 +++++++++++++++- view/book_form.xml | 3 + view/line_form.xml | 6 +- view/wizard_runrepbook_form.xml | 9 +++ 13 files changed, 446 insertions(+), 20 deletions(-) diff --git a/book.py b/book.py index 6484f34..dd92f35 100644 --- a/book.py +++ b/book.py @@ -68,6 +68,13 @@ class Book(Workflow, ModelSQL, ModelView): states=STATES, depends=DEPENDS+['company']) number_atcheck = fields.Boolean(string="number when 'Checking'", help="The numbering of the lines is done in the step Check. If the check mark is inactive, this happens with Done.") + start_date = fields.Date(string='Initial Date', required=True, + states={ + 'readonly': Or( + STATES['readonly'], + Bool(Eval('lines')), + ), + }, depends=DEPENDS+['lines']) start_balance = fields.Numeric(string='Initial Amount', required=True, states={ 'readonly': Or( @@ -146,6 +153,13 @@ class Book(Workflow, ModelSQL, ModelView): def default_company(): return Transaction().context.get('company') or None + @classmethod + def default_start_date(cls): + """ today + """ + IrDate = Pool().get('ir.date') + return IrDate.today() + @classmethod def default_state(cls): return 'open' diff --git a/book.xml b/book.xml index 5b2b1e7..465bcaf 100644 --- a/book.xml +++ b/book.xml @@ -145,6 +145,7 @@ full copyright notices and license terms. --> wfopen Open + An open cashbook can be edited. wfclosed Close + A closed cashbook can no longer be booked. However, it can be reopened afterwards. wfarchive Archive + An archived cashbook is locked. 0: + query.extend([ + ['OR', + ('date', '>', recons[0].date_from), + [ + ('date', '=', recons[0].date_from), + ('reconciliation.id', '=',recons[0].id), + ], + ] + ]) + balance = recons[0].start_amount + + lines = Line.search(query) for line in lines: balance += line.credit - line.debit if line.id == self.id: @@ -535,6 +565,19 @@ class Line(Workflow, ModelSQL, ModelView): raise ValueError('invalid "bookingtype"') return {} + @classmethod + def validate(cls, lines): + """ deny date before 'start_date' of cashbook + """ + super(Line, cls).validate(lines) + for line in lines: + if line.date < line.cashbook.start_date: + raise UserError(gettext( + 'cashbook.msg_line_date_before_book', + datebook = Report.format_date(line.cashbook.start_date), + recname = line.rec_name, + )) + @classmethod def copy(cls, lines, default=None): """ reset values @@ -580,7 +623,7 @@ class Line(Workflow, ModelSQL, ModelView): to_write = [] for lines, values in zip(actions, actions): for line in lines: - # deny write if chashbook is not open + # deny write if cashbook is not open if line.cashbook.state != 'open': raise UserError(gettext( 'cashbook.msg_book_deny_write', diff --git a/locale/de.po b/locale/de.po index 9bdb54f..256b514 100644 --- a/locale/de.po +++ b/locale/de.po @@ -130,6 +130,10 @@ msgctxt "model:ir.message,text:msg_rep_reconciliation_fname" msgid "%(recname)s Reconciliation from %(date_from)s to %(date_to)s" msgstr "%(recname)s Abstimmung von %(date_from)s bis %(date_to)s" +msgctxt "model:ir.message,text:msg_line_date_before_book" +msgid "The date of the cashbook line '%(recname)s' cannot be earlier than the start date '%(datebook)s' of the cashbook." +msgstr "Das Datum der Kassenbuchzeile '%(recname)s' kann nicht vor dem Anfangsdatum '%(datebook)s' des Kassenbuchs liegen." + ############# # res.group # @@ -302,14 +306,26 @@ msgctxt "model:ir.model.button,string:book_wfopen_button" msgid "Open" msgstr "Öffnen" +msgctxt "model:ir.model.button,help:book_wfopen_button" +msgid "An open cashbook can be edited." +msgstr "Ein geöffnetes Kassenbuch kann bearbeitet werden." + msgctxt "model:ir.model.button,string:book_wfclosed_button" msgid "Close" msgstr "Schliessen" +msgctxt "model:ir.model.button,help:book_wfclosed_button" +msgid "A closed cashbook can no longer be booked. However, it can be reopened afterwards." +msgstr "Ein geschlossenes Kassenbuch kann nicht mehr bebucht werden. Es kann jedoch danach wieder geöffnet werden." + msgctxt "model:ir.model.button,string:book_wfarchive_button" msgid "Archive" msgstr "Archiv" +msgctxt "model:ir.model.button,help:book_wfarchive_button" +msgid "An archived cashbook is locked." +msgstr "Ein archiviertes Kassenbuch ist gesperrt." + msgctxt "model:ir.model.button,string:recon_wfedit_button" msgid "Edit" msgstr "Bearbeiten" @@ -402,6 +418,10 @@ msgctxt "field:cashbook.book,start_balance:" msgid "Initial Amount" msgstr "Anfangsbetrag" +msgctxt "field:cashbook.book,start_date:" +msgid "Initial Date" +msgstr "Anfangsdatum" + msgctxt "field:cashbook.book,balance:" msgid "Balance" msgstr "Saldo" @@ -950,6 +970,22 @@ msgctxt "model:cashbook.runrepbook.start,name:" msgid "Cashbook Report" msgstr "Kassenbuch Bericht" +msgctxt "view:cashbook.runrepbook.start:" +msgid "Information" +msgstr "Information" + +msgctxt "view:cashbook.runrepbook.start:" +msgid "Here you can export a cashbook in tabular form for printing." +msgstr "Sie können hier ein Kassenbuch in Tabellenform zum Drucken exportieren." + +msgctxt "view:cashbook.runrepbook.start:" +msgid "The time range for the export is determined by the created reconciliation." +msgstr "Der zeitliche Bereich für den Export wird durch die erstellte Abstimmung festgelegt." + +msgctxt "view:cashbook.runrepbook.start:" +msgid "If you have not already done so, first create a reconciliation for the cashbook." +msgstr "Wenn noch nicht erfolgt, erstellen Sie zunächst eine Abstimmung für das Kassenbuch." + msgctxt "field:cashbook.runrepbook.start,cashbook:" msgid "Cashbook" msgstr "Kassenbuch" diff --git a/locale/en.po b/locale/en.po index 54ab2dc..f1aabcf 100644 --- a/locale/en.po +++ b/locale/en.po @@ -138,9 +138,17 @@ msgctxt "model:res.group,name:group_cashbook_doneline" msgid "Cashbook - WF - Done" msgstr "Cashbook - WF - Done" -msgctxt "model:ir.rule.group,name:rg_book_read" -msgid "Owners, observers and reviewers: Cashbook read" -msgstr "Owners, observers and reviewers: Cashbook read" +msgctxt "model:res.group,name:group_cashbook_admin" +msgid "Cashbook - Administrator" +msgstr "Cashbook - Administrator" + +msgctxt "model:ir.rule.group,name:rg_book_rw_owner" +msgid "Owners: Cashbook read/write" +msgstr "Owners: Cashbook read/write" + +msgctxt "model:ir.rule.group,name:rg_book_read_nonowner" +msgid "Observers and Reviewers: Cashbook read" +msgstr "Observers and Reviewers: Cashbook read" msgctxt "model:ir.rule.group,name:rg_book_write_adm" msgid "Administrators: Cashbook read/write" @@ -866,6 +874,22 @@ msgctxt "model:cashbook.runrepbook.start,name:" msgid "Cashbook Report" msgstr "Cashbook Report" +msgctxt "view:cashbook.runrepbook.start:" +msgid "Information" +msgstr "Information" + +msgctxt "view:cashbook.runrepbook.start:" +msgid "Here you can export a cashbook in tabular form for printing." +msgstr "Here you can export a cashbook in tabular form for printing." + +msgctxt "view:cashbook.runrepbook.start:" +msgid "The time range for the export is determined by the created reconciliation." +msgstr "The time range for the export is determined by the created reconciliation." + +msgctxt "view:cashbook.runrepbook.start:" +msgid "If you have not already done so, first create a reconciliation for the cashbook." +msgstr "If you have not already done so, first create a reconciliation for the cashbook." + msgctxt "field:cashbook.runrepbook.start,cashbook:" msgid "Cashbook" msgstr "Cashbook" @@ -878,3 +902,63 @@ msgctxt "field:cashbook.runrepbook.start,reconciliation:" msgid "Reconciliation" msgstr "Reconciliation" +msgctxt "field:cashbook.runrepbook.start,reconciliations:" +msgid "Reconciliations" +msgstr "Reconciliations" + +msgctxt "report:cashbook.reprecon:" +msgid "Cashbook:" +msgstr "Cashbook:" + +msgctxt "report:cashbook.reprecon:" +msgid "Period:" +msgstr "Period:" + +msgctxt "report:cashbook.reprecon:" +msgid "to" +msgstr "to" + +msgctxt "report:cashbook.reprecon:" +msgid "Bookings:" +msgstr "Bookings:" + +msgctxt "report:cashbook.reprecon:" +msgid "Initial Amount" +msgstr "Initial Amount" + +msgctxt "report:cashbook.reprecon:" +msgid "End Amount" +msgstr "End Amount" + +msgctxt "report:cashbook.reprecon:" +msgid "Date" +msgstr "Date" + +msgctxt "report:cashbook.reprecon:" +msgid "No." +msgstr "No." + +msgctxt "report:cashbook.reprecon:" +msgid "Description" +msgstr "Description" + +msgctxt "report:cashbook.reprecon:" +msgid "Revenue" +msgstr "Revenue" + +msgctxt "report:cashbook.reprecon:" +msgid "Expense" +msgstr "Expense" + +msgctxt "report:cashbook.reprecon:" +msgid "Sum" +msgstr "Sum" + +msgctxt "report:cashbook.reprecon:" +msgid "- Expenses" +msgstr "- Expenses" + +msgctxt "report:cashbook.reprecon:" +msgid "Total" +msgstr "Total" + diff --git a/message.xml b/message.xml index da666f8..2ca8f44 100644 --- a/message.xml +++ b/message.xml @@ -98,6 +98,9 @@ full copyright notices and license terms. --> %(recname)s Reconciliation from %(date_from)s to %(date_to)s + + The date of the cashbook line '%(recname)s' cannot be earlier than the start date '%(datebook)s' of the cashbook. + diff --git a/reconciliation.py b/reconciliation.py index 37bc15f..59a548d 100644 --- a/reconciliation.py +++ b/reconciliation.py @@ -13,6 +13,7 @@ from trytond.i18n import gettext from decimal import Decimal from sql.operators import Equal, Between from sql import Literal, Null +from datetime import timedelta from .book import sel_state_book @@ -299,6 +300,22 @@ class Reconciliation(Workflow, ModelSQL, ModelView): 'num': len(self.lines), } + @classmethod + def default_date_from(cls): + """ 1st day of current month + """ + return Pool().get('ir.date').today().replace(day=1) + + @classmethod + def default_date_to(cls): + """ last day of current month + """ + IrDate = Pool().get('ir.date') + + dt1 = IrDate.today().replace(day=28) + timedelta(days=5) + dt1 = dt1.replace(day=1) - timedelta(days=1) + return dt1 + @classmethod def default_start_amount(cls): return Decimal('0.0') @@ -360,15 +377,31 @@ class Reconciliation(Workflow, ModelSQL, ModelView): def create(cls, vlist): """ add debit/credit """ - Recon = Pool().get('cashbook.recon') + pool = Pool() + Recon = pool.get('cashbook.recon') + Line = pool.get('cashbook.line') + Cashbook = pool.get('cashbook.book') for values in vlist: - # set date_from date_to of predecessor + id_cashbook = values.get('cashbook', -1) + + # set date_from to date_to of predecessor recons = Recon.search([ - ('cashbook.id', '=', values.get('cashbook', -1)), + ('cashbook.id', '=', id_cashbook), ], order=[('date_to', 'DESC')], limit=1) if len(recons) > 0: values['date_from'] = recons[0].date_to + elif id_cashbook != -1: + values['date_from'] = Cashbook(id_cashbook).start_date + + # set date_to to day of last 'checked'-booking in selected cashbook + lines = Line.search([ + ('cashbook.id', '=', id_cashbook), + ('state', '=', 'check'), + ('reconciliation', '=', None), + ], order=[('date', 'DESC')], limit=1) + if len(lines) > 0: + values['date_to'] = lines[0].date cls.check_overlap_dates( values.get('date_from', None), diff --git a/tests/test_book.py b/tests/test_book.py index b2d2a72..34e5c3e 100644 --- a/tests/test_book.py +++ b/tests/test_book.py @@ -72,6 +72,7 @@ class BookTestCase(ModuleTestCase): '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', @@ -106,6 +107,7 @@ class BookTestCase(ModuleTestCase): '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', @@ -142,6 +144,7 @@ class BookTestCase(ModuleTestCase): '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', @@ -333,7 +336,7 @@ class BookTestCase(ModuleTestCase): self.assertEqual(books[0].rec_name, 'Fridas book | 0.00 usd | Open') self.assertRaisesRegex(UserError, - 'You are not allowed to access "Cashbook".', + 'You are not allowed to access "Cashbook.Name".', Book.write, *[ books, diff --git a/tests/test_line.py b/tests/test_line.py index e0f51bd..7848d4e 100644 --- a/tests/test_line.py +++ b/tests/test_line.py @@ -16,6 +16,124 @@ class LineTestCase(ModuleTestCase): 'Test cashbook line module' module = 'cashbook' + @with_transaction() + def test_line_check_balance_by_line(self): + """ create cashbook, lines, reconciliations, + check calculation of balance per line + """ + pool = Pool() + Book = pool.get('cashbook.book') + Lines = pool.get('cashbook.line') + Reconciliation = pool.get('cashbook.recon') + + 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': 'Text 1', + 'category': category.id, + 'bookingtype': 'in', + 'amount': Decimal('1.0'), + 'party': party.id, + }, { + 'date': date(2022, 5, 2), + 'description': 'Text 2', + 'category': category.id, + 'bookingtype': 'in', + 'amount': Decimal('1.0'), + 'party': party.id, + }, { + 'date': date(2022, 5, 15), + 'description': 'Text 3', + 'category': category.id, + 'bookingtype': 'in', + 'amount': Decimal('1.0'), + 'party': party.id, + }, { + 'date': date(2022, 5, 17), + 'description': 'Text 4', + 'category': category.id, + 'bookingtype': 'in', + 'amount': Decimal('1.0'), + 'party': party.id, + }])], + }]) + + self.assertEqual(len(book.lines), 4) + self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]') + self.assertEqual(book.lines[0].balance, Decimal('1.0')) + self.assertEqual(book.lines[0].reconciliation, None) + self.assertEqual(book.lines[0].state, 'edit') + self.assertEqual(book.lines[1].rec_name, '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]') + self.assertEqual(book.lines[1].balance, Decimal('2.0')) + self.assertEqual(book.lines[1].reconciliation, None) + self.assertEqual(book.lines[1].state, 'edit') + self.assertEqual(book.lines[2].rec_name, '05/15/2022|Rev|1.00 usd|Text 3 [Cat1]') + self.assertEqual(book.lines[2].balance, Decimal('3.0')) + self.assertEqual(book.lines[2].reconciliation, None) + self.assertEqual(book.lines[2].state, 'edit') + self.assertEqual(book.lines[3].rec_name, '05/17/2022|Rev|1.00 usd|Text 4 [Cat1]') + self.assertEqual(book.lines[3].balance, Decimal('4.0')) + self.assertEqual(book.lines[3].reconciliation, None) + self.assertEqual(book.lines[3].state, 'edit') + + Lines.wfcheck([book.lines[0], book.lines[1]]) + recon, = Reconciliation.create([{ + 'cashbook': book.id, + }]) + self.assertEqual(recon.rec_name, '05/01/2022 - 05/02/2022 | 0.00 usd - 0.00 usd [0]') + + Reconciliation.wfcheck([recon]) + self.assertEqual(recon.rec_name, '05/01/2022 - 05/02/2022 | 0.00 usd - 2.00 usd [2]') + + self.assertEqual(len(book.lines), 4) + self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]') + self.assertEqual(book.lines[0].balance, Decimal('1.0')) + self.assertEqual(book.lines[0].reconciliation.id, recon.id) + self.assertEqual(book.lines[0].state, 'check') + self.assertEqual(book.lines[1].rec_name, '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]') + self.assertEqual(book.lines[1].balance, Decimal('2.0')) + self.assertEqual(book.lines[1].reconciliation.id, recon.id) + self.assertEqual(book.lines[1].state, 'check') + self.assertEqual(book.lines[2].rec_name, '05/15/2022|Rev|1.00 usd|Text 3 [Cat1]') + self.assertEqual(book.lines[2].balance, Decimal('3.0')) + self.assertEqual(book.lines[2].reconciliation, None) + self.assertEqual(book.lines[2].state, 'edit') + self.assertEqual(book.lines[3].rec_name, '05/17/2022|Rev|1.00 usd|Text 4 [Cat1]') + self.assertEqual(book.lines[3].balance, Decimal('4.0')) + self.assertEqual(book.lines[3].reconciliation, None) + self.assertEqual(book.lines[3].state, 'edit') + + Reconciliation.wfdone([recon]) + self.assertEqual(recon.rec_name, '05/01/2022 - 05/02/2022 | 0.00 usd - 2.00 usd [2]') + + self.assertEqual(len(book.lines), 4) + self.assertEqual(book.lines[0].rec_name, '05/01/2022|Rev|1.00 usd|Text 1 [Cat1]') + self.assertEqual(book.lines[0].balance, Decimal('1.0')) + self.assertEqual(book.lines[0].reconciliation.id, recon.id) + self.assertEqual(book.lines[0].state, 'done') + self.assertEqual(book.lines[1].rec_name, '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]') + self.assertEqual(book.lines[1].balance, Decimal('2.0')) + self.assertEqual(book.lines[1].reconciliation.id, recon.id) + self.assertEqual(book.lines[1].state, 'done') + self.assertEqual(book.lines[2].rec_name, '05/15/2022|Rev|1.00 usd|Text 3 [Cat1]') + self.assertEqual(book.lines[2].balance, Decimal('3.0')) + self.assertEqual(book.lines[2].reconciliation, None) + self.assertEqual(book.lines[2].state, 'edit') + self.assertEqual(book.lines[3].rec_name, '05/17/2022|Rev|1.00 usd|Text 4 [Cat1]') + self.assertEqual(book.lines[3].balance, Decimal('4.0')) + self.assertEqual(book.lines[3].reconciliation, None) + self.assertEqual(book.lines[3].state, 'edit') + @with_transaction() def test_line_create_check_names_search(self): """ create cashbook + line @@ -34,6 +152,7 @@ class LineTestCase(ModuleTestCase): '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': 'Text 1', @@ -115,6 +234,7 @@ class LineTestCase(ModuleTestCase): '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': 'Text 1', @@ -187,6 +307,7 @@ class LineTestCase(ModuleTestCase): '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': 'Text 1', @@ -254,6 +375,7 @@ class LineTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), }]) book, = Book.create([{ @@ -262,6 +384,7 @@ class LineTestCase(ModuleTestCase): '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': 'Transfer Out', @@ -318,6 +441,7 @@ class LineTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), }]) book, = Book.create([{ @@ -326,6 +450,7 @@ class LineTestCase(ModuleTestCase): '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': 'Transfer In', @@ -388,6 +513,7 @@ class LineTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), }]) book, = Book.create([{ @@ -396,6 +522,7 @@ class LineTestCase(ModuleTestCase): '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': 'Revenue', @@ -531,6 +658,7 @@ class LineTestCase(ModuleTestCase): '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': 'Text 1', @@ -582,6 +710,7 @@ class LineTestCase(ModuleTestCase): 'btype': types.id, 'company': company.id, 'currency': company.currency.id, + 'start_date': date(2022, 5, 1), 'number_sequ': self.prep_sequence().id, 'lines': [('create', [{ 'date': date(2022, 5, 1), @@ -623,6 +752,7 @@ class LineTestCase(ModuleTestCase): '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': 'Text 1', @@ -668,6 +798,7 @@ class LineTestCase(ModuleTestCase): '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': 'Text 1', @@ -736,6 +867,7 @@ class LineTestCase(ModuleTestCase): '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', @@ -817,6 +949,7 @@ class LineTestCase(ModuleTestCase): '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', @@ -904,6 +1037,7 @@ class LineTestCase(ModuleTestCase): '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', diff --git a/tests/test_reconciliation.py b/tests/test_reconciliation.py index a25669b..caa3636 100644 --- a/tests/test_reconciliation.py +++ b/tests/test_reconciliation.py @@ -32,6 +32,7 @@ class ReconTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), }]) recon1, = Reconciliation.create([{ @@ -179,6 +180,7 @@ class ReconTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'start_balance': Decimal('12.50'), + 'start_date': date(2022, 5, 1), 'number_sequ': self.prep_sequence().id, 'reconciliations': [('create', [{ 'date': date(2022, 5, 28), @@ -211,6 +213,7 @@ class ReconTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'start_balance': Decimal('12.50'), + 'start_date': date(2022, 5, 1), 'number_sequ': self.prep_sequence().id, 'reconciliations': [('create', [{ 'date': date(2022, 5, 28), @@ -271,6 +274,7 @@ class ReconTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), 'reconciliations': [('create', [{ 'date': date(2022, 5, 28), 'date_from': date(2022, 5, 1), @@ -293,6 +297,56 @@ class ReconTestCase(ModuleTestCase): Reconciliation.wfcheck, recons) + @with_transaction() + def test_recon_autoset_date_to(self): + """ create reconciliation, check: set date_to to last date of checked-line + """ + pool = Pool() + Book = pool.get('cashbook.book') + Line = pool.get('cashbook.line') + Reconciliation = pool.get('cashbook.recon') + + types = self.prep_type() + company = self.prep_company() + party = self.prep_party() + category = self.prep_category(cattype='in') + 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, 5), + 'amount': Decimal('10.0'), + 'bookingtype': 'in', + 'party': party.id, + 'category': category.id, + }, { + 'date': date(2022, 5, 18), + 'amount': Decimal('5.0'), + 'bookingtype': 'in', + 'party': party.id, + 'category': category.id, + }])], + }]) + self.assertEqual(book.name, 'Book 1') + self.assertEqual(book.state, 'open') + Line.wfcheck(list(book.lines)) + + recon, = Reconciliation.create([{ + 'cashbook': book.id, + 'date': date(2022, 5, 28), + 'date_from': date(2022, 5, 5), + 'date_to': date(2022, 5, 31), + }]) + # dates are updates by .create() + self.assertEqual(recon.rec_name, '05/01/2022 - 05/18/2022 | 0.00 usd - 0.00 usd [0]') + + Reconciliation.wfcheck([recon]) + self.assertEqual(recon.rec_name, '05/01/2022 - 05/18/2022 | 0.00 usd - 15.00 usd [2]') + @with_transaction() def test_recon_autoset_date_from(self): """ create reconciliation, check: set date_from to end of predecessor @@ -309,9 +363,10 @@ class ReconTestCase(ModuleTestCase): 'company': company.id, 'currency': company.currency.id, 'number_sequ': self.prep_sequence().id, + 'start_date': date(2022, 5, 1), 'reconciliations': [('create', [{ 'date': date(2022, 5, 28), - 'date_from': date(2022, 5, 1), + 'date_from': date(2022, 5, 5), 'date_to': date(2022, 5, 31), }])], }]) @@ -320,6 +375,10 @@ class ReconTestCase(ModuleTestCase): Reconciliation.wfcheck([book.reconciliations[0]]) Reconciliation.wfdone([book.reconciliations[0]]) + # date_from is corrected by .create() to start_date of book + self.assertEqual(book.reconciliations[0].rec_name, + '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]') + r2, = Reconciliation.create([{ 'cashbook': book.id, 'date_from': date(2022, 6, 10), @@ -359,6 +418,7 @@ class ReconTestCase(ModuleTestCase): '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': 'Text 1', @@ -500,6 +560,7 @@ class ReconTestCase(ModuleTestCase): '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': 'Text 1', @@ -562,6 +623,7 @@ class ReconTestCase(ModuleTestCase): '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': 'Text 1', @@ -625,6 +687,7 @@ class ReconTestCase(ModuleTestCase): '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': 'Text 1', diff --git a/view/book_form.xml b/view/book_form.xml index 32f201e..9689b01 100644 --- a/view/book_form.xml +++ b/view/book_form.xml @@ -34,6 +34,9 @@ full copyright notices and license terms. -->