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. -->
+
+
+
diff --git a/view/line_form.xml b/view/line_form.xml
index c26d5f2..79d5241 100644
--- a/view/line_form.xml
+++ b/view/line_form.xml
@@ -31,7 +31,8 @@ full copyright notices and license terms. -->
-
+
+
@@ -42,9 +43,6 @@ full copyright notices and license terms. -->
-
-
-
diff --git a/view/wizard_runrepbook_form.xml b/view/wizard_runrepbook_form.xml
index b45e5fc..5100b1c 100644
--- a/view/wizard_runrepbook_form.xml
+++ b/view/wizard_runrepbook_form.xml
@@ -3,6 +3,15 @@
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->