reconciliation: check_overlap_dates() in validate() verschoben + tests

This commit is contained in:
Frederik Jaeckel 2022-08-18 13:05:16 +02:00
parent 91a34e216b
commit 0b3f82f6c7
2 changed files with 174 additions and 141 deletions

View file

@ -117,35 +117,31 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
},
})
@classmethod
def check_overlap_dates(cls, date_from, date_to, id_cashbook, record=None):
def check_overlap_dates(self):
""" deny overlap of date_from/date_to between records of same cashbook
allow: date_to=date_from
"""
Recon = Pool().get('cashbook.recon')
query = [
('cashbook.id', '=', id_cashbook),
('cashbook.id', '=', self.cashbook.id),
('id', '!=', self.id),
['OR',
[ # 'start' is inside of other record
('date_from', '<=', date_from),
('date_to', '>', date_from),
('date_from', '<=', self.date_from),
('date_to', '>', self.date_from),
],
[ # 'end' is inside of other record
('date_from', '<', date_to),
('date_to', '>=', date_to),
('date_from', '<', self.date_to),
('date_to', '>=', self.date_to),
],
[ # enclose other record
('date_from', '>=', date_from),
('date_to', '<=', date_to),
('date_from', '>=', self.date_from),
('date_to', '<=', self.date_to),
],
],
]
# avoid finding ourselves
if record:
query.append(('id', '!=', record.id))
if Recon.search_count(query) > 0:
raise UserError(gettext('cashbook.msg_recon_err_overlap'))
@ -373,6 +369,15 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
if self.cashbook:
return self.cashbook.state
@classmethod
def validate(cls, reconciliations):
""" deny overlap of dates
"""
super(Reconciliation, cls).validate(reconciliations)
for reconciliation in reconciliations:
reconciliation.check_overlap_dates()
@classmethod
def create(cls, vlist):
""" add debit/credit
@ -403,10 +408,6 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
if len(lines) > 0:
values['date_to'] = lines[0].date
cls.check_overlap_dates(
values.get('date_from', None),
values.get('date_to', None),
values.get('cashbook', None))
return super(Reconciliation, cls).create(vlist)
@classmethod
@ -418,22 +419,12 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
for reconciliations, values in zip(actions, actions):
# deny write if chashbook is not open
for reconciliation in reconciliations:
# deny overlap
if len(set({'date_from', 'date_to'}).intersection(set(values.keys()))) > 0:
cls.check_overlap_dates(
values.get('date_from', reconciliation.date_from),
values.get('date_to', reconciliation.date_to),
reconciliation.cashbook.id,
reconciliation)
if reconciliation.cashbook.state != 'open':
raise UserError(gettext(
'cashbook.msg_book_deny_write',
bookname = reconciliation.cashbook.rec_name,
state_txt = reconciliation.cashbook.state_string,
))
super(Reconciliation, cls).write(*args)
@classmethod

View file

@ -16,8 +16,8 @@ class ReconTestCase(ModuleTestCase):
module = 'cashbook'
@with_transaction()
def test_recon_check_overlap(self):
""" create, check deny of overlap date
def test_recon_check_overlap_start(self):
""" create, check deny of overlap date - date_from
"""
pool = Pool()
Book = pool.get('cashbook.book')
@ -33,136 +33,178 @@ class ReconTestCase(ModuleTestCase):
'currency': company.currency.id,
'number_sequ': self.prep_sequence().id,
'start_date': date(2022, 5, 1),
}])
recon1, = Reconciliation.create([{
'reconciliations': [('create', [{
'date': date(2022, 5, 1),
'date_from': date(2022, 5, 1),
'date_to': date(2022, 5, 31),
'cashbook': book.id,
}])],
}])
self.assertEqual(recon1.rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
recon2, = Reconciliation.create([{
Book.write(*[
[book],
{
'reconciliations': [('create', [{
'date': date(2022, 6, 1),
'date_from': date(2022, 6, 1),
'date_to': date(2022, 6, 30),
'cashbook': book.id,
}])],
}])
# 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]')
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
self.assertEqual(book.reconciliations[1].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'
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]')
# 'date_from' inside of other record
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[recon2],
[book.reconciliations[1]],
{
'date_from': date(2022, 4, 15),
'date_to': date(2022, 5, 2),
},
])
@with_transaction()
def test_recon_check_overlap_end(self):
""" create, check deny of overlap date - date_to
"""
pool = Pool()
Book = pool.get('cashbook.book')
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,
'number_sequ': self.prep_sequence().id,
'start_date': date(2022, 5, 1),
'reconciliations': [('create', [{
'date': date(2022, 5, 1),
'date_from': date(2022, 5, 1),
'date_to': date(2022, 5, 31),
}])],
}])
Book.write(*[
[book],
{
'reconciliations': [('create', [{
'date': date(2022, 6, 1),
'date_from': date(2022, 6, 1),
'date_to': date(2022, 6, 30),
}])],
}])
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
self.assertEqual(book.reconciliations[1].rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[book.reconciliations[1]],
{
'date_from': date(2022, 5, 30),
},
])
# 'date_from' inside of other record
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[recon2],
{
'date_from': date(2022, 5, 2),
},
])
@with_transaction()
def test_recon_check_overlap_inside(self):
""" create, check deny of overlap date - inside of period
"""
pool = Pool()
Book = pool.get('cashbook.book')
Reconciliation = pool.get('cashbook.recon')
# 'date_from' same date_from like other record
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[recon2],
{
'date_from': date(2022, 5, 1),
},
])
# enclose other record
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[recon2],
{
'date_from': date(2022, 4, 30),
},
])
# within other record
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[recon2],
{
'date_from': date(2022, 5, 2),
'date_to': date(2022, 5, 12),
},
])
# from after to
self.assertRaisesRegex(UserError,
'The value for field "Start Date" in "Cashbook Reconciliation" is not valid according to its domain.',
Reconciliation.write,
*[
[recon2],
{
'date_from': date(2022, 4, 15),
'date_to': date(2022, 4, 10),
},
])
# 'date_to' at 'date_from' of other record - allowed
Reconciliation.write(*[
[recon2],
{
'date_from': date(2022, 4, 15),
'date_to': date(2022, 5, 1),
}])
# 'date_to' after other date_from
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[recon2],
{
'date_to': date(2022, 5, 2),
},
])
# overlap at .create()
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.create,
[{
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,
'number_sequ': self.prep_sequence().id,
'start_date': date(2022, 5, 1),
'reconciliations': [('create', [{
'date': date(2022, 5, 1),
'date_from': date(2022, 4, 1),
'date_to': date(2022, 4, 16),
'cashbook': book.id,
'date_from': date(2022, 5, 1),
'date_to': date(2022, 5, 31),
}])],
}])
recon3, = Reconciliation.create([{
'date': date(2022, 4, 17),
Book.write(*[
[book],
{
'reconciliations': [('create', [{
'date': date(2022, 6, 1),
'date_from': date(2022, 6, 1),
'date_to': date(2022, 6, 15),
'cashbook': book.id,
'date_to': date(2022, 6, 30),
}])],
}])
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, '05/31/2022 - 06/15/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(book.reconciliations[1].rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[book.reconciliations[1]],
{
'date_from': date(2022, 5, 5),
'date_to': date(2022, 5, 15),
},
])
@with_transaction()
def test_recon_check_overlap_enclose(self):
""" create, check deny of overlap date - enclose a period
"""
pool = Pool()
Book = pool.get('cashbook.book')
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,
'number_sequ': self.prep_sequence().id,
'start_date': date(2022, 5, 1),
'reconciliations': [('create', [{
'date': date(2022, 5, 1),
'date_from': date(2022, 5, 1),
'date_to': date(2022, 5, 31),
}])],
}])
Book.write(*[
[book],
{
'reconciliations': [('create', [{
'date': date(2022, 6, 1),
'date_from': date(2022, 6, 1),
'date_to': date(2022, 6, 30),
}])],
}])
self.assertEqual(book.reconciliations[0].rec_name, '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]')
self.assertEqual(book.reconciliations[1].rec_name, '05/31/2022 - 06/30/2022 | 0.00 usd - 0.00 usd [0]')
self.assertRaisesRegex(UserError,
'The date range overlaps with another reconciliation.',
Reconciliation.write,
*[
[book.reconciliations[1]],
{
'date_from': date(2022, 4, 25),
'date_to': date(2022, 6, 10),
},
])
@with_transaction()
def test_recon_set_start_amount_by_cashbook(self):