book: Feld 'start_date' + test,

line: balance-berechnung mit abstimmung gekoppelt + test,
abstimmung: start/enddatum automatisch
This commit is contained in:
Frederik Jaeckel 2022-08-18 11:58:05 +02:00
parent 5729ed0a07
commit 91a34e216b
13 changed files with 446 additions and 20 deletions

14
book.py
View file

@ -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'

View file

@ -145,6 +145,7 @@ full copyright notices and license terms. -->
<record model="ir.model.button" id="book_wfopen_button">
<field name="name">wfopen</field>
<field name="string">Open</field>
<field name="help">An open cashbook can be edited.</field>
<field name="model" search="[('model', '=', 'cashbook.book')]"/>
</record>
<record model="ir.model.button-res.group"
@ -157,6 +158,7 @@ full copyright notices and license terms. -->
<record model="ir.model.button" id="book_wfclosed_button">
<field name="name">wfclosed</field>
<field name="string">Close</field>
<field name="help">A closed cashbook can no longer be booked. However, it can be reopened afterwards.</field>
<field name="model" search="[('model', '=', 'cashbook.book')]"/>
</record>
<record model="ir.model.button-res.group"
@ -169,6 +171,7 @@ full copyright notices and license terms. -->
<record model="ir.model.button" id="book_wfarchive_button">
<field name="name">wfarchive</field>
<field name="string">Archive</field>
<field name="help">An archived cashbook is locked.</field>
<field name="model" search="[('model', '=', 'cashbook.book')]"/>
</record>
<record model="ir.model.button-res.group"

57
line.py
View file

@ -123,7 +123,10 @@ class Line(Workflow, ModelSQL, ModelView):
reconciliation = fields.Many2One(string='Reconciliation', readonly=True,
model_name='cashbook.recon', ondelete='SET NULL',
domain=[('cashbook.id', '=', Eval('cashbook'))],
depends=['cashbook'])
depends=['cashbook'],
states={
'invisible': ~Bool(Eval('reconciliation')),
})
balance = fields.Function(fields.Numeric(string='Balance',
digits=(16, Eval('currency_digits', 2)),
@ -491,17 +494,44 @@ class Line(Workflow, ModelSQL, ModelView):
else:
return 2
@fields.depends('id', 'cashbook', '_parent_cashbook.start_balance', '_parent_cashbook.id')
@fields.depends('id', 'date', 'cashbook', \
'_parent_cashbook.start_balance', '_parent_cashbook.id',\
'reconciliation', '_parent_reconciliation.start_amount')
def on_change_with_balance(self, name=None):
""" compute balance until current line, with current sort order
""" compute balance until current line, with current sort order,
try to use a reconciliation as start to speed up calculation
"""
Line = Pool().get('cashbook.line')
pool = Pool()
Reconciliation = pool.get('cashbook.recon')
Line = pool.get('cashbook.line')
if self.cashbook:
balance = self.cashbook.start_balance
lines = Line.search([
query = [
('cashbook.id', '=', self.cashbook.id),
]
balance = self.cashbook.start_balance
# get existing reconciliation, starting before current line
# this will speed up calculation of by-line-balance
if self.date is not None:
recons = Reconciliation.search([
('cashbook.id', '=', self.cashbook.id),
('date_from', '<=', self.date),
('state', '=', 'done'),
], order=[('date_from', 'DESC')], limit=1)
if len(recons) > 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',

View file

@ -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"

View file

@ -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"

View file

@ -98,6 +98,9 @@ full copyright notices and license terms. -->
<record model="ir.message" id="msg_rep_reconciliation_fname">
<field name="text">%(recname)s Reconciliation from %(date_from)s to %(date_to)s</field>
</record>
<record model="ir.message" id="msg_line_date_before_book">
<field name="text">The date of the cashbook line '%(recname)s' cannot be earlier than the start date '%(datebook)s' of the cashbook.</field>
</record>
</data>
</tryton>

View file

@ -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),

View file

@ -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,

View file

@ -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',

View file

@ -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',

View file

@ -34,6 +34,9 @@ full copyright notices and license terms. -->
<label name="balance"/>
<field name="balance"/>
<newline/>
<label name="start_date"/>
<field name="start_date"/>
<newline/>
<notebook colspan="6">
<page id="pgrecon" string="Reconciliations" col="1">

View file

@ -31,7 +31,8 @@ full copyright notices and license terms. -->
</group>
<label name="amount"/>
<field name="amount" symbol="currency"/>
<newline/>
<label name="reference"/>
<field name="reference"/>
<label name="category"/>
<field name="category"/>
@ -42,9 +43,6 @@ full copyright notices and license terms. -->
</group>
<newline/>
<label name="reference"/>
<field name="reference"/>
<newline/>
<field name="references" colspan="4"/>
<newline/>

View file

@ -3,6 +3,15 @@
The COPYRIGHT file at the top level of this repository contains the
full copyright notices and license terms. -->
<form col="2">
<group colspan="2" id="grpinfo" string="Information" col="1">
<label id="lab1" xalign="0.0"
string="Here you can export a cashbook in tabular form for printing."/>
<label id="lab2" xalign="0.0"
string="The time range for the export is determined by the created reconciliation."/>
<label id="lab3" xalign="0.0"
string="If you have not already done so, first create a reconciliation for the cashbook."/>
</group>
<label name="cashbook"/>
<field name="cashbook" widget="selection"/>