[RFR] Refactoring of direct debit to pull less dependencies.

Result of a sprint with Akexis de Lattre in a corridor at Fosdem 2014.

In a nutshell, this MP moves the hooks that are necessary for account_direct_debit from account_banking_payment to account_banking_payment_export, resulting in a leaner dependency graph [1].

account_banking_payment (and thus account_banking core) is therefore not necessary anymore for doing direct debit.
account_banking_payment can now be seen as providing two essential functions:
1/ adding the notion of transfer account on payment modes (marking the invoices paid as soon as the payment order is sent)
2/ bridging with the bank statement reconciliation features of account_banking core

IMO, the next step in the refactoring process would be to move 1/ to a stand-alone module.

Other things in this branch:
- removing auto_install=True that we found unnecessary and potentially risky
- demo data by Alexis
- a trivial bug fix
- setting noupdate=1 for the SEPA payment mode types
- allow payment of customer refunds lp:1275478
This commit is contained in:
unknown
2014-03-01 15:47:05 +01:00
committed by Stefan Rijnhart
28 changed files with 438 additions and 271 deletions

View File

@@ -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(

View File

@@ -38,12 +38,10 @@
'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

View File

@@ -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

View File

@@ -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.

View File

@@ -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"),
}

View File

@@ -1,41 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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',
}

View File

@@ -3,6 +3,7 @@
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
# (C) 2014 ACSONE SA/NV (<http://acsone.eu>).
#
# 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', '=', '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 = [
('move_id.state', '=', 'posted'),
('reconcile_id', '=', False),
('company_id', '=', payment.mode.company_id.id),
]
super(payment_order_create, self).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

View File

@@ -11,7 +11,6 @@
<field name="inherit_id" ref="account_banking_payment_export.view_payment_mode_form_inherit"/>
<field name="arch" type="xml">
<field name="type" position="after">
<field name="payment_order_type"/>
<group colspan="4" col="4">
<group colspan="2">
<separator colspan="2"

View File

@@ -3,7 +3,8 @@
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
#
# (C) 2013 - 2014 ACSONE SA (<http://acsone.eu>).
#
# All other contributions are (C) by their respective contributors
#
# All Rights Reserved
@@ -49,13 +50,17 @@
'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',
],
'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
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
@@ -63,7 +68,18 @@
* 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
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
* display the maturity date of the move lines when you are in
the wizard to select the lines to pay
''',
'auto_install': True,
'installable': True,
}

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="bank_fortuneo" model="res.bank">
<field name="name">Fortuneo Banque</field>
<field name="bic">FTNOFRP1XXX</field>
<field name="street">26 avenue des Champs Elysées</field>
<field name="zip">75008</field>
<field name="city">Paris</field>
<field name="country" ref="base.fr"/>
</record>
<record id="bank_la_banque_postale" model="res.bank">
<field name="name">La Banque Postale</field>
<field name="bic">PSSTFRPPXXX</field>
<field name="street">115 rue de Sèvres</field>
<field name="zip">75007</field>
<field name="city">Paris</field>
<field name="country" ref="base.fr"/>
</record>
<record id="main_company_iban" model="res.partner.bank">
<field name="acc_number">FR76 4242 4242 4242 4242 4242 424</field>
<field name="state">iban</field>
<field name="bank" ref="bank_la_banque_postale"/>
<field name="partner_id" ref="base.main_partner" />
<field name="bank_name">La Banque Postale</field>
<field name="bank_bic">PSSTFRPPXXX</field>
</record>
<record id="res_partner_12_iban" model="res.partner.bank">
<field name="acc_number">FR66 1212 1212 1212 1212 1212 121</field>
<field name="state">iban</field>
<field name="bank" ref="bank_fortuneo"/>
<field name="partner_id" ref="base.res_partner_12" />
<field name="bank_name">Fortuneo Banque</field>
<field name="bank_bic">FTNOFRP1XXX</field>
</record>
</data>
</openerp>

View File

@@ -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
from . import payment_order_create

View File

@@ -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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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),
}

View File

@@ -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.

View File

@@ -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"),
}

View File

@@ -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

View File

@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2013 ACSONE SA/NV (<http://acsone.eu>);.
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
#
# 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',
}

View File

@@ -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.

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="sepa_credit_transfer_mode" model="payment.mode">
<field name="name">SEPA Credit Transfer La Banque Postale</field>
<field name="journal" ref="account.bank_journal"/>
<field name="bank_id" ref="account_banking_payment_export.main_company_iban"/>
<field name="company_id" ref="base.main_company"/>
<field name="type" ref="export_sepa_sct_001_001_03"/>
</record>
</data>
</openerp>

View File

@@ -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.

View File

@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0"> <!-- TODO : put to 1 when dev of the module is finished -->
<data noupdate="1">
<!-- TODO In the suitable_bank_types field, we should add l10n_fr_rib via a small stupid module -->
<record id="export_sdd_008_001_02" model="payment.mode.type">
<field name="name">SEPA Direct Debit v02 (recommended)</field>
<field name="code">pain.008.001.02</field>
@@ -32,6 +31,5 @@
</record>
</data>
</openerp>

View File

@@ -97,7 +97,7 @@
</record>
<menuitem id="sdd_mandate_menu"
parent="account_banking.menu_finance_banking_settings"
parent="account_payment.menu_main_payment"
action="sdd_mandate_action"
sequence="20"
/>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="sepa_direct_debit_mode" model="payment.mode">
<field name="name">SEPA Direct Debit La Banque Postale</field>
<field name="journal" ref="account.bank_journal"/>
<field name="bank_id" ref="account_banking_payment_export.main_company_iban"/>
<field name="company_id" ref="base.main_company"/>
<field name="type" ref="export_sdd_008_001_02"/>
</record>
<record id="base.main_company" model="res.company">
<field name="sepa_creditor_identifier">FR78ZZZ424242</field>
</record>
<record id="res_partner_12_mandate" model="sdd.mandate">
<field name="partner_bank_id" ref="account_banking_payment_export.res_partner_12_iban"/>
<field name="type">recurrent</field>
<field name="recurrent_sequence_type">first</field>
<field name="signature_date">2014-02-01</field>
<field name="state">valid</field>
</record>
</data>
</openerp>

View File

@@ -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,
}

View File

@@ -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',
],

View File

@@ -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
@@ -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(

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--
Make the payment order type visible
-->
<record id="view_payment_mode_form_inherit" model="ir.ui.view">
<field name="name">payment.mode.form.inherit</field>
<field name="model">payment.mode</field>
<field name="inherit_id" ref="account_banking_payment_export.view_payment_mode_form_inherit"/>
<field name="arch" type="xml">
<field name="type" position="after">
<field name="payment_order_type"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -2,6 +2,9 @@
<openerp>
<data>
<!--
Make the payment order type visible so the use can choose payment or direct debit
-->
<record model="ir.ui.view" id="view_payment_mode_type_form_inherit">
<field name="name">view.payment.mode.type.form</field>
<field name="model">payment.mode.type</field>