line: änderungesperre bei diversen wf-zuständen + test,
abstimmung: datum/betrag anfang/ende korrekt + test für beträge muß noch
This commit is contained in:
parent
01825cc09c
commit
149baef174
10 changed files with 1099 additions and 64 deletions
65
line.py
65
line.py
|
@ -78,7 +78,9 @@ class Line(Workflow, ModelSQL, ModelView):
|
|||
credit = fields.Numeric(string='Credit', digits=(16, Eval('currency_digits', 2)),
|
||||
required=True, readonly=True, depends=['currency_digits'])
|
||||
reconciliation = fields.Many2One(string='Reconciliation', readonly=True,
|
||||
model_name='cashbook.recon', ondelete='SET NULL')
|
||||
model_name='cashbook.recon', ondelete='SET NULL',
|
||||
domain=[('cashbook.id', '=', Eval('cashbook'))],
|
||||
depends=['cashbook'])
|
||||
|
||||
balance = fields.Function(fields.Numeric(string='Balance',
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
|
@ -184,9 +186,12 @@ class Line(Workflow, ModelSQL, ModelView):
|
|||
def get_rec_name(self, name):
|
||||
""" short + name
|
||||
"""
|
||||
return '%(date)s %(desc)s' % {
|
||||
return '%(date)s|%(amount)s %(symbol)s|%(desc)s [%(category)s]' % {
|
||||
'date': Report.format_date(self.date),
|
||||
'desc': (self.description or '-')[:40],
|
||||
'amount': Report.format_number(self.amount or 0.0, None),
|
||||
'symbol': getattr(self.currency, 'symbol', '-'),
|
||||
'category': self.category_view,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -360,8 +365,23 @@ class Line(Workflow, ModelSQL, ModelView):
|
|||
""" add debit/credit
|
||||
"""
|
||||
vlist = [x.copy() for x in vlist]
|
||||
for vals in vlist:
|
||||
vals.update(cls.get_debit_credit(vals))
|
||||
for values in vlist:
|
||||
values.update(cls.get_debit_credit(values))
|
||||
|
||||
# deny add to reconciliation if state is not 'check' or 'done'
|
||||
if values.get('reconciliation', None):
|
||||
if not values.get('state', '-') in ['check', 'done']:
|
||||
date_txt = '-'
|
||||
if values.get('date', None):
|
||||
date_txt = Report.format_date(values.get('date', None))
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_line_deny_recon_by_state',
|
||||
recname = '%(date)s|%(descr)s' % {
|
||||
'date': date_txt,
|
||||
'descr': values.get('description', '-'),
|
||||
},
|
||||
))
|
||||
|
||||
return super(Line, cls).create(vlist)
|
||||
|
||||
@classmethod
|
||||
|
@ -373,14 +393,49 @@ 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
|
||||
if line.cashbook.state != 'open':
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_book_deny_write',
|
||||
bookname = line.cashbook.rec_name,
|
||||
state_txt = line.cashbook.state_string,
|
||||
))
|
||||
if line.reconciliation:
|
||||
# deny state-change to 'edit' if line is linked to reconciliation
|
||||
if values.get('state', '-') == 'edit':
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_line_deny_stateedit_with_recon',
|
||||
recname = line.rec_name,
|
||||
))
|
||||
|
||||
# debit / credit
|
||||
# deny write if reconciliation is 'check' or 'done'
|
||||
if line.reconciliation.state == 'done':
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_line_deny_write_by_reconciliation',
|
||||
recname = line.rec_name,
|
||||
reconame = line.reconciliation.rec_name,
|
||||
))
|
||||
# deny write if line is not 'Edit'
|
||||
if line.state != 'edit':
|
||||
# allow state-update, if its the only action
|
||||
if not ((len(set({'state', 'reconciliation'}).intersection(values.keys())) > 0) \
|
||||
and (len(values.keys()) == 1)):
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_line_deny_write',
|
||||
recname = line.rec_name,
|
||||
state_txt = line.state_string,
|
||||
))
|
||||
|
||||
# deny add to reconciliation if state is not 'check' or 'done'
|
||||
if values.get('reconciliation', None):
|
||||
for line in lines:
|
||||
if not line.state in ['check', 'done']:
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_line_deny_recon_by_state',
|
||||
recname = line.rec_name
|
||||
))
|
||||
|
||||
# update debit / credit
|
||||
if len(set(values.keys()).intersection(set({'amount', 'bookingtype'}))) > 0:
|
||||
for line in lines:
|
||||
values2 = {}
|
||||
|
|
40
locale/de.po
40
locale/de.po
|
@ -38,6 +38,22 @@ msgctxt "model:ir.message,text:msg_line_deny_delete2"
|
|||
msgid "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linestate)s'."
|
||||
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."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_write"
|
||||
msgid "The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed."
|
||||
msgstr "Die Kassenbuchzeile '%(recname)s' ist '%(state_txt)s' und kann nicht geändert werden."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_recon_deny_delete1"
|
||||
msgid "The reconciliation '%(recontxt)s' cannot be deleted because the Cashbook '%(bookname)s' is in state '%(bookstate)s'."
|
||||
msgstr "Die Abstimmung '%(recontxt)s' kann nicht gelöscht werden, weil das Kassenbuch '%(bookname)s' im Status '%(bookstate)s' ist."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_recon_deny_delete2"
|
||||
msgid "The reconciliation '%(recontxt)s' cannot be deleted, its in state '%(reconstate)s'."
|
||||
msgstr "Die Abstimmung '%(recontxt)s' kann nicht gelöscht werden, da sie im Status '%(reconstate)s' ist."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_setting_already_exists"
|
||||
msgid "Settings for this user alredy exists."
|
||||
msgstr "Einstellungen für diesen Benutzer sind bereits vorhanden."
|
||||
|
@ -58,6 +74,22 @@ msgctxt "model:ir.message,text:msg_book_err_startamount_with_lines"
|
|||
msgid "The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings."
|
||||
msgstr "Der Anfangsbetrag des Kassenbuchs '%(bookname)s' kann nicht geändert werden, da es bereits Buchungen enthält."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_recon_by_state"
|
||||
msgid "For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'."
|
||||
msgstr "Für die Abstimmung muss die Zeile '%(recname)s' im Status 'Prüfen' oder 'Fertig' sein."
|
||||
|
||||
msgctxt "model:ir.message,text:mds_recon_deny_line_not_check"
|
||||
msgid "For the reconciliation '%(reconame)s' of the cashbook '%(bookname)s', all lines in the date range from '%(datefrom)s' to '%(dateto)s' must be in the 'Check' state."
|
||||
msgstr "Für die Abstimmung '%(reconame)s' des Kassenbuchs '%(bookname)s' müssen alle Zeilen im Datumsbereich von '%(datefrom)s' bis '%(dateto)s' im Zustand 'Prüfen' sein."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_write_by_reconciliation"
|
||||
msgid "The line '%(recname)s' cannot be changed because the reconciliation '%(reconame)s'is 'Done'."
|
||||
msgstr "Die Zeile '%(recname)s' kann nicht geändert werden, da die Abstimmung '%(reconame)s' ist."
|
||||
|
||||
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."
|
||||
|
||||
|
||||
#############
|
||||
# res.group #
|
||||
|
@ -801,3 +833,11 @@ msgstr "Geschlossen"
|
|||
msgctxt "selection:cashbook.recon,state_cashbook:"
|
||||
msgid "Archive"
|
||||
msgstr "Archiv"
|
||||
|
||||
msgctxt "field:cashbook.recon,start_amount:"
|
||||
msgid "Start Amount"
|
||||
msgstr "Anfangsbetrag"
|
||||
|
||||
msgctxt "field:cashbook.recon,end_amount:"
|
||||
msgid "End Amount"
|
||||
msgstr "Endbetrag"
|
||||
|
|
362
locale/en.po
362
locale/en.po
|
@ -23,8 +23,8 @@ msgid "The cashbook '%(bookname)s' cannot be deleted because it contains %(bookl
|
|||
msgstr "The cashbook '%(bookname)s' cannot be deleted because it contains %(booklines)s lines and is not in the status 'Archive'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_book_deny_write"
|
||||
msgid "The cash book '%(bookname)s' is '%(state_txt)s' and cannot be changed."
|
||||
msgstr "The cash book '%(bookname)s' is '%(state_txt)s' and cannot be changed."
|
||||
msgid "The cashbook '%(bookname)s' is '%(state_txt)s' and cannot be changed."
|
||||
msgstr "The cashbook '%(bookname)s' is '%(state_txt)s' and cannot be changed."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_delete1"
|
||||
msgid "The cashbook line '%(linetxt)s' cannot be deleted because the Cashbook '%(bookname)s' is in state '%(bookstate)s'."
|
||||
|
@ -34,6 +34,18 @@ msgctxt "model:ir.message,text:msg_line_deny_delete2"
|
|||
msgid "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linestate)s'."
|
||||
msgstr "The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linestate)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_write"
|
||||
msgid "The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed."
|
||||
msgstr "The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_recon_deny_delete1"
|
||||
msgid "The reconciliation '%(recontxt)s' cannot be deleted because the Cashbook '%(bookname)s' is in state '%(bookstate)s'."
|
||||
msgstr "The reconciliation '%(recontxt)s' cannot be deleted because the Cashbook '%(bookname)s' is in state '%(bookstate)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_recon_deny_delete2"
|
||||
msgid "The reconciliation '%(recontxt)s' cannot be deleted, its in state '%(reconstate)s'."
|
||||
msgstr "The reconciliation '%(recontxt)s' cannot be deleted, its in state '%(reconstate)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_setting_already_exists"
|
||||
msgid "Settings for this user alredy exists."
|
||||
msgstr "Settings for this user alredy exists."
|
||||
|
@ -42,6 +54,30 @@ msgctxt "model:ir.message,text:msg_category_name_unique"
|
|||
msgid "The category name already exists at this level."
|
||||
msgstr "The category name already exists at this level."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_category_account_unique"
|
||||
msgid "The account is already in use for a category."
|
||||
msgstr "The account is already in use for a category."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_category_type_not_like_parent"
|
||||
msgid "The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'."
|
||||
msgstr "The type of the current category '%(catname)s' must be equal to the type of the parent category '%(parentname)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_book_err_startamount_with_lines"
|
||||
msgid "The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings."
|
||||
msgstr "The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_recon_by_state"
|
||||
msgid "For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'."
|
||||
msgstr "For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'."
|
||||
|
||||
msgctxt "model:ir.message,text:mds_recon_deny_line_not_check"
|
||||
msgid "For the reconciliation '%(reconame)s' of the cashbook '%(bookname)s', all lines in the date range from '%(datefrom)s' to '%(dateto)s' must be in the 'Check' state."
|
||||
msgstr "For the reconciliation '%(reconame)s' of the cashbook '%(bookname)s', all lines in the date range from '%(datefrom)s' to '%(dateto)s' must be in the 'Check' state."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_deny_write_by_reconciliation"
|
||||
msgid "The line '%(recname)s' cannot be changed because the reconciliation '%(reconame)s'is 'Done'."
|
||||
msgstr "The line '%(recname)s' cannot be changed because the reconciliation '%(reconame)s'is 'Done'."
|
||||
|
||||
msgctxt "model:res.group,name:group_cashbook"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
@ -74,6 +110,30 @@ msgctxt "model:ir.rule.group,name:rg_line_read"
|
|||
msgid "Observer: Cashbook line read"
|
||||
msgstr "Observer: Cashbook line read"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rg_line_read"
|
||||
msgid "User in companies"
|
||||
msgstr "User in companies"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rg_type_companies"
|
||||
msgid "User in companies"
|
||||
msgstr "User in companies"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rg_book_companies"
|
||||
msgid "User in companies"
|
||||
msgstr "User in companies"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rg_recon_companies"
|
||||
msgid "User in companies"
|
||||
msgstr "User in companies"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rg_recon_write_adm"
|
||||
msgid "Administrators: Reconciliation read/write"
|
||||
msgstr "Administrators: Reconciliation read/write"
|
||||
|
||||
msgctxt "model:ir.rule.group,name:rg_recon_write"
|
||||
msgid "Owners and reviewers: Reconciliation write"
|
||||
msgstr "Owners and reviewers: Reconciliation write"
|
||||
|
||||
msgctxt "model:ir.ui.menu,name:menu_cashbook"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
@ -86,7 +146,7 @@ msgctxt "model:ir.ui.menu,name:menu_typeconfig"
|
|||
msgid "Cashbook Type"
|
||||
msgstr "Cashbook Type"
|
||||
|
||||
msgctxt "model:ir.ui.menu,name:menu_bookconfig"
|
||||
msgctxt "model:ir.ui.menu,name:menu_booklist"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
||||
|
@ -103,8 +163,8 @@ msgid "Category"
|
|||
msgstr "Category"
|
||||
|
||||
msgctxt "model:ir.action,name:act_book_view"
|
||||
msgid "Account"
|
||||
msgstr "Account"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
||||
msgctxt "model:ir.action,name:act_type_view"
|
||||
msgid "Cashbook Type"
|
||||
|
@ -122,6 +182,18 @@ msgctxt "model:ir.ui.menu,name:act_category_view"
|
|||
msgid "Category"
|
||||
msgstr "Category"
|
||||
|
||||
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_current"
|
||||
msgid "Current Month"
|
||||
msgstr "Current Month"
|
||||
|
||||
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_last"
|
||||
msgid "Last Month"
|
||||
msgstr "Last Month"
|
||||
|
||||
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_all"
|
||||
msgid "All"
|
||||
msgstr "All"
|
||||
|
||||
msgctxt "model:ir.model.button,string:line_wfedit_button"
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
@ -146,13 +218,29 @@ msgctxt "model:ir.model.button,string:book_wfarchive_button"
|
|||
msgid "Archive"
|
||||
msgstr "Archive"
|
||||
|
||||
msgctxt "model:ir.model.button,string:recon_wfedit_button"
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
||||
msgctxt "model:ir.model.button,string:recon_wfcheck_button"
|
||||
msgid "Check"
|
||||
msgstr "Check"
|
||||
|
||||
msgctxt "model:ir.model.button,string:recon_wfdone_button"
|
||||
msgid "Done"
|
||||
msgstr "Done"
|
||||
|
||||
msgctxt "model:cashbook.book,name:"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
||||
msgctxt "view:cashbook.book:"
|
||||
msgid "Owner & Authorizeds"
|
||||
msgstr "Owner & Authorizeds"
|
||||
msgid "Owner and Authorizeds"
|
||||
msgstr "Owner and Authorizeds"
|
||||
|
||||
msgctxt "view:cashbook.book:"
|
||||
msgid "Reconciliations"
|
||||
msgstr "Reconciliations"
|
||||
|
||||
msgctxt "field:cashbook.book,name:"
|
||||
msgid "Name"
|
||||
|
@ -202,14 +290,50 @@ msgctxt "field:cashbook.book,account:"
|
|||
msgid "Account"
|
||||
msgstr "Account"
|
||||
|
||||
msgctxt "field:cashbook.book,company:"
|
||||
msgid "Company"
|
||||
msgstr "Company"
|
||||
|
||||
msgctxt "field:cashbook.book,currency:"
|
||||
msgid "Currency"
|
||||
msgstr "Currency"
|
||||
|
||||
msgctxt "field:cashbook.book,start_balance:"
|
||||
msgid "Initial Amount"
|
||||
msgstr "Initial Amount"
|
||||
|
||||
msgctxt "field:cashbook.book,balance:"
|
||||
msgid "Balance"
|
||||
msgstr "Balance"
|
||||
|
||||
msgctxt "field:cashbook.book,reconciliations:"
|
||||
msgid "Reconciliations"
|
||||
msgstr "Reconciliations"
|
||||
|
||||
msgctxt "field:cashbook.book,lines:"
|
||||
msgid "Lines"
|
||||
msgstr "Lines"
|
||||
|
||||
msgctxt "model:cashbook.line,name:"
|
||||
msgid "Cashbook Line"
|
||||
msgstr "Cashbook Line"
|
||||
|
||||
msgctxt "view:cashbook.line:"
|
||||
msgid "Credit"
|
||||
msgstr "Credit"
|
||||
|
||||
msgctxt "view:cashbook.line:"
|
||||
msgid "Debit"
|
||||
msgstr "Debit"
|
||||
|
||||
msgctxt "view:cashbook.line:"
|
||||
msgid "Cashbook Line"
|
||||
msgstr "Cashbook Line"
|
||||
|
||||
msgctxt "view:cashbook.line:"
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
msgctxt "view:cashbook.line:"
|
||||
msgid "State"
|
||||
msgstr "State"
|
||||
|
@ -246,17 +370,73 @@ msgctxt "field:cashbook.line,month:"
|
|||
msgid "Month"
|
||||
msgstr "Month"
|
||||
|
||||
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_current"
|
||||
msgid "Current Month"
|
||||
msgstr "Current Month"
|
||||
msgctxt "field:cashbook.line,category:"
|
||||
msgid "Category"
|
||||
msgstr "Category"
|
||||
|
||||
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_last"
|
||||
msgid "Last Month"
|
||||
msgstr "Last Month"
|
||||
msgctxt "field:cashbook.line,category_view:"
|
||||
msgid "Category"
|
||||
msgstr "Category"
|
||||
|
||||
msgctxt "model:ir.action.act_window.domain,name:act_line_domain_all"
|
||||
msgid "All"
|
||||
msgstr "All"
|
||||
msgctxt "field:cashbook.line,bookingtype:"
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
msgctxt "help:cashbook.line,bookingtype:"
|
||||
msgid "Type of Booking"
|
||||
msgstr "Type of Booking"
|
||||
|
||||
msgctxt "selection:cashbook.line,bookingtype:"
|
||||
msgid "Revenue"
|
||||
msgstr "Revenue"
|
||||
|
||||
msgctxt "selection:cashbook.line,bookingtype:"
|
||||
msgid "Expense"
|
||||
msgstr "Expense"
|
||||
|
||||
msgctxt "selection:cashbook.line,bookingtype:"
|
||||
msgid "Transfer from"
|
||||
msgstr "Transfer from"
|
||||
|
||||
msgctxt "selection:cashbook.line,bookingtype:"
|
||||
msgid "Transfer to"
|
||||
msgstr "Transfer to"
|
||||
|
||||
msgctxt "field:cashbook.line,company:"
|
||||
msgid "Company"
|
||||
msgstr "Company"
|
||||
|
||||
msgctxt "field:cashbook.line,amount:"
|
||||
msgid "Amount"
|
||||
msgstr "Amount"
|
||||
|
||||
msgctxt "field:cashbook.line,debit:"
|
||||
msgid "Debit"
|
||||
msgstr "Debit"
|
||||
|
||||
msgctxt "field:cashbook.line,credit:"
|
||||
msgid "Credit"
|
||||
msgstr "Credit"
|
||||
|
||||
msgctxt "field:cashbook.line,currency:"
|
||||
msgid "Currency"
|
||||
msgstr "Currency"
|
||||
|
||||
msgctxt "field:cashbook.line,currency_digits:"
|
||||
msgid "Currency Digits"
|
||||
msgstr "Currency Digits"
|
||||
|
||||
msgctxt "field:cashbook.line,balance:"
|
||||
msgid "Balance"
|
||||
msgstr "Balance"
|
||||
|
||||
msgctxt "help:cashbook.line,balance:"
|
||||
msgid "Balance of the cash book up to the current line, if the default sorting applies."
|
||||
msgstr "Balance of the cash book up to the current line, if the default sorting applies."
|
||||
|
||||
msgctxt "field:cashbook.line,reconciliation:"
|
||||
msgid "Reconciliation"
|
||||
msgstr "Reconciliation"
|
||||
|
||||
msgctxt "model:cashbook.type,name:"
|
||||
msgid "Cashbook Type"
|
||||
|
@ -270,17 +450,9 @@ msgctxt "field:cashbook.type,short:"
|
|||
msgid "Abbreviation"
|
||||
msgstr "Abbreviation"
|
||||
|
||||
msgctxt "model:cashbook.type,name:atype_cash"
|
||||
msgid "Cash"
|
||||
msgstr "Cash"
|
||||
|
||||
msgctxt "model:cashbook.type,name:atype_giro"
|
||||
msgid "Giro"
|
||||
msgstr "Giro"
|
||||
|
||||
msgctxt "model:cashbook.type,name:atype_fixtermdep"
|
||||
msgid "Fixed-term deposit"
|
||||
msgstr "Fixed-term deposit"
|
||||
msgctxt "field:cashbook.type,company:"
|
||||
msgid "Company"
|
||||
msgstr "Company"
|
||||
|
||||
msgctxt "model:cashbook.category,name:"
|
||||
msgid "Category"
|
||||
|
@ -330,6 +502,22 @@ msgctxt "field:cashbook.category,right:"
|
|||
msgid "Right"
|
||||
msgstr "Right"
|
||||
|
||||
msgctxt "field:cashbook.category,cattype:"
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
msgctxt "help:cashbook.category,cattype:"
|
||||
msgid "Type of Category"
|
||||
msgstr "Type of Category"
|
||||
|
||||
msgctxt "selection:cashbook.category,cattype:"
|
||||
msgid "Revenue"
|
||||
msgstr "Revenue"
|
||||
|
||||
msgctxt "selection:cashbook.category,cattype:"
|
||||
msgid "Expense"
|
||||
msgstr "Expense"
|
||||
|
||||
msgctxt "model:cashbook.open_lines.start,name:"
|
||||
msgid "Open Cashbook"
|
||||
msgstr "Open Cashbook"
|
||||
|
@ -370,11 +558,11 @@ msgctxt "model:cashbook.open_lines,name:"
|
|||
msgid "Open Cashbook"
|
||||
msgstr "Open Cashbook"
|
||||
|
||||
msgctxt "wizard_button:cashbook.open_lines,start,end:"
|
||||
msgctxt "wizard_button:cashbook.open_lines,askuser,end:"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
msgctxt "wizard_button:cashbook.open_lines,start,open_:"
|
||||
msgctxt "wizard_button:cashbook.open_lines,askuser,open_:"
|
||||
msgid "Open"
|
||||
msgstr "Open"
|
||||
|
||||
|
@ -418,6 +606,10 @@ msgctxt "view:cashbook.configuration:"
|
|||
msgid "Open Cashbook Wizard"
|
||||
msgstr "Open Cashbook Wizard"
|
||||
|
||||
msgctxt "view:cashbook.configuration:"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
||||
msgctxt "field:cashbook.configuration,date_from:"
|
||||
msgid "Start Date"
|
||||
msgstr "Start Date"
|
||||
|
@ -430,10 +622,34 @@ msgctxt "field:cashbook.configuration,checked:"
|
|||
msgid "Checked"
|
||||
msgstr "Checked"
|
||||
|
||||
msgctxt "help:cashbook.configuration,checked:"
|
||||
msgid "Show cashbook lines in Checked-state."
|
||||
msgstr "Show cashbook lines in Checked-state."
|
||||
|
||||
msgctxt "field:cashbook.configuration,done:"
|
||||
msgid "Done"
|
||||
msgstr "Done"
|
||||
|
||||
msgctxt "help:cashbook.configuration,done:"
|
||||
msgid "Show cashbook lines in Done-state."
|
||||
msgstr "Show cashbook lines in Done-state."
|
||||
|
||||
msgctxt "field:cashbook.configuration,catnamelong:"
|
||||
msgid "Category: Show long name"
|
||||
msgstr "Category: Show long name"
|
||||
|
||||
msgctxt "help:cashbook.configuration,catnamelong:"
|
||||
msgid "Shows the long name of the category in the Category field of a cash book line."
|
||||
msgstr "Shows the long name of the category in the Category field of a cash book line."
|
||||
|
||||
msgctxt "field:cashbook.configuration,cataccno:"
|
||||
msgid "Category: Show account number"
|
||||
msgstr "Category: Show account number"
|
||||
|
||||
msgctxt "help:cashbook.configuration,cataccno:"
|
||||
msgid "Shows the number of the linked account in the name of a category."
|
||||
msgstr "Shows the number of the linked account in the name of a category."
|
||||
|
||||
msgctxt "model:cashbook.configuration_user,name:"
|
||||
msgid "User Configuration"
|
||||
msgstr "User Configuration"
|
||||
|
@ -450,3 +666,91 @@ msgctxt "field:cashbook.configuration_user,checked:"
|
|||
msgid "Checked"
|
||||
msgstr "Checked"
|
||||
|
||||
msgctxt "help:cashbook.configuration_user,checked:"
|
||||
msgid "Show cashbook lines in Checked-state."
|
||||
msgstr "Show cashbook lines in Checked-state."
|
||||
|
||||
msgctxt "field:cashbook.configuration_user,done:"
|
||||
msgid "Done"
|
||||
msgstr "Done"
|
||||
|
||||
msgctxt "help:cashbook.configuration_user,done:"
|
||||
msgid "Show cashbook lines in Done-state."
|
||||
msgstr "Show cashbook lines in Done-state."
|
||||
|
||||
msgctxt "field:cashbook.configuration_user,catnamelong:"
|
||||
msgid "Category: Show long name"
|
||||
msgstr "Category: Show long name"
|
||||
|
||||
msgctxt "help:cashbook.configuration_user,catnamelong:"
|
||||
msgid "Shows the long name of the category in the Category field of a cash book line."
|
||||
msgstr "Shows the long name of the category in the Category field of a cash book line."
|
||||
|
||||
msgctxt "field:cashbook.configuration_user,cataccno:"
|
||||
msgid "Category: Show account number"
|
||||
msgstr "Category: Show account number"
|
||||
|
||||
msgctxt "help:cashbook.configuration_user,cataccno:"
|
||||
msgid "Shows the number of the linked account in the name of a category."
|
||||
msgstr "Shows the number of the linked account in the name of a category."
|
||||
|
||||
msgctxt "model:cashbook.recon,name:"
|
||||
msgid "Cashbook Reconciliation"
|
||||
msgstr "Cashbook Reconciliation"
|
||||
|
||||
msgctxt "view:cashbook.recon:"
|
||||
msgid "Reconciliation period"
|
||||
msgstr "Reconciliation period"
|
||||
|
||||
msgctxt "view:cashbook.recon:"
|
||||
msgid "State"
|
||||
msgstr "State"
|
||||
|
||||
msgctxt "field:cashbook.recon,cashbook:"
|
||||
msgid "Cashbook"
|
||||
msgstr "Cashbook"
|
||||
|
||||
msgctxt "field:cashbook.recon,date:"
|
||||
msgid "Date"
|
||||
msgstr "Date"
|
||||
|
||||
msgctxt "field:cashbook.recon,date_from:"
|
||||
msgid "Start Date"
|
||||
msgstr "Start Date"
|
||||
|
||||
msgctxt "field:cashbook.recon,date_to:"
|
||||
msgid "End Date"
|
||||
msgstr "End Date"
|
||||
|
||||
msgctxt "field:cashbook.recon,state:"
|
||||
msgid "State"
|
||||
msgstr "State"
|
||||
|
||||
msgctxt "selection:cashbook.recon,state:"
|
||||
msgid "Edit"
|
||||
msgstr "Edit"
|
||||
|
||||
msgctxt "selection:cashbook.recon,state:"
|
||||
msgid "Check"
|
||||
msgstr "Check"
|
||||
|
||||
msgctxt "selection:cashbook.recon,state:"
|
||||
msgid "Done"
|
||||
msgstr "Done"
|
||||
|
||||
msgctxt "field:cashbook.recon,lines:"
|
||||
msgid "Lines"
|
||||
msgstr "Lines"
|
||||
|
||||
msgctxt "field:cashbook.recon,state_cashbook:"
|
||||
msgid "State of Cashbook"
|
||||
msgstr "State of Cashbook"
|
||||
|
||||
msgctxt "selection:cashbook.recon,state_cashbook:"
|
||||
msgid "Open"
|
||||
msgstr "Open"
|
||||
|
||||
msgctxt "selection:cashbook.recon,state_cashbook:"
|
||||
msgid "Closed"
|
||||
msgstr "Closed"
|
||||
|
||||
|
|
24
message.xml
24
message.xml
|
@ -29,6 +29,18 @@ full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_line_deny_delete2">
|
||||
<field name="text">The cashbook line '%(linetxt)s' cannot be deleted, its in state '%(linestate)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_line_deny_write">
|
||||
<field name="text">The cashbook line '%(recname)s' is '%(state_txt)s' and cannot be changed.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_line_deny_stateedit_with_recon">
|
||||
<field name="text">The status cannot be changed to 'Edit' as long as the line '%(recname)s' is associated with a reconciliation.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_recon_deny_delete1">
|
||||
<field name="text">The reconciliation '%(recontxt)s' cannot be deleted because the Cashbook '%(bookname)s' is in state '%(bookstate)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_recon_deny_delete2">
|
||||
<field name="text">The reconciliation '%(recontxt)s' cannot be deleted, its in state '%(reconstate)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_setting_already_exists">
|
||||
<field name="text">Settings for this user alredy exists.</field>
|
||||
</record>
|
||||
|
@ -44,6 +56,18 @@ full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_book_err_startamount_with_lines">
|
||||
<field name="text">The initial amount of the cash book '%(bookname)s' cannot be changed because it already contains bookings.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_line_deny_recon_by_state">
|
||||
<field name="text">For reconciliation, the line '%(recname)s' must be in the status 'Check' or 'Done'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="mds_recon_deny_line_not_check">
|
||||
<field name="text">For the reconciliation '%(reconame)s' of the cashbook '%(bookname)s', all lines in the date range from '%(datefrom)s' to '%(dateto)s' must be in the 'Check' state.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_line_deny_write_by_reconciliation">
|
||||
<field name="text">The line '%(recname)s' cannot be changed because the reconciliation '%(reconame)s'is 'Done'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_recon_err_overlap">
|
||||
<field name="text">The date range overlaps with another reconciliation.</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains the
|
||||
# full copyright notices and license terms.
|
||||
|
||||
from trytond.model import Workflow, ModelView, ModelSQL, fields, Unique
|
||||
from trytond.model import Workflow, ModelView, ModelSQL, fields
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pyson import Eval, If, Or
|
||||
from trytond.pool import Pool
|
||||
from trytond.report import Report
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.i18n import gettext
|
||||
from decimal import Decimal
|
||||
from sql.operators import Equal, Between
|
||||
from sql import Literal, Null
|
||||
from .book import sel_state_book
|
||||
|
||||
|
||||
|
@ -52,11 +56,19 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
|||
()),
|
||||
],
|
||||
states=STATES, depends=DEPENDS+['date_from'])
|
||||
start_amount = fields.Numeric(string='Start Amount', required=True,
|
||||
readonly=True, digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits'])
|
||||
end_amount = fields.Numeric(string='End Amount', required=True,
|
||||
readonly=True, digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits'])
|
||||
|
||||
lines = fields.One2Many(string='Lines', field='reconciliation',
|
||||
model_name='cashbook.line', states=STATES,
|
||||
depends=DEPENDS+['date_from', 'date_to', 'cashbook'],
|
||||
add_remove=[
|
||||
('cashbook', '=', Eval('cashbook')),
|
||||
('state', 'in', ['check', 'done']),
|
||||
('date', '>=', Eval('date_from')),
|
||||
('date', '<=', Eval('date_to')),
|
||||
],
|
||||
|
@ -65,6 +77,11 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
|||
('date', '<=', Eval('date_to')),
|
||||
])
|
||||
|
||||
currency = fields.Function(fields.Many2One(model_name='currency.currency',
|
||||
string="Currency"), 'on_change_with_currency')
|
||||
currency_digits = fields.Function(fields.Integer(string='Currency Digits'),
|
||||
'on_change_with_currency_digits')
|
||||
|
||||
state = fields.Selection(string='State', required=True, readonly=True,
|
||||
select=True, selection=sel_reconstate)
|
||||
state_string = state.translated('state')
|
||||
|
@ -96,40 +113,169 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
|||
},
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def check_overlap_dates(cls, date_from, date_to, id_cashbook, record=None):
|
||||
""" 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),
|
||||
['OR',
|
||||
[ # 'start' is inside of other record
|
||||
('date_from', '<=', date_from),
|
||||
('date_to', '>', date_from),
|
||||
],
|
||||
[ # 'end' is inside of other record
|
||||
('date_from', '<', date_to),
|
||||
('date_to', '>=', date_to),
|
||||
],
|
||||
[ # enclose other record
|
||||
('date_from', '>=', date_from),
|
||||
('date_to', '<=', 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'))
|
||||
|
||||
@classmethod
|
||||
def check_lines_not_checked(cls, reconciliations):
|
||||
""" deny lines in date-range not 'checked', w/o records at date-limit
|
||||
"""
|
||||
Line = Pool().get('cashbook.line')
|
||||
|
||||
for reconciliation in reconciliations:
|
||||
if Line.search_count([
|
||||
('date', '>', reconciliation.date_from),
|
||||
('date', '<', reconciliation.date_to),
|
||||
('cashbook.id', '=', reconciliation.cashbook.id),
|
||||
('state', '!=', 'check'),
|
||||
]) > 0:
|
||||
raise UserError(gettext(
|
||||
'cashbook.mds_recon_deny_line_not_check',
|
||||
bookname = reconciliation.cashbook.rec_name,
|
||||
reconame = reconciliation.rec_name,
|
||||
datefrom = Report.format_date(reconciliation.date_from),
|
||||
dateto = Report.format_date(reconciliation.date_to),
|
||||
))
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('edit')
|
||||
def wfedit(cls, lines):
|
||||
def wfedit(cls, reconciliations):
|
||||
""" edit
|
||||
"""
|
||||
pass
|
||||
Recon = Pool().get('cashbook.recon')
|
||||
|
||||
to_write = []
|
||||
for reconciliation in reconciliations:
|
||||
values = {
|
||||
'start_amount': Decimal('0.0'),
|
||||
'end_amount': Decimal('0.0'),
|
||||
}
|
||||
|
||||
# unlink lines from reconciliation
|
||||
if len(reconciliation.lines) > 0:
|
||||
values['lines'] = [('remove', [x.id for x in reconciliation.lines])]
|
||||
|
||||
to_write.extend([[reconciliation], values])
|
||||
|
||||
if len(to_write) > 0:
|
||||
Recon.write(*to_write)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('check')
|
||||
def wfcheck(cls, lines):
|
||||
""" is checked
|
||||
def wfcheck(cls, reconciliations):
|
||||
""" checked: add lines of book in date-range to reconciliation,
|
||||
state of lines must be 'checked'
|
||||
"""
|
||||
pass
|
||||
pool = Pool()
|
||||
Line = pool.get('cashbook.line')
|
||||
Recon = pool.get('cashbook.recon')
|
||||
|
||||
cls.check_lines_not_checked(reconciliations)
|
||||
|
||||
to_write = []
|
||||
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
|
||||
else :
|
||||
# not found, use 'start_balance' of cashbook
|
||||
values['start_amount'] = reconciliation.cashbook.start_balance
|
||||
values['end_amount'] = values['start_amount']
|
||||
|
||||
# add 'checked'-lines to reconciliation
|
||||
lines = Line.search([
|
||||
('date', '>=', reconciliation.date_from),
|
||||
('date', '<=', reconciliation.date_to),
|
||||
('cashbook.id', '=', reconciliation.cashbook.id),
|
||||
('reconciliation', '=', None),
|
||||
('state', '=', 'check'),
|
||||
])
|
||||
if len(lines) > 0:
|
||||
values['lines'] = [('add', [x.id for x in lines])]
|
||||
|
||||
# add amounts of new lines
|
||||
values['end_amount'] += sum([x.credit - x.debit for x in lines])
|
||||
# add amounts of already linked lines
|
||||
values['end_amount'] += sum([x.credit - x.debit for x in reconciliation.lines])
|
||||
|
||||
to_write.extend([[reconciliation], values])
|
||||
|
||||
if len(to_write) > 0:
|
||||
Recon.write(*to_write)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('done')
|
||||
def wfdone(cls, lines):
|
||||
def wfdone(cls, reconciliations):
|
||||
""" is done
|
||||
"""
|
||||
pass
|
||||
Line = Pool().get('cashbook.line')
|
||||
|
||||
to_wfdone_line = []
|
||||
for reconciliation in reconciliations:
|
||||
to_wfdone_line.extend(list(reconciliation.lines))
|
||||
|
||||
if len(to_wfdone_line) > 0:
|
||||
Line.wfdone(to_wfdone_line)
|
||||
|
||||
def get_rec_name(self, name):
|
||||
""" short + name
|
||||
"""
|
||||
return '%(from)s - %(to)s: %(amount)s %(symbol)s' % {
|
||||
return '%(from)s - %(to)s | %(start_amount)s %(symbol)s - %(start_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 '-',
|
||||
'amount': Decimal('0.0'),
|
||||
'symbol': getattr(getattr(self.cashbook, 'currency', None), 'symbol', '-'),
|
||||
'start_amount': Report.format_number(self.start_amount or 0.0, None),
|
||||
'end_amount': Report.format_number(self.end_amount or 0.0, None),
|
||||
'symbol': getattr(self.currency, 'symbol', '-'),
|
||||
'num': len(self.lines),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def default_start_amount(cls):
|
||||
return Decimal('0.0')
|
||||
|
||||
@classmethod
|
||||
def default_end_amount(cls):
|
||||
return Decimal('0.0')
|
||||
|
||||
@classmethod
|
||||
def default_state(cls):
|
||||
return 'edit'
|
||||
|
@ -141,6 +287,22 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
|||
IrDate = Pool().get('ir.date')
|
||||
return IrDate.today()
|
||||
|
||||
@fields.depends('cashbook', '_parent_cashbook.currency')
|
||||
def on_change_with_currency(self, name=None):
|
||||
""" currency of cashbook
|
||||
"""
|
||||
if self.cashbook:
|
||||
return self.cashbook.currency.id
|
||||
|
||||
@fields.depends('cashbook', '_parent_cashbook.currency')
|
||||
def on_change_with_currency_digits(self, name=None):
|
||||
""" currency of cashbook
|
||||
"""
|
||||
if self.cashbook:
|
||||
return self.cashbook.currency.digits
|
||||
else:
|
||||
return 2
|
||||
|
||||
@fields.depends('cashbook', '_parent_cashbook.state')
|
||||
def on_change_with_state_cashbook(self, name=None):
|
||||
""" get state of cashbook
|
||||
|
@ -148,4 +310,63 @@ class Reconciliation(Workflow, ModelSQL, ModelView):
|
|||
if self.cashbook:
|
||||
return self.cashbook.state
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
""" add debit/credit
|
||||
"""
|
||||
for values in vlist:
|
||||
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
|
||||
def write(cls, *args):
|
||||
""" deny update if cashbook.line!='open',
|
||||
add or update debit/credit
|
||||
"""
|
||||
actions = iter(args)
|
||||
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
|
||||
def delete(cls, reconciliations):
|
||||
""" deny delete if book is not 'open' or wf is not 'edit'
|
||||
"""
|
||||
for reconciliation in reconciliations:
|
||||
if reconciliation.cashbook.state == 'closed':
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_line_deny_delete1',
|
||||
linetxt = reconciliation.rec_name,
|
||||
bookname = reconciliation.cashbook.rec_name,
|
||||
bookstate = reconciliation.cashbook.state_string,
|
||||
))
|
||||
if reconciliation.state != 'edit':
|
||||
raise UserError(gettext(
|
||||
'cashbook.msg_recon_deny_delete2',
|
||||
recontxt = reconciliation.rec_name,
|
||||
reconstate = reconciliation.state_string,
|
||||
))
|
||||
|
||||
return super(Reconciliation, cls).delete(reconciliations)
|
||||
|
||||
# end Type
|
||||
|
|
|
@ -9,11 +9,13 @@ from trytond.modules.cashbook.tests.test_book import BookTestCase
|
|||
from trytond.modules.cashbook.tests.test_line import LineTestCase
|
||||
from trytond.modules.cashbook.tests.test_config import ConfigTestCase
|
||||
from trytond.modules.cashbook.tests.test_category import CategoryTestCase
|
||||
from trytond.modules.cashbook.tests.test_reconciliation import ReconTestCase
|
||||
|
||||
__all__ = ['suite']
|
||||
|
||||
|
||||
class CashbookTestCase(\
|
||||
ReconTestCase,\
|
||||
CategoryTestCase,\
|
||||
ConfigTestCase,\
|
||||
LineTestCase,
|
||||
|
|
|
@ -51,10 +51,10 @@ class LineTestCase(ModuleTestCase):
|
|||
self.assertEqual(book.state, 'open')
|
||||
self.assertEqual(len(book.lines), 2)
|
||||
self.assertEqual(book.lines[0].date, date(2022, 5, 1))
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022 Text 1')
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]')
|
||||
self.assertEqual(book.lines[0].state_cashbook, 'open')
|
||||
self.assertEqual(book.lines[1].date, date(2022, 5, 2))
|
||||
self.assertEqual(book.lines[1].rec_name, '05/02/2022 Text 2')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/02/2022|1.00 usd|Text 2 [Cat1]')
|
||||
|
||||
self.assertEqual(Lines.search_count([('rec_name', '=', 'Text 1')]), 1)
|
||||
self.assertEqual(Lines.search_count([('rec_name', '=', 'Text 1a')]), 0)
|
||||
|
@ -67,9 +67,9 @@ class LineTestCase(ModuleTestCase):
|
|||
|
||||
# sorting: date -> state -> id
|
||||
self.assertEqual(len(book.lines), 2)
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022 Text 1')
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]')
|
||||
self.assertEqual(book.lines[0].state, 'edit')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/02/2022 Text 2')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/02/2022|1.00 usd|Text 2 [Cat1]')
|
||||
self.assertEqual(book.lines[1].state, 'edit')
|
||||
|
||||
# set to same date
|
||||
|
@ -80,17 +80,17 @@ class LineTestCase(ModuleTestCase):
|
|||
}])
|
||||
# check again
|
||||
book, = Book.search([])
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022 Text 1')
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]')
|
||||
self.assertEqual(book.lines[0].state, 'edit')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/01/2022 Text 2')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/01/2022|1.00 usd|Text 2 [Cat1]')
|
||||
self.assertEqual(book.lines[1].state, 'edit')
|
||||
|
||||
# set to 'check', will sort first
|
||||
Lines.wfcheck([book.lines[1]])
|
||||
book, = Book.search([])
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022 Text 2')
|
||||
self.assertEqual(book.lines[0].rec_name, '05/01/2022|1.00 usd|Text 2 [Cat1]')
|
||||
self.assertEqual(book.lines[0].state, 'check')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/01/2022 Text 1')
|
||||
self.assertEqual(book.lines[1].rec_name, '05/01/2022|1.00 usd|Text 1 [Cat1]')
|
||||
self.assertEqual(book.lines[1].state, 'edit')
|
||||
|
||||
@with_transaction()
|
||||
|
@ -127,6 +127,24 @@ class LineTestCase(ModuleTestCase):
|
|||
self.assertEqual(book.state, 'open')
|
||||
self.assertEqual(len(book.lines), 2)
|
||||
|
||||
Line.write(*[
|
||||
[book.lines[0]],
|
||||
{
|
||||
'description': 'works',
|
||||
}])
|
||||
Line.wfcheck([book.lines[0]])
|
||||
self.assertEqual(book.lines[0].state, 'check')
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The cashbook line '05/01/2022|1.00 usd|works [Cat1]' is 'Checked' and cannot be changed.",
|
||||
Line.write,
|
||||
*[
|
||||
[book.lines[0]],
|
||||
{
|
||||
'description': 'denied by line.state',
|
||||
},
|
||||
])
|
||||
|
||||
Book.wfclosed([book])
|
||||
self.assertEqual(book.state, 'closed')
|
||||
|
||||
|
@ -521,7 +539,7 @@ class LineTestCase(ModuleTestCase):
|
|||
self.assertEqual(book.lines[0].state, 'check')
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The cashbook line '05/01/2022 Text 1' cannot be deleted, its in state 'Checked'.",
|
||||
"The cashbook line '05/01/2022|1.00 usd|Test 1 [Cat1]' cannot be deleted, its in state 'Checked'.",
|
||||
Lines.delete,
|
||||
[book.lines[0]])
|
||||
|
||||
|
@ -586,14 +604,14 @@ class LineTestCase(ModuleTestCase):
|
|||
lines = Line.search([])
|
||||
self.assertEqual(len(lines), 1)
|
||||
self.assertEqual(lines[0].cashbook.rec_name, 'Fridas book | 1.00 usd | Open')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]')
|
||||
|
||||
Line.write(*[
|
||||
lines,
|
||||
{
|
||||
'description': 'Test 2',
|
||||
}])
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]')
|
||||
|
||||
@with_transaction()
|
||||
def test_line_permission_reviewer(self):
|
||||
|
@ -659,25 +677,25 @@ class LineTestCase(ModuleTestCase):
|
|||
self.assertEqual(len(lines), 1)
|
||||
self.assertEqual(len(lines[0].cashbook.reviewer.users), 1)
|
||||
self.assertEqual(lines[0].cashbook.reviewer.users[0].rec_name, 'Diego')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]')
|
||||
Line.write(*[
|
||||
lines,
|
||||
{
|
||||
'description': 'Test 2',
|
||||
}])
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]')
|
||||
|
||||
# change to user 'frida' read/write line
|
||||
with Transaction().set_user(usr_lst[0].id):
|
||||
lines = Line.search([])
|
||||
self.assertEqual(len(lines), 1)
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]')
|
||||
Line.write(*[
|
||||
lines,
|
||||
{
|
||||
'description': 'Test 3',
|
||||
}])
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 3')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 3 [Cat1]')
|
||||
|
||||
@with_transaction()
|
||||
def test_line_permission_observer(self):
|
||||
|
@ -743,7 +761,7 @@ class LineTestCase(ModuleTestCase):
|
|||
self.assertEqual(len(lines), 1)
|
||||
self.assertEqual(len(lines[0].cashbook.observer.users), 1)
|
||||
self.assertEqual(lines[0].cashbook.observer.users[0].rec_name, 'Diego')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]')
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
'You are not allowed to write to records "[0-9]{1,}" of "Cashbook Line" because of at least one of these rules:\nOwners and reviewers: Cashbook line write - ',
|
||||
|
@ -759,12 +777,12 @@ class LineTestCase(ModuleTestCase):
|
|||
with Transaction().set_user(usr_lst[0].id):
|
||||
lines = Line.search([])
|
||||
self.assertEqual(len(lines), 1)
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 1')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 1 [Cat1]')
|
||||
Line.write(*[
|
||||
lines,
|
||||
{
|
||||
'description': 'Test 2',
|
||||
}])
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022 Test 2')
|
||||
self.assertEqual(lines[0].rec_name, '05/01/2022|1.00 usd|Test 2 [Cat1]')
|
||||
|
||||
# end LineTestCase
|
||||
|
|
365
tests/test_reconciliation.py
Normal file
365
tests/test_reconciliation.py
Normal file
|
@ -0,0 +1,365 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# This file is part of the cashbook-module from m-ds for Tryton.
|
||||
# The COPYRIGHT file at the top level of this repository contains the
|
||||
# full copyright notices and license terms.
|
||||
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.exceptions import UserError
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class ReconTestCase(ModuleTestCase):
|
||||
'Test cashbook reconciliation module'
|
||||
module = 'cashbook'
|
||||
|
||||
@with_transaction()
|
||||
def test_recon_check_overlap(self):
|
||||
""" create, check deny of overlap date
|
||||
"""
|
||||
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,
|
||||
}])
|
||||
|
||||
recon1, = Reconciliation.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([{
|
||||
'date': date(2022, 6, 1),
|
||||
'date_from': date(2022, 6, 1),
|
||||
'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]')
|
||||
|
||||
# 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]')
|
||||
|
||||
# 'date_from' inside of other record
|
||||
self.assertRaisesRegex(UserError,
|
||||
'The date range overlaps with another reconciliation.',
|
||||
Reconciliation.write,
|
||||
*[
|
||||
[recon2],
|
||||
{
|
||||
'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),
|
||||
},
|
||||
])
|
||||
|
||||
# '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,
|
||||
[{
|
||||
'date': date(2022, 5, 1),
|
||||
'date_from': date(2022, 4, 1),
|
||||
'date_to': date(2022, 4, 16),
|
||||
'cashbook': book.id,
|
||||
}])
|
||||
|
||||
recon3, = Reconciliation.create([{
|
||||
'date': date(2022, 4, 17),
|
||||
'date_from': date(2022, 4, 1),
|
||||
'date_to': date(2022, 4, 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]')
|
||||
|
||||
@with_transaction()
|
||||
def test_recon_create_check_line_add_to_recon(self):
|
||||
""" create, booklines, add reconciliation
|
||||
"""
|
||||
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, 5, 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, '05/05/2022|1.00 usd|Text 2 [Cat1]')
|
||||
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)
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"For reconciliation, the line '05/01/2022|1.00 usd|Text 1 [Cat1]' must be in the status 'Check' or 'Done'.",
|
||||
Lines.write,
|
||||
*[
|
||||
[book.lines[0]],
|
||||
{
|
||||
'reconciliation': book.reconciliations[0].id,
|
||||
}
|
||||
])
|
||||
Lines.wfcheck(book.lines)
|
||||
|
||||
Lines.write(*[
|
||||
list(book.lines),
|
||||
{
|
||||
'reconciliation': book.reconciliations[0].id,
|
||||
}])
|
||||
self.assertEqual(len(book.reconciliations[0].lines), 2)
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The status cannot be changed to 'Edit' as long as the line '05/01/2022|1.00 usd|Text 1 [Cat1]' is associated with a reconciliation.",
|
||||
Lines.wfedit,
|
||||
[book.lines[0]])
|
||||
|
||||
@with_transaction()
|
||||
def test_recon_check_deny_delete(self):
|
||||
""" create, booklines, reconciliation, try delete
|
||||
"""
|
||||
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'),
|
||||
}])],
|
||||
'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')
|
||||
|
||||
Lines.wfcheck(list(book.lines))
|
||||
Reconciliation.wfcheck(list(book.reconciliations))
|
||||
self.assertEqual(len(book.reconciliations), 1)
|
||||
self.assertEqual(len(book.reconciliations[0].lines), 1)
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The reconciliation '05/01/2022 - 05/31/2022 | 0.00 - 0.00 usd [0]' cannot be deleted, its in state 'Check'.",
|
||||
Reconciliation.delete,
|
||||
list(book.reconciliations))
|
||||
|
||||
Book.wfclosed([book])
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The cashbook line '05/01/2022 - 05/31/2022: 0.00 usd' cannot be deleted because the Cashbook 'Book 1 | 1.00 usd | Closed' is in state 'Closed'.",
|
||||
Reconciliation.delete,
|
||||
list(book.reconciliations))
|
||||
|
||||
self.assertRaisesRegex(UserError,
|
||||
"The cash book 'Book 1 | 1.00 usd | Closed' is 'Closed' and cannot be changed.",
|
||||
Reconciliation.write,
|
||||
*[
|
||||
list(book.reconciliations),
|
||||
{
|
||||
'date': date(2022, 5, 29),
|
||||
},
|
||||
])
|
||||
|
||||
@with_transaction()
|
||||
def test_recon_check_wf_edit_to_check(self):
|
||||
""" create, booklines, add reconciliation
|
||||
"""
|
||||
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, 5, 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, '05/05/2022|1.00 usd|Text 2 [Cat1]')
|
||||
self.assertEqual(book.lines[0].reconciliation, None)
|
||||
self.assertEqual(book.lines[1].reconciliation, None)
|
||||
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)
|
||||
|
||||
# run wf, fail with lines not 'checked'
|
||||
self.assertRaisesRegex(UserError,
|
||||
"For the reconciliation '05/01/2022 - 05/31/2022 | 0.00 usd - 0.00 usd [0]' of the cashbook 'Book 1 | 2.00 usd | Open', all lines in the date range from '05/01/2022' to '05/31/2022' must be in the 'Check' state.",
|
||||
Reconciliation.wfcheck,
|
||||
list(book.reconciliations),
|
||||
)
|
||||
|
||||
# edit --> check
|
||||
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]')
|
||||
|
||||
# check --> edit
|
||||
Reconciliation.wfedit(list(book.reconciliations))
|
||||
self.assertEqual(len(book.reconciliations[0].lines), 0)
|
||||
self.assertEqual(book.lines[0].reconciliation, None)
|
||||
self.assertEqual(book.lines[1].reconciliation, None)
|
||||
|
||||
# end ReconTestCase
|
|
@ -22,7 +22,11 @@ full copyright notices and license terms. -->
|
|||
<button name="wfdone"/>
|
||||
</group>
|
||||
|
||||
<label id="lab1" string=" " colspan="4"/>
|
||||
<label name="start_amount"/>
|
||||
<field name="start_amount"/>
|
||||
<label name="end_amount"/>
|
||||
<field name="end_amount"/>
|
||||
|
||||
<label name="date"/>
|
||||
<field name="date"/>
|
||||
<newline/>
|
||||
|
|
|
@ -7,6 +7,8 @@ full copyright notices and license terms. -->
|
|||
<field name="date"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="start_amount"/>
|
||||
<field name="end_amount"/>
|
||||
<field name="lines"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
|
|
Loading…
Reference in a new issue