diff --git a/line.py b/line.py
index 5cdc934..64734a5 100644
--- a/line.py
+++ b/line.py
@@ -77,6 +77,23 @@ class Line(Workflow, ModelSQL, ModelView):
required=True, readonly=True, depends=['currency_digits'])
credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)),
required=True, readonly=True, depends=['currency_digits'])
+
+ booktransf = fields.Many2One(string='Transfer Cashbook',
+ ondelete='RESTRICT', model_name='cashbook.book',
+ domain=[('cashbook.owner.id', '=', Eval('context',{}).get('user', -1))],
+ states={
+ 'readonly': STATES['readonly'],
+ 'invisible': ~Eval('bookingtype', '').in_(['mvin', 'mvout']),
+ 'required': Eval('bookingtype', '').in_(['mvin', 'mvout']),
+ }, depends=DEPENDS+['bookingtype'])
+ party = fields.Many2One(string='Party', model_name='party.party',
+ ondelete='RESTRICT',
+ states={
+ 'readonly': STATES['readonly'],
+ 'invisible': ~Eval('bookingtype', '').in_(['in', 'out']),
+ 'required': Eval('bookingtype', '').in_(['in', 'out']),
+ }, depends=DEPENDS+['bookingtype'])
+
reconciliation = fields.Many2One(string='Reconciliation', readonly=True,
model_name='cashbook.recon', ondelete='SET NULL',
domain=[('cashbook.id', '=', Eval('cashbook'))],
@@ -147,7 +164,36 @@ class Line(Workflow, ModelSQL, ModelView):
def wfcheck(cls, lines):
""" line is checked
"""
- pass
+ pool = Pool()
+ Recon = pool.get('cashbook.recon')
+
+ for line in lines:
+ # deny if date is in range of existing reconciliation
+ # allow cashbook-line at range-limits
+ if Recon.search_count([
+ ('state', 'in', ['check', 'done']),
+ ('cashbook.id', '=', line.cashbook.id),
+ ('date_from', '<', line.date),
+ ('date_to', '>', line.date),
+ ]) > 0:
+ raise UserError(gettext(
+ 'cashbook.msg_line_err_write_to_reconciled',
+ datetxt = Report.format_date(line.date),
+ ))
+ # deny if date is at reconciliation limits and two
+ # reconciliations exist
+ if Recon.search_count([
+ ('state', 'in', ['check', 'done']),
+ ('cashbook.id', '=', line.cashbook.id),
+ ['OR',
+ ('date_from', '=', line.date),
+ ('date_to', '=', line.date),
+ ]
+ ]) > 1:
+ raise UserError(gettext(
+ 'cashbook.msg_line_err_write_to_reconciled',
+ datetxt = Report.format_date(line.date),
+ ))
@classmethod
@ModelView.button
diff --git a/locale/de.po b/locale/de.po
index 8c8fb1d..ea9a08d 100644
--- a/locale/de.po
+++ b/locale/de.po
@@ -39,8 +39,8 @@ msgid "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linest
msgstr "Die Kassenbuchzeile '%(linetxt)s' kann nicht gelöscht werden, da sie im Status '%(linestate)s' ist."
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."
-msgstr "Der Status kann nicht in 'Bearbeiten' geändert werden, solange die Zeile '%(recname)s' mit einer Abstimmung verbunden ist."
+msgid "The status cannot be changed to 'Edit' while the line '%(recname)s' is associated with a reconciliation."
+msgstr "Der Status kann nicht in 'Bearbeiten' geändert werden, während die Zeile '%(recname)s' mit einer Abstimmung verbunden ist."
msgctxt "model:ir.message,text:msg_line_deny_write"
msgid "The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed."
@@ -86,6 +86,22 @@ msgctxt "model:ir.message,text:msg_recon_err_overlap"
msgid "The date range overlaps with another reconciliation."
msgstr "Der Datumsbereich überschneidet sich mit einer anderen Abstimmung."
+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 "Für das Datum '%(datetxt)s' gibt es bereits eine abgeschlossene Abstimmung. Verwenden Sie ein anderes Datum."
+
+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 "Im Datumsbereich von %(date_from)s bis %(date_to)s existieren noch Kassenbuchzeilen, die zu keiner Abstimmung gehören."
+
+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 "Das Anfangsdatum '%(datefrom)s' der aktuellen Abstimmung '%(recname)s' muß dem Endedatum '%(dateto)s' des Vorgängers entsprechen."
+
+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 "Der Vorgänger '%(recname_p)s' muss sich im Status 'Fertig' befinden, bevor Sie den aktuellen Abgleich '%(recname_c)s' prüfen können."
+
#############
# res.group #
@@ -474,6 +490,10 @@ msgctxt "field:cashbook.line,reconciliation:"
msgid "Reconciliation"
msgstr "Abstimmung"
+msgctxt "field:cashbook.line,party:"
+msgid "Party"
+msgstr "Partei"
+
#################
# cashbook.type #
@@ -809,3 +829,7 @@ msgstr "Anfangsbetrag"
msgctxt "field:cashbook.recon,end_amount:"
msgid "End Amount"
msgstr "Endbetrag"
+
+msgctxt "field:cashbook.recon,predecessor:"
+msgid "Predecessor"
+msgstr "Vorgänger"
diff --git a/message.xml b/message.xml
index 236efe0..2658a50 100644
--- a/message.xml
+++ b/message.xml
@@ -33,7 +33,7 @@ full copyright notices and license terms. -->
The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed.
- The status cannot be changed to 'Edit' as long as the line '%(recname)s' is associated with a reconciliation.
+ The status cannot be changed to 'Edit' while the line '%(recname)s' is associated with a reconciliation.
The reconciliation '%(recontxt)s' cannot be deleted because the Cashbook '%(bookname)s' is in state '%(bookstate)s'.
@@ -65,6 +65,18 @@ full copyright notices and license terms. -->
The date range overlaps with another reconciliation.
+
+ For the date '%(datetxt)s' there is already a completed reconciliation. Use a different date.
+
+
+ In the date range from %(date_from)s to %(date_to)s, there are still cashbook lines that do not belong to any reconciliation.
+
+
+ The start date '%(datefrom)s' of the current reconciliation '%(recname)s' must correspond to the end date '%(dateto)s' of the predecessor.
+
+
+ The predecessor '%(recname_p)s' must be in the 'Done' state before you can check the current reconciliation '%(recname_c)s'.
+
diff --git a/reconciliation.py b/reconciliation.py
index 55fe50c..f74cf2f 100644
--- a/reconciliation.py
+++ b/reconciliation.py
@@ -81,6 +81,9 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
string="Currency"), 'on_change_with_currency')
currency_digits = fields.Function(fields.Integer(string='Currency Digits'),
'on_change_with_currency_digits')
+ predecessor = fields.Function(fields.Many2One(string='Predecessor', readonly=True,
+ model_name='cashbook.recon'),
+ 'on_change_with_predecessor')
state = fields.Selection(string='State', required=True, readonly=True,
select=True, selection=sel_reconstate)
@@ -207,16 +210,25 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
for reconciliation in reconciliations:
values = {}
- # get start_amount: end_amount of predecessor
- pre_recon = Recon.search([
- ('cashbook.id', '=', reconciliation.cashbook.id),
- ('date_to', '<=', reconciliation.date_from),
- ('state', 'in', ['check', 'done']),
- ], order=[('date_to', 'DESC')], limit=1)
- if len(pre_recon) > 0:
- values['start_amount'] = pre_recon[0].end_amount
+ if reconciliation.predecessor:
+ # predecessor must be 'done'
+ if reconciliation.predecessor.state != 'done':
+ raise UserError(gettext(
+ 'cashbook.msg_recon_predecessor_not_done',
+ recname_p = reconciliation.predecessor.rec_name,
+ recname_c = reconciliation.rec_name,
+ ))
+
+ # check if current.date_from == predecessor.date_to
+ if reconciliation.predecessor.date_to != reconciliation.date_from:
+ raise UserError(gettext(
+ 'cashbook.msg_recon_date_from_to_mismatch',
+ datefrom = Report.format_date(reconciliation.date_from),
+ dateto = Report.format_date(reconciliation.predecessor.date_to),
+ recname = reconciliation.rec_name,
+ ))
+ values['start_amount'] = reconciliation.predecessor.end_amount
else :
- # not found, use 'start_balance' of cashbook
values['start_amount'] = reconciliation.cashbook.start_balance
values['end_amount'] = values['start_amount']
@@ -253,13 +265,32 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
for reconciliation in reconciliations:
to_wfdone_line.extend(list(reconciliation.lines))
+ # deny if there are lines not linked to reconciliation
+ if Line.search_count([
+ ('cashbook.id', '=', reconciliation.cashbook.id),
+ ('reconciliation', '=', None),
+ ['OR',
+ [ # lines inside of date-range
+ ('date', '>', reconciliation.date_from),
+ ('date', '<', reconciliation.date_to),
+ ],
+ # lines at from-date must relate to a reconciliation
+ ('date', '=', reconciliation.date_from),
+ ],
+ ]) > 0:
+ raise UserError(gettext(
+ 'cashbook.msg_recon_lines_no_linked',
+ date_from = Report.format_date(reconciliation.date_from),
+ date_to = Report.format_date(reconciliation.date_to),
+ ))
+
if len(to_wfdone_line) > 0:
Line.wfdone(to_wfdone_line)
def get_rec_name(self, name):
""" short + name
"""
- return '%(from)s - %(to)s | %(start_amount)s %(symbol)s - %(start_amount)s %(symbol)s [%(num)s]' % {
+ return '%(from)s - %(to)s | %(start_amount)s %(symbol)s - %(end_amount)s %(symbol)s [%(num)s]' % {
'from': Report.format_date(self.date_from, None) if self.date_from is not None else '-',
'to': Report.format_date(self.date_to, None) if self.date_to is not None else '-',
'start_amount': Report.format_number(self.start_amount or 0.0, None),
@@ -287,6 +318,21 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
IrDate = Pool().get('ir.date')
return IrDate.today()
+ @fields.depends('cashbook', '_parent_cashbook.id', 'date_from')
+ def on_change_with_predecessor(self, name=None):
+ """ get predecessor
+ """
+ Recon = Pool().get('cashbook.recon')
+
+ if self.cashbook:
+ if self.date_from is not None:
+ reconciliations = Recon.search([
+ ('cashbook.id', '=', self.cashbook.id),
+ ('date_from', '<', self.date_from),
+ ], order=[('date_from', 'DESC')], limit=1)
+ if len(reconciliations) > 0:
+ return reconciliations[0].id
+
@fields.depends('cashbook', '_parent_cashbook.currency')
def on_change_with_currency(self, name=None):
""" currency of cashbook
@@ -314,7 +360,16 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
def create(cls, vlist):
""" add debit/credit
"""
+ Recon = Pool().get('cashbook.recon')
+
for values in vlist:
+ # set date_from date_to of predecessor
+ recons = Recon.search([
+ ('cashbook.id', '=', values.get('cashbook', -1)),
+ ], order=[('date_to', 'DESC')], limit=1)
+ if len(recons) > 0:
+ values['date_from'] = recons[0].date_to
+
cls.check_overlap_dates(
values.get('date_from', None),
values.get('date_to', None),
diff --git a/tests/test_reconciliation.py b/tests/test_reconciliation.py
index 6e12b81..998b649 100644
--- a/tests/test_reconciliation.py
+++ b/tests/test_reconciliation.py
@@ -47,15 +47,10 @@ class ReconTestCase(ModuleTestCase):
'date_to': date(2022, 6, 30),
'cashbook': book.id,
}])
- self.assertEqual(recon2.rec_name, '06/01/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
+ # updated by create to date_to of predecessor
+ self.assertEqual(recon2.rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
# same day for end of '0' and start of '1'
- Reconciliation.write(*[
- [recon2],
- {
- 'date_from': date(2022, 5, 31),
- },
- ])
self.assertEqual(recon1.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
self.assertEqual(recon2.rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
@@ -146,7 +141,7 @@ class ReconTestCase(ModuleTestCase):
},
])
- # overlap at create
+ # overlap at .create()
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.create,
@@ -159,13 +154,183 @@ class ReconTestCase(ModuleTestCase):
recon3, = Reconciliation.create([{
'date': date(2022, 4, 17),
- 'date_from': date(2022, 4, 1),
- 'date_to': date(2022, 4, 15),
+ 'date_from': date(2022, 6, 1),
+ 'date_to': date(2022, 6, 15),
'cashbook': book.id,
}])
self.assertEqual(recon1.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
self.assertEqual(recon2.rec_name, '04/15/2022 - 05/01/2022 | 0.00 usd - 0.00 usd [0]')
- self.assertEqual(recon3.rec_name, '04/01/2022 - 04/15/2022 | 0.00 usd - 0.00 usd [0]')
+ self.assertEqual(recon3.rec_name, '05/31/2022 - 06/15/2022 | 0.00 usd - 0.00 usd [0]')
+
+ @with_transaction()
+ def test_recon_set_start_amount_by_cashbook(self):
+ """ set stat-amount from cashbook-setting
+ """
+ pool = Pool()
+ Book = pool.get('cashbook.book')
+ Reconciliation = pool.get('cashbook.recon')
+
+ types = self.prep_type()
+ company = self.prep_company()
+ book, = Book.create([{
+ 'name': 'Book 1',
+ 'btype': types.id,
+ 'company': company.id,
+ 'currency': company.currency.id,
+ 'start_balance': Decimal('12.50'),
+ 'reconciliations': [('create', [{
+ 'date': date(2022, 5, 28),
+ 'date_from': date(2022, 5, 1),
+ 'date_to': date(2022, 5, 31),
+ }])],
+ }])
+ self.assertEqual(book.name, 'Book 1')
+ self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
+
+ Reconciliation.wfcheck(list(book.reconciliations))
+ self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 12.50 usd - 12.50 usd [0]')
+
+ @with_transaction()
+ def test_recon_set_start_amount_by_predecessor(self):
+ """ set stat-amount from end_amount of predecessor
+ """
+ pool = Pool()
+ Book = pool.get('cashbook.book')
+ Lines = pool.get('cashbook.line')
+ Reconciliation = pool.get('cashbook.recon')
+
+ types = self.prep_type()
+ company = self.prep_company()
+ category = self.prep_category(cattype='in')
+ book, = Book.create([{
+ 'name': 'Book 1',
+ 'btype': types.id,
+ 'company': company.id,
+ 'currency': company.currency.id,
+ 'start_balance': Decimal('12.50'),
+ 'reconciliations': [('create', [{
+ 'date': date(2022, 5, 28),
+ 'date_from': date(2022, 5, 1),
+ 'date_to': date(2022, 5, 31),
+ }])],
+ 'lines': [('create', [{
+ 'date': date(2022, 5, 5),
+ 'bookingtype': 'in',
+ 'category': category.id,
+ 'description': 'Line 1',
+ 'amount': Decimal('5.0'),
+ }, {
+ 'date': date(2022, 5, 5),
+ 'bookingtype': 'in',
+ 'category': category.id,
+ 'description': 'Line 2',
+ 'amount': Decimal('7.0'),
+ },])],
+ }])
+ self.assertEqual(book.name, 'Book 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(len(book.reconciliations[0].lines), 0)
+
+ Lines.wfcheck(list(book.lines))
+ Reconciliation.wfcheck(list(book.reconciliations))
+
+ self.assertEqual(book.reconciliations[0].state, 'check')
+ self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 12.50 usd - 24.50 usd [2]')
+ Reconciliation.wfdone(list(book.reconciliations))
+ self.assertEqual(book.reconciliations[0].state, 'done')
+
+ recons = Reconciliation.create([{
+ 'cashbook': book.id,
+ 'date_from': date(2022, 5, 31),
+ 'date_to': date(2022, 6, 30),
+ }])
+ self.assertEqual(recons[0].rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
+ Reconciliation.wfcheck(recons)
+ self.assertEqual(recons[0].rec_name, '05/31/2022 - 06/30/2022 | 24.50 usd - 24.50 usd [0]')
+
+ @with_transaction()
+ def test_recon_predecessor_done(self):
+ """ predecessor must be done
+ """
+ pool = Pool()
+ Book = pool.get('cashbook.book')
+ Reconciliation = pool.get('cashbook.recon')
+
+ types = self.prep_type()
+ company = self.prep_company()
+ book, = Book.create([{
+ 'name': 'Book 1',
+ 'btype': types.id,
+ 'company': company.id,
+ 'currency': company.currency.id,
+ 'reconciliations': [('create', [{
+ 'date': date(2022, 5, 28),
+ 'date_from': date(2022, 5, 1),
+ 'date_to': date(2022, 5, 31),
+ }])],
+ }])
+ self.assertEqual(book.name, 'Book 1')
+ self.assertEqual(book.state, 'open')
+ Reconciliation.wfcheck(list(book.reconciliations))
+ 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].state, 'check')
+
+ recons = Reconciliation.create([{
+ 'cashbook': book.id,
+ 'date_from': date(2022, 5, 31),
+ 'date_to': date(2022, 6, 30),
+ }])
+ self.assertRaisesRegex(UserError,
+ "The predecessor '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]' must be in the 'Done' state before you can check the current reconciliation '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]'.",
+ Reconciliation.wfcheck,
+ recons)
+
+ @with_transaction()
+ def test_recon_autoset_date_from(self):
+ """ create reconciliation, check: set date_from to end of predecessor
+ """
+ pool = Pool()
+ Book = pool.get('cashbook.book')
+ Reconciliation = pool.get('cashbook.recon')
+
+ types = self.prep_type()
+ company = self.prep_company()
+ book, = Book.create([{
+ 'name': 'Book 1',
+ 'btype': types.id,
+ 'company': company.id,
+ 'currency': company.currency.id,
+ 'reconciliations': [('create', [{
+ 'date': date(2022, 5, 28),
+ 'date_from': date(2022, 5, 1),
+ 'date_to': date(2022, 5, 31),
+ }])],
+ }])
+ self.assertEqual(book.name, 'Book 1')
+ self.assertEqual(book.state, 'open')
+ Reconciliation.wfcheck([book.reconciliations[0]])
+ Reconciliation.wfdone([book.reconciliations[0]])
+
+ r2, = Reconciliation.create([{
+ 'cashbook': book.id,
+ 'date_from': date(2022, 6, 10),
+ 'date_to': date(2022, 6, 30),
+ }])
+ self.assertEqual(r2.rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
+
+ # update 'date_from' to wrong value
+ Reconciliation.write(*[
+ [r2],
+ {
+ 'date_from': date(2022, 6, 1),
+ }])
+ self.assertEqual(r2.rec_name, '06/01/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
+
+ self.assertRaisesRegex(UserError,
+ "The start date '06/01/2022' of the current reconciliation '06/01/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]' must correspond to the end date '05/31/2022' of the predecessor.",
+ Reconciliation.wfcheck,
+ [r2])
@with_transaction()
def test_recon_create_check_line_add_to_recon(self):
@@ -235,6 +400,133 @@ class ReconTestCase(ModuleTestCase):
Lines.wfedit,
[book.lines[0]])
+ # unlink lines from reconciliation
+ self.assertEqual(book.reconciliations[0].state, 'edit')
+ self.assertEqual(len(book.reconciliations[0].lines), 2)
+ Reconciliation.wfcheck(list(book.reconciliations))
+ Reconciliation.wfedit(list(book.reconciliations))
+ self.assertEqual(book.reconciliations[0].state, 'edit')
+ self.assertEqual(len(book.reconciliations[0].lines), 0)
+
+ # move date of 2nd line to june 1
+ # set reconciliation to 'check'
+ Lines.wfedit([book.lines[1]])
+ Lines.write(*[
+ [book.lines[1]],
+ {
+ 'date': date(2022, 6, 1),
+ }])
+ # check reconciliation, this linkes the 1st line by date
+ Reconciliation.wfcheck(list(book.reconciliations))
+ self.assertEqual(book.reconciliations[0].state, 'check')
+ 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.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]')
+ self.assertEqual(book.lines[1].rec_name, '06/01/2022|1.00 usd|Text 2 [Cat1]')
+
+ # move 2nd line into date-range of checked-reconciliation, wf-check
+ Lines.write(*[
+ [book.lines[1]],
+ {
+ 'date': date(2022, 5, 20),
+ }])
+ self.assertRaisesRegex(UserError,
+ "For the date '05/20/2022' there is already a completed reconciliation. Use a different date.",
+ Lines.wfcheck,
+ [book.lines[1]])
+
+ # set date to end of date-range of reconciliation
+ # should work
+ Lines.write(*[
+ [book.lines[1]],
+ {
+ 'date': date(2022, 5, 31),
+ }])
+ Lines.wfcheck([book.lines[1]]) # ok
+ Lines.wfedit([book.lines[1]])
+ Lines.write(*[
+ [book.lines[1]],
+ {
+ 'date': date(2022, 7, 1),
+ }])
+
+ # add 2nd reconciliation
+ recon2, = Reconciliation.create([{
+ 'cashbook': book.id,
+ 'date_from': date(2022, 5, 31),
+ 'date_to': date(2022, 6, 30),
+ }])
+ Reconciliation.wfdone([book.reconciliations[0]])
+ Reconciliation.wfcheck([recon2])
+
+ Lines.write(*[
+ [book.lines[1]],
+ {
+ 'date': date(2022, 5, 31),
+ }])
+ self.assertRaisesRegex(UserError,
+ "For the date '05/31/2022' there is already a completed reconciliation. Use a different date.",
+ Lines.wfcheck,
+ [book.lines[1]])
+
+ @with_transaction()
+ def test_recon_check_wfcheck_missing_lines(self):
+ """ create, booklines, check missing line at wfcheck
+ """
+ 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()
+ book, = Book.create([{
+ 'name': 'Book 1',
+ 'btype': types.id,
+ 'company': company.id,
+ 'currency': company.currency.id,
+ 'lines': [('create', [{
+ 'date': date(2022, 5, 1),
+ 'description': 'Text 1',
+ 'category': category.id,
+ 'bookingtype': 'in',
+ 'amount': Decimal('1.0'),
+ }, {
+ 'date': date(2022, 6, 5),
+ 'description': 'Text 2',
+ 'category': category.id,
+ 'bookingtype': 'in',
+ 'amount': Decimal('1.0'),
+ }])],
+ 'reconciliations': [('create', [{
+ 'date': date(2022, 5, 28),
+ 'date_from': date(2022, 5, 1),
+ 'date_to': date(2022, 5, 31),
+ }])],
+ }])
+ self.assertEqual(book.name, 'Book 1')
+ self.assertEqual(book.state, 'open')
+ 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[1].rec_name, '06/05/2022|1.00 usd|Text 2 [Cat1]')
+
+ Lines.wfcheck([book.lines[0]])
+ Reconciliation.wfcheck([book.reconciliations[0]])
+ 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]')
+
+ Lines.write(*[
+ [book.lines[1]],
+ {
+ 'date': date(2022, 5, 15),
+ }])
+
+ self.assertRaisesRegex(UserError,
+ "In the date range from 05/01/2022 to 05/31/2022, there are still cashbook lines that do not belong to any reconciliation.",
+ Reconciliation.wfdone,
+ [book.reconciliations[0]])
+
@with_transaction()
def test_recon_check_deny_delete(self):
""" create, booklines, reconciliation, try delete
@@ -353,8 +645,8 @@ class ReconTestCase(ModuleTestCase):
Lines.wfcheck(book.lines)
Reconciliation.wfcheck(list(book.reconciliations))
self.assertEqual(len(book.reconciliations[0].lines), 2)
- self.assertEqual(book.lines[0].reconciliation.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [2]')
- self.assertEqual(book.lines[1].reconciliation.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [2]')
+ self.assertEqual(book.lines[0].reconciliation.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 2.00 usd [2]')
+ self.assertEqual(book.lines[1].reconciliation.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 2.00 usd [2]')
# check --> edit
Reconciliation.wfedit(list(book.reconciliations))
diff --git a/tryton.cfg b/tryton.cfg
index 4ecb482..5a132ab 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -3,6 +3,7 @@ version=6.0.0
depends:
res
currency
+ party
company
xml:
icon.xml
diff --git a/view/line_form.xml b/view/line_form.xml
index aa45808..8314acb 100644
--- a/view/line_form.xml
+++ b/view/line_form.xml
@@ -7,7 +7,12 @@ full copyright notices and license terms. -->
-
+
+
+
+
+
+
diff --git a/view/line_list.xml b/view/line_list.xml
index 9d959d4..ec8702d 100644
--- a/view/line_list.xml
+++ b/view/line_list.xml
@@ -5,6 +5,8 @@ full copyright notices and license terms. -->
+
+