From 82d857e32f6f87ae4fc2a7ff75aea4f3af9050d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 16 Feb 2014 14:55:30 +0100 Subject: [PATCH 01/10] [FIX] trivial bug fix --- account_banking_pain_base/banking_export_pain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py index 5a063c5ee..279dc5f5a 100644 --- a/account_banking_pain_base/banking_export_pain.py +++ b/account_banking_pain_base/banking_export_pain.py @@ -295,7 +295,7 @@ class banking_export_pain(orm.AbstractModel): party_agent_bic = etree.SubElement( party_agent_institution, gen_args.get('bic_xml_tag')) party_agent_bic.text = bic - except except_orm: + except orm.except_orm: if order == 'C': if iban[0:2] != gen_args['initiating_party_country_code']: raise orm.except_orm( From 80202a5c650d1a4d48fa8bbac6f70c21ec1e66a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 16 Feb 2014 14:56:24 +0100 Subject: [PATCH 02/10] [IMP] move SEPA direct debit menu entries to a menu that does not depend on the core account_banking --- account_banking_sepa_direct_debit/sdd_mandate_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_banking_sepa_direct_debit/sdd_mandate_view.xml b/account_banking_sepa_direct_debit/sdd_mandate_view.xml index d86f74f5b..409919dc5 100644 --- a/account_banking_sepa_direct_debit/sdd_mandate_view.xml +++ b/account_banking_sepa_direct_debit/sdd_mandate_view.xml @@ -97,7 +97,7 @@ From da5f663d2fe9edc4b6c87d20b1639339642d9a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 16 Feb 2014 14:59:11 +0100 Subject: [PATCH 03/10] [FIX] do not auto_install account_banking_payment_export --- account_banking_payment_export/__openerp__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py index 8640f5bb3..f745f9690 100644 --- a/account_banking_payment_export/__openerp__.py +++ b/account_banking_payment_export/__openerp__.py @@ -3,7 +3,7 @@ # # Copyright (C) 2009 EduSense BV (). # (C) 2011 - 2013 Therp BV (). -# +# # All other contributions are (C) by their respective contributors # # All Rights Reserved @@ -55,7 +55,7 @@ 'description': ''' Infrastructure to export payment orders. - This technical module provides the base infrastructure to export + This technical module provides the base infrastructure to export payment orders for electronic banking. It provides the following technical features: * a new payment.mode.type model @@ -64,6 +64,5 @@ * the "make payment" button launches a wizard depending on the payment.mode.type * a manual payment mode type is provided as an example, with a default "do nothing" wizard ''', - 'auto_install': True, 'installable': True, } From 9fc12b5ca84679ea9ecbe109fc39e280fdea672a Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sun, 16 Feb 2014 15:01:09 +0100 Subject: [PATCH 04/10] [IMP] Add demo data --- account_banking_payment_export/__openerp__.py | 1 + .../demo/banking_demo.xml | 43 +++++++++++++++++++ .../__openerp__.py | 1 + .../sepa_credit_transfer_demo.xml | 15 +++++++ .../__openerp__.py | 1 + .../data/payment_type_sdd.xml | 4 +- .../sepa_direct_debit_demo.xml | 27 ++++++++++++ 7 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 account_banking_payment_export/demo/banking_demo.xml create mode 100644 account_banking_sepa_credit_transfer/sepa_credit_transfer_demo.xml create mode 100644 account_banking_sepa_direct_debit/sepa_direct_debit_demo.xml diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py index f745f9690..eb81771e9 100644 --- a/account_banking_payment_export/__openerp__.py +++ b/account_banking_payment_export/__openerp__.py @@ -52,6 +52,7 @@ 'data/payment_mode_type.xml', 'security/ir.model.access.csv', ], + 'demo': ['demo/banking_demo.xml'], 'description': ''' Infrastructure to export payment orders. diff --git a/account_banking_payment_export/demo/banking_demo.xml b/account_banking_payment_export/demo/banking_demo.xml new file mode 100644 index 000000000..1b220f072 --- /dev/null +++ b/account_banking_payment_export/demo/banking_demo.xml @@ -0,0 +1,43 @@ + + + + + + + Fortuneo Banque + FTNOFRP1XXX + 26 avenue des Champs Elysées + 75008 + Paris + + + + + La Banque Postale + PSSTFRPPXXX + 115 rue de Sèvres + 75007 + Paris + + + + + FR76 4242 4242 4242 4242 4242 424 + iban + + + La Banque Postale + PSSTFRPPXXX + + + + FR66 1212 1212 1212 1212 1212 121 + iban + + + Fortuneo Banque + FTNOFRP1XXX + + + + diff --git a/account_banking_sepa_credit_transfer/__openerp__.py b/account_banking_sepa_credit_transfer/__openerp__.py index 762ede89e..9b0521aea 100644 --- a/account_banking_sepa_credit_transfer/__openerp__.py +++ b/account_banking_sepa_credit_transfer/__openerp__.py @@ -36,6 +36,7 @@ 'data/payment_type_sepa_sct.xml', 'security/ir.model.access.csv', ], + 'demo': ['sepa_credit_transfer_demo.xml'], 'description': ''' Module to export payment orders in SEPA XML file format. diff --git a/account_banking_sepa_credit_transfer/sepa_credit_transfer_demo.xml b/account_banking_sepa_credit_transfer/sepa_credit_transfer_demo.xml new file mode 100644 index 000000000..77abf1b34 --- /dev/null +++ b/account_banking_sepa_credit_transfer/sepa_credit_transfer_demo.xml @@ -0,0 +1,15 @@ + + + + + + + SEPA Credit Transfer La Banque Postale + + + + + + + + diff --git a/account_banking_sepa_direct_debit/__openerp__.py b/account_banking_sepa_direct_debit/__openerp__.py index 95ac05413..cd603fc03 100644 --- a/account_banking_sepa_direct_debit/__openerp__.py +++ b/account_banking_sepa_direct_debit/__openerp__.py @@ -44,6 +44,7 @@ 'data/mandate_reference_sequence.xml', 'security/ir.model.access.csv', ], + 'demo': ['sepa_direct_debit_demo.xml'], 'description': ''' Module to export direct debit payment orders in SEPA XML file format. diff --git a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml index fcc742531..a17b3b21c 100644 --- a/account_banking_sepa_direct_debit/data/payment_type_sdd.xml +++ b/account_banking_sepa_direct_debit/data/payment_type_sdd.xml @@ -1,9 +1,8 @@ - + - SEPA Direct Debit v02 (recommended) pain.008.001.02 @@ -32,6 +31,5 @@ - diff --git a/account_banking_sepa_direct_debit/sepa_direct_debit_demo.xml b/account_banking_sepa_direct_debit/sepa_direct_debit_demo.xml new file mode 100644 index 000000000..220261088 --- /dev/null +++ b/account_banking_sepa_direct_debit/sepa_direct_debit_demo.xml @@ -0,0 +1,27 @@ + + + + + + + SEPA Direct Debit La Banque Postale + + + + + + + + FR78ZZZ424242 + + + + + recurrent + first + 2014-02-01 + valid + + + + From 9ca27914c387856a9cbdc44959195d7b260e37cb Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sun, 16 Feb 2014 15:03:28 +0100 Subject: [PATCH 05/10] [FIX] ALlow payment of customer refunds --- .../model/payment_order_create.py | 2 +- .../model/__init__.py | 3 +- .../model/account_move_line.py | 98 +++++++++++++++++++ .../model/account_move_line.py | 2 +- 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 account_banking_payment_export/model/account_move_line.py diff --git a/account_banking_payment/model/payment_order_create.py b/account_banking_payment/model/payment_order_create.py index a3d1ed9b0..33c10ded1 100644 --- a/account_banking_payment/model/payment_order_create.py +++ b/account_banking_payment/model/payment_order_create.py @@ -34,7 +34,7 @@ class payment_order_create(orm.TransientModel): self, cr, uid, payment_order, domain, context=None): if payment_order.payment_order_type == 'payment': domain += [ - ('account_id.type', '=', 'payable'), + ('account_id.type', 'in', ('payable', 'receivable')), ('amount_to_pay', '>', 0) ] return True diff --git a/account_banking_payment_export/model/__init__.py b/account_banking_payment_export/model/__init__.py index 5c7e00141..ea50d43a4 100644 --- a/account_banking_payment_export/model/__init__.py +++ b/account_banking_payment_export/model/__init__.py @@ -1,5 +1,6 @@ +from . import account_move_line from . import account_payment from . import bank_payment_manual from . import payment_mode from . import payment_mode_type -from . import payment_order_create \ No newline at end of file +from . import payment_order_create diff --git a/account_banking_payment_export/model/account_move_line.py b/account_banking_payment_export/model/account_move_line.py new file mode 100644 index 000000000..67c8b849d --- /dev/null +++ b/account_banking_payment_export/model/account_move_line.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2004-2014 OpenERP S.A. (http://www.openerp.com/) +# (C) 2014 Akretion (http://www.akretion.com/) +# +# 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 operator import itemgetter + + +# All the code below aims at fixing one small issue in _to_pay_search() +# But _to_pay_search() is the search function of the field 'amount_to_pay' +# which is a field.function and these functions are not inheritable in OpenERP. +# So we have to inherit the field 'amount_to_pay' and duplicate the related +# functions +# If the patch that I proposed in this bug report +# https://bugs.launchpad.net/openobject-addons/+bug/1275478 +# is integrated in addons/account_payment, then we will be able to remove this +# file. -- Alexis de Lattre +class account_move_line(orm.Model): + _inherit = 'account.move.line' + + def amount_to_pay(self, cr, uid, ids, name, arg=None, context=None): + """ Return the amount still to pay regarding all the payemnt orders + (excepting cancelled orders)""" + if not ids: + return {} + cr.execute("""SELECT ml.id, + CASE WHEN ml.amount_currency < 0 + THEN - ml.amount_currency + ELSE ml.credit + END - + (SELECT coalesce(sum(amount_currency),0) + FROM payment_line pl + INNER JOIN payment_order po + ON (pl.order_id = po.id) + WHERE move_line_id = ml.id + AND po.state != 'cancel') AS amount + FROM account_move_line ml + WHERE id IN %s""", (tuple(ids),)) + r = dict(cr.fetchall()) + return r + + def _to_pay_search(self, cr, uid, obj, name, args, context=None): + if not args: + return [] + line_obj = self.pool.get('account.move.line') + query = line_obj._query_get(cr, uid, context={}) + where = ' and '.join(map(lambda x: '''(SELECT + CASE WHEN l.amount_currency < 0 + THEN - l.amount_currency + ELSE l.credit + END - coalesce(sum(pl.amount_currency), 0) + FROM payment_line pl + INNER JOIN payment_order po ON (pl.order_id = po.id) + WHERE move_line_id = l.id + AND po.state != 'cancel' + ) %(operator)s %%s ''' % {'operator': x[1]}, args)) + sql_args = tuple(map(itemgetter(2), args)) + + cr.execute(('''SELECT id + FROM account_move_line l + WHERE account_id IN (select id + FROM account_account + WHERE type in %s AND active) + AND reconcile_id IS null + AND credit > 0 + AND ''' + where + ' and ' + query), + (('payable', 'receivable'),)+sql_args ) + # The patch we have compared to the original function in + # addons/account_payment is just above : + # original code : type = 'payable' + # fixed code : type in ('payable', 'receivable') + + res = cr.fetchall() + if not res: + return [('id', '=', '0')] + return [('id', 'in', map(lambda x:x[0], res))] + + _columns = { + 'amount_to_pay': fields.function(amount_to_pay, + type='float', string='Amount to pay', fnct_search=_to_pay_search), + } diff --git a/account_direct_debit/model/account_move_line.py b/account_direct_debit/model/account_move_line.py index a90c2945a..d71f2f4e2 100644 --- a/account_direct_debit/model/account_move_line.py +++ b/account_direct_debit/model/account_move_line.py @@ -27,7 +27,7 @@ class account_move_line(orm.Model): _inherit = "account.move.line" def amount_to_receive(self, cr, uid, ids, name, arg={}, context=None): - """ + """ Return the amount still to receive regarding all the debit orders (excepting canceled orders). This is the reverse from amount_to_pay() in From e2be1a6e0d97d2ce20100cd6c6765c48d802befd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 16 Feb 2014 17:13:15 +0100 Subject: [PATCH 06/10] [IMP] refactoring in order to use direct debit independently of bank statement import In a nutshell, this commit - moves payment_order_type (payment|debit) to account_banking_payment_export - makes payment_order_type visible in account_direct_debit - make direct_debit depend on account_banking_payment_export --- account_banking_payment/__openerp__.py | 3 +- account_banking_payment/model/__init__.py | 1 - .../model/account_payment.py | 9 - account_banking_payment/model/payment_mode.py | 4 - .../model/payment_mode_type.py | 41 ---- .../model/payment_order_create.py | 176 +---------------- account_banking_payment/view/payment_mode.xml | 1 - account_banking_payment_export/__openerp__.py | 5 + .../model/account_payment.py | 14 +- .../model/payment_mode.py | 4 + .../model/payment_mode_type.py | 12 +- .../model/payment_order_create.py | 187 +++++++++++++++--- account_banking_tests/__openerp__.py | 1 - account_direct_debit/__openerp__.py | 4 +- .../model/account_move_line.py | 6 +- account_direct_debit/view/payment_mode.xml | 20 ++ .../view/payment_mode_type.xml | 3 + 17 files changed, 232 insertions(+), 259 deletions(-) delete mode 100644 account_banking_payment/model/payment_mode_type.py create mode 100644 account_direct_debit/view/payment_mode.xml rename {account_banking_payment => account_direct_debit}/view/payment_mode_type.xml (83%) diff --git a/account_banking_payment/__openerp__.py b/account_banking_payment/__openerp__.py index 033485126..7ff0465f0 100644 --- a/account_banking_payment/__openerp__.py +++ b/account_banking_payment/__openerp__.py @@ -38,12 +38,11 @@ 'view/account_payment.xml', 'view/banking_transaction_wizard.xml', 'view/payment_mode.xml', - 'view/payment_mode_type.xml', 'view/payment_order_create_view.xml', 'workflow/account_payment.xml', ], 'description': ''' - This addon adds payment infrastructure to the Banking Addons. + This addon adds payment reconciliation infrastructure to the Banking Addons. * Extends payments for digital banking: + Adapted workflow in payments to reflect banking operations diff --git a/account_banking_payment/model/__init__.py b/account_banking_payment/model/__init__.py index cf509d816..60600f542 100644 --- a/account_banking_payment/model/__init__.py +++ b/account_banking_payment/model/__init__.py @@ -1,6 +1,5 @@ import account_payment import payment_line -import payment_mode_type import payment_mode import payment_order_create import banking_import_transaction diff --git a/account_banking_payment/model/account_payment.py b/account_banking_payment/model/account_payment.py index bfe33fb2f..0f4763af3 100644 --- a/account_banking_payment/model/account_payment.py +++ b/account_banking_payment/model/account_payment.py @@ -104,18 +104,9 @@ class payment_order(orm.Model): "execution." ) ), - 'payment_order_type': fields.selection( - [('payment', 'Payment'),('debit', 'Direct debit')], - 'Payment order type', required=True, - readonly=True, states={'draft': [('readonly', False)]}, - ), 'date_sent': fields.date('Send date', readonly=True), } - _defaults = { - 'payment_order_type': 'payment', - } - def _write_payment_lines(self, cr, uid, ids, **kwargs): ''' ORM method for setting attributes of corresponding payment.line objects. diff --git a/account_banking_payment/model/payment_mode.py b/account_banking_payment/model/payment_mode.py index 31e1cb65b..7a3e1be98 100644 --- a/account_banking_payment/model/payment_mode.py +++ b/account_banking_payment/model/payment_mode.py @@ -49,8 +49,4 @@ class payment_mode(orm.Model): help=('Limit selected invoices to invoices with these payment ' 'terms') ), - 'payment_order_type': fields.related( - 'type', 'payment_order_type', readonly=True, type='selection', - selection=[('payment', 'Payment'), ('debit', 'Direct debit')], - string="Payment Order Type"), } diff --git a/account_banking_payment/model/payment_mode_type.py b/account_banking_payment/model/payment_mode_type.py deleted file mode 100644 index 572cce869..000000000 --- a/account_banking_payment/model/payment_mode_type.py +++ /dev/null @@ -1,41 +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 payment_mode_type(orm.Model): - _inherit = 'payment.mode.type' - - _columns = { - 'payment_order_type': fields.selection( - [('payment', 'Payment'),('debit', 'Direct debit')], - 'Payment order type', required=True, - ), - } - - _defaults = { - 'payment_order_type': 'payment', - } diff --git a/account_banking_payment/model/payment_order_create.py b/account_banking_payment/model/payment_order_create.py index 33c10ded1..b2b339374 100644 --- a/account_banking_payment/model/payment_order_create.py +++ b/account_banking_payment/model/payment_order_create.py @@ -3,6 +3,7 @@ # # Copyright (C) 2009 EduSense BV (). # (C) 2011 - 2013 Therp BV (). +# (C) 2014 ACSONE SA/NV (). # # All other contributions are (C) by their respective contributors # @@ -23,8 +24,7 @@ # ############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ +from openerp.osv import orm class payment_order_create(orm.TransientModel): @@ -32,173 +32,13 @@ class payment_order_create(orm.TransientModel): def extend_payment_order_domain( self, cr, uid, payment_order, domain, context=None): - if payment_order.payment_order_type == 'payment': - domain += [ - ('account_id.type', 'in', ('payable', 'receivable')), - ('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 = [ - ('move_id.state', '=', 'posted'), - ('reconcile_id', '=', False), - ('company_id', '=', payment.mode.company_id.id), - ] + super(self, payment_order_create).extend_payment_order_domain( + cr, uid, payment_order, domain, context=context) # apply payment term filter - if payment.mode.payment_term_ids: + if payment_order.mode.payment_term_ids: domain += [ - ('invoice.payment_term', 'in', - [term.id for term in payment.mode.payment_term_ids] + ('invoice.payment_term', 'in', + [term.id for term in payment_order.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 - model in account_payment. - - pass the payment mode to line2bank() - - allow invoices to create influence on the payment process: not only 'Free' - references are allowed, but others as well - - check date_to_pay is not in the past. - ''' - - order_obj = self.pool.get('payment.order') - line_obj = self.pool.get('account.move.line') - payment_obj = self.pool.get('payment.line') - if context is None: - context = {} - data = self.read(cr, uid, ids, [], context=context)[0] - line_ids = data['entries'] - if not line_ids: - return {'type': 'ir.actions.act_window_close'} - - 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) - line2bank = line_obj.line2bank( - cr, uid, line_ids, payment.mode.id, context) - _today = fields.date.context_today(self, cr, uid, context=context) - ### end account banking - - ## Finally populate the current payment with new lines: - for line in line_obj.browse(cr, uid, line_ids, context=context): - if payment.date_prefered == "now": - #no payment date => immediate payment - date_to_pay = False - elif payment.date_prefered == 'due': - ### account_banking - # date_to_pay = line.date_maturity - date_to_pay = ( - line.date_maturity - if line.date_maturity and line.date_maturity > _today - else False) - ### end account banking - elif payment.date_prefered == 'fixed': - ### account_banking - # date_to_pay = payment.date_scheduled - date_to_pay = ( - payment.date_scheduled - if payment.date_scheduled and payment.date_scheduled > _today - else False) - ### end account banking - - ### account_banking - state = communication2 = False - communication = line.ref or '/' - if line.invoice: - if line.invoice.type in ('in_invoice', 'in_refund'): - if line.invoice.reference_type == 'structured': - state = 'structured' - communication = line.invoice.reference - else: - state = 'normal' - communication2 = line.invoice.reference - else: - # Make sure that the communication includes the - # customer invoice number (in the case of debit order) - communication = line.invoice.number.replace('/', '') - state = 'structured' - if line.invoice.number != line.ref: - communication2 = line.ref - else: - state = 'normal' - communication2 = line.ref - - # support debit orders when enabled - if (payment.payment_order_type == 'debit' and - 'amount_to_receive' in line): - amount_currency = line.amount_to_receive - else: - amount_currency = line.amount_to_pay - ### end account_banking - - payment_obj.create(cr, uid, { - 'move_line_id': line.id, - 'amount_currency': amount_currency, - 'bank_id': line2bank.get(line.id), - 'order_id': payment.id, - 'partner_id': line.partner_id and line.partner_id.id or False, - ### account banking - # 'communication': line.ref or '/' - 'communication': communication, - 'communication2': communication2, - '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), - }, context=context) - return {'name': _('Payment Orders'), - 'context': context, - 'view_type': 'form', - 'view_mode': 'form,tree', - 'res_model': 'payment.order', - 'res_id': context['active_id'], - 'type': 'ir.actions.act_window', - } + return True diff --git a/account_banking_payment/view/payment_mode.xml b/account_banking_payment/view/payment_mode.xml index 95d250652..c46823c8d 100644 --- a/account_banking_payment/view/payment_mode.xml +++ b/account_banking_payment/view/payment_mode.xml @@ -11,7 +11,6 @@ - ). # (C) 2011 - 2013 Therp BV (). +# (C) 2013 - 2014 ACSONE SA (). # # All other contributions are (C) by their respective contributors # @@ -64,6 +65,10 @@ * a better implementation of payment_mode.suitable_bank_types() based on payment.mode.type * the "make payment" button launches a wizard depending on the payment.mode.type * a manual payment mode type is provided as an example, with a default "do nothing" wizard + * add a payment_order_type (payment|debit) as a basis of direct debit support + (this field becomes visible when account_direct_debit is installed) + * make the search function of the payment export wizard extensible + * fix lp:1275478: allow payment of customer refunds ''', 'installable': True, } diff --git a/account_banking_payment_export/model/account_payment.py b/account_banking_payment_export/model/account_payment.py index e5a14e8aa..045b3d867 100644 --- a/account_banking_payment_export/model/account_payment.py +++ b/account_banking_payment_export/model/account_payment.py @@ -23,7 +23,7 @@ # ############################################################################## -from openerp.osv import orm +from openerp.osv import orm, fields from openerp.tools.translate import _ from openerp import netsvc @@ -31,6 +31,18 @@ from openerp import netsvc class payment_order(orm.Model): _inherit = 'payment.order' + _columns = { + 'payment_order_type': fields.selection( + [('payment', 'Payment'), ('debit', 'Direct debit')], + 'Payment order type', required=True, + readonly=True, states={'draft': [('readonly', False)]}, + ), + } + + _defaults = { + 'payment_order_type': 'payment', + } + def launch_wizard(self, cr, uid, ids, context=None): """ Search for a wizard to launch according to the type. diff --git a/account_banking_payment_export/model/payment_mode.py b/account_banking_payment_export/model/payment_mode.py index 0d85d3aa3..798c8ed20 100644 --- a/account_banking_payment_export/model/payment_mode.py +++ b/account_banking_payment_export/model/payment_mode.py @@ -49,4 +49,8 @@ class payment_mode(orm.Model): required=True, help='Select the Payment Type for the Payment Mode.' ), + 'payment_order_type': fields.related( + 'type', 'payment_order_type', readonly=True, type='selection', + selection=[('payment', 'Payment'), ('debit', 'Direct debit')], + string="Payment Order Type"), } diff --git a/account_banking_payment_export/model/payment_mode_type.py b/account_banking_payment_export/model/payment_mode_type.py index dbc60d5ab..a50e56a85 100644 --- a/account_banking_payment_export/model/payment_mode_type.py +++ b/account_banking_payment_export/model/payment_mode_type.py @@ -41,7 +41,7 @@ class payment_mode_type(orm.Model): 'suitable_bank_types': fields.many2many( 'res.partner.bank.type', 'bank_type_payment_type_rel', - 'pay_type_id','bank_type_id', + 'pay_type_id', 'bank_type_id', 'Suitable bank types', required=True), 'ir_model_id': fields.many2one( 'ir.model', 'Payment wizard', @@ -49,8 +49,16 @@ class payment_mode_type(orm.Model): 'Leave empty for manual processing'), domain=[('osv_memory', '=', True)], ), + 'payment_order_type': fields.selection( + [('payment', 'Payment'), ('debit', 'Direct debit')], + 'Payment order type', required=True, + ), } - + + _defaults = { + 'payment_order_type': 'payment', + } + def _auto_init(self, cr, context=None): r = super(payment_mode_type, self)._auto_init(cr, context=context) # migrate xmlid from manual_bank_transfer to avoid dependency on account_banking diff --git a/account_banking_payment_export/model/payment_order_create.py b/account_banking_payment_export/model/payment_order_create.py index 278d4327a..8e32831bc 100644 --- a/account_banking_payment_export/model/payment_order_create.py +++ b/account_banking_payment_export/model/payment_order_create.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # -# Copyright (C) 2013 ACSONE SA/NV ();. +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). # # All other contributions are (C) by their respective contributors # @@ -22,37 +23,175 @@ # ############################################################################## -from openerp.osv import orm +from openerp.osv import orm, fields +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 += [ + ('account_id.type', 'in', ('payable', 'receivable')), + ('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 = [ + ('move_id.state', '=', 'posted'), + ('reconcile_id', '=', False), + ('company_id', '=', payment.mode.company_id.id), + ] + 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 adapts the core create_payment() - to pass the payment mode to line2bank() through the context, - so it is in turn propagated to suitable_bank_types(). - - This is necessary because the core does not propagate the payment mode to line2bank: t = None in - http://bazaar.launchpad.net/~openerp/openobject-addons/7.0/view/head:/account_payment/wizard/account_payment_order.py#L72 - - Hack idea courtesy Stefan Rijnhart. ''' - if context is None: - context = {} + This method is a slightly modified version of the existing method on this + model in account_payment. + - pass the payment mode to line2bank() + - allow invoices to create influence on the payment process: not only 'Free' + references are allowed, but others as well + - check date_to_pay is not in the past. + ''' + order_obj = self.pool.get('payment.order') - payment = order_obj.browse(cr, uid, context['active_id'], context=context) - context['_fix_payment_mode_id'] = payment.mode.id - return super(payment_order_create, self).create_payment(cr, uid, ids, context=context) - - -class account_move_line(orm.Model): - _inherit = 'account.move.line' - - def line2bank(self, cr, uid, ids, payment_mode_id=None, context=None): - '''Obtain payment_type from context, see create_payment above''' + line_obj = self.pool.get('account.move.line') + payment_obj = self.pool.get('payment.line') if context is None: context = {} - payment_mode_id = payment_mode_id or context.get('_fix_payment_mode_id') - return super(account_move_line, self).line2bank(cr, uid, ids, payment_mode_id, context=context) + data = self.read(cr, uid, ids, [], context=context)[0] + line_ids = data['entries'] + if not line_ids: + return {'type': 'ir.actions.act_window_close'} + 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) + line2bank = line_obj.line2bank( + cr, uid, line_ids, payment.mode.id, context) + _today = fields.date.context_today(self, cr, uid, context=context) + ### end account banking + + ## Finally populate the current payment with new lines: + for line in line_obj.browse(cr, uid, line_ids, context=context): + if payment.date_prefered == "now": + #no payment date => immediate payment + date_to_pay = False + elif payment.date_prefered == 'due': + ### account_banking + # date_to_pay = line.date_maturity + date_to_pay = ( + line.date_maturity + if line.date_maturity and line.date_maturity > _today + else False) + ### end account banking + elif payment.date_prefered == 'fixed': + ### account_banking + # date_to_pay = payment.date_scheduled + date_to_pay = ( + payment.date_scheduled + if payment.date_scheduled and payment.date_scheduled > _today + else False) + ### end account banking + + ### account_banking + state = communication2 = False + communication = line.ref or '/' + if line.invoice: + if line.invoice.type in ('in_invoice', 'in_refund'): + if line.invoice.reference_type == 'structured': + state = 'structured' + communication = line.invoice.reference + else: + state = 'normal' + communication2 = line.invoice.reference + else: + # Make sure that the communication includes the + # customer invoice number (in the case of debit order) + communication = line.invoice.number.replace('/', '') + state = 'structured' + if line.invoice.number != line.ref: + communication2 = line.ref + else: + state = 'normal' + communication2 = line.ref + + # support debit orders when enabled + if (payment.payment_order_type == 'debit' and + 'amount_to_receive' in line): + amount_currency = line.amount_to_receive + else: + amount_currency = line.amount_to_pay + ### end account_banking + + payment_obj.create(cr, uid, { + 'move_line_id': line.id, + 'amount_currency': amount_currency, + 'bank_id': line2bank.get(line.id), + 'order_id': payment.id, + 'partner_id': line.partner_id and line.partner_id.id or False, + ### account banking + # 'communication': line.ref or '/' + 'communication': communication, + 'communication2': communication2, + '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), + }, context=context) + return {'name': _('Payment Orders'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'payment.order', + 'res_id': context['active_id'], + 'type': 'ir.actions.act_window', + } diff --git a/account_banking_tests/__openerp__.py b/account_banking_tests/__openerp__.py index 59eff6ce9..04e3fdd70 100644 --- a/account_banking_tests/__openerp__.py +++ b/account_banking_tests/__openerp__.py @@ -37,6 +37,5 @@ dependencies installed, so that you can run the tests. If you only run the tests manually, you don't even have to install this module, only its dependencies. ''', - 'auto_install': False, 'installable': True, } diff --git a/account_direct_debit/__openerp__.py b/account_direct_debit/__openerp__.py index 5cc16dcac..12fa1d227 100644 --- a/account_direct_debit/__openerp__.py +++ b/account_direct_debit/__openerp__.py @@ -25,10 +25,12 @@ 'author': ['Therp BV', 'Smile'], 'website': 'https://launchpad.net/banking-addons', 'category': 'Banking addons', - 'depends': ['account_banking_payment'], + 'depends': ['account_banking_payment_export'], 'data': [ 'view/account_payment.xml', 'view/account_invoice.xml', + 'view/payment_mode.xml', + 'view/payment_mode_type.xml', 'workflow/account_invoice.xml', 'data/account_payment_term.xml', ], diff --git a/account_direct_debit/model/account_move_line.py b/account_direct_debit/model/account_move_line.py index d71f2f4e2..4cd7fab6c 100644 --- a/account_direct_debit/model/account_move_line.py +++ b/account_direct_debit/model/account_move_line.py @@ -87,7 +87,7 @@ class account_move_line(orm.Model): return [('id', '=', '0')] return [('id', 'in', map(lambda x:x[0], res))] - def line2bank(self, cr, uid, ids, payment_mode_id=None, context=None): + def line2bank(self, cr, uid, ids, payment_mode_id, context=None): '''I have to inherit this function for direct debits to fix the following issue : if the customer invoice has a value for 'partner_bank_id', then it will take this partner_bank_id @@ -98,8 +98,6 @@ class account_move_line(orm.Model): if context is None: context = {} pay_mode_obj = self.pool['payment.mode'] - payment_mode_id = ( - payment_mode_id or context.get('_fix_payment_mode_id')) if payment_mode_id: pay_mode = pay_mode_obj.browse( cr, uid, payment_mode_id, context=context) @@ -116,7 +114,7 @@ class account_move_line(orm.Model): break return line2bank return super(account_move_line, self).line2bank( - cr, uid, ids, payment_mode_id=payment_mode_id, context=context) + cr, uid, ids, payment_mode_id, context=context) _columns = { 'amount_to_receive': fields.function( diff --git a/account_direct_debit/view/payment_mode.xml b/account_direct_debit/view/payment_mode.xml new file mode 100644 index 000000000..043990df0 --- /dev/null +++ b/account_direct_debit/view/payment_mode.xml @@ -0,0 +1,20 @@ + + + + + + + payment.mode.form.inherit + payment.mode + + + + + + + + + + diff --git a/account_banking_payment/view/payment_mode_type.xml b/account_direct_debit/view/payment_mode_type.xml similarity index 83% rename from account_banking_payment/view/payment_mode_type.xml rename to account_direct_debit/view/payment_mode_type.xml index eb8ce821a..eb726750d 100644 --- a/account_banking_payment/view/payment_mode_type.xml +++ b/account_direct_debit/view/payment_mode_type.xml @@ -2,6 +2,9 @@ + view.payment.mode.type.form payment.mode.type From d2b7fd679d2c990102ba6f45f0e663b3cddae509 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 19 Feb 2014 11:32:17 +0100 Subject: [PATCH 07/10] Move view from account_banking_payment to account_banking_payment_export. --- account_banking_payment/__openerp__.py | 1 - account_banking_payment_export/__openerp__.py | 1 + .../view/payment_order_create_view.xml | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename {account_banking_payment => account_banking_payment_export}/view/payment_order_create_view.xml (100%) diff --git a/account_banking_payment/__openerp__.py b/account_banking_payment/__openerp__.py index 7ff0465f0..831e794ad 100644 --- a/account_banking_payment/__openerp__.py +++ b/account_banking_payment/__openerp__.py @@ -38,7 +38,6 @@ 'view/account_payment.xml', 'view/banking_transaction_wizard.xml', 'view/payment_mode.xml', - 'view/payment_order_create_view.xml', 'workflow/account_payment.xml', ], 'description': ''' diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py index bc7572306..4e970b96f 100644 --- a/account_banking_payment_export/__openerp__.py +++ b/account_banking_payment_export/__openerp__.py @@ -50,6 +50,7 @@ 'view/bank_payment_manual.xml', 'view/payment_mode.xml', 'view/payment_mode_type.xml', + 'view/payment_order_create_view.xml', 'data/payment_mode_type.xml', 'security/ir.model.access.csv', ], diff --git a/account_banking_payment/view/payment_order_create_view.xml b/account_banking_payment_export/view/payment_order_create_view.xml similarity index 100% rename from account_banking_payment/view/payment_order_create_view.xml rename to account_banking_payment_export/view/payment_order_create_view.xml From 46a4e2ea64b87f4a0bf723e7f91f792b3ad7730c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 21 Feb 2014 23:26:42 +0100 Subject: [PATCH 08/10] [IMP] improve account_banking_payment_export documentation to clarify its scope --- account_banking_payment_export/__openerp__.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py index bc7572306..1c4793975 100644 --- a/account_banking_payment_export/__openerp__.py +++ b/account_banking_payment_export/__openerp__.py @@ -55,7 +55,9 @@ ], 'demo': ['demo/banking_demo.xml'], 'description': ''' - Infrastructure to export payment orders. + Infrastructure to export payment orders + plus some bug fixes and obvious enhancements to payment orders + that will hopefully land in offical addons one day. This technical module provides the base infrastructure to export payment orders for electronic banking. It provides the following @@ -65,8 +67,14 @@ * a better implementation of payment_mode.suitable_bank_types() based on payment.mode.type * the "make payment" button launches a wizard depending on the payment.mode.type * a manual payment mode type is provided as an example, with a default "do nothing" wizard - * add a payment_order_type (payment|debit) as a basis of direct debit support - (this field becomes visible when account_direct_debit is installed) + + To enable the use of payment order to collect money for customers, + it adds a payment_order_type (payment|debit) as a basis of direct debit support + (this field becomes visible when account_direct_debit is installed). + Refactoring note: this field should ideally go in account_direct_debit, + but account_banking_payment currently depends on it. + + Bug fixes and enhancement that should land in official addons: * make the search function of the payment export wizard extensible * fix lp:1275478: allow payment of customer refunds ''', From 05086d91fa2863a1982165740a955226b8e89c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 21 Feb 2014 23:29:26 +0100 Subject: [PATCH 09/10] [FIX] typo in super() --- 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 b2b339374..7d071b44e 100644 --- a/account_banking_payment/model/payment_order_create.py +++ b/account_banking_payment/model/payment_order_create.py @@ -32,7 +32,7 @@ class payment_order_create(orm.TransientModel): def extend_payment_order_domain( self, cr, uid, payment_order, domain, context=None): - super(self, payment_order_create).extend_payment_order_domain( + super(payment_order_create, self).extend_payment_order_domain( cr, uid, payment_order, domain, context=context) # apply payment term filter if payment_order.mode.payment_term_ids: From f839a7f0ce8057760cdb982b9b91b3c478530b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 21 Feb 2014 23:35:18 +0100 Subject: [PATCH 10/10] [IMP] more account_banking_payment_export documentation --- account_banking_payment_export/__openerp__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py index bb95a4930..11835c973 100644 --- a/account_banking_payment_export/__openerp__.py +++ b/account_banking_payment_export/__openerp__.py @@ -78,6 +78,8 @@ Bug fixes and enhancement that should land in official addons: * make the search function of the payment export wizard extensible * fix lp:1275478: allow payment of customer refunds + * display the maturity date of the move lines when you are in + the wizard to select the lines to pay ''', 'installable': True, }