From 5ae5d657f8fedf4a008c1283389112a56191ebf6 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Mon, 27 May 2013 21:36:20 +0200 Subject: [PATCH 01/26] [ADD] Foreporting crude support for full payment workflow including transferral move that pays the invoices --- account_banking/banking_import_transaction.py | 20 +++++--- account_banking_nl_girotel/girotel.py | 16 +++++- .../model/banking_import_transaction.py | 50 ++++++++++++------- account_direct_debit/model/account_payment.py | 27 ++++++---- 4 files changed, 74 insertions(+), 39 deletions(-) diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index 0e223b84f..14a38f0e3 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -810,6 +810,12 @@ class banking_import_transaction(orm.Model): move_info['invoice_ids'][0] ) return vals + + def hook_match_payment(self, cr, uid, transaction, log, context=None): + """ + To override in module 'account_banking_payment' + """ + return False def match(self, cr, uid, ids, results=None, context=None): if not ids: @@ -1020,13 +1026,13 @@ class banking_import_transaction(orm.Model): ), context=context) # rebrowse the current record after writing transaction = self.browse(cr, uid, transaction.id, context=context) - # Match full direct debit orders - if transaction.type == bt.DIRECT_DEBIT and has_payment: - move_info = self._match_debit_order( - cr, uid, transaction, results['log'], context) - if transaction.type == bt.STORNO and has_payment: - move_info = self._match_storno( - cr, uid, transaction, results['log'], context) + + # Match payment and direct debit orders + move_info_payment = hook_match_payment( + cr, uid, transaction, results['log'], context=context) + if move_info_payment: + move_info = move_info_payment + # Allow inclusion of generated bank invoices if transaction.type == bt.BANK_COSTS: lines = self._match_costs( diff --git a/account_banking_nl_girotel/girotel.py b/account_banking_nl_girotel/girotel.py index 9b0e56087..792770f19 100644 --- a/account_banking_nl_girotel/girotel.py +++ b/account_banking_nl_girotel/girotel.py @@ -45,6 +45,7 @@ As a counter measure, all imported data is converted to SWIFT-format before usag from account_banking.parsers import models from account_banking.parsers.convert import str2date, to_swift from tools.translate import _ +import re import csv bt = models.mem_bank_transaction @@ -105,6 +106,13 @@ class transaction_message(object): self.date = str2date(self.date, '%Y%m%d') if self.direction == 'A': self.transferred_amount = -float(self.transferred_amount) + if (self.transfer_type == 'VZ' + and (not self.remote_account or self.remote_account == '0') + and (not self.message or re.match('^\s*$', self.message)) + and self.remote_owner.startswith('TOTAAL ')): + self.transfer_type = 'PB' + self.message = self.remote_owner + self.remove_owner = False else: self.transferred_amount = float(self.transferred_amount) self.local_account = self.local_account.zfill(10) @@ -140,7 +148,8 @@ class transaction(models.mem_bank_transaction): 'GT': bt.ORDER, 'IC': bt.DIRECT_DEBIT, 'OV': bt.ORDER, - 'VZ': bt.PAYMENT_BATCH, + 'VZ': bt.ORDER, + 'PB': bt.PAYMENT_BATCH, } def __init__(self, line, *args, **kwargs): @@ -171,11 +180,14 @@ class transaction(models.mem_bank_transaction): 4. Cash withdrawals from banks are too not seen as a transfer between two accounts - the cash exits the banking system. These withdrawals have their transfer_type set to 'GM'. + 5. Aggregated payment batches. These transactions have transfer type + 'VZ' natively but are changed to 'PB' while parsing. These transactions + have no remote account. ''' return bool(self.transferred_amount and self.execution_date and ( self.remote_account or self.transfer_type in [ - 'DV', 'BT', 'BA', 'GM', + 'DV', 'PB', 'BT', 'BA', 'GM', ])) def refold_message(self, message): diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index 21cfc2fd4..e08a61ffb 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -32,24 +32,30 @@ from openerp.addons.decimal_precision import decimal_precision as dp class banking_import_transaction(orm.Model): _inherit = 'banking.import.transaction' - def _match_debit_order( - self, cr, uid, trans, log, context=None): + def _match_payment_order( + self, cr, uid, trans, log, order_type='payment', context=None): - def is_zero(total): + def equals_order_amount(payment_order, transferred_amount): + if (not hasattr(payment_order, 'payment_order_type') + or payment_order.payment_order_type == 'payment'): + sign = 1 + else: + sign = -1 + total = payment_order.total + sign * transferred_amount return self.pool.get('res.currency').is_zero( cr, uid, trans.statement_id.currency, total) payment_order_obj = self.pool.get('payment.order') order_ids = payment_order_obj.search( - cr, uid, [('payment_order_type', '=', 'debit'), + cr, uid, [('payment_order_type', '=', order_type), ('state', '=', 'sent'), ('date_sent', '<=', trans.execution_date), ], limit=0, context=context) orders = payment_order_obj.browse(cr, uid, order_ids, context) candidates = [x for x in orders if - is_zero(x.total - trans.transferred_amount)] + equals_order_amount(x.total - trans.transferred_amount)] if len(candidates) > 0: # retrieve the common account_id, if any account_id = False @@ -170,10 +176,6 @@ class banking_import_transaction(orm.Model): raise orm.except_orm( _("Cannot reconcile"), _("Cannot reconcile: no direct debit order")) - if transaction.payment_order_id.payment_order_type != 'debit': - raise orm.except_orm( - _("Cannot reconcile"), - _("Reconcile payment order not implemented")) reconcile_id = payment_order_obj.debit_reconcile_transfer( cr, uid, transaction.payment_order_id.id, @@ -231,11 +233,7 @@ class banking_import_transaction(orm.Model): if not transaction.payment_order_id: raise orm.except_orm( _("Cannot unreconcile"), - _("Cannot unreconcile: no direct debit order")) - if transaction.payment_order_id.payment_order_type != 'debit': - raise orm.except_orm( - _("Cannot unreconcile"), - _("Unreconcile payment order not implemented")) + _("Cannot unreconcile: no payment or direct debit order")) return payment_order_obj.debit_unreconcile_transfer( cr, uid, transaction.payment_order_id.id, transaction.statement_line_id.reconcile_id.id, @@ -355,11 +353,25 @@ class banking_import_transaction(orm.Model): ) return vals - def match(self, cr, uid, ids, results=None, context=None): - res = super(banking_import_transaction, self).match( - cr, uid, ids, results=results, context=context) - - return res + def hook_match_payment(cr, uid, transaction, log, context=None): + """ + Called from match() in the core module. + Match payment batches, direct debit orders and stornos + """ + move_info = False + if transaction.type == bt.PAYMENT_BATCH: + move_info = self._match_payment_order( + cr, uid, transaction, log, + order_type='payment', context=context) + elif transaction.type == bt.DIRECT_DEBIT: + move_info = self._match_payment_order( + cr, uid, transaction, log, + order_type='debit', context=context) + elif transaction.type == bt.STORNO: + move_info = self._match_storno( + cr, uid, transaction, log, + context=context) + return move_info def __init__(self, pool, cr): """ diff --git a/account_direct_debit/model/account_payment.py b/account_direct_debit/model/account_payment.py index fe4cb6d7b..56c9fcbbf 100644 --- a/account_direct_debit/model/account_payment.py +++ b/account_direct_debit/model/account_payment.py @@ -102,7 +102,7 @@ class payment_order(osv.osv): if not wkf_ok: raise osv.except_osv( _("Cannot unreconcile"), - _("Cannot unreconcile debit order: "+ + _("Cannot unreconcile payment order: "+ "Workflow will not allow it.")) return True @@ -119,7 +119,7 @@ class payment_order(osv.osv): return False else: # TODO: define conditions for 'payment' orders - return False + return True return True def action_sent(self, cr, uid, ids, context=None): @@ -135,8 +135,6 @@ class payment_order(osv.osv): account_move_line_obj = self.pool.get('account.move.line') payment_line_obj = self.pool.get('payment.line') for order in self.browse(cr, uid, ids, context=context): - if order.payment_order_type != 'debit': - continue for line in order.line_ids: # basic checks if not line.move_line_id: @@ -152,23 +150,28 @@ class payment_order(osv.osv): move_id = account_move_obj.create(cr, uid, { 'journal_id': order.mode.transfer_journal_id.id, - 'name': 'Debit order %s' % line.move_line_id.move_id.name, - 'reference': 'DEB%s' % line.move_line_id.move_id.name, + 'name': '%s order %s' % (order.payment_order_type, + line.move_line_id.move_id.name), + 'reference': '%s%s' % (order.payment_order_type[:3].upper(), + line.move_line_id.move_id.name), }, context=context) # TODO: take multicurrency into account # create the debit move line on the transfer account vals = { - 'name': 'Debit order for %s' % ( + 'name': '%s order for %s' % ( + 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': line.partner_id.id, 'account_id': order.mode.transfer_account_id.id, - 'credit': 0.0, - 'debit': line.amount, + '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': time.strftime('%Y-%m-%d'), } transfer_move_line_id = account_move_line_obj.create( @@ -177,8 +180,10 @@ class payment_order(osv.osv): # create the debit move line on the receivable account vals.update({ 'account_id': line.move_line_id.account_id.id, - 'credit': line.amount, - 'debit': 0.0, + 'credit': (order.payment_order_type == 'debit' + and line.amount or 0.0), + 'debit': (order.payment_order_type == 'payment' + and line.amount or 0.0), }) reconcile_move_line_id = account_move_line_obj.create( cr, uid, vals, context=context) From 345381a8a71e8c204e9a4af4f3439aab77c8686e Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 07:16:26 +0200 Subject: [PATCH 02/26] [RFR] Move workflow adaptions from debit module to payment module --- .../workflow/account_payment.xml | 22 ++++++++++++++++ account_direct_debit/__openerp__.py | 7 +++--- .../migrations/7.0.2/pre-migration.py | 12 +++++++++ .../workflow/account_payment.xml | 25 ------------------- 4 files changed, 37 insertions(+), 29 deletions(-) create mode 100644 account_direct_debit/migrations/7.0.2/pre-migration.py delete mode 100644 account_direct_debit/workflow/account_payment.xml diff --git a/account_banking_payment/workflow/account_payment.xml b/account_banking_payment/workflow/account_payment.xml index e09d697a7..fb16f0e5a 100644 --- a/account_banking_payment/workflow/account_payment.xml +++ b/account_banking_payment/workflow/account_payment.xml @@ -34,5 +34,27 @@ write({'state':'rejected'}) sent + + + + + + + + + + + test_undo_done() + undo_done + + diff --git a/account_direct_debit/__openerp__.py b/account_direct_debit/__openerp__.py index 274513c3b..da3d223c7 100644 --- a/account_direct_debit/__openerp__.py +++ b/account_direct_debit/__openerp__.py @@ -1,6 +1,6 @@ ############################################################################## # -# Copyright (C) 2011 Therp BV (). +# Copyright (C) 2011 - 2013 Therp BV (). # Copyright (C) 2011 Smile (). # All Rights Reserved # @@ -20,9 +20,9 @@ ############################################################################## { 'name': 'Direct Debit', - 'version': '6.1.1.134', + 'version': '7.0.2.134', 'license': 'AGPL-3', - 'author': 'Therp BV / Smile', + 'author': '['Therp BV', 'Smile']', 'website': 'https://launchpad.net/banking-addons', 'category': 'Banking addons', 'depends': ['account_banking'], @@ -30,7 +30,6 @@ 'view/account_payment.xml', 'view/account_invoice.xml', 'workflow/account_invoice.xml', - 'workflow/account_payment.xml', 'data/account_payment_term.xml', ], 'description': ''' diff --git a/account_direct_debit/migrations/7.0.2/pre-migration.py b/account_direct_debit/migrations/7.0.2/pre-migration.py new file mode 100644 index 000000000..29fa9d6aa --- /dev/null +++ b/account_direct_debit/migrations/7.0.2/pre-migration.py @@ -0,0 +1,12 @@ +def migrate(cr, version): + if not version: + return + # workflow state moved to another module + cr.execute( + """ + UPDATE ir_model_data + SET module = 'account_banking_payment' + WHERE name = 'trans_done_sent' + AND module = 'account_direct_debit' + """) + diff --git a/account_direct_debit/workflow/account_payment.xml b/account_direct_debit/workflow/account_payment.xml deleted file mode 100644 index 7ea27c523..000000000 --- a/account_direct_debit/workflow/account_payment.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - test_undo_done() - undo_done - - - From b05036098f7d4ae3fa4e548b2f84eeb9dc840dd4 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 13:49:08 +0200 Subject: [PATCH 03/26] [RFR] Sort out move line code between payment and debit module --- .../model/account_move_line.py | 74 ++----------------- account_direct_debit/model/account_payment.py | 4 +- 2 files changed, 9 insertions(+), 69 deletions(-) diff --git a/account_direct_debit/model/account_move_line.py b/account_direct_debit/model/account_move_line.py index 9a00955b1..943268912 100644 --- a/account_direct_debit/model/account_move_line.py +++ b/account_direct_debit/model/account_move_line.py @@ -2,9 +2,8 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# This module additional (C) 2011 Therp BV (). -# (C) 2011 Smile Benelux (). +# This module (C) 2011 - 2013 Therp BV (). +# (C) 2011 Smile Benelux (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -22,10 +21,9 @@ ############################################################################## from operator import itemgetter -from osv import fields, osv -from tools.translate import _ +from openerp.osv import fields, orm -class account_move_line(osv.osv): +class account_move_line(orm.Model): _inherit = "account.move.line" def amount_to_receive(self, cr, uid, ids, name, arg={}, context=None): @@ -55,6 +53,9 @@ class account_move_line(osv.osv): return r def _to_receive_search(self, cr, uid, obj, name, args, context=None): + """ + Reverse of account_payment/account_move_line.py:_to_pay_search() + """ if not args: return [] line_obj = self.pool.get('account.move.line') @@ -86,70 +87,9 @@ class account_move_line(osv.osv): return [('id', '=', '0')] return [('id', 'in', map(lambda x:x[0], res))] - def _dummy(self, cr, user, ids, name, arg, context=None): - res = {} - if ids: - res = dict([(x, False) for x in ids]) - return res - - def _invoice_payment_term_id_search( - self, cr, uid, obj, name, args, context=None): - """ - Allow to search move lines associated with an invoice with - a particular payment term - """ - if not args: - return [] - invoice_obj = self.pool.get('account.invoice') - invoice_ids = invoice_obj.search( - cr, uid, [('payment_term', args[0][1], args[0][2])], - context=context) - operator = 'in' # (args[0][1] not in ['in', '=', '==', 'like', 'ilike'] - # and 'not in' or 'in') - if not invoice_ids: - return [('id', operator, [])] - cr.execute('SELECT l.id ' \ - 'FROM account_move_line l, account_invoice i ' \ - 'WHERE l.move_id = i.move_id AND i.id in %s', (tuple(invoice_ids),)) - res = cr.fetchall() - if not res: - return [('id', '=', False)] - return [('id', operator, [x[0] for x in res])] - - def _invoice_state_search(self, cr, uid, obj, name, args, context=None): - if not args: - return [] - invoice_obj = self.pool.get('account.invoice') - invoice_ids = invoice_obj.search( - cr, uid, [('state', args[0][1], args[0][2])], - context=context) - operator = 'in' # (args[0][1] not in ['in', '=', '==', 'like', 'ilike'] - # and 'not in' or 'in') - if not invoice_ids: - return [('id', operator, [])] - cr.execute('SELECT l.id ' \ - 'FROM account_move_line l, account_invoice i ' \ - 'WHERE l.move_id = i.move_id AND i.id in %s', (tuple(invoice_ids),)) - res = cr.fetchall() - if not res: - return [('id', '=', False)] - return [('id', operator, [x[0] for x in res])] - _columns = { 'amount_to_receive': fields.function( amount_to_receive, method=True, type='float', string='Amount to receive', fnct_search=_to_receive_search), - 'payment_term_id': fields.function( - _dummy, method=True, - string='Select by invoice payment term', - type='many2one', relation='account.payment.term', - fnct_search=_invoice_payment_term_id_search), - 'invoice_state': fields.function( - _dummy, method=True, - string='Select by invoice state', - type='char', size=24, - fnct_search=_invoice_state_search), } - -account_move_line() diff --git a/account_direct_debit/model/account_payment.py b/account_direct_debit/model/account_payment.py index 56c9fcbbf..abdce4977 100644 --- a/account_direct_debit/model/account_payment.py +++ b/account_direct_debit/model/account_payment.py @@ -443,7 +443,7 @@ class payment_order_create(osv.osv_memory): domain = [ ('reconcile_id', '=', False), ('account_id.type', '=', 'receivable'), - ('invoice_state', '!=', 'debit_denied'), + ('invoice.state', '!=', 'debit_denied'), ('amount_to_receive', '>', 0), ] else: @@ -456,7 +456,7 @@ class payment_order_create(osv.osv_memory): # apply payment term filter if payment.mode.payment_term_ids: domain = domain + [ - ('payment_term_id', 'in', + ('invoice.payment_term', 'in', [term.id for term in payment.mode.payment_term_ids] ) ] From 7fc4e0f975ada2359cc4ef2b3bc35db64e5d1277 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 14:56:27 +0200 Subject: [PATCH 04/26] [RFR] Sort out payment/payment line code between payment and debit module --- .../model/account_payment.py | 171 +++++-- account_banking_payment/model/payment_line.py | 86 +++- account_banking_payment/model/payment_mode.py | 20 + account_direct_debit/model/__init__.py | 1 + account_direct_debit/model/account_payment.py | 444 +----------------- account_direct_debit/model/payment_line.py | 211 +++++++++ 6 files changed, 461 insertions(+), 472 deletions(-) create mode 100644 account_direct_debit/model/payment_line.py diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 1e05e9a77..a0428a312 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -181,18 +181,6 @@ class payment_order(orm.Model): cr, uid, ids, *args ) - def action_sent(self, cr, uid, ids, context=None): - ''' - Set both self and payment lines to state 'sent'. - ''' - self._write_payment_lines(cr, uid, ids, export_state='sent') - self.write(cr, uid, ids, { - 'state': 'sent', - 'date_sent': fields.date.context_today( - self, cr, uid, context=context), - }, context=context) - return True - def action_rejected(self, cr, uid, ids, *args): ''' Set both self and payment lines to state 'rejected'. @@ -215,26 +203,145 @@ class payment_order(orm.Model): cr, uid, ids, *args ) - """ - Hooks for processing direct debit orders, such as implemented in - account_direct_debit module. - """ - def debit_reconcile_transfer( - self, cr, uid, payment_order_id, amount, currency, context=None): + def debit_reconcile_transfer(self, cr, uid, payment_order_id, + amount, currency, context=None): """ - Reconcile the payment order if the amount is correct. Return the - id of the reconciliation. + During import of bank statements, create the reconcile on the transfer + account containing all the open move lines on the transfer account. """ - raise orm.except_orm( - _("Cannot reconcile"), - _("Cannot reconcile debit order: "+ - "Not implemented.")) + move_line_obj = self.pool.get('account.move.line') + order = self.browse(cr, uid, payment_order_id, context) + line_ids = [] + reconcile_id = False + for order_line in order.line_ids: + for line in order_line.debit_move_line_id.move_id.line_id: + 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): + reconcile_id = self.pool.get('account.move.reconcile').create( + cr, uid, + {'type': 'auto', 'line_id': [(6, 0, line_ids)]}, + context) + # set direct debit order to finished state + wf_service = netsvc.LocalService('workflow') + wf_service.trg_validate( + 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): - """ Unreconcile the payment_order if at all possible """ - raise orm.except_orm( - _("Cannot unreconcile"), - _("Cannot unreconcile debit order: "+ - "Not implemented.")) + 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. + Raise on failure for rollback. + """ + self.pool.get('account.move.reconcile').unlink( + cr, uid, reconcile_id, context=context) + wkf_ok = netsvc.LocalService('workflow').trg_validate( + uid, 'payment.order', payment_order_id, 'undo_done', cr) + if not wkf_ok: + raise orm.except_orm( + _("Cannot unreconcile"), + _("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. + + The debit module actually enforces a criterium in its + override of this method for debit orders. + """ + return True + + 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. + """ + res = super(payment_order, self).action_sent( + cr, uid, ids, context) + + account_move_obj = self.pool.get('account.move') + account_move_line_obj = self.pool.get('account.move.line') + payment_line_obj = self.pool.get('payment.line') + for order in self.browse(cr, uid, ids, context=context): + for line in order.line_ids: + # basic checks + if not line.move_line_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_id = account_move_obj.create(cr, uid, { + 'journal_id': order.mode.transfer_journal_id.id, + 'name': '%s order %s' % (order.payment_order_type, + line.move_line_id.move_id.name), + 'reference': '%s%s' % (order.payment_order_type[:3].upper(), + line.move_line_id.move_id.name), + }, context=context) + + # TODO: take multicurrency into account + + # create the debit move line on the transfer account + vals = { + 'name': '%s order for %s' % ( + 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': line.partner_id.id, + '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({ + '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), + }) + reconcile_move_line_id = account_move_line_obj.create( + cr, uid, vals, context=context) + + # register the debit move line on the payment line + # and call reconciliation on it + payment_line_obj.write( + cr, uid, line.id, + {'debit_move_line_id': reconcile_move_line_id}, + context=context) + + payment_line_obj.debit_reconcile( + cr, uid, line.id, context=context) + account_move_obj.post(cr, uid, [move_id], context=context) + + self._write_payment_lines(cr, uid, ids, export_state='sent') + self.write(cr, uid, ids, { + 'state': 'sent', + 'date_sent': fields.date.context_today( + self, cr, uid, context=context), + }, context=context) + + return res diff --git a/account_banking_payment/model/payment_line.py b/account_banking_payment/model/payment_line.py index 30bef3564..7d1b29176 100644 --- a/account_banking_payment/model/payment_line.py +++ b/account_banking_payment/model/payment_line.py @@ -24,7 +24,8 @@ ############################################################################## from openerp.osv import orm, fields - +from openerp import netsvc +from openerp.tools.translate import _ class payment_line(orm.Model): ''' @@ -216,3 +217,86 @@ class payment_line(orm.Model): """ return False + + def debit_reconcile(self, cr, uid, payment_line_id, context=None): + """ + Reconcile a debit order's payment line with the the move line + that it is based on. Called from payment_order.action_sent(). + As the amount is derived directly from the counterpart move line, + we do not expect a write off. Take partially reconcilions into + account though. + + :param payment_line_id: the single id of the canceled payment line + """ + + if isinstance(payment_line_id, (list, tuple)): + payment_line_id = payment_line_id[0] + reconcile_obj = self.pool.get('account.move.reconcile') + move_line_obj = self.pool.get('account.move.line') + payment_line = self.browse(cr, uid, payment_line_id, context=context) + + debit_move_line = payment_line.debit_move_line_id + torec_move_line = payment_line.move_line_id + + if (not debit_move_line or not torec_move_line): + raise orm.except_orm( + _('Can not reconcile'), + _('No move line for line %s') % payment_line.name) + if torec_move_line.reconcile_id: # torec_move_line.reconcile_partial_id: + raise orm.except_orm( + _('Error'), + _('Move line %s has already been reconciled') % + torec_move_line.name + ) + if debit_move_line.reconcile_id or debit_move_line.reconcile_partial_id: + raise orm.except_orm( + _('Error'), + _('Move line %s has already been reconciled') % + debit_move_line.name + ) + + def is_zero(total): + return self.pool.get('res.currency').is_zero( + cr, uid, debit_move_line.company_id.currency_id, total) + + line_ids = [debit_move_line.id, torec_move_line.id] + if torec_move_line.reconcile_partial_id: + line_ids = [ + x.id for x in + debit_move_line.reconcile_partial_id.line_partial_ids + ] + [torec_move_line.id] + + total = move_line_obj.get_balance(cr, uid, line_ids) + vals = { + 'type': 'auto', + 'line_id': is_zero(total) and [(6, 0, line_ids)] or [(6, 0, [])], + 'line_partial_ids': is_zero(total) and [(6, 0, [])] or [(6, 0, line_ids)], + } + + if torec_move_line.reconcile_partial_id: + reconcile_obj.write( + cr, uid, debit_move_line.reconcile_partial_id.id, + vals, context=context) + else: + reconcile_obj.create( + cr, uid, vals, context=context) + for line_id in line_ids: + netsvc.LocalService("workflow").trg_trigger( + uid, 'account.move.line', line_id, cr) + + # If a bank transaction of a storno was first confirmed + # and now canceled (the invoice is now in state 'debit_denied' + if torec_move_line.invoice: + netsvc.LocalService("workflow").trg_validate( + uid, 'account.invoice', torec_move_line.invoice.id, + 'undo_debit_denied', cr) + + + _columns = { + 'debit_move_line_id': fields.many2one( + # this line is part of the credit side of move 2a + # from the documentation + 'account.move.line', 'Debit move line', + readonly=True, + help="Move line through which the debit order pays the invoice"), + } diff --git a/account_banking_payment/model/payment_mode.py b/account_banking_payment/model/payment_mode.py index a250afa40..9e2d30b27 100644 --- a/account_banking_payment/model/payment_mode.py +++ b/account_banking_payment/model/payment_mode.py @@ -48,4 +48,24 @@ class payment_mode(orm.Model): 'payment.mode.type', 'Payment type', help='Select the Payment Type for the Payment Mode.' ), + 'transfer_account_id': fields.many2one( + 'account.account', 'Transfer account', + domain=[('type', '=', 'other'), + ('reconcile', '=', True)], + help=('Pay off lines in sent orders with a ' + 'move on this account. For debit type modes only. ' + 'You can only select accounts of type regular that ' + 'are marked for reconciliation'), + ), + 'transfer_journal_id': fields.many2one( + 'account.journal', 'Transfer journal', + help=('Journal to write payment entries when confirming ' + 'a debit order of this mode'), + ), + 'payment_term_ids': fields.many2many( + 'account.payment.term', 'account_payment_order_terms_rel', + 'mode_id', 'term_id', 'Payment terms', + help=('Limit selected invoices to invoices with these payment ' + 'terms') + ), } diff --git a/account_direct_debit/model/__init__.py b/account_direct_debit/model/__init__.py index 4e258d292..b9f45c8e8 100644 --- a/account_direct_debit/model/__init__.py +++ b/account_direct_debit/model/__init__.py @@ -1,3 +1,4 @@ import account_payment +import payment_line import account_move_line import account_invoice diff --git a/account_direct_debit/model/account_payment.py b/account_direct_debit/model/account_payment.py index abdce4977..a36ac2ae4 100644 --- a/account_direct_debit/model/account_payment.py +++ b/account_direct_debit/model/account_payment.py @@ -1,36 +1,9 @@ # -*- coding: utf-8 -*- -import time -from osv import osv, fields +from openerp.osv import orm, fields import netsvc from tools.translate import _ -class payment_mode(osv.osv): - _inherit = 'payment.mode' - _columns = { - 'transfer_account_id': fields.many2one( - 'account.account', 'Transfer account', - domain=[('type', '=', 'other'), - ('reconcile', '=', True)], - help=('Pay off lines in sent orders with a ' + - 'move on this account. For debit type modes only. ' + - 'You can only select accounts of type regular that ' + - 'are marked for reconciliation'), - ), - 'transfer_journal_id': fields.many2one( - 'account.journal', 'Transfer journal', - help=('Journal to write payment entries when confirming ' + - 'a debit order of this mode'), - ), - 'payment_term_ids': fields.many2many( - 'account.payment.term', 'account_payment_order_terms_rel', - 'mode_id', 'term_id', 'Payment terms', - help=('Limit selected invoices to invoices with these payment ' + - 'terms') - ), - } -payment_mode() - -class payment_order(osv.osv): +class payment_order(orm.Model): _inherit = 'payment.order' def fields_view_get(self, cr, user, view_id=None, view_type='form', @@ -56,56 +29,11 @@ class payment_order(osv.osv): context['search_payment_order_type'])] # the magic is in the value of the selection res['fields']['mode']['selection'] = mode_obj._name_search( - cr, user, args=domain) + cr, user, args=domain, context=context) # also update the domain res['fields']['mode']['domain'] = domain return res - 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 - account containing all the open move lines on the transfer account. - """ - move_line_obj = self.pool.get('account.move.line') - order = self.browse(cr, uid, payment_order_id, context) - line_ids = [] - reconcile_id = False - for order_line in order.line_ids: - for line in order_line.debit_move_line_id.move_id.line_id: - 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): - reconcile_id = self.pool.get('account.move.reconcile').create( - cr, uid, - {'type': 'auto', 'line_id': [(6, 0, line_ids)]}, - context) - # set direct debit order to finished state - wf_service = netsvc.LocalService('workflow') - wf_service.trg_validate( - 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): - """ - Due to a cancelled bank statements import, unreconcile the move on - the transfer account. Delegate the conditions to the workflow. - Raise on failure for rollback. - """ - self.pool.get('account.move.reconcile').unlink( - cr, uid, reconcile_id, context=context) - wkf_ok = netsvc.LocalService('workflow').trg_validate( - uid, 'payment.order', payment_order_id, 'undo_done', cr) - if not wkf_ok: - raise osv.except_osv( - _("Cannot unreconcile"), - _("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 @@ -117,367 +45,5 @@ class payment_order(osv.osv): for line in order.line_ids: if line.storno: return False - else: - # TODO: define conditions for 'payment' orders - return True - return True - - 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. - """ - res = super(payment_order, self).action_sent( - cr, uid, ids, context) - - account_move_obj = self.pool.get('account.move') - account_move_line_obj = self.pool.get('account.move.line') - payment_line_obj = self.pool.get('payment.line') - for order in self.browse(cr, uid, ids, context=context): - for line in order.line_ids: - # basic checks - if not line.move_line_id: - raise osv.except_osv( - _('Error'), - _('No move line provided for line %s') % line.name) - if line.move_line_id.reconcile_id: - raise osv.except_osv( - _('Error'), - _('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 order %s' % (order.payment_order_type, - line.move_line_id.move_id.name), - 'reference': '%s%s' % (order.payment_order_type[:3].upper(), - line.move_line_id.move_id.name), - }, context=context) - - # TODO: take multicurrency into account - - # create the debit move line on the transfer account - vals = { - 'name': '%s order for %s' % ( - 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': line.partner_id.id, - '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': time.strftime('%Y-%m-%d'), - } - 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({ - '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), - }) - reconcile_move_line_id = account_move_line_obj.create( - cr, uid, vals, context=context) - - # register the debit move line on the payment line - # and call reconciliation on it - payment_line_obj.write( - cr, uid, line.id, - {'debit_move_line_id': reconcile_move_line_id}, - context=context) - - payment_line_obj.debit_reconcile( - cr, uid, line.id, context=context) - account_move_obj.post(cr, uid, [move_id], context=context) - return res - -payment_order() - -class payment_line(osv.osv): - _inherit = 'payment.line' - - def debit_storno(self, cr, uid, payment_line_id, amount, - currency, storno_retry=True, context=None): - """ - The processing of a storno is triggered by a debit - transfer on one of the company's bank accounts. - This method offers to re-reconcile the original debit - payment. For this purpose, we have registered that - payment move on the payment line. - - Return the (now incomplete) reconcile id. The caller MUST - re-reconcile this reconcile with the bank transfer and - re-open the associated invoice. - - :param payment_line_id: the single payment line id - :param amount: the (signed) amount debited from the bank account - :param currency: the bank account's currency *browse object* - :param boolean storno_retry: when True, attempt to reopen the invoice, \ - set the invoice to 'Debit denied' otherwise. - :return: an incomplete reconcile for the caller to fill - :rtype: database id of an account.move.reconcile resource. - """ - - move_line_obj = self.pool.get('account.move.line') - reconcile_obj = self.pool.get('account.move.reconcile') - line = self.browse(cr, uid, payment_line_id) - reconcile_id = False - if (line.debit_move_line_id and not line.storno and - self.pool.get('res.currency').is_zero( - cr, uid, currency, ( - (line.debit_move_line_id.credit or 0.0) - - (line.debit_move_line_id.debit or 0.0) + amount))): - # Two different cases, full and partial - # Both cases differ subtly in the procedure to follow - # Needs refractoring, but why is this not in the OpenERP API? - # Actually, given the nature of a direct debit order and storno, - # we should not need to take partial into account on the side of - # the debit_move_line. - if line.debit_move_line_id.reconcile_partial_id: - reconcile_id = line.debit_move_line_id.reconcile_partial_id.id - attribute = 'reconcile_partial_id' - if len(line.debit_move_line_id.reconcile_id.line_partial_ids) == 2: - # reuse the simple reconcile for the storno transfer - reconcile_obj.write( - cr, uid, reconcile_id, { - 'line_id': [(6, 0, line.debit_move_line_id.id)], - 'line_partial_ids': [(6, 0, [])], - }, context=context) - else: - # split up the original reconcile in a partial one - # and a new one for reconciling the storno transfer - reconcile_obj.write( - cr, uid, reconcile_id, { - 'line_partial_ids': [(3, line.debit_move_line_id.id)], - }, context=context) - reconcile_id = reconcile_obj.create( - cr, uid, { - 'type': 'auto', - 'line_id': [(6, 0, line.debit_move_line_id.id)], - }, context=context) - elif line.debit_move_line_id.reconcile_id: - reconcile_id = line.debit_move_line_id.reconcile_id.id - if len(line.debit_move_line_id.reconcile_id.line_id) == 2: - # reuse the simple reconcile for the storno transfer - reconcile_obj.write( - cr, uid, reconcile_id, { - 'line_id': [(6, 0, [line.debit_move_line_id.id])] - }, context=context) - else: - # split up the original reconcile in a partial one - # and a new one for reconciling the storno transfer - partial_ids = [ - x.id for x in line.debit_move_line_id.reconcile_id.line_id - if x.id != line.debit_move_line_id.id - ] - reconcile_obj.write( - cr, uid, reconcile_id, { - 'line_partial_ids': [(6, 0, partial_ids)], - 'line_id': [(6, 0, [])], - }, context=context) - reconcile_id = reconcile_obj.create( - cr, uid, { - 'type': 'auto', - 'line_id': [(6, 0, line.debit_move_line_id.id)], - }, context=context) - # mark the payment line for storno processed - if reconcile_id: - self.write(cr, uid, [payment_line_id], - {'storno': True}, context=context) - # put forth the invoice workflow - if line.move_line_id.invoice: - activity = (storno_retry and 'open_test' - or 'invoice_debit_denied') - netsvc.LocalService("workflow").trg_validate( - uid, 'account.invoice', line.move_line_id.invoice.id, - activity, cr) - return reconcile_id - - def get_storno_account_id(self, cr, uid, payment_line_id, amount, - currency, context=None): - """ - Check the match of the arguments, and return the account associated - with the storno. - Used in account_banking interactive mode - - :param payment_line_id: the single payment line id - :param amount: the (signed) amount debited from the bank account - :param currency: the bank account's currency *browse object* - :return: an account if there is a full match, False otherwise - :rtype: database id of an account.account resource. - """ - - line = self.browse(cr, uid, payment_line_id) - account_id = False - if (line.debit_move_line_id and not line.storno and - self.pool.get('res.currency').is_zero( - cr, uid, currency, ( - (line.debit_move_line_id.credit or 0.0) - - (line.debit_move_line_id.debit or 0.0) + amount))): - account_id = line.debit_move_line_id.account_id.id - return account_id - - def debit_reconcile(self, cr, uid, payment_line_id, context=None): - """ - Reconcile a debit order's payment line with the the move line - that it is based on. Called from payment_order.action_sent(). - As the amount is derived directly from the counterpart move line, - we do not expect a write off. Take partially reconcilions into - account though. - - :param payment_line_id: the single id of the canceled payment line - """ - - if isinstance(payment_line_id, (list, tuple)): - payment_line_id = payment_line_id[0] - reconcile_obj = self.pool.get('account.move.reconcile') - move_line_obj = self.pool.get('account.move.line') - payment_line = self.browse(cr, uid, payment_line_id, context=context) - - debit_move_line = payment_line.debit_move_line_id - torec_move_line = payment_line.move_line_id - - if payment_line.storno: - raise osv.except_osv( - _('Can not reconcile'), - _('Cancelation of payment line \'%s\' has already been ' + - 'processed') % payment_line.name) - if (not debit_move_line or not torec_move_line): - raise osv.except_osv( - _('Can not reconcile'), - _('No move line for line %s') % payment_line.name) - if torec_move_line.reconcile_id: # torec_move_line.reconcile_partial_id: - raise osv.except_osv( - _('Error'), - _('Move line %s has already been reconciled') % - torec_move_line.name - ) - if debit_move_line.reconcile_id or debit_move_line.reconcile_partial_id: - raise osv.except_osv( - _('Error'), - _('Move line %s has already been reconciled') % - debit_move_line.name - ) - - def is_zero(total): - return self.pool.get('res.currency').is_zero( - cr, uid, debit_move_line.company_id.currency_id, total) - - line_ids = [debit_move_line.id, torec_move_line.id] - if torec_move_line.reconcile_partial_id: - line_ids = [ - x.id for x in debit_move_line.reconcile_partial_id.line_partial_ids] + [torec_move_line_id] - - total = move_line_obj.get_balance(cr, uid, line_ids) - vals = { - 'type': 'auto', - 'line_id': is_zero(total) and [(6, 0, line_ids)] or [(6, 0, [])], - 'line_partial_ids': is_zero(total) and [(6, 0, [])] or [(6, 0, line_ids)], - } - - if torec_move_line.reconcile_partial_id: - reconcile_obj.write( - cr, uid, debit_move_line.reconcile_partial_id.id, - vals, context=context) - else: - reconcile_obj.create( - cr, uid, vals, context=context) - for line_id in line_ids: - netsvc.LocalService("workflow").trg_trigger( - uid, 'account.move.line', line_id, cr) - - # If a bank transaction of a storno was first confirmed - # and now canceled (the invoice is now in state 'debit_denied' - if torec_move_line.invoice: - netsvc.LocalService("workflow").trg_validate( - uid, 'account.invoice', torec_move_line.invoice.id, - 'undo_debit_denied', cr) - - - - _columns = { - 'debit_move_line_id': fields.many2one( - # this line is part of the credit side of move 2a - # from the documentation - 'account.move.line', 'Debit move line', - readonly=True, - help="Move line through which the debit order pays the invoice"), - 'storno': fields.boolean( - 'Storno', - readonly=True, - help=("If this is true, the debit order has been canceled " + - "by the bank or by the customer")), - } -payment_line() - - -class payment_order_create(osv.osv_memory): - _inherit = 'payment.order.create' - - def search_entries(self, cr, uid, ids, context=None): - """ - This method taken from account_payment module. - We adapt the domain based on the payment_order_type - """ - line_obj = self.pool.get('account.move.line') - mod_obj = self.pool.get('ir.model.data') - if context is None: - context = {} - data = self.read(cr, uid, ids, [], context=context)[0] - search_due_date = data['duedate'] - - ### start account_direct_debit ### - payment = self.pool.get('payment.order').browse( - cr, uid, context['active_id'], context=context) - # Search for move line to pay: - if payment.payment_order_type == 'debit': - domain = [ - ('reconcile_id', '=', False), - ('account_id.type', '=', 'receivable'), - ('invoice.state', '!=', 'debit_denied'), - ('amount_to_receive', '>', 0), - ] - else: - domain = [ - ('reconcile_id', '=', False), - ('account_id.type', '=', 'payable'), - ('amount_to_pay', '>', 0) - ] - domain.append(('company_id', '=', payment.mode.company_id.id)) - # apply payment term filter - if payment.mode.payment_term_ids: - domain = domain + [ - ('invoice.payment_term', 'in', - [term.id for term in payment.mode.payment_term_ids] - ) - ] - # domain = [('reconcile_id', '=', False), ('account_id.type', '=', 'payable'), ('amount_to_pay', '>', 0)] - ### end account_direct_debit ### - - domain = domain + ['|', ('date_maturity', '<=', search_due_date), ('date_maturity', '=', False)] - line_ids = line_obj.search(cr, uid, domain, context=context) - context.update({'line_ids': line_ids}) - model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context) - resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] - return {'name': ('Entry Lines'), - 'context': context, - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'payment.order.create', - 'views': [(resource_id,'form')], - 'type': 'ir.actions.act_window', - 'target': 'new', - } -payment_order_create() - - - + return super(payment_order, self).test_undo_done( + cr, uid, ids, context=context) diff --git a/account_direct_debit/model/payment_line.py b/account_direct_debit/model/payment_line.py new file mode 100644 index 000000000..7bfbe8527 --- /dev/null +++ b/account_direct_debit/model/payment_line.py @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +from openerp.osv import orm, fields +import netsvc +from tools.translate import _ + +class payment_line(orm.Model): + _inherit = 'payment.line' + + def debit_storno(self, cr, uid, payment_line_id, amount, + currency, storno_retry=True, context=None): + """ + The processing of a storno is triggered by a debit + transfer on one of the company's bank accounts. + This method offers to re-reconcile the original debit + payment. For this purpose, we have registered that + payment move on the payment line. + + Return the (now incomplete) reconcile id. The caller MUST + re-reconcile this reconcile with the bank transfer and + re-open the associated invoice. + + :param payment_line_id: the single payment line id + :param amount: the (signed) amount debited from the bank account + :param currency: the bank account's currency *browse object* + :param boolean storno_retry: when True, attempt to reopen the invoice, \ + set the invoice to 'Debit denied' otherwise. + :return: an incomplete reconcile for the caller to fill + :rtype: database id of an account.move.reconcile resource. + """ + + move_line_obj = self.pool.get('account.move.line') + reconcile_obj = self.pool.get('account.move.reconcile') + line = self.browse(cr, uid, payment_line_id) + reconcile_id = False + if (line.debit_move_line_id and not line.storno and + self.pool.get('res.currency').is_zero( + cr, uid, currency, ( + (line.debit_move_line_id.credit or 0.0) - + (line.debit_move_line_id.debit or 0.0) + amount))): + # Two different cases, full and partial + # Both cases differ subtly in the procedure to follow + # Needs refractoring, but why is this not in the OpenERP API? + # Actually, given the nature of a direct debit order and storno, + # we should not need to take partial into account on the side of + # the debit_move_line. + if line.debit_move_line_id.reconcile_partial_id: + reconcile_id = line.debit_move_line_id.reconcile_partial_id.id + attribute = 'reconcile_partial_id' + if len(line.debit_move_line_id.reconcile_id.line_partial_ids) == 2: + # reuse the simple reconcile for the storno transfer + reconcile_obj.write( + cr, uid, reconcile_id, { + 'line_id': [(6, 0, line.debit_move_line_id.id)], + 'line_partial_ids': [(6, 0, [])], + }, context=context) + else: + # split up the original reconcile in a partial one + # and a new one for reconciling the storno transfer + reconcile_obj.write( + cr, uid, reconcile_id, { + 'line_partial_ids': [(3, line.debit_move_line_id.id)], + }, context=context) + reconcile_id = reconcile_obj.create( + cr, uid, { + 'type': 'auto', + 'line_id': [(6, 0, line.debit_move_line_id.id)], + }, context=context) + elif line.debit_move_line_id.reconcile_id: + reconcile_id = line.debit_move_line_id.reconcile_id.id + if len(line.debit_move_line_id.reconcile_id.line_id) == 2: + # reuse the simple reconcile for the storno transfer + reconcile_obj.write( + cr, uid, reconcile_id, { + 'line_id': [(6, 0, [line.debit_move_line_id.id])] + }, context=context) + else: + # split up the original reconcile in a partial one + # and a new one for reconciling the storno transfer + partial_ids = [ + x.id for x in line.debit_move_line_id.reconcile_id.line_id + if x.id != line.debit_move_line_id.id + ] + reconcile_obj.write( + cr, uid, reconcile_id, { + 'line_partial_ids': [(6, 0, partial_ids)], + 'line_id': [(6, 0, [])], + }, context=context) + reconcile_id = reconcile_obj.create( + cr, uid, { + 'type': 'auto', + 'line_id': [(6, 0, line.debit_move_line_id.id)], + }, context=context) + # mark the payment line for storno processed + if reconcile_id: + self.write(cr, uid, [payment_line_id], + {'storno': True}, context=context) + # put forth the invoice workflow + if line.move_line_id.invoice: + activity = (storno_retry and 'open_test' + or 'invoice_debit_denied') + netsvc.LocalService("workflow").trg_validate( + uid, 'account.invoice', line.move_line_id.invoice.id, + activity, cr) + return reconcile_id + + def get_storno_account_id(self, cr, uid, payment_line_id, amount, + currency, context=None): + """ + Check the match of the arguments, and return the account associated + with the storno. + Used in account_banking interactive mode + + :param payment_line_id: the single payment line id + :param amount: the (signed) amount debited from the bank account + :param currency: the bank account's currency *browse object* + :return: an account if there is a full match, False otherwise + :rtype: database id of an account.account resource. + """ + + line = self.browse(cr, uid, payment_line_id) + account_id = False + if (line.debit_move_line_id and not line.storno and + self.pool.get('res.currency').is_zero( + cr, uid, currency, ( + (line.debit_move_line_id.credit or 0.0) - + (line.debit_move_line_id.debit or 0.0) + amount))): + account_id = line.debit_move_line_id.account_id.id + return account_id + + def debit_reconcile(self, cr, uid, payment_line_id, context=None): + """ + Raise if a payment line is passed for which storno is True + """ + if isinstance(payment_line_id, (list, tuple)): + payment_line_id = payment_line_id[0] + payment_line = self.read( + cr, uid, payment_line_id, ['storno', 'name'], context=context) + if payment_line['storno']: + raise orm.except_orm( + _('Can not reconcile'), + _('Cancelation of payment line \'%s\' has already been ' + 'processed') % payment_line['name']) + return super(self, payment_line).debit_reconcile( + cr, uid, payment_line_id, context=context) + + _columns = { + 'storno': fields.boolean( + 'Storno', + readonly=True, + help=("If this is true, the debit order has been canceled " + "by the bank or by the customer")), + } + + +class payment_order_create(orm.Model_memory): + _inherit = 'payment.order.create' + + def search_entries(self, cr, uid, ids, context=None): + """ + This method taken from account_payment module. + We adapt the domain based on the payment_order_type + """ + line_obj = self.pool.get('account.move.line') + mod_obj = self.pool.get('ir.model.data') + if context is None: + context = {} + data = self.read(cr, uid, ids, [], context=context)[0] + search_due_date = data['duedate'] + + ### start account_direct_debit ### + payment = self.pool.get('payment.order').browse( + cr, uid, context['active_id'], context=context) + # Search for move line to pay: + if payment.payment_order_type == 'debit': + domain = [ + ('reconcile_id', '=', False), + ('account_id.type', '=', 'receivable'), + ('invoice.state', '!=', 'debit_denied'), + ('amount_to_receive', '>', 0), + ] + else: + domain = [ + ('reconcile_id', '=', False), + ('account_id.type', '=', 'payable'), + ('amount_to_pay', '>', 0) + ] + domain.append(('company_id', '=', payment.mode.company_id.id)) + # apply payment term filter + if payment.mode.payment_term_ids: + domain = domain + [ + ('invoice.payment_term', 'in', + [term.id for term in payment.mode.payment_term_ids] + ) + ] + # domain = [('reconcile_id', '=', False), ('account_id.type', '=', 'payable'), ('amount_to_pay', '>', 0)] + ### end account_direct_debit ### + + domain = domain + ['|', ('date_maturity', '<=', search_due_date), ('date_maturity', '=', False)] + line_ids = line_obj.search(cr, uid, domain, context=context) + context.update({'line_ids': line_ids}) + model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context) + resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] + return {'name': ('Entry Lines'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'payment.order.create', + 'views': [(resource_id,'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + } From fd6cac4854ef238a55770bce9ed75d33fc59f14a Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 15:37:47 +0200 Subject: [PATCH 05/26] [RFR] Sort out 'add invoices' wizard code between payment and debit module --- .../model/payment_order_create.py | 81 +++++++++++++++++-- account_direct_debit/model/__init__.py | 1 + account_direct_debit/model/payment_line.py | 59 -------------- .../model/payment_order_create.py | 41 ++++++++++ 4 files changed, 117 insertions(+), 65 deletions(-) create mode 100644 account_direct_debit/model/payment_order_create.py diff --git a/account_banking_payment/model/payment_order_create.py b/account_banking_payment/model/payment_order_create.py index 2ee4eafab..b39a6bf2e 100644 --- a/account_banking_payment/model/payment_order_create.py +++ b/account_banking_payment/model/payment_order_create.py @@ -25,12 +25,78 @@ from datetime import datetime from openerp.osv import orm, fields -from openerp.misc import DEFAULT_SERVER_DATE_FORMAT +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT +from openerp.tools.translate import _ class payment_order_create(orm.TransientModel): _inherit = 'payment.order.create' + def extend_payment_order_domain( + self, cr, uid, payment_order, domain, context=None): + if payment_order.payment_order_type == 'payment': + domain += [ + ('reconcile_id', '=', False), + ('account_id.type', '=', 'payable'), + ('amount_to_pay', '>', 0) + ] + return True + + def search_entries(self, cr, uid, ids, context=None): + """ + This method taken from account_payment module. + We adapt the domain based on the payment_order_type + """ + line_obj = self.pool.get('account.move.line') + mod_obj = self.pool.get('ir.model.data') + if context is None: + context = {} + data = self.read(cr, uid, ids, ['duedate'], context=context)[0] + search_due_date = data['duedate'] + + ### start account_banking_payment ### + payment = self.pool.get('payment.order').browse( + cr, uid, context['active_id'], context=context) + # Search for move line to pay: + domain = [ + ('reconcile_id', '=', False), + ('company_id', '=', payment.mode.company_id.id), + ] + # apply payment term filter + if payment.mode.payment_term_ids: + domain += [ + ('invoice.payment_term', 'in', + [term.id for term in payment.mode.payment_term_ids] + ) + ] + self.extend_payment_order_domain( + cr, uid, payment, domain, context=context) + ### end account_direct_debit ### + + domain = domain + [ + '|', ('date_maturity', '<=', search_due_date), + ('date_maturity', '=', False) + ] + line_ids = line_obj.search(cr, uid, domain, context=context) + context.update({'line_ids': line_ids}) + model_data_ids = mod_obj.search( + cr, uid,[ + ('model', '=', 'ir.ui.view'), + ('name', '=', 'view_create_payment_order_lines')], + context=context) + resource_id = mod_obj.read( + cr, uid, model_data_ids, fields=['res_id'], + context=context)[0]['res_id'] + return {'name': _('Entry Lines'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'payment.order.create', + 'views': [(resource_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + } + def create_payment(self, cr, uid, ids, context=None): ''' This method is a slightly modified version of the existing method on this @@ -51,7 +117,8 @@ class payment_order_create(orm.TransientModel): if not line_ids: return {'type': 'ir.actions.act_window_close'} - payment = order_obj.browse(cr, uid, context['active_id'], context=context) + payment = order_obj.browse( + cr, uid, context['active_id'], context=context) ### account banking # t = None # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context) @@ -75,10 +142,10 @@ class payment_order_create(orm.TransientModel): ### end account banking elif payment.date_prefered == 'fixed': ### account_banking - # date_to_pay = payment.date_planned + # date_to_pay = payment.date_scheduled date_to_pay = ( - payment.date_planned - if payment.date_planned and payment.date_planned > _today + payment.date_scheduled + if payment.date_scheduled and payment.date_scheduled > _today else False) ### end account banking @@ -121,6 +188,8 @@ class payment_order_create(orm.TransientModel): 'state': state, ### end account banking 'date': date_to_pay, - 'currency': line.invoice and line.invoice.currency_id.id or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id, + 'currency': (line.invoice and line.invoice.currency_id.id + or line.journal_id.currency.id + or line.journal_id.company_id.currency_id.id), }, context=context) return {'type': 'ir.actions.act_window_close'} diff --git a/account_direct_debit/model/__init__.py b/account_direct_debit/model/__init__.py index b9f45c8e8..b3558c40e 100644 --- a/account_direct_debit/model/__init__.py +++ b/account_direct_debit/model/__init__.py @@ -2,3 +2,4 @@ import account_payment import payment_line import account_move_line import account_invoice +import payment_order_create diff --git a/account_direct_debit/model/payment_line.py b/account_direct_debit/model/payment_line.py index 7bfbe8527..1f396068b 100644 --- a/account_direct_debit/model/payment_line.py +++ b/account_direct_debit/model/payment_line.py @@ -150,62 +150,3 @@ class payment_line(orm.Model): help=("If this is true, the debit order has been canceled " "by the bank or by the customer")), } - - -class payment_order_create(orm.Model_memory): - _inherit = 'payment.order.create' - - def search_entries(self, cr, uid, ids, context=None): - """ - This method taken from account_payment module. - We adapt the domain based on the payment_order_type - """ - line_obj = self.pool.get('account.move.line') - mod_obj = self.pool.get('ir.model.data') - if context is None: - context = {} - data = self.read(cr, uid, ids, [], context=context)[0] - search_due_date = data['duedate'] - - ### start account_direct_debit ### - payment = self.pool.get('payment.order').browse( - cr, uid, context['active_id'], context=context) - # Search for move line to pay: - if payment.payment_order_type == 'debit': - domain = [ - ('reconcile_id', '=', False), - ('account_id.type', '=', 'receivable'), - ('invoice.state', '!=', 'debit_denied'), - ('amount_to_receive', '>', 0), - ] - else: - domain = [ - ('reconcile_id', '=', False), - ('account_id.type', '=', 'payable'), - ('amount_to_pay', '>', 0) - ] - domain.append(('company_id', '=', payment.mode.company_id.id)) - # apply payment term filter - if payment.mode.payment_term_ids: - domain = domain + [ - ('invoice.payment_term', 'in', - [term.id for term in payment.mode.payment_term_ids] - ) - ] - # domain = [('reconcile_id', '=', False), ('account_id.type', '=', 'payable'), ('amount_to_pay', '>', 0)] - ### end account_direct_debit ### - - domain = domain + ['|', ('date_maturity', '<=', search_due_date), ('date_maturity', '=', False)] - line_ids = line_obj.search(cr, uid, domain, context=context) - context.update({'line_ids': line_ids}) - model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context) - resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] - return {'name': ('Entry Lines'), - 'context': context, - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'payment.order.create', - 'views': [(resource_id,'form')], - 'type': 'ir.actions.act_window', - 'target': 'new', - } diff --git a/account_direct_debit/model/payment_order_create.py b/account_direct_debit/model/payment_order_create.py new file mode 100644 index 000000000..b2bbdeb95 --- /dev/null +++ b/account_direct_debit/model/payment_order_create.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm + + +class payment_order_create(orm.TransientModel): + _inherit = 'payment.order.create' + + def extend_payment_order_domain( + self, cr, uid, payment_order, domain, context=None): + super(payment_order_create, self).extend_payment_order_domain( + cr, uid, payment_order, domain, context=context) + if payment_order.payment_order_type == 'debit': + domain += [ + ('account_id.type', '=', 'receivable'), + ('invoice.state', '!=', 'debit_denied'), + ('amount_to_receive', '>', 0), + ] + return True From 0bc3cdaa8f9337be44b3171fa5ec7a95da234298 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 15:41:42 +0200 Subject: [PATCH 06/26] [RFR] License and API --- account_direct_debit/model/account_invoice.py | 31 ++++++++++++++++--- account_payment_shortcut/__init__.py | 1 + account_payment_shortcut/payment_order.py | 28 ++++++++++++++--- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/account_direct_debit/model/account_invoice.py b/account_direct_debit/model/account_invoice.py index 9f9c483b6..c49db4cd4 100644 --- a/account_direct_debit/model/account_invoice.py +++ b/account_direct_debit/model/account_invoice.py @@ -1,6 +1,29 @@ # -*- coding: utf-8 -*- -from osv import osv, fields -from tools.translate import _ +############################################################################## +# +# Copyright (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields +from openerp.tools.translate import _ """ This module adds support for Direct debit orders as applicable @@ -98,7 +121,7 @@ Two cases need to be distinguisted: open invoices with a matured invoice- or due date. """ -class account_invoice(osv.osv): +class account_invoice(orm.Model): _inherit = "account.invoice" def __init__(self, pool, cr): @@ -139,5 +162,3 @@ class account_invoice(osv.osv): if not invoice['reconciled']: return False return True - -account_invoice() diff --git a/account_payment_shortcut/__init__.py b/account_payment_shortcut/__init__.py index da88e0bdd..e1873cda0 100644 --- a/account_payment_shortcut/__init__.py +++ b/account_payment_shortcut/__init__.py @@ -1 +1,2 @@ +# -*- coding: utf-8 -*- import payment_order diff --git a/account_payment_shortcut/payment_order.py b/account_payment_shortcut/payment_order.py index 5953f4910..68523325d 100644 --- a/account_payment_shortcut/payment_order.py +++ b/account_payment_shortcut/payment_order.py @@ -1,8 +1,30 @@ # -*- coding: utf-8 -*- -from osv import osv, fields +############################################################################## +# +# Copyright (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## -class payment_order_create(osv.osv_memory): +from osv import orm +class payment_order_create(orm.TransientModel): _inherit = 'payment.order.create' def default_get(self, cr, uid, fields_list, context=None): @@ -27,5 +49,3 @@ class payment_order_create(osv.osv_memory): res['entries'] = context['line_ids'] return res - -payment_order_create() From cd80149d3a47c64808556d6d91183d68a2f2bdcf Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 15:56:55 +0200 Subject: [PATCH 07/26] [FIX] Update reference to obsolete field on payment order --- account_banking_nl_clieop/wizard/export_clieop.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/account_banking_nl_clieop/wizard/export_clieop.py b/account_banking_nl_clieop/wizard/export_clieop.py index ba25f246b..641507124 100644 --- a/account_banking_nl_clieop/wizard/export_clieop.py +++ b/account_banking_nl_clieop/wizard/export_clieop.py @@ -194,8 +194,8 @@ class banking_export_clieop_wizard(osv.osv_memory): runs[payment_type] = [payment_order] if payment_order.date_prefered == 'fixed': - if payment_order.date_planned: - execution_date = strpdate(payment_order.date_planned) + if payment_order.date_scheduled: + execution_date = strpdate(payment_order.date_scheduled) else: execution_date = today elif payment_order.date_prefered == 'now': From 702a052aebbaa90b64727bf844e1f7178cded25d Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 16:08:18 +0200 Subject: [PATCH 08/26] [RFR] License, API --- account_banking/account_banking.py | 48 +++++++------- account_banking/banking_import_transaction.py | 4 +- account_banking/wizard/bank_import.py | 32 +++++----- account_banking/wizard/banktools.py | 48 +++++++------- .../account_banking_nl_clieop.py | 11 ++-- .../wizard/export_clieop.py | 63 +++++++++---------- .../model/account_bank_statement_line.py | 6 +- .../model/account_voucher_instant.py | 20 +++--- 8 files changed, 114 insertions(+), 118 deletions(-) diff --git a/account_banking/account_banking.py b/account_banking/account_banking.py index 8a6dd055f..009bbe603 100644 --- a/account_banking/account_banking.py +++ b/account_banking/account_banking.py @@ -267,7 +267,7 @@ class account_banking_imported_file(orm.Model): } _defaults = { 'date': fields.date.context_today, - 'user_id': lambda self, cursor, uid, context: uid, + 'user_id': lambda self, cr, uid, context: uid, } account_banking_imported_file() @@ -320,12 +320,12 @@ class account_bank_statement(orm.Model): ['journal_id','period_id']), ] - def _get_period(self, cursor, uid, date, context=None): + def _get_period(self, cr, uid, date, context=None): ''' Find matching period for date, not meant for _defaults. ''' period_obj = self.pool.get('account.period') - periods = period_obj.find(cursor, uid, dt=date, context=context) + periods = period_obj.find(cr, uid, dt=date, context=context) return periods and periods[0] or False def _prepare_move( @@ -467,12 +467,12 @@ class account_bank_statement_line(orm.Model): _inherit = 'account.bank.statement.line' _description = 'Bank Transaction' - def _get_period(self, cursor, user, context=None): + def _get_period(self, cr, uid, context=None): date = context.get('date', None) - periods = self.pool.get('account.period').find(cursor, user, dt=date) + periods = self.pool.get('account.period').find(cr, uid, dt=date) return periods and periods[0] or False - def _get_currency(self, cursor, user, context=None): + def _get_currency(self, cr, uid, context=None): ''' Get the default currency (required to allow other modules to function, which assume currency to be a calculated field and thus optional) @@ -480,7 +480,7 @@ class account_bank_statement_line(orm.Model): which is inaccessible from within this method. ''' res_users_obj = self.pool.get('res.users') - return res_users_obj.browse(cursor, user, user, + return res_users_obj.browse(cr, uid, uid, context=context).company_id.currency_id.id def _get_invoice_id(self, cr, uid, ids, name, args, context=None): @@ -605,7 +605,7 @@ class res_partner_bank(orm.Model): iban = sepa.IBAN(acc_number) return (str(iban), iban.localized_BBAN) - def create(self, cursor, uid, vals, context=None): + def create(self, cr, uid, vals, context=None): ''' Create dual function IBAN account for SEPA countries ''' @@ -614,7 +614,7 @@ class res_partner_bank(orm.Model): or vals.get('acc_number_domestic', False)) vals['acc_number'], vals['acc_number_domestic'] = ( self._correct_IBAN(iban)) - return self._founder.create(self, cursor, uid, vals, context) + return self._founder.create(self, cr, uid, vals, context) def write(self, cr, uid, ids, vals, context=None): ''' @@ -637,7 +637,7 @@ class res_partner_bank(orm.Model): self._founder.write(self, cr, uid, account['id'], vals, context) return True - def search(self, cursor, uid, args, *rest, **kwargs): + def search(self, cr, uid, args, *rest, **kwargs): ''' Overwrite search, as both acc_number and iban now can be filled, so the original base_iban 'search and search again fuzzy' tactic now can @@ -698,7 +698,7 @@ class res_partner_bank(orm.Model): # Original search results = super(res_partner_bank, self).search( - cursor, uid, newargs, *rest, **kwargs) + cr, uid, newargs, *rest, **kwargs) return results def read( @@ -721,23 +721,23 @@ class res_partner_bank(orm.Model): return records return records[0] - def check_iban(self, cursor, uid, ids): + def check_iban(self, cr, uid, ids): ''' Check IBAN number ''' - for bank_acc in self.browse(cursor, uid, ids): + for bank_acc in self.browse(cr, uid, ids): if bank_acc.state == 'iban' and bank_acc.acc_number: iban = sepa.IBAN(bank_acc.acc_number) if not iban.valid: return False return True - def get_bban_from_iban(self, cursor, uid, ids, context=None): + def get_bban_from_iban(self, cr, uid, ids, context=None): ''' Return the local bank account number aka BBAN from the IBAN. ''' res = {} - for record in self.browse(cursor, uid, ids, context): + for record in self.browse(cr, uid, ids, context): if not record.state == 'iban': res[record.id] = False else: @@ -763,7 +763,7 @@ class res_partner_bank(orm.Model): ) def onchange_domestic( - self, cursor, uid, ids, acc_number, + self, cr, uid, ids, acc_number, partner_id, country_id, context=None): ''' Trigger to find IBAN. When found: @@ -785,7 +785,7 @@ class res_partner_bank(orm.Model): # which can be overridden by the user. # 1. Use provided country_id (manually filled) if country_id: - country = country_obj.browse(cursor, uid, country_id) + country = country_obj.browse(cr, uid, country_id) country_ids = [country_id] # 2. Use country_id of found bank accounts # This can be usefull when there is no country set in the partners @@ -793,7 +793,7 @@ class res_partner_bank(orm.Model): # account itself before this method was triggered. elif ids and len(ids) == 1: partner_bank_obj = self.pool.get('res.partner.bank') - partner_bank_id = partner_bank_obj.browse(cursor, uid, ids[0]) + partner_bank_id = partner_bank_obj.browse(cr, uid, ids[0]) if partner_bank_id.country_id: country = partner_bank_id.country_id country_ids = [country.id] @@ -804,12 +804,12 @@ class res_partner_bank(orm.Model): # bank account, hence the additional check. elif partner_id: partner_obj = self.pool.get('res.partner') - country = partner_obj.browse(cursor, uid, partner_id).country + country = partner_obj.browse(cr, uid, partner_id).country country_ids = country and [country.id] or [] # 4. Without any of the above, take the country from the company of # the handling user if not country_ids: - user = self.pool.get('res.users').browse(cursor, uid, uid) + user = self.pool.get('res.users').browse(cr, uid, uid) # Try user companies partner (user no longer has address in 6.1) if (user.company_id and user.company_id.partner_id and @@ -830,7 +830,7 @@ class res_partner_bank(orm.Model): # Complete data with online database when available if country_ids: country = country_obj.browse( - cursor, uid, country_ids[0], context=context) + cr, uid, country_ids[0], context=context) values['country_id'] = country_ids[0] if country and country.code in sepa.IBAN.countries: try: @@ -842,7 +842,7 @@ class res_partner_bank(orm.Model): values['acc_number'] = unicode(iban_acc) values['state'] = 'iban' bank_id, country_id = get_or_create_bank( - self.pool, cursor, uid, + self.pool, cr, uid, info.bic or iban_acc.BIC_searchkey, name = info.bank ) @@ -911,7 +911,7 @@ class res_bank(orm.Model): ''' _inherit = 'res.bank' - def onchange_bic(self, cursor, uid, ids, bic, name, context=None): + def onchange_bic(self, cr, uid, ids, bic, name, context=None): ''' Trigger to auto complete other fields. ''' @@ -924,7 +924,7 @@ class res_bank(orm.Model): if address and address.country_id: country_id = self.pool.get('res.country').search( - cursor, uid, [('code','=',address.country_id)] + cr, uid, [('code','=',address.country_id)] ) country_id = country_id and country_id[0] or False else: diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index 14a38f0e3..e882a8627 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -1630,14 +1630,14 @@ account_bank_statement_line() class account_bank_statement(orm.Model): _inherit = 'account.bank.statement' - def _end_balance(self, cursor, user, ids, name, attr, context=None): + def _end_balance(self, cr, uid, ids, name, attr, context=None): """ This method taken from account/account_bank_statement.py and altered to take the statement line subflow into account """ res = {} - statements = self.browse(cursor, user, ids, context=context) + statements = self.browse(cr, uid, ids, context=context) for statement in statements: res[statement.id] = statement.balance_start diff --git a/account_banking/wizard/bank_import.py b/account_banking/wizard/bank_import.py index 9687b7dfd..873b439b7 100644 --- a/account_banking/wizard/bank_import.py +++ b/account_banking/wizard/bank_import.py @@ -28,9 +28,9 @@ This module contains the business logic of the wizard account_banking_import. The parsing is done in the parser modules. Every parser module is required to use parser.models as a mean of communication with the business logic. ''' -from osv import orm, fields import base64 import datetime +from openerp.osv import orm, fields from openerp.tools.translate import _ from openerp.addons.account_banking.parsers import models from openerp.addons.account_banking.parsers import convert @@ -97,13 +97,13 @@ class banking_import_line(orm.TransientModel): class banking_import(orm.TransientModel): _name = 'account.banking.bank.import' - def import_statements_file(self, cursor, uid, ids, context): + def import_statements_file(self, cr, uid, ids, context): ''' Import bank statements / bank transactions file. This method is a wrapper for the business logic on the transaction. The parser modules represent the decoding logic. ''' - banking_import = self.browse(cursor, uid, ids, context)[0] + banking_import = self.browse(cr, uid, ids, context)[0] statements_file = banking_import.file data = base64.decodestring(statements_file) @@ -125,10 +125,10 @@ class banking_import(orm.TransientModel): # Get the company company = (banking_import.company or - user_obj.browse(cursor, uid, uid, context).company_id) + user_obj.browse(cr, uid, uid, context).company_id) # Parse the file - statements = parser.parse(cursor, data) + statements = parser.parse(cr, data) if any([x for x in statements if not x.is_valid()]): raise orm.except_orm( @@ -137,7 +137,7 @@ class banking_import(orm.TransientModel): ) # Create the file now, as the statements need to be linked to it - import_id = statement_file_obj.create(cursor, uid, dict( + import_id = statement_file_obj.create(cr, uid, dict( company_id = company.id, file = statements_file, state = 'unfinished', @@ -184,7 +184,7 @@ class banking_import(orm.TransientModel): else: # Pull account info/currency account_info = banktools.get_company_bank_account( - self.pool, cursor, uid, statement.local_account, + self.pool, cr, uid, statement.local_account, statement.local_currency, company, results.log ) if not account_info: @@ -238,7 +238,7 @@ class banking_import(orm.TransientModel): # (e.g. a datetime string of the moment of import) # and have potential duplicates flagged by the # matching procedure - statement_ids = statement_obj.search(cursor, uid, [ + statement_ids = statement_obj.search(cr, uid, [ ('name', '=', statement.id), ('date', '=', convert.date2str(statement.date)), ]) @@ -252,7 +252,7 @@ class banking_import(orm.TransientModel): # Get the period for the statement (as bank statement object checks this) period_ids = period_obj.search( - cursor, uid, [ + cr, uid, [ ('company_id', '=', company.id), ('date_start', '<=', statement.date), ('date_stop', '>=', statement.date), @@ -270,7 +270,7 @@ class banking_import(orm.TransientModel): continue # Create the bank statement record - statement_id = statement_obj.create(cursor, uid, dict( + statement_id = statement_obj.create(cr, uid, dict( name = statement.id, journal_id = account_info.journal_id.id, date = convert.date2str(statement.date), @@ -302,21 +302,21 @@ class banking_import(orm.TransientModel): values['local_currency'] = statement.local_currency transaction_id = import_transaction_obj.create( - cursor, uid, values, context=context) + cr, uid, values, context=context) transaction_ids.append(transaction_id) results.stat_loaded_cnt += 1 - import_transaction_obj.match(cursor, uid, transaction_ids, results=results, context=context) + import_transaction_obj.match(cr, uid, transaction_ids, results=results, context=context) #recompute statement end_balance for validation statement_obj.button_dummy( - cursor, uid, imported_statement_ids, context=context) + cr, uid, imported_statement_ids, context=context) # Original code. Didn't take workflow logistics into account... # - #cursor.execute( + #cr.execute( # "UPDATE payment_order o " # "SET state = 'done', " # "date_done = '%s' " @@ -358,13 +358,13 @@ class banking_import(orm.TransientModel): ] text_log = '\n'.join(report + results.log) state = results.error_cnt and 'error' or 'ready' - statement_file_obj.write(cursor, uid, import_id, dict( + statement_file_obj.write(cr, uid, import_id, dict( state = state, log = text_log, ), context) if not imported_statement_ids or not results.trans_loaded_cnt: # file state can be 'ready' while import state is 'error' state = 'error' - self.write(cursor, uid, [ids[0]], dict( + self.write(cr, uid, [ids[0]], dict( import_id = import_id, log = text_log, state = state, statement_ids = [(6, 0, imported_statement_ids)], ), context) diff --git a/account_banking/wizard/banktools.py b/account_banking/wizard/banktools.py index abec5ef12..aad9ddf10 100644 --- a/account_banking/wizard/banktools.py +++ b/account_banking/wizard/banktools.py @@ -50,7 +50,7 @@ def get_period(pool, cr, uid, date, company, log=None): return False return period_ids[0] -def get_bank_accounts(pool, cursor, uid, account_number, log, fail=False): +def get_bank_accounts(pool, cr, uid, account_number, log, fail=False): ''' Get the bank account with account number account_number ''' @@ -59,13 +59,13 @@ def get_bank_accounts(pool, cursor, uid, account_number, log, fail=False): return False partner_bank_obj = pool.get('res.partner.bank') - bank_account_ids = partner_bank_obj.search(cursor, uid, [ + bank_account_ids = partner_bank_obj.search(cr, uid, [ ('acc_number', '=', account_number) ]) if not bank_account_ids: # SR 2012-02-19 does the search() override in res_partner_bank # provides this result on the previous query? - bank_account_ids = partner_bank_obj.search(cursor, uid, [ + bank_account_ids = partner_bank_obj.search(cr, uid, [ ('acc_number_domestic', '=', account_number) ]) if not bank_account_ids: @@ -75,7 +75,7 @@ def get_bank_accounts(pool, cursor, uid, account_number, log, fail=False): % dict(account_no=account_number) ) return False - return partner_bank_obj.browse(cursor, uid, bank_account_ids) + return partner_bank_obj.browse(cr, uid, bank_account_ids) def _has_attr(obj, attr): # Needed for dangling addresses and a weird exception scheme in @@ -154,14 +154,14 @@ def get_or_create_partner(pool, cr, uid, name, address, postal_code, city, partner_id = partner_ids[0] return partner_id -def get_company_bank_account(pool, cursor, uid, account_number, currency, +def get_company_bank_account(pool, cr, uid, account_number, currency, company, log): ''' Get the matching bank account for this company. Currency is the ISO code for the requested currency. ''' results = struct() - bank_accounts = get_bank_accounts(pool, cursor, uid, account_number, log, + bank_accounts = get_bank_accounts(pool, cr, uid, account_number, log, fail=True) if not bank_accounts: return False @@ -184,12 +184,12 @@ def get_company_bank_account(pool, cursor, uid, account_number, currency, # Find matching journal for currency journal_obj = pool.get('account.journal') - journal_ids = journal_obj.search(cursor, uid, [ + journal_ids = journal_obj.search(cr, uid, [ ('type', '=', 'bank'), ('currency.name', '=', currency or company.currency_id.name) ]) if currency == company.currency_id.name: - journal_ids_no_curr = journal_obj.search(cursor, uid, [ + journal_ids_no_curr = journal_obj.search(cr, uid, [ ('type', '=', 'bank'), ('currency', '=', False) ]) journal_ids.extend(journal_ids_no_curr) @@ -197,9 +197,9 @@ def get_company_bank_account(pool, cursor, uid, account_number, currency, criteria.append(('journal_id', 'in', journal_ids)) # Find bank account settings - bank_settings_ids = bank_settings_obj.search(cursor, uid, criteria) + bank_settings_ids = bank_settings_obj.search(cr, uid, criteria) if bank_settings_ids: - settings = bank_settings_obj.browse(cursor, uid, bank_settings_ids)[0] + settings = bank_settings_obj.browse(cr, uid, bank_settings_ids)[0] results.company_id = company results.journal_id = settings.journal_id @@ -217,7 +217,7 @@ def get_company_bank_account(pool, cursor, uid, account_number, currency, return results -def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None, +def get_or_create_bank(pool, cr, uid, bic, online=False, code=None, name=None): ''' Find or create the bank with the provided BIC code. @@ -233,27 +233,27 @@ def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None, if len(bic) < 8: # search key bank_ids = bank_obj.search( - cursor, uid, [ + cr, uid, [ ('bic', '=', bic[:6]) ]) if not bank_ids: bank_ids = bank_obj.search( - cursor, uid, [ + cr, uid, [ ('bic', 'ilike', bic + '%') ]) else: bank_ids = bank_obj.search( - cursor, uid, [ + cr, uid, [ ('bic', '=', bic) ]) if bank_ids and len(bank_ids) == 1: - banks = bank_obj.browse(cursor, uid, bank_ids) + banks = bank_obj.browse(cr, uid, bank_ids) return banks[0].id, banks[0].country.id country_obj = pool.get('res.country') country_ids = country_obj.search( - cursor, uid, [('code', '=', bic[4:6])] + cr, uid, [('code', '=', bic[4:6])] ) country_id = country_ids and country_ids[0] or False bank_id = False @@ -261,7 +261,7 @@ def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None, if online: info, address = sepa.online.bank_info(bic) if info: - bank_id = bank_obj.create(cursor, uid, dict( + bank_id = bank_obj.create(cr, uid, dict( code = info.code, name = info.name, street = address.street, @@ -275,7 +275,7 @@ def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None, info = struct(name=name, code=code) if not online or not bank_id: - bank_id = bank_obj.create(cursor, uid, dict( + bank_id = bank_obj.create(cr, uid, dict( code = info.code or 'UNKNOW', name = info.name or _('Unknown Bank'), country = country_id, @@ -283,7 +283,7 @@ def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None, )) return bank_id, country_id -def create_bank_account(pool, cursor, uid, partner_id, +def create_bank_account(pool, cr, uid, partner_id, account_number, holder_name, address, city, country_code, log, bic=False, ): @@ -309,16 +309,16 @@ def create_bank_account(pool, cursor, uid, partner_id, if not country_code: country = pool.get('res.partner').browse( - cursor, uid, partner_id).country + cr, uid, partner_id).country country_code = country.code country_id = country.id else: if iban.valid: - country_ids = country_obj.search(cursor, uid, + country_ids = country_obj.search(cr, uid, [('code', '=', iban.countrycode)] ) else: - country_ids = country_obj.search(cursor, uid, + country_ids = country_obj.search(cr, uid, [('code', '=', country_code)] ) country_id = country_ids[0] @@ -339,10 +339,10 @@ def create_bank_account(pool, cursor, uid, partner_id, bic = account_info.bic if bic: - values.bank = get_or_create_bank(pool, cursor, uid, bic)[0] + values.bank = get_or_create_bank(pool, cr, uid, bic)[0] values.bank_bic = bic # Create bank account and return - return pool.get('res.partner.bank').create(cursor, uid, values) + return pool.get('res.partner.bank').create(cr, uid, values) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_banking_nl_clieop/account_banking_nl_clieop.py b/account_banking_nl_clieop/account_banking_nl_clieop.py index b0da0bb74..44b68c3cb 100644 --- a/account_banking_nl_clieop/account_banking_nl_clieop.py +++ b/account_banking_nl_clieop/account_banking_nl_clieop.py @@ -1,6 +1,7 @@ ############################################################################## # # Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). # All Rights Reserved # # This program is free software: you can redistribute it and/or modify @@ -18,11 +19,12 @@ # ############################################################################## -from osv import osv, fields from datetime import date -from tools.translate import _ +from openerp.osv import orm, fields +from openerp.tools.translate import _ -class clieop_export(osv.osv): + +class clieop_export(orm.Model): '''ClieOp3 Export''' _name = 'banking.export.clieop' _description = __doc__ @@ -94,6 +96,3 @@ class clieop_export(osv.osv): 'state': 'draft', 'daynumber': get_daynr, } -clieop_export() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_banking_nl_clieop/wizard/export_clieop.py b/account_banking_nl_clieop/wizard/export_clieop.py index 641507124..985455887 100644 --- a/account_banking_nl_clieop/wizard/export_clieop.py +++ b/account_banking_nl_clieop/wizard/export_clieop.py @@ -2,6 +2,7 @@ ############################################################################## # # Copyright (C) 2009 EduSense BV (). +# 2011 - 2013 Therp BV (). # All Rights Reserved # # This program is free software: you can redistribute it and/or modify @@ -21,11 +22,11 @@ import base64 from datetime import datetime, date, timedelta -from osv import osv, fields -from tools.translate import _ -import netsvc -from account_banking import sepa -import clieop +from openerp.osv import orm, fields +from openerp.tools.translate import _ +from openerp import netsvc +from openerp.addons.account_banking import sepa +from openerp.addons.account_banking_nl_clieop.wizard import clieop def strpdate(arg, format='%Y-%m-%d'): '''shortcut''' @@ -35,7 +36,7 @@ def strfdate(arg, format='%Y-%m-%d'): '''shortcut''' return arg.strftime(format) -class banking_export_clieop_wizard(osv.osv_memory): +class banking_export_clieop_wizard(orm.TransientModel): _name = 'banking.export.clieop.wizard' _description = 'Client Opdrachten Export' _columns = { @@ -155,17 +156,17 @@ class banking_export_clieop_wizard(osv.osv_memory): 'test': True, } - def create(self, cursor, uid, vals, context=None): + def create(self, cr, uid, vals, context=None): ''' Retrieve a sane set of default values based on the payment orders from the context. ''' if 'batchtype' not in vals: - self.check_orders(cursor, uid, vals, context) + self.check_orders(cr, uid, vals, context) return super(banking_export_clieop_wizard, self).create( - cursor, uid, vals, context) + cr, uid, vals, context) - def check_orders(self, cursor, uid, vals, context): + def check_orders(self, cr, uid, vals, context): ''' Check payment type for all orders. @@ -177,14 +178,14 @@ class banking_export_clieop_wizard(osv.osv_memory): Also mind that rates for batches are way higher than those for transactions. It pays to limit the number of batches. ''' - today = date.today() + today = fields.date.context_date(self, cr, uid, context=context) payment_order_obj = self.pool.get('payment.order') # Payment order ids are provided in the context payment_order_ids = context.get('active_ids', []) runs = {} # Only orders of same type can be combined - payment_orders = payment_order_obj.browse(cursor, uid, payment_order_ids) + payment_orders = payment_order_obj.browse(cr, uid, payment_order_ids) for payment_order in payment_orders: payment_type = payment_order.mode.type.code @@ -212,12 +213,12 @@ class banking_export_clieop_wizard(osv.osv_memory): else: execution_date = today if execution_date and execution_date >= max_date: - raise osv.except_osv( + raise orm.except_orm( _('Error'), _('You can\'t create ClieOp orders more than 30 days in advance.') ) if len(runs) != 1: - raise osv.except_osv( + raise orm.except_orm( _('Error'), _('You can only combine payment orders of the same type') ) @@ -231,12 +232,12 @@ class banking_export_clieop_wizard(osv.osv_memory): 'state': 'create', }) - def create_clieop(self, cursor, uid, ids, context): + def create_clieop(self, cr, uid, ids, context): ''' Wizard to actually create the ClieOp3 file ''' payment_order_obj = self.pool.get('payment.order') - clieop_export = self.browse(cursor, uid, ids, context)[0] + clieop_export = self.browse(cr, uid, ids, context)[0] clieopfile = None for payment_order in clieop_export.payment_order_ids: if not clieopfile: @@ -253,7 +254,7 @@ class banking_export_clieop_wizard(osv.osv_memory): else: our_account_nr = payment_order.mode.bank_id.acc_number if not our_account_nr: - raise osv.except_osv( + raise orm.except_orm( _('Error'), _('Your bank account has to have a valid account number') ) @@ -267,7 +268,7 @@ class banking_export_clieop_wizard(osv.osv_memory): accountno_sender = our_account_nr, seqno = self.pool.get( 'banking.export.clieop').get_daynr( - cursor, uid, context=context), + cr, uid, context=context), test = clieop_export['test'] ) @@ -291,7 +292,7 @@ class banking_export_clieop_wizard(osv.osv_memory): for line in payment_order.line_ids: # Check on missing partner of bank account (this can happen!) if not line.bank_id or not line.bank_id.partner_id: - raise osv.except_osv( + raise orm.except_orm( _('Error'), _('There is insufficient information.\r\n' 'Both destination address and account ' @@ -314,7 +315,7 @@ class banking_export_clieop_wizard(osv.osv_memory): # Is this an IBAN account? if iban.valid: if iban.countrycode != 'NL': - raise osv.except_osv( + raise orm.except_orm( _('Error'), _('You cannot send international bank transfers ' 'through ClieOp3!') @@ -331,7 +332,7 @@ class banking_export_clieop_wizard(osv.osv_memory): # Generate the specifics of this clieopfile order = clieopfile.order file_id = self.pool.get('banking.export.clieop').create( - cursor, uid, dict( + cr, uid, dict( filetype = order.name_transactioncode, identification = order.identification, prefered_date = strfdate(order.preferred_execution_date), @@ -346,7 +347,7 @@ class banking_export_clieop_wizard(osv.osv_memory): [6, 0, [x.id for x in clieop_export['payment_order_ids']]] ], ), context) - self.write(cursor, uid, [ids[0]], dict( + self.write(cr, uid, [ids[0]], dict( filetype = order.name_transactioncode, testcode = order.testcode, file_id = file_id, @@ -364,31 +365,27 @@ class banking_export_clieop_wizard(osv.osv_memory): 'res_id': ids[0] or False, } - def cancel_clieop(self, cursor, uid, ids, context): + def cancel_clieop(self, cr, uid, ids, context): ''' Cancel the ClieOp: just drop the file ''' - clieop_export = self.read(cursor, uid, ids, ['file_id'], context)[0] - self.pool.get('banking.export.clieop').unlink(cursor, uid, clieop_export['file_id'][0]) + clieop_export = self.read(cr, uid, ids, ['file_id'], context)[0] + self.pool.get('banking.export.clieop').unlink(cr, uid, clieop_export['file_id'][0]) return {'type': 'ir.actions.act_window_close'} - def save_clieop(self, cursor, uid, ids, context): + def save_clieop(self, cr, uid, ids, context): ''' Save the ClieOp: mark all payments in the file as 'sent', if not a test ''' clieop_export = self.browse( - cursor, uid, ids, context)[0] + cr, uid, ids, context)[0] if not clieop_export['test']: clieop_obj = self.pool.get('banking.export.clieop') payment_order_obj = self.pool.get('payment.order') clieop_file = clieop_obj.write( - cursor, uid, clieop_export['file_id'].id, {'state': 'sent'} + cr, uid, clieop_export['file_id'].id, {'state': 'sent'} ) wf_service = netsvc.LocalService('workflow') for order in clieop_export['payment_order_ids']: - wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cursor) + wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cr) return {'type': 'ir.actions.act_window_close'} - -banking_export_clieop_wizard() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/bank_statement_instant_voucher/model/account_bank_statement_line.py b/bank_statement_instant_voucher/model/account_bank_statement_line.py index cf8beb9c3..a72205281 100644 --- a/bank_statement_instant_voucher/model/account_bank_statement_line.py +++ b/bank_statement_instant_voucher/model/account_bank_statement_line.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# This module copyright (C) 2012 Therp BV (). +# This module copyright (C) 2012 - 2013 Therp BV (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -19,10 +19,10 @@ # ############################################################################## -from openerp.osv import osv, fields +from openerp.osv import orm, fields -class account_bank_statement_line(osv.Model): +class account_bank_statement_line(orm.Model): _inherit = 'account.bank.statement.line' def create_instant_voucher(self, cr, uid, ids, context=None): res = False diff --git a/bank_statement_instant_voucher/model/account_voucher_instant.py b/bank_statement_instant_voucher/model/account_voucher_instant.py index 7ca3727ba..3c7354ded 100644 --- a/bank_statement_instant_voucher/model/account_voucher_instant.py +++ b/bank_statement_instant_voucher/model/account_voucher_instant.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# This module copyright (C) 2012 Therp BV (). +# This module copyright (C) 2012 - 2013 Therp BV (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -19,12 +19,12 @@ # ############################################################################## -from openerp.osv import osv, fields +from openerp.osv import orm, fields from openerp.tools.translate import _ from openerp.addons.decimal_precision import decimal_precision as dp -class instant_voucher(osv.TransientModel): +class instant_voucher(orm.TransientModel): _name = 'account.voucher.instant' _description = 'Instant Voucher' @@ -76,7 +76,7 @@ class instant_voucher(osv.TransientModel): cr, uid, [('company_id', '=', line.company_id.id), ('type', '=', voucher_type)]) if not journal_ids: - osv.exept_osv( + orm.exept_orm( _('Error'), _('No %s journal defined') % voucher_type) @@ -156,7 +156,7 @@ class instant_voucher(osv.TransientModel): context.get('active_id') or context.get('active_ids') and context.get('active_ids')[0]) if not res['statement_line_id']: - raise osv.except_osv( + raise orm.except_orm( _('Error'), _('Cannot determine statement line')) line = self.pool.get('account.bank.statement.line').browse( @@ -212,7 +212,7 @@ class instant_voucher(osv.TransientModel): instant.voucher_id.company_id.currency_id) if (instant.statement_line_id.statement_id.currency.id != voucher_currency.id): - raise osv.except_osv( + raise orm.except_orm( _("Error"), _("Currency on the bank statement line needs to be the " "same as on the voucher. Currency conversion is not yet " @@ -222,7 +222,7 @@ class instant_voucher(osv.TransientModel): cr, uid, [instant.voucher_id.id], context=context) instant.refresh() if instant.voucher_id.state != 'posted': - raise osv.except_osv( + raise orm.except_orm( _("Error"), _("The voucher could not be posted.")) if instant.voucher_id.move_id.state != 'posted': @@ -230,12 +230,12 @@ class instant_voucher(osv.TransientModel): cr, uid, [instant.voucher_id.move_id.id], context=context) instant.refresh() if instant.voucher_id.move_id.state != 'posted': - raise osv.except_osv( + raise orm.except_orm( _("Error"), _("The voucher's move line could not be posted.")) if not self.pool.get('res.currency').is_zero( cr, uid, voucher_currency, instant.balance): - raise osv.except_osv( + raise orm.except_orm( _("Error"), _("The amount on the bank statement line needs to be the " "same as on the voucher. Write-off is not yet " @@ -245,7 +245,7 @@ class instant_voucher(osv.TransientModel): # and trigger its posting and reconciliation. if 'import_transaction_id' in statement_line_obj._columns: if instant.statement_line_id.state == 'confirmed': - raise osv.except_osv( + raise orm.except_orm( _("Error"), _("Cannot match a confirmed statement line")) if not instant.statement_line_id.import_transaction_id: From 3c5fdecf374c55351563dc243289694073efee52 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 16:17:56 +0200 Subject: [PATCH 09/26] [RFR] Rename field 'debit_move_line_id' --- .../model/account_payment.py | 4 +- .../model/banking_import_transaction.py | 2 +- account_banking_payment/model/payment_line.py | 18 +++---- account_direct_debit/i18n/nl.po | 4 +- .../migrations/7.0.2/pre-migration.py | 47 ++++++++++++++++++- account_direct_debit/model/payment_line.py | 42 ++++++++--------- 6 files changed, 81 insertions(+), 36 deletions(-) diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index a0428a312..558314678 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -214,7 +214,7 @@ class payment_order(orm.Model): line_ids = [] reconcile_id = False for order_line in order.line_ids: - for line in order_line.debit_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 not line.reconcile_id: line_ids.append(line.id) if self.pool.get('res.currency').is_zero( @@ -330,7 +330,7 @@ class payment_order(orm.Model): # and call reconciliation on it payment_line_obj.write( cr, uid, line.id, - {'debit_move_line_id': reconcile_move_line_id}, + {'transit_move_line_id': reconcile_move_line_id}, context=context) payment_line_obj.debit_reconcile( diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index e08a61ffb..176c4053b 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -59,7 +59,7 @@ class banking_import_transaction(orm.Model): if len(candidates) > 0: # retrieve the common account_id, if any account_id = False - for line in candidates[0].line_ids[0].debit_move_line_id.move_id.line_id: + for line in candidates[0].line_ids[0].transit_move_line_id.move_id.line_id: if line.account_id.type == 'other': account_id = line.account_id.id break diff --git a/account_banking_payment/model/payment_line.py b/account_banking_payment/model/payment_line.py index 7d1b29176..f46010a1e 100644 --- a/account_banking_payment/model/payment_line.py +++ b/account_banking_payment/model/payment_line.py @@ -235,10 +235,10 @@ class payment_line(orm.Model): move_line_obj = self.pool.get('account.move.line') payment_line = self.browse(cr, uid, payment_line_id, context=context) - debit_move_line = payment_line.debit_move_line_id + transit_move_line = payment_line.transit_move_line_id torec_move_line = payment_line.move_line_id - if (not debit_move_line or not torec_move_line): + if (not transit_move_line or not torec_move_line): raise orm.except_orm( _('Can not reconcile'), _('No move line for line %s') % payment_line.name) @@ -248,22 +248,22 @@ class payment_line(orm.Model): _('Move line %s has already been reconciled') % torec_move_line.name ) - if debit_move_line.reconcile_id or debit_move_line.reconcile_partial_id: + if transit_move_line.reconcile_id or transit_move_line.reconcile_partial_id: raise orm.except_orm( _('Error'), _('Move line %s has already been reconciled') % - debit_move_line.name + transit_move_line.name ) def is_zero(total): return self.pool.get('res.currency').is_zero( - cr, uid, debit_move_line.company_id.currency_id, total) + cr, uid, transit_move_line.company_id.currency_id, total) - line_ids = [debit_move_line.id, torec_move_line.id] + line_ids = [transit_move_line.id, torec_move_line.id] if torec_move_line.reconcile_partial_id: line_ids = [ x.id for x in - debit_move_line.reconcile_partial_id.line_partial_ids + transit_move_line.reconcile_partial_id.line_partial_ids ] + [torec_move_line.id] total = move_line_obj.get_balance(cr, uid, line_ids) @@ -275,7 +275,7 @@ class payment_line(orm.Model): if torec_move_line.reconcile_partial_id: reconcile_obj.write( - cr, uid, debit_move_line.reconcile_partial_id.id, + cr, uid, transit_move_line.reconcile_partial_id.id, vals, context=context) else: reconcile_obj.create( @@ -293,7 +293,7 @@ class payment_line(orm.Model): _columns = { - 'debit_move_line_id': fields.many2one( + 'transit_move_line_id': fields.many2one( # this line is part of the credit side of move 2a # from the documentation 'account.move.line', 'Debit move line', diff --git a/account_direct_debit/i18n/nl.po b/account_direct_debit/i18n/nl.po index 6fedca692..3ba66c199 100644 --- a/account_direct_debit/i18n/nl.po +++ b/account_direct_debit/i18n/nl.po @@ -175,7 +175,7 @@ msgid "The payment line name must be unique!" msgstr "De betaalregelnaam moet uniek zijn!" #. module: account_direct_debit -#: field:payment.line,debit_move_line_id:0 +#: field:payment.line,transit_move_line_id:0 msgid "Debit move line" msgstr "Debetboeking" @@ -200,7 +200,7 @@ msgid "Invoice" msgstr "Factuur" #. module: account_direct_debit -#: help:payment.line,debit_move_line_id:0 +#: help:payment.line,transit_move_line_id:0 msgid "Move line through which the debit order pays the invoice" msgstr "Dagboekregel waarmee de incasso-opdracht de factuur voldoet" diff --git a/account_direct_debit/migrations/7.0.2/pre-migration.py b/account_direct_debit/migrations/7.0.2/pre-migration.py index 29fa9d6aa..3dd113401 100644 --- a/account_direct_debit/migrations/7.0.2/pre-migration.py +++ b/account_direct_debit/migrations/7.0.2/pre-migration.py @@ -1,6 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +def rename_columns(cr, column_spec): + """ + Rename table columns. Taken from OpenUpgrade. + + :param column_spec: a hash with table keys, with lists of tuples as values. \ + Tuples consist of (old_name, new_name). + + """ + for table in column_spec.keys(): + for (old, new) in column_spec[table]: + logger.info("table %s, column %s: renaming to %s", + table, old, new) + cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % (table, old, new,)) + cr.execute('DROP INDEX IF EXISTS "%s_%s_index"' % (table, old)) + def migrate(cr, version): if not version: return + # workflow state moved to another module cr.execute( """ @@ -9,4 +49,9 @@ def migrate(cr, version): WHERE name = 'trans_done_sent' AND module = 'account_direct_debit' """) - + + # rename field debit_move_line_id + rename_columns(cr, { + 'payment_line': [ + ('debit_move_line_id', 'transit_move_line_id'), + ]}) diff --git a/account_direct_debit/model/payment_line.py b/account_direct_debit/model/payment_line.py index 1f396068b..0f493cc39 100644 --- a/account_direct_debit/model/payment_line.py +++ b/account_direct_debit/model/payment_line.py @@ -32,25 +32,25 @@ class payment_line(orm.Model): reconcile_obj = self.pool.get('account.move.reconcile') line = self.browse(cr, uid, payment_line_id) reconcile_id = False - if (line.debit_move_line_id and not line.storno and + if (line.transit_move_line_id and not line.storno and self.pool.get('res.currency').is_zero( cr, uid, currency, ( - (line.debit_move_line_id.credit or 0.0) - - (line.debit_move_line_id.debit or 0.0) + amount))): + (line.transit_move_line_id.credit or 0.0) - + (line.transit_move_line_id.debit or 0.0) + amount))): # Two different cases, full and partial # Both cases differ subtly in the procedure to follow # Needs refractoring, but why is this not in the OpenERP API? # Actually, given the nature of a direct debit order and storno, # we should not need to take partial into account on the side of - # the debit_move_line. - if line.debit_move_line_id.reconcile_partial_id: - reconcile_id = line.debit_move_line_id.reconcile_partial_id.id + # the transit_move_line. + if line.transit_move_line_id.reconcile_partial_id: + reconcile_id = line.transit_move_line_id.reconcile_partial_id.id attribute = 'reconcile_partial_id' - if len(line.debit_move_line_id.reconcile_id.line_partial_ids) == 2: + if len(line.transit_move_line_id.reconcile_id.line_partial_ids) == 2: # reuse the simple reconcile for the storno transfer reconcile_obj.write( cr, uid, reconcile_id, { - 'line_id': [(6, 0, line.debit_move_line_id.id)], + 'line_id': [(6, 0, line.transit_move_line_id.id)], 'line_partial_ids': [(6, 0, [])], }, context=context) else: @@ -58,27 +58,27 @@ class payment_line(orm.Model): # and a new one for reconciling the storno transfer reconcile_obj.write( cr, uid, reconcile_id, { - 'line_partial_ids': [(3, line.debit_move_line_id.id)], + 'line_partial_ids': [(3, line.transit_move_line_id.id)], }, context=context) reconcile_id = reconcile_obj.create( cr, uid, { 'type': 'auto', - 'line_id': [(6, 0, line.debit_move_line_id.id)], + 'line_id': [(6, 0, line.transit_move_line_id.id)], }, context=context) - elif line.debit_move_line_id.reconcile_id: - reconcile_id = line.debit_move_line_id.reconcile_id.id - if len(line.debit_move_line_id.reconcile_id.line_id) == 2: + elif line.transit_move_line_id.reconcile_id: + reconcile_id = line.transit_move_line_id.reconcile_id.id + if len(line.transit_move_line_id.reconcile_id.line_id) == 2: # reuse the simple reconcile for the storno transfer reconcile_obj.write( cr, uid, reconcile_id, { - 'line_id': [(6, 0, [line.debit_move_line_id.id])] + 'line_id': [(6, 0, [line.transit_move_line_id.id])] }, context=context) else: # split up the original reconcile in a partial one # and a new one for reconciling the storno transfer partial_ids = [ - x.id for x in line.debit_move_line_id.reconcile_id.line_id - if x.id != line.debit_move_line_id.id + x.id for x in line.transit_move_line_id.reconcile_id.line_id + if x.id != line.transit_move_line_id.id ] reconcile_obj.write( cr, uid, reconcile_id, { @@ -88,7 +88,7 @@ class payment_line(orm.Model): reconcile_id = reconcile_obj.create( cr, uid, { 'type': 'auto', - 'line_id': [(6, 0, line.debit_move_line_id.id)], + 'line_id': [(6, 0, line.transit_move_line_id.id)], }, context=context) # mark the payment line for storno processed if reconcile_id: @@ -119,12 +119,12 @@ class payment_line(orm.Model): line = self.browse(cr, uid, payment_line_id) account_id = False - if (line.debit_move_line_id and not line.storno and + if (line.transit_move_line_id and not line.storno and self.pool.get('res.currency').is_zero( cr, uid, currency, ( - (line.debit_move_line_id.credit or 0.0) - - (line.debit_move_line_id.debit or 0.0) + amount))): - account_id = line.debit_move_line_id.account_id.id + (line.transit_move_line_id.credit or 0.0) - + (line.transit_move_line_id.debit or 0.0) + amount))): + account_id = line.transit_move_line_id.account_id.id return account_id def debit_reconcile(self, cr, uid, payment_line_id, context=None): From 4b998a263e5a1132af103acdf79a004d862922c5 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 May 2013 16:42:13 +0200 Subject: [PATCH 10/26] [RFR] Sort out view changes between debit and payment modules --- .../view/account_payment.xml | 21 ++++++++++++++ account_direct_debit/view/account_invoice.xml | 14 ++++------ account_direct_debit/view/account_payment.xml | 28 ++----------------- 3 files changed, 28 insertions(+), 35 deletions(-) diff --git a/account_banking_payment/view/account_payment.xml b/account_banking_payment/view/account_payment.xml index b07d6c98f..b2233c225 100644 --- a/account_banking_payment/view/account_payment.xml +++ b/account_banking_payment/view/account_payment.xml @@ -41,5 +41,26 @@ + + + payment.mode.form add transfer account + payment.mode + + form + + + + + + + + + diff --git a/account_direct_debit/view/account_invoice.xml b/account_direct_debit/view/account_invoice.xml index 8004dbc84..c43ee8bcb 100644 --- a/account_direct_debit/view/account_invoice.xml +++ b/account_direct_debit/view/account_invoice.xml @@ -16,14 +16,6 @@ - - - - payment.mode.form add transfer account - payment.mode - - form - - - - - - - - - diff --git a/account_banking_payment/view/bank_payment_manual.xml b/account_banking_payment/view/bank_payment_manual.xml index 64e8bd08a..538862ca3 100644 --- a/account_banking_payment/view/bank_payment_manual.xml +++ b/account_banking_payment/view/bank_payment_manual.xml @@ -4,9 +4,8 @@ Form for manual payment wizard payment.manual - form - + - - diff --git a/account_banking_payment/view/payment_mode.xml b/account_banking_payment/view/payment_mode.xml index 1f54cda12..bb3c19ff4 100644 --- a/account_banking_payment/view/payment_mode.xml +++ b/account_banking_payment/view/payment_mode.xml @@ -12,15 +12,29 @@ - - - + + + + + + + + + + + From 1aac39a95212995223780182fe2d204145e27390 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 29 May 2013 16:20:31 +0200 Subject: [PATCH 13/26] [RFR] Remove unused field 'export_state' on payment line --- .../model/account_payment.py | 14 +-- .../model/banking_import_transaction.py | 1 - account_banking_payment/model/payment_line.py | 113 +----------------- 3 files changed, 5 insertions(+), 123 deletions(-) diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 558314678..0e4e2f147 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -73,6 +73,8 @@ class payment_order(orm.Model): 'line_ids': fields.one2many( 'payment.line', 'order_id', 'Payment lines', states={ + 'open': [('readonly', True)], + 'cancel': [('readonly', True)], 'sent': [('readonly', True)], 'rejected': [('readonly', True)], 'done': [('readonly', True)] @@ -172,20 +174,10 @@ class payment_order(orm.Model): ]) payment_line_obj.write(cr, uid, line_ids, kwargs) - def set_to_draft(self, cr, uid, ids, *args): - ''' - Set both self and payment lines to state 'draft'. - ''' - self._write_payment_lines(cr, uid, ids, export_state='draft') - return super(payment_order, self).set_to_draft( - cr, uid, ids, *args - ) - def action_rejected(self, cr, uid, ids, *args): ''' Set both self and payment lines to state 'rejected'. ''' - self._write_payment_lines(cr, uid, ids, export_state='rejected') wf_service = netsvc.LocalService('workflow') for id in ids: wf_service.trg_validate(uid, 'payment.order', id, 'rejected', cr) @@ -197,7 +189,6 @@ class payment_order(orm.Model): ''' self._write_payment_lines( cr, uid, ids, - export_state='done', date_done=fields.date.context_today(self, cr, uid)) return super(payment_order, self).set_done( cr, uid, ids, *args @@ -337,7 +328,6 @@ class payment_order(orm.Model): cr, uid, line.id, context=context) account_move_obj.post(cr, uid, [move_id], context=context) - self._write_payment_lines(cr, uid, ids, export_state='sent') self.write(cr, uid, ids, { 'state': 'sent', 'date_sent': fields.date.context_today( diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index 176c4053b..8d6ab0295 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -196,7 +196,6 @@ class banking_import_transaction(orm.Model): payment_line_obj = self.pool.get('payment.line') payment_line_obj.write( cr, uid, transaction.payment_line_id.id, { - 'export_state': 'done', 'date_done': transaction.statement_line_id.date, } ) diff --git a/account_banking_payment/model/payment_line.py b/account_banking_payment/model/payment_line.py index 3d5bdf247..4edcd9199 100644 --- a/account_banking_payment/model/payment_line.py +++ b/account_banking_payment/model/payment_line.py @@ -29,7 +29,7 @@ from openerp.tools.translate import _ class payment_line(orm.Model): ''' - Add extra export_state and date_done fields; make destination bank account + Add some fields; make destination bank account mandatory, as it makes no sense to send payments into thin air. Edit: Payments can be by cash too, which is prohibited by mandatory bank accounts. @@ -37,127 +37,21 @@ class payment_line(orm.Model): _inherit = 'payment.line' _columns = { # New fields - 'export_state': fields.selection([ - ('draft', 'Draft'), - ('open','Confirmed'), - ('cancel','Cancelled'), - ('sent', 'Sent'), - ('rejected', 'Rejected'), - ('done','Done'), - ], 'State', select=True - ), 'msg': fields.char('Message', size=255, required=False, readonly=True), 'date_done': fields.date( 'Date Confirmed', select=True, readonly=True), - - # Redefined fields: added states - 'name': fields.char( - 'Your Reference', size=64, required=True, - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), + # Communication: required is dependend on the mode 'communication': fields.char( 'Communication', size=64, required=False, help=("Used as the message between ordering customer and current " "company. Depicts 'What do you want to say to the recipient" " about this order ?'" ), - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, ), + # Communication2: enlarge to 128 'communication2': fields.char( 'Communication 2', size=128, help='The successor message of Communication.', - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'move_line_id': fields.many2one( - 'account.move.line', 'Entry line', - domain=[('reconcile_id','=', False), - ('account_id.type', '=','payable') - ], - help=('This Entry Line will be referred for the information of ' - 'the ordering customer.' - ), - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'amount_currency': fields.float( - 'Amount in Partner Currency', digits=(16,2), - required=True, - help='Payment amount in the partner currency', - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'currency': fields.many2one( - 'res.currency', 'Partner Currency', required=True, - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'bank_id': fields.many2one( - 'res.partner.bank', 'Destination Bank account', - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'order_id': fields.many2one( - 'payment.order', 'Order', required=True, - ondelete='cascade', select=True, - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'partner_id': fields.many2one( - 'res.partner', string="Partner", required=True, - help='The Ordering Customer', - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'date': fields.date( - 'Payment Date', - help=("If no payment date is specified, the bank will treat this " - "payment line directly" - ), - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, - ), - 'state': fields.selection([ - ('normal','Free'), - ('structured','Structured') - ], 'Communication Type', required=True, - states={ - 'sent': [('readonly', True)], - 'rejected': [('readonly', True)], - 'done': [('readonly', True)] - }, ), 'transit_move_line_id': fields.many2one( # this line is part of the credit side of move 2a @@ -169,7 +63,6 @@ class payment_line(orm.Model): } _defaults = { - 'export_state': 'draft', 'msg': '', } From 08436c0bf5231ebeb9f6548565931fb4669c4fc8 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 29 May 2013 16:42:50 +0200 Subject: [PATCH 14/26] [FIX] Move attributes to from 'states' dictionary to view --- account_banking_payment/model/payment_line.py | 12 ------------ account_banking_payment/view/account_payment.xml | 7 +++++++ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/account_banking_payment/model/payment_line.py b/account_banking_payment/model/payment_line.py index 4edcd9199..3abae5ff0 100644 --- a/account_banking_payment/model/payment_line.py +++ b/account_banking_payment/model/payment_line.py @@ -66,18 +66,6 @@ class payment_line(orm.Model): 'msg': '', } - def fields_get(self, cr, uid, fields=None, context=None): - res = super(payment_line, self).fields_get(cr, uid, fields, context) - if 'communication' in res: - res['communication'].setdefault('states', {}) - res['communication']['states']['structured'] = [('required', True)] - if 'communication2' in res: - res['communication2'].setdefault('states', {}) - res['communication2']['states']['structured'] = [('readonly', True)] - res['communication2']['states']['normal'] = [('readonly', False)] - - return res - """ Hooks for processing direct debit orders, such as implemented in account_direct_debit module. diff --git a/account_banking_payment/view/account_payment.xml b/account_banking_payment/view/account_payment.xml index 1d6b3c1e9..4f7601332 100644 --- a/account_banking_payment/view/account_payment.xml +++ b/account_banking_payment/view/account_payment.xml @@ -21,6 +21,13 @@ position="attributes"> launch_wizard + + + { + 'readonly': [('state', '=', 'normal')] + } + From 9e36b2f3246b881fe5163129da83554ce1df5dab Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 29 May 2013 16:52:31 +0200 Subject: [PATCH 15/26] [FIX] Fixes from testing --- .../account_banking_nl_clieop.py | 2 +- account_banking_nl_clieop/wizard/export_clieop.py | 11 ++++++----- account_banking_payment/model/account_payment.py | 5 +---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/account_banking_nl_clieop/account_banking_nl_clieop.py b/account_banking_nl_clieop/account_banking_nl_clieop.py index 44b68c3cb..97925c8f4 100644 --- a/account_banking_nl_clieop/account_banking_nl_clieop.py +++ b/account_banking_nl_clieop/account_banking_nl_clieop.py @@ -82,7 +82,7 @@ class clieop_export(orm.Model): last = 1 last_ids = self.search(cr, uid, [ ('date_generated', '=', - fields.date.context_today(cr,uid,context)) + fields.date.context_today(self, cr,uid,context)) ], context=context) if last_ids: last = 1 + max([x['daynumber'] for x in self.read( diff --git a/account_banking_nl_clieop/wizard/export_clieop.py b/account_banking_nl_clieop/wizard/export_clieop.py index 985455887..8655262da 100644 --- a/account_banking_nl_clieop/wizard/export_clieop.py +++ b/account_banking_nl_clieop/wizard/export_clieop.py @@ -25,16 +25,17 @@ from datetime import datetime, date, timedelta from openerp.osv import orm, fields from openerp.tools.translate import _ from openerp import netsvc +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT from openerp.addons.account_banking import sepa from openerp.addons.account_banking_nl_clieop.wizard import clieop -def strpdate(arg, format='%Y-%m-%d'): +def strpdate(arg): '''shortcut''' - return datetime.strptime(arg, format).date() + return datetime.strptime(arg, DEFAULT_SERVER_DATE_FORMAT).date() -def strfdate(arg, format='%Y-%m-%d'): +def strfdate(arg): '''shortcut''' - return arg.strftime(format) + return arg.strftime(DEFAULT_SERVER_DATE_FORMAT) class banking_export_clieop_wizard(orm.TransientModel): _name = 'banking.export.clieop.wizard' @@ -178,7 +179,7 @@ class banking_export_clieop_wizard(orm.TransientModel): Also mind that rates for batches are way higher than those for transactions. It pays to limit the number of batches. ''' - today = fields.date.context_date(self, cr, uid, context=context) + today = strpdate(fields.date.context_today(self, cr, uid, context=context)) payment_order_obj = self.pool.get('payment.order') # Payment order ids are provided in the context diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 0e4e2f147..6ef4a8036 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -256,9 +256,6 @@ class payment_order(orm.Model): the debit order. This happens when the debit order file is generated. """ - res = super(payment_order, self).action_sent( - cr, uid, ids, context) - account_move_obj = self.pool.get('account.move') account_move_line_obj = self.pool.get('account.move.line') payment_line_obj = self.pool.get('payment.line') @@ -334,4 +331,4 @@ class payment_order(orm.Model): self, cr, uid, context=context), }, context=context) - return res + return True From 30273810f2e8e892f27d71daae6295151c9ff03e Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 29 May 2013 16:53:14 +0200 Subject: [PATCH 16/26] [IMP] Test run on clieop defaults to False --- account_banking_nl_clieop/wizard/export_clieop.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/account_banking_nl_clieop/wizard/export_clieop.py b/account_banking_nl_clieop/wizard/export_clieop.py index 8655262da..915c46bb6 100644 --- a/account_banking_nl_clieop/wizard/export_clieop.py +++ b/account_banking_nl_clieop/wizard/export_clieop.py @@ -153,10 +153,6 @@ class banking_export_clieop_wizard(orm.TransientModel): ), } - _defaults = { - 'test': True, - } - def create(self, cr, uid, vals, context=None): ''' Retrieve a sane set of default values based on the payment orders From 7dc915753a82891dc78804af4503867ffde86e2e Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 29 May 2013 20:10:56 +0200 Subject: [PATCH 17/26] [RFR] Remove obsolete workaround for lp:915975 [RFR] Remove unused method --- .../wizard/banking_transaction_wizard.py | 47 +------------------ 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/account_banking/wizard/banking_transaction_wizard.py b/account_banking/wizard/banking_transaction_wizard.py index 5e85b9b11..1667c6a10 100644 --- a/account_banking/wizard/banking_transaction_wizard.py +++ b/account_banking/wizard/banking_transaction_wizard.py @@ -99,36 +99,10 @@ class banking_transaction_wizard(orm.TransientModel): manual_invoice_id = vals.pop('manual_invoice_id', False) manual_move_line_id = vals.pop('manual_move_line_id', False) - # Support for writing fields.related is still flakey: - # https://bugs.launchpad.net/openobject-server/+bug/915975 - # Will do so myself. - - # Separate the related fields - transaction_vals = {} - wizard_vals = vals.copy() - for key in vals.keys(): - field = self._columns[key] - if (isinstance(field, fields.related) and - field._arg[0] == 'import_transaction_id'): - transaction_vals[field._arg[1]] = vals[key] - del wizard_vals[key] - - # write the related fields on the transaction model - if isinstance(ids, int): - ids = [ids] - for wizard in self.browse(cr, uid, ids, context=context): - if wizard.import_transaction_id: - transaction_obj.write( - cr, uid, wizard.import_transaction_id.id, - transaction_vals, context=context) - - # write other fields to the wizard model res = super(banking_transaction_wizard, self).write( - cr, uid, ids, wizard_vals, context=context) + cr, uid, ids, vals, context=context) - # End of workaround for lp:915975 - - """ Process the logic of the written values """ + # Process the logic of the written values # An invoice is selected from multiple candidates if vals and 'invoice_id' in vals: @@ -271,24 +245,9 @@ class banking_transaction_wizard(orm.TransientModel): {'duplicate': not wiz['duplicate']}, context=context) return self.create_act_window(cr, uid, ids, context=None) - def _get_default_match_type(self, cr, uid, context=None): - """ - Take initial value for the match type from the statement line - """ - res = False - if context and 'statement_line_id' in context: - res = self.pool.get('account.bank.statement.line').read( - cr, uid, context['statement_line_id'], - ['match_type'], context=context)['match_type'] - return res - def button_done(self, cr, uid, ids, context=None): return {'nodestroy': False, 'type': 'ir.actions.act_window_close'} - _defaults = { -# 'match_type': _get_default_match_type, - } - _columns = { 'name': fields.char('Name', size=64), 'statement_line_id': fields.many2one( @@ -363,8 +322,6 @@ class banking_transaction_wizard(orm.TransientModel): string="Analytic Account"), 'move_currency_amount': fields.related('import_transaction_id','move_currency_amount', type='float', string='Match Currency Amount', readonly=True), - #'manual_payment_order_id': fields.many2one( - # 'payment.order', "Payment order to reconcile"), } banking_transaction_wizard() From 1d81e9f30bd7d6f8ac7c8123127176ca6db749a5 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Thu, 30 May 2013 00:26:36 +0200 Subject: [PATCH 18/26] [RFR] Payment order workflow now allows cancelling of reconciled orders [FIX] Fixes from testing [IMP] Manual matching of payment orders and lines --- account_banking/account_banking.py | 2 +- account_banking/banking_import_transaction.py | 26 ++++++++--- .../wizard/banking_transaction_wizard.py | 14 +++++- .../model/account_payment.py | 29 ++++++++++--- .../model/banking_import_transaction.py | 15 ++----- .../model/banking_transaction_wizard.py | 38 ++++++++++++++++ .../view/banking_transaction_wizard.xml | 19 ++++---- .../workflow/account_payment.xml | 43 +++++++++++-------- 8 files changed, 135 insertions(+), 51 deletions(-) diff --git a/account_banking/account_banking.py b/account_banking/account_banking.py index 009bbe603..5a279bd1b 100644 --- a/account_banking/account_banking.py +++ b/account_banking/account_banking.py @@ -398,7 +398,7 @@ class account_bank_statement(orm.Model): # Write stored reconcile_id and pay invoices through workflow if st_line.reconcile_id: move_ids = [move.id for move in st_line.move_ids] - torec = account_move_obj.search( + torec = account_move_line_obj.search( cr, uid, [ ('move_id', 'in', move_ids), ('account_id', '=', st_line.account_id.id)], diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index e882a8627..5dadb1747 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -1358,9 +1358,16 @@ class banking_import_transaction(orm.Model): 'parent_id': fields.many2one( 'banking.import.transaction', 'Split off from this transaction'), # match fields - 'match_type': fields.selection( - [('manual', 'Manual'), ('move','Move'), ('invoice', 'Invoice'), - ], 'Match type'), + 'match_type': fields.selection([ + ('move','Move'), + ('invoice', 'Invoice'), + ('payment', 'Payment line'), + ('payment_order', 'Payment order'), + ('storno', 'Storno'), + ('manual', 'Manual'), + ('payment_manual', 'Payment line (manual)'), + ('payment_order_manual', 'Payment order (manual)'), + ], 'Match type'), 'match_multi': fields.function( _get_match_multi, method=True, string='Multi match', type='boolean'), @@ -1429,9 +1436,16 @@ class account_bank_statement_line(orm.Model): string='Possible duplicate import', readonly=True), 'match_type': fields.related( 'import_transaction_id', 'match_type', type='selection', - selection=[('manual', 'Manual'), ('move','Move'), - ('invoice', 'Invoice'), - ], + selection=[ + ('move','Move'), + ('invoice', 'Invoice'), + ('payment', 'Payment line'), + ('payment_order', 'Payment order'), + ('storno', 'Storno'), + ('manual', 'Manual'), + ('payment_manual', 'Payment line (manual)'), + ('payment_order_manual', 'Payment order (manual)'), + ], string='Match type', readonly=True,), 'state': fields.selection( [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', diff --git a/account_banking/wizard/banking_transaction_wizard.py b/account_banking/wizard/banking_transaction_wizard.py index 1667c6a10..4bc9a1954 100644 --- a/account_banking/wizard/banking_transaction_wizard.py +++ b/account_banking/wizard/banking_transaction_wizard.py @@ -300,8 +300,18 @@ class banking_transaction_wizard(orm.TransientModel): 'import_transaction_id', 'match_multi', type="boolean", string='Multiple matches'), 'match_type': fields.related( - 'import_transaction_id', 'match_type', - type="char", size=16, string='Match type', readonly=True), + 'import_transaction_id', 'match_type', type='selection', + selection=[ + ('move','Move'), + ('invoice', 'Invoice'), + ('payment', 'Payment line'), + ('payment_order', 'Payment order'), + ('storno', 'Storno'), + ('manual', 'Manual'), + ('payment_manual', 'Payment line (manual)'), + ('payment_order_manual', 'Payment order (manual)'), + ], + string='Match type', readonly=True), 'manual_invoice_id': fields.many2one( 'account.invoice', 'Match this invoice', domain=[('reconciled', '=', False)]), diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 6ef4a8036..10d114c4d 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -227,12 +227,17 @@ class payment_order(orm.Model): Due to a cancelled bank statements import, unreconcile the move on the transfer account. Delegate the conditions to the workflow. Raise on failure for rollback. + + Workflow appears to return False even on success so we just check + the order's state that we know to be set to 'sent' in that case. """ self.pool.get('account.move.reconcile').unlink( - cr, uid, reconcile_id, context=context) - wkf_ok = netsvc.LocalService('workflow').trg_validate( + cr, uid, [reconcile_id], context=context) + netsvc.LocalService('workflow').trg_validate( uid, 'payment.order', payment_order_id, 'undo_done', cr) - if not wkf_ok: + state = self.pool.get('payment.order').read( + cr, uid, payment_order_id, ['state'], context=context)['state'] + if state != 'sent': raise orm.except_orm( _("Cannot unreconcile"), _("Cannot unreconcile payment order: "+ @@ -245,9 +250,19 @@ class payment_order(orm.Model): payment orders that were reconciled with bank transfers which are being cancelled. - The debit module actually enforces a criterium in its - override of this method for debit orders. + Test if the payment order has not been reconciled. Depends + on the restriction that transit move lines should use an + account of type 'other', and on the restriction of payment + and debit orders that they only take moves on accounts + payable/receivable. """ + 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: + if (line.account_id.type == 'other' and + line.reconcile_id): + return False return True def action_sent(self, cr, uid, ids, context=None): @@ -325,10 +340,12 @@ class payment_order(orm.Model): 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, { - 'state': 'sent', 'date_sent': fields.date.context_today( self, cr, uid, context=context), }, context=context) return True + + diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index 8d6ab0295..91b489ed2 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -298,17 +298,6 @@ class banking_import_transaction(orm.Model): cr, uid, transaction.payment_line_id.id, context) _columns = { - 'match_type': fields.selection( - # Add payment and storno types - [ - ('manual', 'Manual'), - ('move','Move'), - ('invoice', 'Invoice'), - ('payment', 'Payment'), - ('payment_order', 'Payment order'), - ('storno', 'Storno'), - ], - 'Match type'), 'payment_order_ids': fields.many2many( 'payment.order', 'banking_transaction_payment_order_rel', 'order_id', 'transaction_id', 'Payment orders'), @@ -390,10 +379,14 @@ class banking_import_transaction(orm.Model): 'storno': self._confirm_storno.__func__, 'payment_order': self._confirm_payment_order.__func__, 'payment': self._confirm_payment.__func__, + 'payment_order_manual': self._confirm_payment_order.__func__, + 'payment_manual': self._confirm_payment.__func__, }) self.cancel_map.update({ 'storno': self._cancel_storno.__func__, 'payment_order': self._cancel_payment_order.__func__, 'payment': self._cancel_payment.__func__, + 'payment_order_manual': self._cancel_payment_order.__func__, + 'payment_manual': self._cancel_payment.__func__, }) diff --git a/account_banking_payment/model/banking_transaction_wizard.py b/account_banking_payment/model/banking_transaction_wizard.py index 470a81c81..111e371fe 100644 --- a/account_banking_payment/model/banking_transaction_wizard.py +++ b/account_banking_payment/model/banking_transaction_wizard.py @@ -28,6 +28,35 @@ from openerp.osv import orm, fields class banking_transaction_wizard(orm.TransientModel): _inherit = 'banking.transaction.wizard' + + def write(self, cr, uid, ids, vals, context=None): + """ + Check for manual payment orders or lines + """ + if not vals: + return True + manual_payment_order_id = vals.pop('manual_payment_order_id', False) + manual_payment_line_id = vals.pop('manual_payment_line_id', False) + res = super(banking_transaction_wizard, self).write( + cr, uid, ids, vals, context=context) + if manual_payment_order_id or manual_payment_line_id: + transaction_id = self.read( + cr, uid, ids[0], + ['import_transaction_id'], + context=context)['import_transaction_id'][0] + write_vals = {} + if manual_payment_order_id: + write_vals.update( + {'payment_order_id': manual_payment_order_id, + 'match_type': 'payment_order_manual'}) + else: + write_vals.update( + {'payment_line_id': manual_payment_line_id, + 'match_type': 'payment_manual'}) + self.pool.get('banking.import.transaction').clear_and_write( + cr, uid, transaction_id, write_vals, context=context) + return res + _columns = { 'payment_line_id': fields.related( 'import_transaction_id', 'payment_line_id', @@ -42,4 +71,13 @@ class banking_transaction_wizard(orm.TransientModel): 'import_transaction_id', 'payment_order_id', string="Payment order to reconcile", type='many2one', relation='payment.order'), + 'manual_payment_order_id': fields.many2one( + 'payment.order', 'Match this payment order', + domain=[('state', '=', 'sent')]), + 'manual_payment_line_id': fields.many2one( + 'payment.line', 'Match this payment line', + domain=[ + ('order_id.state', '=', 'sent'), + ('date_done', '=', False), + ]), } diff --git a/account_banking_payment/view/banking_transaction_wizard.xml b/account_banking_payment/view/banking_transaction_wizard.xml index fa9118107..708158c95 100644 --- a/account_banking_payment/view/banking_transaction_wizard.xml +++ b/account_banking_payment/view/banking_transaction_wizard.xml @@ -13,20 +13,23 @@ + attrs="{'invisible': [('match_type', 'not in', + ('storno', 'payment', 'payment_manual'))]}" + /> + + + + diff --git a/account_banking_payment/workflow/account_payment.xml b/account_banking_payment/workflow/account_payment.xml index fb16f0e5a..3db2f9fb6 100644 --- a/account_banking_payment/workflow/account_payment.xml +++ b/account_banking_payment/workflow/account_payment.xml @@ -8,6 +8,13 @@ action_sent() function + + + sent_wait + + write({'state': 'sent'}) + function + rejected @@ -16,33 +23,35 @@ write({'state':'rejected'}) function - - - - - done - - - - - - rejected - - + sent - + + + + + + + + + + done + + + + + + rejected + @@ -51,7 +60,7 @@ write({'state':'rejected'}) - + test_undo_done() undo_done From 4656a4de4b36b61d346eff031949f0761fec035a Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Thu, 30 May 2013 12:03:41 +0200 Subject: [PATCH 19/26] [FIX] Don't overwrite match_type field's selection again --- account_banking_payment/model/__init__.py | 1 - .../model/account_bank_statement_line.py | 40 ------------------- .../model/banking_import_transaction.py | 1 + 3 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 account_banking_payment/model/account_bank_statement_line.py diff --git a/account_banking_payment/model/__init__.py b/account_banking_payment/model/__init__.py index 02640f10d..9908c8e01 100644 --- a/account_banking_payment/model/__init__.py +++ b/account_banking_payment/model/__init__.py @@ -4,7 +4,6 @@ import payment_mode import payment_mode_type import payment_order_create import banking_import_transaction -import account_bank_statement_line import banking_transaction_wizard import bank_payment_manual import banking_import_line diff --git a/account_banking_payment/model/account_bank_statement_line.py b/account_banking_payment/model/account_bank_statement_line.py deleted file mode 100644 index 4cf2ead46..000000000 --- a/account_banking_payment/model/account_bank_statement_line.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2009 EduSense BV (). -# (C) 2011 - 2013 Therp BV (). -# -# All other contributions are (C) by their respective contributors -# -# All Rights Reserved -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import orm, fields - - -class account_bank_statement_line(orm.Model): - _inherit = 'account.bank.statement.line' - _columns = { - 'match_type': fields.related( - # Add payment and storno types - 'import_transaction_id', 'match_type', type='selection', - selection=[('manual', 'Manual'), ('move','Move'), - ('invoice', 'Invoice'), ('payment', 'Payment'), - ('payment_order', 'Payment order'), - ('storno', 'Storno')], - string='Match type', readonly=True,), - } diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index 91b489ed2..4d5a225be 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -324,6 +324,7 @@ class banking_import_transaction(orm.Model): return self.write( cr, uid, ids, { 'payment_line_id': False, + 'payment_order_id': False, 'payment_order_ids': [(6, 0, [])], }, context=context) From b15cf15cd53dcf5242c3a5a823169871e93f2b01 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 4 Jun 2013 13:56:05 +0200 Subject: [PATCH 20/26] [FIX] Various fixes [IMP] Improvements on payment matching --- .../wizard/banking_transaction_wizard.py | 38 +++++++++---------- .../model/account_payment.py | 5 +++ .../model/banking_import_transaction.py | 20 ++++++---- .../model/banking_transaction_wizard.py | 32 +++++++++++++--- 4 files changed, 63 insertions(+), 32 deletions(-) diff --git a/account_banking/wizard/banking_transaction_wizard.py b/account_banking/wizard/banking_transaction_wizard.py index bdd5ed471..e070ffb2b 100644 --- a/account_banking/wizard/banking_transaction_wizard.py +++ b/account_banking/wizard/banking_transaction_wizard.py @@ -90,9 +90,11 @@ class banking_transaction_wizard(orm.TransientModel): statement_line_obj = self.pool.get('account.bank.statement.line') transaction_obj = self.pool.get('banking.import.transaction') - if not vals: + if not vals or not ids: return True + wiz = self.browse(cr, uid, ids[0], context=context) + # The following fields get never written # they are just triggers for manual matching # which populates regular fields on the transaction @@ -103,19 +105,20 @@ class banking_transaction_wizard(orm.TransientModel): res = super(banking_transaction_wizard, self).write( cr, uid, ids, vals, context=context) + wiz.refresh() # Process the logic of the written values # An invoice is selected from multiple candidates if vals and 'invoice_id' in vals: - for wiz in self.browse(cr, uid, ids, context=context): - if (wiz.import_transaction_id.match_type == 'invoice' and + if (wiz.import_transaction_id.match_type == 'invoice' and wiz.import_transaction_id.invoice_id): - # the current value might apply - if (wiz.move_line_id and wiz.move_line_id.invoice and - wiz.move_line_id.invoice.id == wiz.invoice_id.id): - found = True - continue + found = False + # the current value might apply + if (wiz.move_line_id and wiz.move_line_id.invoice and + wiz.move_line_id.invoice == wiz.invoice_id): + found = True + else: # Otherwise, retrieve the move line for this invoice # Given the arity of the relation, there is are always # multiple possibilities but the move lines here are @@ -123,8 +126,8 @@ class banking_transaction_wizard(orm.TransientModel): # and the regular invoice workflow should only come up with # one of those only. for move_line in wiz.import_transaction_id.move_line_ids: - if (move_line.invoice.id == - wiz.import_transaction_id.invoice_id.id): + if (move_line.invoice == + wiz.import_transaction_id.invoice_id): transaction_obj.write( cr, uid, wiz.import_transaction_id.id, { 'move_line_id': move_line.id, }, context=context) @@ -135,15 +138,12 @@ class banking_transaction_wizard(orm.TransientModel): }, context=context) found = True break - # Cannot match the invoice - if not found: - # transaction_obj.write( - # cr, uid, wiz.import_transaction_id.id, - # { 'invoice_id': False, }, context=context) - orm.except_orm( - _("No entry found for the selected invoice"), - _("No entry found for the selected invoice. " + - "Try manual reconciliation.")) + # Cannot match the invoice + if not found: + orm.except_orm( + _("No entry found for the selected invoice"), + _("No entry found for the selected invoice. " + + "Try manual reconciliation.")) if manual_move_line_id or manual_invoice_id \ or manual_move_line_ids or manual_invoice_ids: diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index 10d114c4d..b6836c931 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -204,6 +204,11 @@ class payment_order(orm.Model): order = self.browse(cr, uid, payment_order_id, context) line_ids = [] reconcile_id = False + if not order.line_ids[0].transit_move_line_id: + wf_service = netsvc.LocalService('workflow') + wf_service.trg_validate( + uid, 'payment.order', payment_order_id, 'done', cr) + return False for order_line in order.line_ids: for line in order_line.transit_move_line_id.move_id.line_id: if line.account_id.type == 'other' and not line.reconcile_id: diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index 1282442e5..10a615018 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -27,6 +27,7 @@ from openerp.osv import orm, fields from openerp import netsvc from openerp.tools.translate import _ from openerp.addons.decimal_precision import decimal_precision as dp +from openerp.addons.account_banking.parsers.models import mem_bank_transaction as bt class banking_import_transaction(orm.Model): @@ -55,15 +56,15 @@ class banking_import_transaction(orm.Model): limit=0, context=context) orders = payment_order_obj.browse(cr, uid, order_ids, context) candidates = [x for x in orders if - equals_order_amount(x.total - trans.transferred_amount) and - x.line_ids and x.line_ids[0].transit_move_line_id] + equals_order_amount(x, trans.transferred_amount)] if len(candidates) > 0: # retrieve the common account_id, if any account_id = False - for line in candidates[0].line_ids[0].transit_move_line_id.move_id.line_id: - if line.account_id.type == 'other': - account_id = line.account_id.id - break + if (candidates[0].line_ids[0].transit_move_line_id): + for line in candidates[0].line_ids[0].transit_move_line_id.move_id.line_id: + if line.account_id.type == 'other': + account_id = line.account_id.id + break return dict( move_line_ids = False, match_type = 'payment_order', @@ -234,6 +235,11 @@ class banking_import_transaction(orm.Model): raise orm.except_orm( _("Cannot unreconcile"), _("Cannot unreconcile: no payment or direct debit order")) + if not transaction.statement_line_id.reconcile_id: + raise orm.except_orm( + _("Cannot unreconcile"), + _("Payment orders without transfer move lines cannot be " + "unreconciled this way")) return payment_order_obj.debit_unreconcile_transfer( cr, uid, transaction.payment_order_id.id, transaction.statement_line_id.reconcile_id.id, @@ -343,7 +349,7 @@ class banking_import_transaction(orm.Model): ) return vals - def hook_match_payment(cr, uid, transaction, log, context=None): + def hook_match_payment(self, cr, uid, transaction, log, context=None): """ Called from match() in the core module. Match payment batches, direct debit orders and stornos diff --git a/account_banking_payment/model/banking_transaction_wizard.py b/account_banking_payment/model/banking_transaction_wizard.py index 111e371fe..31b6a4842 100644 --- a/account_banking_payment/model/banking_transaction_wizard.py +++ b/account_banking_payment/model/banking_transaction_wizard.py @@ -24,6 +24,7 @@ ############################################################################## from openerp.osv import orm, fields +from openerp.tools.translate import _ class banking_transaction_wizard(orm.TransientModel): @@ -33,19 +34,38 @@ class banking_transaction_wizard(orm.TransientModel): """ Check for manual payment orders or lines """ - if not vals: + if not vals or not ids: return True manual_payment_order_id = vals.pop('manual_payment_order_id', False) manual_payment_line_id = vals.pop('manual_payment_line_id', False) res = super(banking_transaction_wizard, self).write( cr, uid, ids, vals, context=context) if manual_payment_order_id or manual_payment_line_id: - transaction_id = self.read( - cr, uid, ids[0], - ['import_transaction_id'], - context=context)['import_transaction_id'][0] + transaction_id = self.browse( + cr, uid, ids[0], + context=context).import_transaction_id write_vals = {} if manual_payment_order_id: + payment_order = self.pool.get('payment.order').browse( + cr, uid, manual_payment_order_id, + context=context) + if payment_order.payment_order_type == 'payment': + sign = 1 + else: + sign = -1 + total = (payment_order.total + sign * + transaction_id.transferred_amount) + if not self.pool.get('res.currency').is_zero( + cr, uid, transaction_id.statement_id.currency, total): + raise orm.except_orm( + _('Error'), + _('When matching a payment order, the amounts have to ' + 'match exactly')) + + if payment_order.mode and payment_order.mode.transfer_account_id: + transaction_id.statement_line_id.write({ + 'account_id': payment_order.mode.transfer_account_id.id, + }) write_vals.update( {'payment_order_id': manual_payment_order_id, 'match_type': 'payment_order_manual'}) @@ -54,7 +74,7 @@ class banking_transaction_wizard(orm.TransientModel): {'payment_line_id': manual_payment_line_id, 'match_type': 'payment_manual'}) self.pool.get('banking.import.transaction').clear_and_write( - cr, uid, transaction_id, write_vals, context=context) + cr, uid, transaction_id.id, write_vals, context=context) return res _columns = { From ad4784cbd44878d572625e9284b718f368993539 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 4 Jun 2013 15:44:24 +0200 Subject: [PATCH 21/26] [RFR] Do not reuse the transaction amount but always take the statement line amount. To be able to do so, create the transaction's statement line a little earlier. [FIX] Syntax error in assigning confirm_map items [RFR] Remove autosplit functionality that was already disabled [FIX] Logical order of the arguments in an error message --- account_banking/banking_import_transaction.py | 120 ++++++++---------- .../model/banking_import_transaction.py | 27 ++-- .../model/banking_transaction_wizard.py | 4 +- 3 files changed, 65 insertions(+), 86 deletions(-) diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index 082fa4e24..4023e2908 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -62,7 +62,7 @@ class banking_import_transaction(orm.Model): return [] digits = dp.get_precision('Account')(cr)[1] - amount = round(abs(trans.transferred_amount), digits) + amount = round(abs(trans.statement_line_id.amount), digits) # Make sure to be able to pinpoint our costs invoice for later # matching reference = '%s.%s: %s' % (trans.statement, trans.transaction, trans.reference) @@ -233,10 +233,6 @@ class banking_import_transaction(orm.Model): digits = dp.get_precision('Account')(cr)[1] partial = False - # Disabled splitting transactions for now - # TODO allow splitting in the interactive wizard - allow_splitting = False - # Search invoice on partner if partner_ids: candidates = [ @@ -276,7 +272,7 @@ class banking_import_transaction(orm.Model): candidates = [ x for x in move_lines if (is_zero(x.move_id, ((x.debit or 0.0) - (x.credit or 0.0)) - - trans.transferred_amount) + trans.statement_line_id.amount) and convert.str2date(x.date, '%Y-%m-%d') <= (convert.str2date(trans.execution_date, '%Y-%m-%d') + self.payment_window) @@ -292,7 +288,7 @@ class banking_import_transaction(orm.Model): # TODO: currency coercing best = [x for x in candidates if (is_zero(x.move_id, ((x.debit or 0.0) - (x.credit or 0.0)) - - trans.transferred_amount) + trans.statement_line_id.amount) and convert.str2date(x.date, '%Y-%m-%d') <= (convert.str2date(trans.execution_date, '%Y-%m-%d') + self.payment_window)) @@ -343,7 +339,7 @@ class banking_import_transaction(orm.Model): trans2 = None if move_line and partial: - found = round(trans.transferred_amount, digits) + found = round(trans.statement_line_id.amount, digits) if abs(expected) == abs(found): partial = False # Last partial payment will not flag invoice paid without @@ -358,24 +354,6 @@ class banking_import_transaction(orm.Model): elif abs(expected) > abs(found): # Partial payment, reuse invoice _cache(move_line, expected - found) - elif abs(expected) < abs(found) and allow_splitting: - # Possible combined payments, need to split transaction to - # verify - _cache(move_line) - trans2 = self.copy( - cr, uid, trans.id, - dict( - transferred_amount = trans.transferred_amount - expected, - transaction = trans.transaction + 'b', - parent_id = trans.id, - ), context=context) - # update the current record - self.write(cr, uid, trans.id, dict( - transferred_amount = expected, - transaction = trans.transaction + 'a', - ), context) - # rebrowse the current record after writing - trans = self.browse(cr, uid, trans.id, context=context) if move_line: account_ids = [ x.id for x in bank_account_ids @@ -712,7 +690,7 @@ class banking_import_transaction(orm.Model): # due to float representation and rounding difficulties for trans in self.browse(cr, uid, ids, context=context): if self.pool.get('res.currency').is_zero( - cr, uid, + cr, uid, trans.statement_id.currency, me['transferred_amount'] - trans.transferred_amount): dupes.append(trans.id) @@ -878,12 +856,6 @@ class banking_import_transaction(orm.Model): else: transaction = transactions[i] - if (transaction.statement_line_id and - transaction.statement_line_id.state == 'confirmed'): - raise orm.except_orm( - _("Cannot perform match"), - _("Cannot perform match on a confirmed transction")) - if transaction.local_account in error_accounts: results['trans_skipped_cnt'] += 1 if not injected: @@ -968,6 +940,44 @@ class banking_import_transaction(orm.Model): else: info[transaction.local_account][currency_code] = account_info + # Link accounting period + period_id = banktools.get_period( + self.pool, cr, uid, transaction.effective_date, + company, results['log']) + if not period_id: + results['trans_skipped_cnt'] += 1 + if not injected: + i += 1 + continue + + if transaction.statement_line_id: + if transaction.statement_line_id.state == 'confirmed': + raise orm.except_orm( + _("Cannot perform match"), + _("Cannot perform match on a confirmed transction")) + else: + values = { + 'name': '%s.%s' % (transaction.statement, transaction.transaction), + 'date': transaction.effective_date, + 'amount': transaction.transferred_amount, + 'statement_id': transaction.statement_id.id, + 'note': transaction.message, + 'ref': transaction.reference, + 'period_id': period_id, + 'currency': account_info.currency_id.id, + 'import_transaction_id': transaction.id, + 'account_id': ( + transaction.transferred_amount < 0 and + account_info.default_credit_account_id.id or + account_info.default_debit_account_id.id), + } + statement_line_id = statement_line_obj.create(cr, uid, values, context) + results['trans_loaded_cnt'] += 1 + transaction.write({'statement_line_id': statement_line_id}) + transaction.refresh() + if transaction.statement_id.id not in imported_statement_ids: + imported_statement_ids.append(transaction.statement_id.id) + # Final check: no coercion of currencies! if transaction.local_currency \ and account_info.currency_id.name != transaction.local_currency: @@ -977,8 +987,8 @@ class banking_import_transaction(orm.Model): ' uses different currency than the defined bank journal.' ) % { 'bank_account': transactions.local_account, - 'transaction_id': transaction.statement, - 'statement_id': transaction.transaction, + 'statement_id': transaction.statement, + 'transaction_id': transaction.transaction, } ) error_accounts[transaction.local_account] = True @@ -987,16 +997,6 @@ class banking_import_transaction(orm.Model): i += 1 continue - # Link accounting period - period_id = banktools.get_period( - self.pool, cr, uid, transaction.effective_date, - company, results['log']) - if not period_id: - results['trans_skipped_cnt'] += 1 - if not injected: - i += 1 - continue - # When bank costs are part of transaction itself, split it. if transaction.type != bt.BANK_COSTS and transaction.provision_costs: # Create new transaction for bank costs @@ -1080,7 +1080,7 @@ class banking_import_transaction(orm.Model): # Credit means payment... isn't it? if (not move_info - and transaction.transferred_amount < 0 and payment_lines): + and transaction.statement_line_id.amount < 0 and payment_lines): # Link open payment - if any # Note that _match_payment is defined in the # account_banking_payment module which should be installed @@ -1111,7 +1111,7 @@ class banking_import_transaction(orm.Model): # settings to overrule this. Note that you need to change # the internal type of these accounts to either 'payable' # or 'receivable' to enable usage like this. - if transaction.transferred_amount < 0: + if transaction.statement_line_id.amount < 0: if len(partner_banks) == 1: account_id = ( partner_banks[0].partner_id.property_account_payable and @@ -1127,7 +1127,7 @@ class banking_import_transaction(orm.Model): if len(partner_banks) != 1 or not account_id or account_id == def_rec_account_id: account_id = (account_info.default_debit_account_id and account_info.default_debit_account_id.id) - values = {} + values = {'account_id': account_id} self_values = {} if move_info: results['trans_matched_cnt'] += 1 @@ -1145,28 +1145,8 @@ class banking_import_transaction(orm.Model): len(partner_banks) == 1): values['partner_bank_id'] = partner_banks[0].id - if not transaction.statement_line_id: - values.update(dict( - name = '%s.%s' % (transaction.statement, transaction.transaction), - date = transaction.effective_date, - amount = transaction.transferred_amount, - statement_id = transaction.statement_id.id, - note = transaction.message, - ref = transaction.reference, - period_id = period_id, - currency = account_info.currency_id.id, - account_id = account_id, - import_transaction_id = transaction.id, - )) - - statement_line_id = statement_line_obj.create(cr, uid, values, context) - results['trans_loaded_cnt'] += 1 - self_values['statement_line_id'] = statement_line_id - if transaction.statement_id.id not in imported_statement_ids: - imported_statement_ids.append(transaction.statement_id.id) - else: - statement_line_obj.write( - cr, uid, transaction.statement_line_id.id, values, context) + statement_line_obj.write( + cr, uid, transaction.statement_line_id.id, values, context) self.write(cr, uid, transaction.id, self_values, context) if not injected: i += 1 diff --git a/account_banking_payment/model/banking_import_transaction.py b/account_banking_payment/model/banking_import_transaction.py index 10a615018..59fd5b6c9 100644 --- a/account_banking_payment/model/banking_import_transaction.py +++ b/account_banking_payment/model/banking_import_transaction.py @@ -44,7 +44,7 @@ class banking_import_transaction(orm.Model): sign = -1 total = payment_order.total + sign * transferred_amount return self.pool.get('res.currency').is_zero( - cr, uid, trans.statement_id.currency, total) + cr, uid, trans.statement_line_id.statement_id.currency, total) payment_order_obj = self.pool.get('payment.order') @@ -56,7 +56,7 @@ class banking_import_transaction(orm.Model): limit=0, context=context) orders = payment_order_obj.browse(cr, uid, order_ids, context) candidates = [x for x in orders if - equals_order_amount(x, trans.transferred_amount)] + equals_order_amount(x, trans.statement_line_id.amount)] if len(candidates) > 0: # retrieve the common account_id, if any account_id = False @@ -89,7 +89,7 @@ class banking_import_transaction(orm.Model): # stornos MUST have an exact match if len(line_ids) == 1: account_id = payment_line_obj.get_storno_account_id( - cr, uid, line_ids[0], trans.transferred_amount, + cr, uid, line_ids[0], trans.statement_line_id.amount, trans.statement_id.currency, context=None) if account_id: return dict( @@ -121,7 +121,7 @@ class banking_import_transaction(orm.Model): x for x in payment_lines if x.communication == trans.reference and round(x.amount, digits) == -round( - trans.transferred_amount, digits) + trans.statement_line_id.amount, digits) and trans.remote_account in (x.bank_id.acc_number, x.bank_id.acc_number_domestic) ] @@ -326,15 +326,14 @@ class banking_import_transaction(orm.Model): return res def clear_and_write(self, cr, uid, ids, vals=None, context=None): - super(banking_import_transaction, self).clear_and_write( + write_vals = { + 'payment_line_id': False, + 'payment_order_id': False, + 'payment_order_ids': [(6, 0, [])], + } + write_vals.update(vals or {}) + return super(banking_import_transaction, self).clear_and_write( cr, uid, ids, vals=vals, context=context) - return self.write( - cr, uid, ids, { - 'payment_line_id': False, - 'payment_order_id': False, - 'payment_order_ids': [(6, 0, [])], - }, - context=context) def move_info2values(self, move_info): vals = super(banking_import_transaction, self).move_info2values( @@ -376,7 +375,7 @@ class banking_import_transaction(orm.Model): """ super(banking_import_transaction, self).__init__(pool, cr) - banking_import_transaction.confirm_map.update({ + self.confirm_map.update({ 'storno': banking_import_transaction._confirm_storno, 'payment_order': banking_import_transaction._confirm_payment_order, 'payment': banking_import_transaction._confirm_payment, @@ -384,7 +383,7 @@ class banking_import_transaction(orm.Model): 'payment_manual': banking_import_transaction._confirm_payment, }) - banking_import_transaction.cancel_map.update({ + self.cancel_map.update({ 'storno': banking_import_transaction._cancel_storno, 'payment_order': banking_import_transaction._cancel_payment_order, 'payment': banking_import_transaction._cancel_payment, diff --git a/account_banking_payment/model/banking_transaction_wizard.py b/account_banking_payment/model/banking_transaction_wizard.py index 31b6a4842..a2f7a359b 100644 --- a/account_banking_payment/model/banking_transaction_wizard.py +++ b/account_banking_payment/model/banking_transaction_wizard.py @@ -54,9 +54,9 @@ class banking_transaction_wizard(orm.TransientModel): else: sign = -1 total = (payment_order.total + sign * - transaction_id.transferred_amount) + transaction_id.statement_line_id.amount) if not self.pool.get('res.currency').is_zero( - cr, uid, transaction_id.statement_id.currency, total): + cr, uid, transaction_id.statement_line_id.statement_id.currency, total): raise orm.except_orm( _('Error'), _('When matching a payment order, the amounts have to ' From dc77f219ec862c6921c4ceaee4ffc663d6c1afcb Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 4 Jun 2013 16:33:22 +0200 Subject: [PATCH 22/26] [FIX] Method reference --- account_banking/banking_import_transaction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking/banking_import_transaction.py b/account_banking/banking_import_transaction.py index 4023e2908..0af8b4974 100644 --- a/account_banking/banking_import_transaction.py +++ b/account_banking/banking_import_transaction.py @@ -1030,7 +1030,7 @@ class banking_import_transaction(orm.Model): transaction = self.browse(cr, uid, transaction.id, context=context) # Match payment and direct debit orders - move_info_payment = hook_match_payment( + move_info_payment = self.hook_match_payment( cr, uid, transaction, results['log'], context=context) if move_info_payment: move_info = move_info_payment From cf6c8e624eeb09c098362168d85c9bf5d2350f00 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 4 Jun 2013 16:48:54 +0200 Subject: [PATCH 23/26] [FIX] Only allow posted move lines in payment order --- account_banking_payment/model/payment_order_create.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_payment/model/payment_order_create.py b/account_banking_payment/model/payment_order_create.py index b39a6bf2e..24a2e1dd6 100644 --- a/account_banking_payment/model/payment_order_create.py +++ b/account_banking_payment/model/payment_order_create.py @@ -36,7 +36,6 @@ class payment_order_create(orm.TransientModel): self, cr, uid, payment_order, domain, context=None): if payment_order.payment_order_type == 'payment': domain += [ - ('reconcile_id', '=', False), ('account_id.type', '=', 'payable'), ('amount_to_pay', '>', 0) ] @@ -59,6 +58,7 @@ class payment_order_create(orm.TransientModel): cr, uid, context['active_id'], context=context) # Search for move line to pay: domain = [ + ('move_id.state', '=', 'posted'), ('reconcile_id', '=', False), ('company_id', '=', payment.mode.company_id.id), ] From 2936dcc710959a7fd863f0c7e76f53487f5b40d6 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 25 Jun 2013 17:34:11 +0200 Subject: [PATCH 24/26] [MGR] HSBC module depends on split off payment part --- account_banking_uk_hsbc/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_uk_hsbc/__openerp__.py b/account_banking_uk_hsbc/__openerp__.py index 06ab216b7..77a9359b9 100644 --- a/account_banking_uk_hsbc/__openerp__.py +++ b/account_banking_uk_hsbc/__openerp__.py @@ -25,7 +25,7 @@ 'author': 'credativ Ltd', 'website': 'http://www.credativ.co.uk', 'category': 'Account Banking', - 'depends': ['account_banking'], + 'depends': ['account_banking_payment'], 'data': [ 'account_banking_uk_hsbc.xml', 'hsbc_clientid_view.xml', From 8482cf9f1133d67a1eef5b811725b988e21514a0 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 25 Jun 2013 17:40:51 +0200 Subject: [PATCH 25/26] [FIX] Add context to browse calls in account_banking.py --- account_banking/account_banking.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/account_banking/account_banking.py b/account_banking/account_banking.py index 5a279bd1b..14d9cc807 100644 --- a/account_banking/account_banking.py +++ b/account_banking/account_banking.py @@ -450,7 +450,7 @@ class account_voucher(orm.Model): context = {} if not context.get('period_id') and context.get('move_line_ids'): return self.pool.get('account.move.line').browse( - cr, uid , context.get('move_line_ids'))[0].period_id.id + cr, uid , context.get('move_line_ids'), context=context)[0].period_id.id return super(account_voucher, self)._get_period(cr, uid, context) account_voucher() @@ -721,11 +721,11 @@ class res_partner_bank(orm.Model): return records return records[0] - def check_iban(self, cr, uid, ids): + def check_iban(self, cr, uid, ids, context=None): ''' Check IBAN number ''' - for bank_acc in self.browse(cr, uid, ids): + for bank_acc in self.browse(cr, uid, ids, context=context): if bank_acc.state == 'iban' and bank_acc.acc_number: iban = sepa.IBAN(bank_acc.acc_number) if not iban.valid: @@ -785,7 +785,7 @@ class res_partner_bank(orm.Model): # which can be overridden by the user. # 1. Use provided country_id (manually filled) if country_id: - country = country_obj.browse(cr, uid, country_id) + country = country_obj.browse(cr, uid, country_id, context=context) country_ids = [country_id] # 2. Use country_id of found bank accounts # This can be usefull when there is no country set in the partners @@ -793,7 +793,7 @@ class res_partner_bank(orm.Model): # account itself before this method was triggered. elif ids and len(ids) == 1: partner_bank_obj = self.pool.get('res.partner.bank') - partner_bank_id = partner_bank_obj.browse(cr, uid, ids[0]) + partner_bank_id = partner_bank_obj.browse(cr, uid, ids[0], context=context) if partner_bank_id.country_id: country = partner_bank_id.country_id country_ids = [country.id] @@ -804,12 +804,12 @@ class res_partner_bank(orm.Model): # bank account, hence the additional check. elif partner_id: partner_obj = self.pool.get('res.partner') - country = partner_obj.browse(cr, uid, partner_id).country + country = partner_obj.browse(cr, uid, partner_id, context=context).country country_ids = country and [country.id] or [] # 4. Without any of the above, take the country from the company of # the handling user if not country_ids: - user = self.pool.get('res.users').browse(cr, uid, uid) + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) # Try user companies partner (user no longer has address in 6.1) if (user.company_id and user.company_id.partner_id and From 85de0d758157ac78e81ee8da6b89855571c23930 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 26 Jun 2013 23:10:06 +0200 Subject: [PATCH 26/26] [FIX] Improve translatable labels for move and move lines --- account_banking_payment/model/account_payment.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index b6836c931..30a283f33 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -279,6 +279,10 @@ class payment_order(orm.Model): account_move_obj = self.pool.get('account.move') account_move_line_obj = self.pool.get('account.move.line') payment_line_obj = self.pool.get('payment.line') + labels = { + 'payment': _('Payment order'), + 'debit': _('Direct debit order'), + } for order in self.browse(cr, uid, ids, context=context): for line in order.line_ids: # basic checks @@ -295,8 +299,8 @@ class payment_order(orm.Model): move_id = account_move_obj.create(cr, uid, { 'journal_id': order.mode.transfer_journal_id.id, - 'name': '%s order %s' % (order.payment_order_type, - line.move_line_id.move_id.name), + 'name': '%s %s' % (labels[order.payment_order_type], + line.move_line_id.move_id.name), 'reference': '%s%s' % (order.payment_order_type[:3].upper(), line.move_line_id.move_id.name), }, context=context) @@ -305,8 +309,8 @@ class payment_order(orm.Model): # create the debit move line on the transfer account vals = { - 'name': '%s order for %s' % ( - order.payment_order_type, + '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),