diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 0f4763af3..8c7374047 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -3,7 +3,7 @@ # # Copyright (C) 2009 EduSense BV (). # (C) 2011 - 2013 Therp BV (). -# +# # All other contributions are (C) by their respective contributors # # All Rights Reserved @@ -63,11 +63,11 @@ class payment_order(orm.Model): ), 'state': fields.selection([ ('draft', 'Draft'), - ('open','Confirmed'), - ('cancel','Cancelled'), + ('open', 'Confirmed'), + ('cancel', 'Cancelled'), ('sent', 'Sent'), ('rejected', 'Rejected'), - ('done','Done'), + ('done', 'Done'), ], 'State', select=True ), 'line_ids': fields.one2many( @@ -81,7 +81,7 @@ class payment_order(orm.Model): }, ), 'user_id': fields.many2one( - 'res.users','User', required=True, + 'res.users', 'User', required=True, states={ 'sent': [('readonly', True)], 'rejected': [('readonly', True)], @@ -98,18 +98,19 @@ class payment_order(orm.Model): 'rejected': [('readonly', True)], 'done': [('readonly', True)] }, - help=("Choose an option for the Payment Order:'Fixed' stands for a " - "date specified by you.'Directly' stands for the direct " + help=("Choose an option for the Payment Order:'Fixed' stands for " + "a date specified by you.'Directly' stands for the direct " "execution.'Due date' stands for the scheduled date of " "execution." - ) + ) ), 'date_sent': fields.date('Send date', readonly=True), } def _write_payment_lines(self, cr, uid, ids, **kwargs): ''' - ORM method for setting attributes of corresponding payment.line objects. + ORM method for setting attributes of corresponding payment.line + objects. Note that while this is ORM compliant, it is also very ineffecient due to the absence of filters on writes and hence the requirement to filter on the client(=OpenERP server) side. @@ -143,7 +144,7 @@ class payment_order(orm.Model): cr, uid, ids, *args ) - def debit_reconcile_transfer(self, cr, uid, payment_order_id, + def debit_reconcile_transfer(self, cr, uid, payment_order_id, amount, currency, context=None): """ During import of bank statements, create the reconcile on the transfer @@ -163,10 +164,10 @@ class payment_order(orm.Model): if line.account_id.type == 'other' and not line.reconcile_id: line_ids.append(line.id) if self.pool.get('res.currency').is_zero( - cr, uid, currency, - move_line_obj.get_balance(cr, uid, line_ids) - amount): + cr, uid, currency, + move_line_obj.get_balance(cr, uid, line_ids) - amount): reconcile_id = self.pool.get('account.move.reconcile').create( - cr, uid, + cr, uid, {'type': 'auto', 'line_id': [(6, 0, line_ids)]}, context) # set direct debit order to finished state @@ -175,8 +176,9 @@ class payment_order(orm.Model): uid, 'payment.order', payment_order_id, 'done', cr) return reconcile_id - def debit_unreconcile_transfer(self, cr, uid, payment_order_id, reconcile_id, - amount, currency, context=None): + def debit_unreconcile_transfer( + self, cr, uid, payment_order_id, reconcile_id, amount, currency, + context=None): """ Due to a cancelled bank statements import, unreconcile the move on the transfer account. Delegate the conditions to the workflow. @@ -194,12 +196,12 @@ class payment_order(orm.Model): if state != 'sent': raise orm.except_orm( _("Cannot unreconcile"), - _("Cannot unreconcile payment order: "+ + _("Cannot unreconcile payment order: " "Workflow will not allow it.")) return True def test_undo_done(self, cr, uid, ids, context=None): - """ + """ Called from the workflow. Used to unset done state on payment orders that were reconciled with bank transfers which are being cancelled. @@ -213,14 +215,68 @@ class payment_order(orm.Model): for order in self.browse(cr, uid, ids, context=context): for order_line in order.line_ids: if order_line.transit_move_line_id.move_id: - for line in order_line.transit_move_line_id.move_id.line_id: + for line in \ + order_line.transit_move_line_id.move_id.line_id: if (line.account_id.type == 'other' and line.reconcile_id): return False return True - + + def _prepare_transfer_move( + self, cr, uid, order, line, labels, context=None): + vals = { + 'journal_id': order.mode.transfer_journal_id.id, + 'name': '%s %s' % (labels[order.payment_order_type], + line.move_line_id + and line.move_line_id.move_id.name + or line.communication), + 'ref': '%s %s' % (order.payment_order_type[:3].upper(), + line.move_line_id + and line.move_line_id.move_id.name + or line.communication), + } + return vals + + def _prepare_move_line_transfer_account( + self, cr, uid, order, line, move_id, labels, context=None): + vals = { + 'name': _('%s for %s') % ( + labels[order.payment_order_type], + line.move_line_id and (line.move_line_id.invoice + and line.move_line_id.invoice.number + or line.move_line_id.name) + or line.communication), + 'move_id': move_id, + 'partner_id': False, + 'account_id': order.mode.transfer_account_id.id, + 'credit': (order.payment_order_type == 'payment' + and line.amount or 0.0), + 'debit': (order.payment_order_type == 'debit' + and line.amount or 0.0), + 'date': fields.date.context_today( + self, cr, uid, context=context), + } + return vals + + def _update_move_line_partner_account( + self, cr, uid, order, line, vals, context=None): + vals.update({ + 'partner_id': line.partner_id.id, + 'account_id': (line.move_line_id + and line.move_line_id.account_id.id + or False), + # if not line.move_line_id, the field 'account_id' must be set by + # another module that inherit this function, like for example in + # the module purchase_payment_order + 'credit': (order.payment_order_type == 'debit' + and line.amount or 0.0), + 'debit': (order.payment_order_type == 'payment' + and line.amount or 0.0), + }) + return vals + def action_sent(self, cr, uid, ids, context=None): - """ + """ Create the moves that pay off the move lines from the debit order. This happens when the debit order file is generated. @@ -233,63 +289,35 @@ class payment_order(orm.Model): 'debit': _('Direct debit order'), } for order in self.browse(cr, uid, ids, context=context): - if not order.mode.transfer_journal_id or not order.mode.transfer_account_id: + if not order.mode.transfer_journal_id \ + or not order.mode.transfer_account_id: continue for line in order.line_ids: # basic checks - if not line.move_line_id: + if line.move_line_id and line.move_line_id.reconcile_id: raise orm.except_orm( _('Error'), - _('No move line provided for line %s') % line.name) - if line.move_line_id.reconcile_id: - raise orm.except_orm( - _('Error'), - _('Move line %s has already been paid/reconciled') % - line.move_line_id.name - ) + _('Move line %s has already been paid/reconciled') + % line.move_line_id.name) - move_id = account_move_obj.create(cr, uid, { - 'journal_id': order.mode.transfer_journal_id.id, - 'name': '%s %s' % (labels[order.payment_order_type], - line.move_line_id.move_id.name), - 'ref': '%s%s' % (order.payment_order_type[:3].upper(), - line.move_line_id.move_id.name), - }, context=context) + move_id = account_move_obj.create( + cr, uid, self._prepare_transfer_move( + cr, uid, order, line, labels, context=context), + context=context) # TODO: take multicurrency into account - - # create the debit move line on the transfer account - vals = { - 'name': _('%s for %s') % ( - labels[order.payment_order_type], - line.move_line_id.invoice and - line.move_line_id.invoice.number or - line.move_line_id.name), - 'move_id': move_id, - 'partner_id': False, - 'account_id': order.mode.transfer_account_id.id, - 'credit': (order.payment_order_type == 'payment' - and line.amount or 0.0), - 'debit': (order.payment_order_type == 'debit' - and line.amount or 0.0), - 'date': fields.date.context_today( - self, cr, uid, context=context), - } - transfer_move_line_id = account_move_line_obj.create( - cr, uid, vals, context=context) - # create the debit move line on the receivable account - vals.update({ - 'partner_id': line.partner_id.id, - 'account_id': line.move_line_id.account_id.id, - 'credit': (order.payment_order_type == 'debit' - and line.amount or 0.0), - 'debit': (order.payment_order_type == 'payment' - and line.amount or 0.0), - }) + # create the debit move line on the transfer account + ml_vals = self._prepare_move_line_transfer_account( + cr, uid, order, line, move_id, labels, context=context) + account_move_line_obj.create(cr, uid, ml_vals, context=context) + + # create the debit move line on the partner account + self._update_move_line_partner_account( + cr, uid, order, line, ml_vals, context=context) reconcile_move_line_id = account_move_line_obj.create( - cr, uid, vals, context=context) - + cr, uid, ml_vals, context=context) + # register the debit move line on the payment line # and call reconciliation on it payment_line_obj.write( @@ -297,16 +325,15 @@ class payment_order(orm.Model): {'transit_move_line_id': reconcile_move_line_id}, context=context) - payment_line_obj.debit_reconcile( - cr, uid, line.id, context=context) + if line.move_line_id: + payment_line_obj.debit_reconcile( + cr, uid, line.id, context=context) account_move_obj.post(cr, uid, [move_id], context=context) # State field is written by act_sent_wait self.write(cr, uid, ids, { - 'date_sent': fields.date.context_today( - self, cr, uid, context=context), - }, context=context) + 'date_sent': fields.date.context_today( + self, cr, uid, context=context), + }, context=context) return True - -