Add bank.payment.lines object to allow grouping in the payments

This commit is contained in:
Alexis de Lattre
2015-09-21 12:32:45 +02:00
committed by Pedro M. Baeza
parent fae53c0450
commit edcf09147e
24 changed files with 649 additions and 174 deletions

View File

@@ -32,13 +32,14 @@
'website': 'https://github.com/OCA/bank-payment',
'category': 'Banking addons',
'depends': [
'account_payment',
'account_banking_payment_export',
],
'data': [
'views/account_banking_mandate_view.xml',
'views/account_invoice_view.xml',
'views/account_payment_view.xml',
'views/res_partner_bank_view.xml',
'views/bank_payment_line_view.xml',
'data/mandate_reference_sequence.xml',
'data/report_paperformat.xml',
'security/mandate_security.xml',

View File

@@ -1,26 +1,27 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Mandate module for openERP
# Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
# @author: Cyril Sester <csester@compassion.ch>,
# Alexis de Lattre <alexis.delattre@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 . import account_banking_mandate
from . import account_invoice
from . import res_partner_bank
from . import payment_line
# -*- encoding: utf-8 -*-
##############################################################################
#
# Mandate module for openERP
# Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
# @author: Cyril Sester <csester@compassion.ch>,
# Alexis de Lattre <alexis.delattre@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 . import account_banking_mandate
from . import account_invoice
from . import res_partner_bank
from . import payment_line
from . import bank_payment_line

View File

@@ -0,0 +1,38 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Mandate module for Odoo
# Copyright (C) 2015 Akretion (http://www.akretion.com)
# @author: Alexis de Lattre <alexis.delattre@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 import models, fields, api
class BankPaymentLine(models.Model):
_inherit = 'bank.payment.line'
mandate_id = fields.Many2one(
comodel_name='account.banking.mandate', string='Direct Debit Mandate',
related='payment_line_ids.mandate_id')
@api.model
def same_fields_payment_line_and_bank_payment_line(self):
res = super(BankPaymentLine, self).\
same_fields_payment_line_and_bank_payment_line()
res.append('mandate_id')
return res

View File

@@ -1,74 +1,76 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Mandate module for openERP
# Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
# @author: Cyril Sester <csester@compassion.ch>,
# Alexis de Lattre <alexis.delattre@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 import models, fields, api, exceptions, _
class PaymentLine(models.Model):
_inherit = 'payment.line'
mandate_id = fields.Many2one(
comodel_name='account.banking.mandate', string='Direct Debit Mandate',
domain=[('state', '=', 'valid')])
@api.model
def create(self, vals=None):
"""If the customer invoice has a mandate, take it
otherwise, take the first valid mandate of the bank account
"""
if vals is None:
vals = {}
partner_bank_id = vals.get('bank_id')
move_line_id = vals.get('move_line_id')
if (self.env.context.get('search_payment_order_type') == 'debit' and
'mandate_id' not in vals):
if move_line_id:
line = self.env['account.move.line'].browse(move_line_id)
if (line.invoice and line.invoice.type == 'out_invoice' and
line.invoice.mandate_id):
vals.update({
'mandate_id': line.invoice.mandate_id.id,
'bank_id': line.invoice.mandate_id.partner_bank_id.id,
})
if partner_bank_id and 'mandate_id' not in vals:
mandates = self.env['account.banking.mandate'].search(
[('partner_bank_id', '=', partner_bank_id),
('state', '=', 'valid')])
if mandates:
vals['mandate_id'] = mandates[0].id
return super(PaymentLine, self).create(vals)
@api.one
@api.constrains('mandate_id', 'bank_id')
def _check_mandate_bank_link(self):
if (self.mandate_id and self.bank_id and
self.mandate_id.partner_bank_id.id !=
self.bank_id.id):
raise exceptions.Warning(
_("The payment line with reference '%s' has the bank account "
"'%s' which is not attached to the mandate '%s' (this "
"mandate is attached to the bank account '%s').") %
(self.name,
self.bank_id.name_get()[0][1],
self.mandate_id.unique_mandate_reference,
self.mandate_id.partner_bank_id.name_get()[0][1]))
# -*- encoding: utf-8 -*-
##############################################################################
#
# Mandate module for Odoo
# Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
# @author: Cyril Sester <csester@compassion.ch>,
# Alexis de Lattre <alexis.delattre@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 import models, fields, api, exceptions, _
class PaymentLine(models.Model):
_inherit = 'payment.line'
mandate_id = fields.Many2one(
comodel_name='account.banking.mandate', string='Direct Debit Mandate',
domain=[('state', '=', 'valid')])
@api.model
def create(self, vals=None):
"""If the customer invoice has a mandate, take it
otherwise, take the first valid mandate of the bank account
"""
if vals is None:
vals = {}
partner_bank_id = vals.get('bank_id')
move_line_id = vals.get('move_line_id')
if (self.env.context.get('search_payment_order_type') == 'debit' and
'mandate_id' not in vals):
if move_line_id:
line = self.env['account.move.line'].browse(move_line_id)
if (line.invoice and line.invoice.type == 'out_invoice' and
line.invoice.mandate_id):
vals.update({
'mandate_id': line.invoice.mandate_id.id,
'bank_id': line.invoice.mandate_id.partner_bank_id.id,
})
if partner_bank_id and 'mandate_id' not in vals:
mandates = self.env['account.banking.mandate'].search(
[('partner_bank_id', '=', partner_bank_id),
('state', '=', 'valid')])
if mandates:
vals['mandate_id'] = mandates[0].id
return super(PaymentLine, self).create(vals)
@api.one
@api.constrains('mandate_id', 'bank_id')
def _check_mandate_bank_link(self):
if (self.mandate_id and self.bank_id and
self.mandate_id.partner_bank_id.id !=
self.bank_id.id):
raise exceptions.Warning(
_("The payment line with reference '%s' has the bank account "
"'%s' which is not attached to the mandate '%s' (this "
"mandate is attached to the bank account '%s').") %
(self.name,
self.env['res.partner.bank'].name_get(
[self.bank_id.id])[0][1],
self.mandate_id.unique_mandate_reference,
self.env['res.partner.bank'].name_get(
[self.mandate_id.partner_bank_id.id])[0][1]))

View File

@@ -10,14 +10,18 @@
<record id="view_mandate_payment_order_form" model="ir.ui.view">
<field name="name">mandate.payment.order.form</field>
<field name="model">payment.order</field>
<field name="inherit_id" ref="account_payment.view_payment_order_form"/>
<field name="inherit_id" ref="account_banking_payment_export.view_payment_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='line_ids']/form/notebook/page/group/field[@name='bank_id']" position="after">
<field name="mandate_id" domain="[('partner_bank_id', '=', bank_id), ('state', '=', 'valid')]" invisible="context.get('search_payment_order_type')!='debit'" context="{'default_partner_bank_id': bank_id}"/>
<xpath expr="//field[@name='line_ids']/form//field[@name='bank_id']" position="after">
<field name="mandate_id"
domain="[('partner_bank_id', '=', bank_id), ('state', '=', 'valid')]"
invisible="context.get('search_payment_order_type')!='debit'"
context="{'default_partner_bank_id': bank_id}"/>
<newline />
</xpath>
<xpath expr="//field[@name='line_ids']/tree/field[@name='bank_id']" position="after">
<field name="mandate_id" string="DD Mandate" invisible="context.get('search_payment_order_type')!='debit'"/>
<field name="mandate_id" string="Mandate"
invisible="context.get('search_payment_order_type')!='debit'"/>
</xpath>
</field>
</record>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Akretion (http://www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<record id="bank_payment_line_form" model="ir.ui.view">
<field name="name">banking.mandate.bank.payment.line.form</field>
<field name="model">bank.payment.line</field>
<field name="inherit_id" ref="account_banking_payment_export.bank_payment_line_form"/>
<field name="arch" type="xml">
<field name="bank_id" position="after">
<field name="mandate_id"
invisible="context.get('search_payment_order_type')!='debit'"/>
</field>
</field>
</record>
<record id="bank_payment_line_tree" model="ir.ui.view">
<field name="name">banking.mandate.bank.payment.line.tree</field>
<field name="model">bank.payment.line</field>
<field name="inherit_id" ref="account_banking_payment_export.bank_payment_line_tree"/>
<field name="arch" type="xml">
<field name="bank_id" position="after">
<field name="mandate_id" string="Mandate"
invisible="context.get('search_payment_order_type')!='debit'"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -37,6 +37,7 @@
},
'data': [
'views/payment_line_view.xml',
'views/bank_payment_line_view.xml',
'views/payment_mode_view.xml',
'views/res_company_view.xml',
],

View File

@@ -21,6 +21,7 @@
##############################################################################
from . import payment_line
from . import bank_payment_line
from . import payment_mode
from . import res_company
from . import banking_export_pain

View File

@@ -0,0 +1,40 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# PAIN Base module for Odoo
# Copyright (C) 2013-2015 Akretion (http://www.akretion.com)
# @author: Alexis de Lattre <alexis.delattre@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 import models, fields, api
class BankPaymentLine(models.Model):
_inherit = 'bank.payment.line'
priority = fields.Selection(
related='payment_line_ids.priority', string='Priority')
struct_communication_type = fields.Selection(
related='payment_line_ids.struct_communication_type',
string='Structured Communication Type')
@api.model
def same_fields_payment_line_and_bank_payment_line(self):
res = super(BankPaymentLine, self).\
same_fields_payment_line_and_bank_payment_line()
res += ['priority', 'struct_communication_type']
return res

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Akretion (http://www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<record id="bank_payment_line_form" model="ir.ui.view">
<field name="name">pain.base.bank.payment.line.form</field>
<field name="model">bank.payment.line</field>
<field name="inherit_id" ref="account_banking_payment_export.bank_payment_line_form"/>
<field name="arch" type="xml">
<field name="bank_id" position="after">
<field name="priority"/>
</field>
<field name="state" position="after">
<field name="struct_communication_type" attrs="{'invisible': [('state', '!=', 'structured')]}"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -7,25 +7,10 @@
<openerp>
<data>
<record id="view_payment_line_form" model="ir.ui.view">
<field name="name">pain.base.payment.line.form</field>
<field name="model">payment.line</field>
<field name="inherit_id" ref="account_payment.view_payment_line_form"/>
<field name="arch" type="xml">
<field name="bank_id" position="after">
<field name="priority"/>
<newline />
</field>
<field name="state" position="after">
<field name="struct_communication_type" attrs="{'invisible': [('state', '!=', 'structured')], 'required': [('state', '=', 'structured')]}"/>
</field>
</field>
</record>
<record id="view_payment_order_form" model="ir.ui.view">
<field name="name">pain.base.payment.line.inside.order.form</field>
<field name="model">payment.order</field>
<field name="inherit_id" ref="account_payment.view_payment_order_form"/>
<field name="inherit_id" ref="account_banking_payment_export.view_payment_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='line_ids']/form//field[@name='bank_id']" position="after">
<field name="priority"/>

View File

@@ -41,9 +41,11 @@
'views/account_payment.xml',
'views/payment_mode.xml',
'views/payment_mode_type.xml',
'views/bank_payment_line.xml',
'wizard/bank_payment_manual.xml',
'wizard/payment_order_create_view.xml',
'data/payment_mode_type.xml',
'data/bank_payment_line_seq.xml',
'workflow/account_payment.xml',
'security/ir.model.access.csv',
],

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<record id="bank_payment_line_seq_type" model="ir.sequence.type">
<field name="name">Bank Payment Line</field>
<field name="code">bank.payment.line</field>
</record>
<record id="bank_payment_line_seq" model="ir.sequence">
<field name="name">Bank Payment Line</field>
<field name="code">bank.payment.line</field>
<field name="prefix">L</field>
<field name="padding">5</field>
<field name="number_next">1</field>
<field name="company_id" eval="False"/>
</record>
</data>
</openerp>

View File

@@ -6,3 +6,5 @@ from . import payment_mode_type
from . import payment_mode
from . import account_move_line
from . import account_invoice
from . import bank_payment_line
from . import payment_line

View File

@@ -43,6 +43,9 @@ class PaymentOrder(models.Model):
readonly=True, states={'draft': [('readonly', False)]})
mode_type = fields.Many2one('payment.mode.type', related='mode.type',
string='Payment Type')
bank_line_ids = fields.One2many(
'bank.payment.line', 'order_id', string="Bank Payment Lines",
readonly=True)
total = fields.Float(compute='_compute_total', store=True)
@api.depends('line_ids', 'line_ids.amount')
@@ -95,3 +98,56 @@ class PaymentOrder(models.Model):
'state': 'done',
})
return True
@api.multi
def action_cancel(self):
for order in self:
order.write({'state': 'cancel'})
order.bank_line_ids.unlink()
return True
@api.model
def _prepare_bank_payment_line(self, paylines):
return {
'order_id': paylines[0].order_id.id,
'payment_line_ids': [(6, 0, paylines.ids)],
'communication': '-'.join(
[line.communication for line in paylines]),
}
@api.multi
def action_open(self):
"""
Called when you click on the 'Confirm' button
Set the 'date' on payment line depending on the 'date_prefered'
setting of the payment.order
Re-generate the bank payment lines
"""
res = super(PaymentOrder, self).action_open()
bplo = self.env['bank.payment.line']
today = fields.Date.context_today(self)
for order in self:
# Delete existing bank payment lines
order.bank_line_ids.unlink()
# Create the bank payment lines from the payment lines
group_paylines = {} # id = hashcode, value = payment lines
for payline in order.line_ids:
# Compute requested payment date
if order.date_prefered == 'due':
requested_date = payline.ml_maturity_date or today
elif order.date_prefered == 'fixed':
requested_date = order.date_scheduled or today
else:
requested_date = today
# Write requested_date on 'date' field of payment line
payline.date = requested_date
hashcode = payline.payment_line_hashcode()
if hashcode in group_paylines:
group_paylines[hashcode] += payline
else:
group_paylines[hashcode] = payline
# Create bank payment lines
for paylines in group_paylines.values():
vals = self._prepare_bank_payment_line(paylines)
bplo.create(vals)
return res

View File

@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2015 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@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 import models, fields, api
import openerp.addons.decimal_precision as dp
class BankPaymentLine(models.Model):
_name = 'bank.payment.line'
_description = 'Bank Payment Lines'
name = fields.Char(string='Bank Payment Line Ref', required=True)
order_id = fields.Many2one(
'payment.order', string='Order', ondelete='cascade', select=True)
payment_line_ids = fields.One2many(
'payment.line', 'bank_line_id', string='Payment Lines')
partner_id = fields.Many2one(
'res.partner', string='Partner', related='payment_line_ids.partner_id')
# Function Float fields are sometimes badly displayed in tree view,
# see bug report https://github.com/odoo/odoo/issues/8632
amount_currency = fields.Float(
string='Amount', digits=dp.get_precision('Account'),
compute='_compute_amount')
# I would have prefered currency_id, but I need to keep the field names
# similar to the field names of payment.line
currency = fields.Many2one(
'res.currency', string='Currency', required=True,
related='payment_line_ids.currency')
bank_id = fields.Many2one(
'res.partner.bank', string='Bank Account',
related='payment_line_ids.bank_id')
date = fields.Date(
string='Payment Date', related='payment_line_ids.date')
state = fields.Selection(
related='payment_line_ids.state', string='Communication Type')
communication = fields.Char(string='Communication', required=True)
company_id = fields.Many2one(
'res.company', string='Company', readonly=True,
related='order_id.company_id', store=True)
@api.model
def same_fields_payment_line_and_bank_payment_line(self):
"""
This list of fields is used both to compute the grouping
hashcode and to copy the values from payment line
to bank payment line
The fields must have the same name on the 2 objects
"""
same_fields = [
'currency', 'partner_id',
'bank_id', 'date', 'state']
return same_fields
@api.one
@api.depends('payment_line_ids.amount_currency')
def _compute_amount(self):
amount = 0.0
for payline in self.payment_line_ids:
amount += payline.amount_currency
self.amount_currency = amount
@api.model
@api.returns('self')
def create(self, vals):
if vals.get('name', '/') == '/':
vals['name'] = self.env['ir.sequence'].next_by_code(
'bank.payment.line')
return super(BankPaymentLine, self).create(vals)

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2015 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@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 import models, fields, api
class PaymentLine(models.Model):
_inherit = 'payment.line'
bank_line_id = fields.Many2one(
'bank.payment.line', string='Bank Payment Line')
@api.multi
def payment_line_hashcode(self):
self.ensure_one()
bplo = self.env['bank.payment.line']
values = []
for field in bplo.same_fields_payment_line_and_bank_payment_line():
values.append(unicode(self[field]))
hashcode = '-'.join(values)
return hashcode

View File

@@ -1,2 +1,3 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_payment_mode_type","payment.mode.type","model_payment_mode_type","account_payment.group_account_payment",1,1,1,1
"access_bank_payment_line","Full access on bank.payment.line to Payment Manager","model_bank_payment_line","account_payment.group_account_payment",1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_payment_mode_type payment.mode.type model_payment_mode_type account_payment.group_account_payment 1 1 1 1
3 access_bank_payment_line Full access on bank.payment.line to Payment Manager model_bank_payment_line account_payment.group_account_payment 1 1 1 1

View File

@@ -1,27 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- restore wizard functionality when making payments
-->
<data>
<record id="view_banking_payment_order_form_1" model="ir.ui.view">
<field name="name">account.payment.order.form.banking-1</field>
<field name="inherit_id" ref="account_payment.view_payment_order_form" />
<field name="model">payment.order</field>
<field name="arch" type="xml">
<xpath expr="//button[@string='Make Payments']"
position="attributes">
<attribute name="name">launch_wizard</attribute>
</xpath>
<field name="mode" position="after">
<field name="mode_type" invisible="1"/>
</field>
<xpath expr="//button[@string='Invoices']" position="attributes">
<attribute name="attrs">{
'invisible': [('state', '!=', 'draft')]}</attribute>
</xpath>
</field>
</record>
</data>
<!-- restore wizard functionality when making payments -->
<record id="view_payment_order_form" model="ir.ui.view">
<field name="name">account.payment.order.form.banking-1</field>
<field name="inherit_id" ref="account_payment.view_payment_order_form" />
<field name="model">payment.order</field>
<field name="arch" type="xml">
<xpath expr="//button[@string='Make Payments']" position="attributes">
<attribute name="name">launch_wizard</attribute>
</xpath>
<field name="mode" position="after">
<field name="mode_type" invisible="1"/>
</field>
<xpath expr="//button[@string='Invoices']" position="attributes">
<attribute name="attrs">{
'invisible': [('state', '!=', 'draft')]}</attribute>
</xpath>
<!-- sorry, I have no choice but to replace the line_ids field
in order to introduce a 'notebook' in this view -->
<field name="line_ids" position="replace">
<notebook>
<page string="Payment Lines" name="payment-lines">
<!-- copy/paste from the view that we inherit -->
<field name="line_ids" context="{'order_id': active_id or False}" >
<form string="Payment Line">
<notebook>
<page string="Payment">
<group col="4">
<field name="move_line_id" on_change="onchange_move_line(move_line_id,parent.mode,parent.date_prefered,parent.date_scheduled,currency,company_currency)" domain="[('reconcile_id','=', False), ('credit', '>',0), ('account_id.reconcile', '=', True),('amount_to_pay','>', 0)] "/>
<separator colspan="4" string="Transaction Information"/>
<field name="date"/>
<label for="amount_currency" string="Amount"/>
<div>
<field name="amount_currency" on_change="onchange_amount(amount_currency,currency,company_currency)" class="oe_inline"/>
<field name="currency" nolabel="1" class="oe_inline"/>
</div>
<field name="partner_id" on_change="onchange_partner(partner_id,parent.mode)"/>
<field domain="[('partner_id','=',partner_id)]" name="bank_id"/>
<separator colspan="2" string="Owner Account"/>
<separator colspan="2" string="Partner Bank Account"/>
<field colspan="2" name="info_owner" nolabel="1"/>
<field colspan="2" name="info_partner" nolabel="1"/>
<field colspan="4" name="communication"/>
<field colspan="4" name="communication2"/>
<field name="name"/>
<field name="state"/>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
</group>
</page>
<page string="Information">
<group col="4" string="General Information">
<label for="amount" groups="base.group_multi_currency"/>
<div groups="base.group_multi_currency">
<field name="amount" class="oe_inline"/>
<field name="company_currency" class="oe_inline"/>
</div>
<separator colspan="4" string="Entry Information"/>
<field name="create_date" readonly="1"/>
<field name="ml_maturity_date"/>
<field name="ml_inv_ref"/>
<field name="bank_line_id" readonly="1"/>
</group>
</page>
</notebook>
</form>
<tree string="Payment Line">
<field name="ml_inv_ref" />
<field name="partner_id"/>
<field name="communication"/>
<field name="bank_id" domain="[('partner_id', '=', partner_id)]"/>
<field name="ml_maturity_date"/>
<field name="date"/>
<field name="amount_currency" string="Amount"/>
<field name="currency"/>
<field name="name"/>
<field name="amount" sum="Total in Company Currency" invisible="1"/>
</tree>
</field>
<!-- end of the copy/paste -->
</page>
<page string="Bank Payment Lines" name="bank-payment-lines">
<field name="bank_line_ids" context="{'search_payment_order_type': context.get('search_payment_order_type')}"/>
</page>
</notebook>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!--
Copyright (C) 2015 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
The licence is in the file __openerp__.py
-->
<record id="bank_payment_line_form" model="ir.ui.view">
<field name="name">bank.payment.line.form</field>
<field name="model">bank.payment.line</field>
<field name="arch" type="xml">
<form string="Bank Payment Line">
<group name="main">
<field name="order_id"
invisible="not context.get('bank_payment_line_main_view')"/>
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"
invisible="not context.get('bank_payment_line_main_view')"/>
<field name="partner_id"/>
<field name="date"/>
<field name="amount_currency" widget="monetary"
options="{'currency_field': 'currency'}"/>
<field name="currency" invisible="1"/>
<field name="bank_id"/>
<field name="state"/>
<field name="communication"/>
</group>
<group string="Related Payment Lines" name="payment-lines">
<field name="payment_line_ids" nolabel="1"/>
</group>
</form>
</field>
</record>
<record id="bank_payment_line_tree" model="ir.ui.view">
<field name="name">bank.payment.line.tree</field>
<field name="model">bank.payment.line</field>
<field name="arch" type="xml">
<tree string="Bank Payment Lines">
<field name="order_id"
invisible="not context.get('bank_payment_line_main_view')"/>
<field name="partner_id"/>
<field name="communication"/>
<field name="bank_id"/>
<field name="date"/>
<field name="amount_currency" widget="monetary"
options="{'currency_field': 'currency'}"/>
<field name="currency"/>
<field name="name"/>
<field name="company_id" groups="base.group_multi_company"
invisible="not context.get('bank_payment_line_main_view')"/>
</tree>
</field>
</record>
<record id="bank_payment_line_action" model="ir.actions.act_window">
<field name="name">Bank Payment Lines</field>
<field name="res_model">bank.payment.line</field>
<field name="view_mode">tree,form</field>
<field name="context">{'bank_payment_line_main_view': True}</field>
</record>
</data>
</openerp>

View File

@@ -12,5 +12,9 @@
<field name="action">action_done()</field>
</record>
<record id="account_payment.act_cancel" model="workflow.activity">
<field name="action">action_cancel()</field>
</record>
</data>
</openerp>

View File

@@ -151,25 +151,19 @@ class BankingExportSepaWizard(models.TransientModel):
lines_per_group = {}
# key = (requested_date, priority)
# values = list of lines as object
today = fields.Date.context_today(self)
for payment_order in self.payment_order_ids:
total_amount = total_amount + payment_order.total
for line in payment_order.line_ids:
for line in payment_order.bank_line_ids:
priority = line.priority
if payment_order.date_prefered == 'due':
requested_date = line.ml_maturity_date or today
elif payment_order.date_prefered == 'fixed':
requested_date = payment_order.date_scheduled or today
else:
requested_date = today
key = (requested_date, priority)
# The field line.date is the requested payment date
# taking into account the 'date_prefered' setting
# cf account_banking_payment_export/models/account_payment.py
# in the inherit of action_open()
key = (line.date, priority)
if key in lines_per_group:
lines_per_group[key].append(line)
else:
lines_per_group[key] = [line]
# Write requested_date on 'Payment date' of the pay line
if requested_date != line.date:
line.date = requested_date
for (requested_date, priority), lines in lines_per_group.items():
# B. Payment info
payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 = \
@@ -220,9 +214,9 @@ class BankingExportSepaWizard(models.TransientModel):
amount_control_sum_2_5 += line.amount_currency
if not line.bank_id:
raise Warning(
_("Missing Bank Account on invoice '%s' (payment "
"order line reference '%s').")
% (line.ml_inv_ref.number, line.name))
_("Bank account is missing on the bank payment line "
"of partner '%s' (reference '%s').")
% (line.partner_id.name, line.name))
self.generate_party_block(
credit_transfer_transaction_info_2_27, 'Cdtr',
'C', 'line.partner_id.name', 'line.bank_id.acc_number',

View File

@@ -144,25 +144,22 @@ class BankingExportSddWizard(models.TransientModel):
# key = (requested_date, priority, sequence type)
# value = list of lines as objects
# Iterate on payment orders
today = fields.Date.context_today(self)
for payment_order in self.payment_order_ids:
total_amount = total_amount + payment_order.total
# Iterate each payment lines
for line in payment_order.line_ids:
for line in payment_order.bank_line_ids:
transactions_count_1_6 += 1
priority = line.priority
if payment_order.date_prefered == 'due':
requested_date = line.ml_maturity_date or today
elif payment_order.date_prefered == 'fixed':
requested_date = payment_order.date_scheduled or today
else:
requested_date = today
# The field line.date is the requested payment date
# taking into account the 'date_prefered' setting
# cf account_banking_payment_export/models/account_payment.py
# in the inherit of action_open()
if not line.mandate_id:
raise Warning(
_("Missing SEPA Direct Debit mandate on the payment "
"line with partner '%s' and Invoice ref '%s'.")
% (line.partner_id.name,
line.ml_inv_ref.number))
_("Missing SEPA Direct Debit mandate on the "
"bank payment line with partner '%s' "
"(reference '%s'.")
% (line.partner_id.name, line.name))
scheme = line.mandate_id.scheme
if line.mandate_id.state != 'valid':
raise Warning(
@@ -191,14 +188,11 @@ class BankingExportSddWizard(models.TransientModel):
line.mandate_id.recurrent_sequence_type
assert seq_type_label is not False
seq_type = seq_type_map[seq_type_label]
key = (requested_date, priority, seq_type, scheme)
key = (line.date, priority, seq_type, scheme)
if key in lines_per_group:
lines_per_group[key].append(line)
else:
lines_per_group[key] = [line]
# Write requested_exec_date on 'Payment date' of the pay line
if requested_date != line.date:
line.date = requested_date
for (requested_date, priority, sequence_type, scheme), lines in \
lines_per_group.items():

View File

@@ -129,3 +129,6 @@ class PaymentLine(models.Model):
'Storno', readonly=True,
help="If this is true, the debit order has been canceled by the bank "
"or by the customer")
# The original string is "Destination Bank Account"...
# but in direct debit this field is the *Source* Bank Account !
bank_id = fields.Many2one(string='Partner Bank Account')