[FIX] Ability to encode statements manually,

as well as compatibility with point_of_sale module (lp 992141)
[FIX] Post vouchers using workflow
[FIX] Remove redundant move_id fields on statement line.
	Use existing move_ids field instead. This restores
	the ability to cancel legacy (stateless) statement lines.
This commit is contained in:
Stefan Rijnhart
2012-05-02 15:23:51 +02:00
parent a94a1e4fd4
commit 7fa5c32b88
2 changed files with 98 additions and 76 deletions

View File

@@ -320,6 +320,26 @@ class account_bank_statement(osv.osv):
# 'currency': _currency,
}
def _check_company_id(self, cr, uid, ids, context=None):
"""
Adapt this constraint method from the account module to reflect the
move of period_id to the statement line
"""
for statement in self.browse(cr, uid, ids, context=context):
if (statement.period_id and
statement.company_id.id != statement.period_id.company_id.id):
return False
for line in statement.line_ids:
if (line.period_id and
statement.company_id.id != line.period_id.company_id.id):
return False
return True
# Redefine the constraint, or it still refer to the original method
_constraints = [
(_check_company_id, 'The journal and period chosen have to belong to the same company.', ['journal_id','period_id']),
]
def _get_period(self, cursor, uid, date, context=None):
'''
Find matching period for date, not meant for _defaults.
@@ -339,10 +359,12 @@ class account_bank_statement(osv.osv):
context=None):
# This is largely a copy of the original code in account
# Modifications are marked with AB
# Modifications by account_voucher are merged below.
# As there is no valid inheritance mechanism for large actions, this
# is the only option to add functionality to existing actions.
# WARNING: when the original code changes, this trigger has to be
# updated in sync.
if context is None:
context = {}
res_currency_obj = self.pool.get('res.currency')
@@ -350,8 +372,36 @@ class account_bank_statement(osv.osv):
account_move_line_obj = self.pool.get('account.move.line')
account_bank_statement_line_obj = self.pool.get(
'account.bank.statement.line')
st_line = account_bank_statement_line_obj.browse(cr, uid, st_line_id,
context=context)
st_line = account_bank_statement_line_obj.browse(
cr, uid, st_line_id, context=context)
# Start account voucher
# Post the voucher and update links between statement and moves
if st_line.voucher_id:
voucher_pool = self.pool.get('account.voucher')
wf_service = netsvc.LocalService("workflow")
voucher_pool.write(
cr, uid, [st_line.voucher_id.id], {'number': st_line_number}, context=context)
if st_line.voucher_id.state == 'cancel':
voucher_pool.action_cancel_draft(
cr, uid, [st_line.voucher_id.id], context=context)
wf_service.trg_validate(
uid, 'account.voucher', st_line.voucher_id.id, 'proforma_voucher', cr)
v = voucher_pool.browse(
cr, uid, st_line.voucher_id.id, context=context)
account_bank_statement_line_obj.write(cr, uid, [st_line_id], {
'move_ids': [(4, v.move_id.id, False)]
})
account_move_line_obj.write(
cr, uid, [x.id for x in v.move_ids],
{'statement_id': st_line.statement_id.id}, context=context)
# End of account_voucher
st_line.refresh()
# AB: The voucher journal isn't automatically posted, so post it (if needed)
if not st_line.voucher_id.journal_id.entry_posted:
account_move_obj.post(cr, uid, [st_line.voucher_id.move_id.id], context={})
return True
st = st_line.statement_id
context.update({'date': st_line.date})
@@ -1133,7 +1183,7 @@ class res_partner_bank(osv.osv):
'''
Create dual function IBAN account for SEPA countries
'''
if vals['state'] == 'iban':
if vals.get('state') == 'iban':
iban = vals.get('acc_number',False) or vals.get('acc_number_domestic',False)
vals['acc_number'], vals['acc_number_domestic'] = (
self._correct_IBAN(iban))

View File

@@ -722,7 +722,13 @@ class banking_import_transaction(osv.osv):
st_line = transaction.statement_line_id
if transaction.match_type:
if st_line.voucher_id:
# Cancel and delete the vouchers
# Although vouchers can be associated with statement lines
# in standard OpenERP, we consider ourselves owner of the voucher
# if the line has an associated transaction
# Upon canceling of the statement line/transaction,
# we cancel and delete the vouchers.
# Otherwise, the statement line will leave the voucher
# unless the statement line itself is deleted.
voucher_pool.cancel_voucher(
cr, uid, [st_line.voucher_id.id], context=context)
voucher_pool.action_cancel_draft(
@@ -730,7 +736,7 @@ class banking_import_transaction(osv.osv):
voucher_pool.unlink(
cr, uid, [st_line.voucher_id.id], context=context)
# Allow canceling of legacy entries
elif st_line.reconcile_id:
if not st_line.voucher_id and st_line.reconcile_id:
self._legacy_cancel_move(cr, uid, transaction, context=context)
return True
@@ -760,7 +766,11 @@ class banking_import_transaction(osv.osv):
else:
account_id = journal.default_debit_account_id.id
cancel_line = False
for line in transaction.statement_line_id.move_id.line_id:
move_lines = [
# There should usually be just one move, I think
move.line_id for move in transaction.statement_line_id.move_ids
]
for line in move_lines:
if line.account_id.id != account_id:
cancel_line = line
break
@@ -800,7 +810,6 @@ class banking_import_transaction(osv.osv):
def cancel(self, cr, uid, ids, context=None):
if ids and isinstance(ids, (int, float)):
ids = [ids]
move_pool = self.pool.get('account.move')
for transaction in self.browse(cr, uid, ids, context):
if not transaction.match_type:
continue
@@ -811,14 +820,6 @@ class banking_import_transaction(osv.osv):
self.cancel_map[transaction.match_type](
self, cr, uid, transaction.id, context)
self._legacy_clear_up_writeoff(cr, uid, transaction, context=context)
if transaction.statement_line_id.move_id:
# We allow for people canceling and removing
# the associated payments, which can lead to confirmed
# statement lines without an associated move
move_pool.button_cancel(
cr, uid, [transaction.statement_line_id.move_id.id], context)
move_pool.unlink(
cr, uid, [transaction.statement_line_id.move_id.id], context)
return True
confirm_map = {
@@ -1682,9 +1683,6 @@ class account_bank_statement_line(osv.osv):
'state': fields.selection(
[('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State',
readonly=True, required=True),
'move_id': fields.many2one(
'account.move', 'Move', readonly=True,
help="The accounting move associated with this line"),
}
_defaults = {
@@ -1751,14 +1749,21 @@ class account_bank_statement_line(osv.osv):
"journal!") % (st_line.statement_id.journal_id.name,))
if not st_line.amount:
continue
if not st_line.period_id:
self.write(
cr, uid, [st_line.id], {
'period_id': self._get_period(
cr, uid, {'date': st_line.date})
})
st_line.refresh()
# Generate the statement number, if it is not already done
st = st_line.statement_id
if not st.name == '/':
st_number = st.name
else:
if st.journal_id.sequence_id:
c = {'fiscalyear_id': st.period_id.fiscalyear_id.id}
period = st.period_id or st_line.period_id
c = {'fiscalyear_id': period.fiscalyear_id.id}
st_number = obj_seq.next_by_id(cr, uid, st.journal_id.sequence_id.id, context=c)
else:
st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement')
@@ -1768,59 +1773,23 @@ class account_bank_statement_line(osv.osv):
import_transaction_obj.confirm(
cr, uid, st_line.import_transaction_id.id, context)
st_line.refresh()
if st_line.voucher_id:
# Check if this line has been matched against a journal item
# Line has been matched, so post it via a voucher
self._post_voucher(cr, uid, ids, st_line, move_pool, context=context)
else:
# Check to see if the line has an account that can be used to generate a journal entry
if st_line.account_id:
# Generate a journal for the entry using the standard bank statement code
self._create_move(cr, uid, st_line, statement_pool, st, st_number, context=context)
else:
raise osv.except_osv(
_('Statement line has no account'),
_("You cannot confirm a bank statement line that has no account against it (%s.%s)") %
(st_line.statement_id.name, st_line.name,))
st_line_number = statement_pool.get_next_st_line_number(
cr, uid, st_number, st_line, context)
company_currency_id = st.journal_id.company_id.currency_id.id
statement_pool.create_move_from_st_line(
cr, uid, st_line.id, company_currency_id, st_line_number, context)
self.write(
cr, uid, st_line.id, {'state': 'confirmed'}, context)
return True
def _create_move(
self, cr, uid, st_line, statement_pool, st, st_number, context):
"""
The line is not matched against a move, but the account has been
defined for the line. Generate a journal entry for the statement
line that transfers the full amount against the account.
"""
st_line_number = statement_pool.get_next_st_line_number(
cr, uid, st_number, st_line, context)
company_currency_id = st.journal_id.company_id.currency_id.id
move_id = statement_pool.create_move_from_st_line(
cr, uid, st_line.id, company_currency_id, st_line_number, context)
self.write(
cr, uid, st_line.id, {'state': 'confirmed', 'move_id': move_id}, context)
def _post_voucher(self, cr, uid, ids, st_line, move_pool, context):
# If the voucher is in draft mode, then post it
if st_line.voucher_id.state in ('draft','proforma'):
st_line.voucher_id.action_move_line_create()
st_line.voucher_id.refresh()
# Update the statement line to indicate that it has been posted
# ... no longer need to set the move_id on the voucher?
self.write(cr, uid, st_line.id, {'state': 'confirmed'}, context)
# The voucher journal isn't automatically posted, so post it (if needed)
if not st_line.voucher_id.journal_id.entry_posted:
move_pool.post(cr, uid, [st_line.voucher_id.move_id.id], context={})
def cancel(self, cr, uid, ids, context=None):
if ids and isinstance(ids, (int, float)):
ids = [ids]
import_transaction_obj = self.pool.get('banking.import.transaction')
move_pool = self.pool.get('account.move')
transaction_cancel_ids = []
set_draft_ids = []
move_unlink_ids = []
# harvest ids for various actions
for st_line in self.browse(cr, uid, ids, context):
if st_line.state != 'confirmed':
@@ -1832,19 +1801,22 @@ class account_bank_statement_line(osv.osv):
"already been confirmed"))
if st_line.import_transaction_id:
transaction_cancel_ids.append(st_line.import_transaction_id.id)
else:
if not st_line.move_id:
raise osv.except_osv(
_("Cannot cancel bank transaction"),
_("Cannot cancel this bank transaction. The information "
"needed to undo the accounting entries has not been "
"recorded"))
# Cancel transaction immediately.
# If it has voucher, this will clean up
# the moves on the st_line.
import_transaction_obj.cancel(
cr, uid, [st_line.import_transaction_id.id], context=context)
st_line.refresh()
for line in st_line.move_ids:
# We allow for people canceling and removing
# the associated payments, which can lead to confirmed
# statement lines without an associated move
move_unlink_ids.append(line.id)
set_draft_ids.append(st_line.id)
# Perform actions
import_transaction_obj.cancel(
cr, uid, transaction_cancel_ids, context=context)
move_pool.button_cancel(
cr, uid, move_unlink_ids, context=context)
move_pool.unlink(cr, uid, move_unlink_ids, context=context)
self.write(
cr, uid, set_draft_ids, {'state': 'draft'}, context=context)
return True