From edcf09147ecc4eb26035287b55f118603c3ae94f Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Mon, 21 Sep 2015 12:32:45 +0200
Subject: [PATCH 01/28] Add bank.payment.lines object to allow grouping in the
payments
---
account_banking_mandate/__openerp__.py | 3 +-
account_banking_mandate/models/__init__.py | 53 ++++---
.../models/bank_payment_line.py | 38 +++++
.../models/payment_line.py | 150 +++++++++---------
.../views/account_payment_view.xml | 12 +-
.../views/bank_payment_line_view.xml | 36 +++++
account_banking_pain_base/__openerp__.py | 1 +
account_banking_pain_base/models/__init__.py | 1 +
.../models/bank_payment_line.py | 40 +++++
.../views/bank_payment_line_view.xml | 25 +++
.../views/payment_line_view.xml | 17 +-
account_banking_payment_export/__openerp__.py | 2 +
.../data/bank_payment_line_seq.xml | 26 +++
.../models/__init__.py | 2 +
.../models/account_payment.py | 56 +++++++
.../models/bank_payment_line.py | 86 ++++++++++
.../models/payment_line.py | 39 +++++
.../security/ir.model.access.csv | 1 +
.../views/account_payment.xml | 112 ++++++++++---
.../views/bank_payment_line.xml | 66 ++++++++
.../workflow/account_payment.xml | 4 +
.../wizard/export_sepa.py | 24 ++-
.../wizard/export_sdd.py | 26 ++-
account_direct_debit/models/payment_line.py | 3 +
24 files changed, 649 insertions(+), 174 deletions(-)
create mode 100644 account_banking_mandate/models/bank_payment_line.py
create mode 100644 account_banking_mandate/views/bank_payment_line_view.xml
create mode 100644 account_banking_pain_base/models/bank_payment_line.py
create mode 100644 account_banking_pain_base/views/bank_payment_line_view.xml
create mode 100644 account_banking_payment_export/data/bank_payment_line_seq.xml
create mode 100644 account_banking_payment_export/models/bank_payment_line.py
create mode 100644 account_banking_payment_export/models/payment_line.py
create mode 100644 account_banking_payment_export/views/bank_payment_line.xml
diff --git a/account_banking_mandate/__openerp__.py b/account_banking_mandate/__openerp__.py
index 0309a15d2..abee60c18 100644
--- a/account_banking_mandate/__openerp__.py
+++ b/account_banking_mandate/__openerp__.py
@@ -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',
diff --git a/account_banking_mandate/models/__init__.py b/account_banking_mandate/models/__init__.py
index 480270819..4b191f0d1 100644
--- a/account_banking_mandate/models/__init__.py
+++ b/account_banking_mandate/models/__init__.py
@@ -1,26 +1,27 @@
-# -*- encoding: utf-8 -*-
-##############################################################################
-#
-# Mandate module for openERP
-# Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
-# @author: Cyril Sester ,
-# Alexis de Lattre
-#
-# 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 . 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 ,
+# Alexis de Lattre
+#
+# 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 . import account_banking_mandate
+from . import account_invoice
+from . import res_partner_bank
+from . import payment_line
+from . import bank_payment_line
diff --git a/account_banking_mandate/models/bank_payment_line.py b/account_banking_mandate/models/bank_payment_line.py
new file mode 100644
index 000000000..cb268198c
--- /dev/null
+++ b/account_banking_mandate/models/bank_payment_line.py
@@ -0,0 +1,38 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# Mandate module for Odoo
+# Copyright (C) 2015 Akretion (http://www.akretion.com)
+# @author: Alexis de Lattre
+#
+# 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 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
diff --git a/account_banking_mandate/models/payment_line.py b/account_banking_mandate/models/payment_line.py
index a8815251d..fa044ea29 100644
--- a/account_banking_mandate/models/payment_line.py
+++ b/account_banking_mandate/models/payment_line.py
@@ -1,74 +1,76 @@
-# -*- encoding: utf-8 -*-
-##############################################################################
-#
-# Mandate module for openERP
-# Copyright (C) 2014 Compassion CH (http://www.compassion.ch)
-# @author: Cyril Sester ,
-# Alexis de Lattre
-#
-# 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 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 ,
+# Alexis de Lattre
+#
+# 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 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]))
diff --git a/account_banking_mandate/views/account_payment_view.xml b/account_banking_mandate/views/account_payment_view.xml
index 39ec86953..9d2ced2cf 100644
--- a/account_banking_mandate/views/account_payment_view.xml
+++ b/account_banking_mandate/views/account_payment_view.xml
@@ -10,14 +10,18 @@
mandate.payment.order.formpayment.order
-
+
-
-
+
+
-
+
diff --git a/account_banking_mandate/views/bank_payment_line_view.xml b/account_banking_mandate/views/bank_payment_line_view.xml
new file mode 100644
index 000000000..25c8656e5
--- /dev/null
+++ b/account_banking_mandate/views/bank_payment_line_view.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+ banking.mandate.bank.payment.line.form
+ bank.payment.line
+
+
+
+
+
+
+
+
+
+ banking.mandate.bank.payment.line.tree
+ bank.payment.line
+
+
+
+
+
+
+
+
+
+
+
diff --git a/account_banking_pain_base/__openerp__.py b/account_banking_pain_base/__openerp__.py
index 191ffb3cd..7d89c69a4 100644
--- a/account_banking_pain_base/__openerp__.py
+++ b/account_banking_pain_base/__openerp__.py
@@ -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',
],
diff --git a/account_banking_pain_base/models/__init__.py b/account_banking_pain_base/models/__init__.py
index 8a4154482..829202c43 100644
--- a/account_banking_pain_base/models/__init__.py
+++ b/account_banking_pain_base/models/__init__.py
@@ -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
diff --git a/account_banking_pain_base/models/bank_payment_line.py b/account_banking_pain_base/models/bank_payment_line.py
new file mode 100644
index 000000000..c00d9d9d0
--- /dev/null
+++ b/account_banking_pain_base/models/bank_payment_line.py
@@ -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
+#
+# 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 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
diff --git a/account_banking_pain_base/views/bank_payment_line_view.xml b/account_banking_pain_base/views/bank_payment_line_view.xml
new file mode 100644
index 000000000..65e993ad6
--- /dev/null
+++ b/account_banking_pain_base/views/bank_payment_line_view.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ pain.base.bank.payment.line.form
+ bank.payment.line
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/account_banking_pain_base/views/payment_line_view.xml b/account_banking_pain_base/views/payment_line_view.xml
index f92b1bbf5..03759b568 100644
--- a/account_banking_pain_base/views/payment_line_view.xml
+++ b/account_banking_pain_base/views/payment_line_view.xml
@@ -7,25 +7,10 @@
-
- pain.base.payment.line.form
- payment.line
-
-
-
-
-
-
-
-
-
-
-
-
pain.base.payment.line.inside.order.formpayment.order
-
+
diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py
index f362e919c..c9beef545 100644
--- a/account_banking_payment_export/__openerp__.py
+++ b/account_banking_payment_export/__openerp__.py
@@ -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',
],
diff --git a/account_banking_payment_export/data/bank_payment_line_seq.xml b/account_banking_payment_export/data/bank_payment_line_seq.xml
new file mode 100644
index 000000000..37c572bf7
--- /dev/null
+++ b/account_banking_payment_export/data/bank_payment_line_seq.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ Bank Payment Line
+ bank.payment.line
+
+
+
+ Bank Payment Line
+ bank.payment.line
+ L
+ 5
+ 1
+
+
+
+
+
diff --git a/account_banking_payment_export/models/__init__.py b/account_banking_payment_export/models/__init__.py
index 797c1ddf3..738dcdbfd 100644
--- a/account_banking_payment_export/models/__init__.py
+++ b/account_banking_payment_export/models/__init__.py
@@ -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
diff --git a/account_banking_payment_export/models/account_payment.py b/account_banking_payment_export/models/account_payment.py
index 3cad2f4cc..9768644f3 100644
--- a/account_banking_payment_export/models/account_payment.py
+++ b/account_banking_payment_export/models/account_payment.py
@@ -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
diff --git a/account_banking_payment_export/models/bank_payment_line.py b/account_banking_payment_export/models/bank_payment_line.py
new file mode 100644
index 000000000..d26e317d5
--- /dev/null
+++ b/account_banking_payment_export/models/bank_payment_line.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2015 Akretion (http://www.akretion.com)
+# @author Alexis de Lattre
+#
+# 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 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)
diff --git a/account_banking_payment_export/models/payment_line.py b/account_banking_payment_export/models/payment_line.py
new file mode 100644
index 000000000..9ef29e39f
--- /dev/null
+++ b/account_banking_payment_export/models/payment_line.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2015 Akretion (http://www.akretion.com)
+# @author Alexis de Lattre
+#
+# 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 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
diff --git a/account_banking_payment_export/security/ir.model.access.csv b/account_banking_payment_export/security/ir.model.access.csv
index 699f2d023..3bcb21020 100644
--- a/account_banking_payment_export/security/ir.model.access.csv
+++ b/account_banking_payment_export/security/ir.model.access.csv
@@ -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
diff --git a/account_banking_payment_export/views/account_payment.xml b/account_banking_payment_export/views/account_payment.xml
index 1ad55ce81..20e5cc564 100644
--- a/account_banking_payment_export/views/account_payment.xml
+++ b/account_banking_payment_export/views/account_payment.xml
@@ -1,27 +1,95 @@
-
-
+
-
- account.payment.order.form.banking-1
-
- payment.order
-
-
- launch_wizard
-
-
-
-
-
- {
- 'invisible': [('state', '!=', 'draft')]}
-
-
-
-
+
+
+ account.payment.order.form.banking-1
+
+ payment.order
+
+
+ launch_wizard
+
+
+
+
+
+ {
+ 'invisible': [('state', '!=', 'draft')]}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/account_banking_payment_export/views/bank_payment_line.xml b/account_banking_payment_export/views/bank_payment_line.xml
new file mode 100644
index 000000000..df4a308ba
--- /dev/null
+++ b/account_banking_payment_export/views/bank_payment_line.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+ bank.payment.line.form
+ bank.payment.line
+
+
+
+
+
+
+ bank.payment.line.tree
+ bank.payment.line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bank Payment Lines
+ bank.payment.line
+ tree,form
+ {'bank_payment_line_main_view': True}
+
+
+
+
diff --git a/account_banking_payment_export/workflow/account_payment.xml b/account_banking_payment_export/workflow/account_payment.xml
index ac5cf4a79..7528a75a4 100644
--- a/account_banking_payment_export/workflow/account_payment.xml
+++ b/account_banking_payment_export/workflow/account_payment.xml
@@ -12,5 +12,9 @@
action_done()
+
+ action_cancel()
+
+
diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py
index 09768ca5c..bd868009d 100644
--- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py
+++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py
@@ -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',
diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py
index b76e14050..ff5662c46 100644
--- a/account_banking_sepa_direct_debit/wizard/export_sdd.py
+++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py
@@ -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():
diff --git a/account_direct_debit/models/payment_line.py b/account_direct_debit/models/payment_line.py
index 0da003002..4fc667daf 100644
--- a/account_direct_debit/models/payment_line.py
+++ b/account_direct_debit/models/payment_line.py
@@ -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')
From 212f5f992e232c545fcff9c25abda590b408a53f Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Wed, 23 Sep 2015 18:18:37 +0200
Subject: [PATCH 02/28] Allow to select customer refunds in direct debit order
and supplier refunds in payment order (to reduce the amount to pay)
---
.../models/account_payment.py | 21 +++-
.../views/account_payment.xml | 3 +-
.../wizard/payment_order_create.py | 11 ++-
.../model/account_payment.py | 71 ++++++--------
.../model/payment_line.py | 96 ++++++++++---------
.../models/account_move_line.py | 71 +-------------
.../views/account_payment.xml | 41 ++++----
.../wizard/payment_order_create.py | 8 +-
8 files changed, 130 insertions(+), 192 deletions(-)
diff --git a/account_banking_payment_export/models/account_payment.py b/account_banking_payment_export/models/account_payment.py
index 9768644f3..74ea5108c 100644
--- a/account_banking_payment_export/models/account_payment.py
+++ b/account_banking_payment_export/models/account_payment.py
@@ -130,7 +130,7 @@ class PaymentOrder(models.Model):
# 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
+ group_paylines = {} # key = hashcode
for payline in order.line_ids:
# Compute requested payment date
if order.date_prefered == 'due':
@@ -143,11 +143,22 @@ class PaymentOrder(models.Model):
payline.date = requested_date
hashcode = payline.payment_line_hashcode()
if hashcode in group_paylines:
- group_paylines[hashcode] += payline
+ group_paylines[hashcode]['paylines'] += payline
+ group_paylines[hashcode]['total'] +=\
+ payline.amount_currency
else:
- group_paylines[hashcode] = payline
+ group_paylines[hashcode] = {
+ 'paylines': payline,
+ 'total': payline.amount_currency,
+ }
# Create bank payment lines
- for paylines in group_paylines.values():
- vals = self._prepare_bank_payment_line(paylines)
+ for paydict in group_paylines.values():
+ # Block if a bank payment line is <= 0
+ if paydict['total'] <= 0:
+ raise exceptions.Warning(
+ _("The amount for Partner '%s' is negative (%.2f) !")
+ % (paydict['paylines'][0].partner_id.name,
+ paydict['total']))
+ vals = self._prepare_bank_payment_line(paydict['paylines'])
bplo.create(vals)
return res
diff --git a/account_banking_payment_export/views/account_payment.xml b/account_banking_payment_export/views/account_payment.xml
index 20e5cc564..0e9340e1e 100644
--- a/account_banking_payment_export/views/account_payment.xml
+++ b/account_banking_payment_export/views/account_payment.xml
@@ -14,6 +14,7 @@
+ {
@@ -30,7 +31,7 @@
-
+
diff --git a/account_banking_payment_export/wizard/payment_order_create.py b/account_banking_payment_export/wizard/payment_order_create.py
index 613f88eba..726f26e86 100644
--- a/account_banking_payment_export/wizard/payment_order_create.py
+++ b/account_banking_payment_export/wizard/payment_order_create.py
@@ -56,8 +56,7 @@ class PaymentOrderCreate(models.TransientModel):
# Do not propose partially reconciled credit lines,
# as they are deducted from a customer invoice, and
# will not be refunded with a payment.
- domain += [('credit', '>', 0),
- '|',
+ domain += ['|',
('account_id.type', '=', 'payable'),
'&',
('account_id.type', '=', 'receivable'),
@@ -171,7 +170,13 @@ class PaymentOrderCreate(models.TransientModel):
# customer invoice number (in the case of debit order)
communication = line.invoice.number.replace('/', '')
state = 'structured'
- amount_currency = line.amount_residual_currency
+ # support debit orders when enabled
+ if line.debit > 0:
+ amount_currency = line.amount_residual_currency * -1
+ else:
+ amount_currency = line.amount_residual_currency
+ if payment.payment_order_type == 'debit':
+ amount_currency *= -1
line2bank = line.line2bank(payment.mode.id)
# -- end account banking
res = {'move_line_id': line.id,
diff --git a/account_banking_payment_transfer/model/account_payment.py b/account_banking_payment_transfer/model/account_payment.py
index eafd6260b..f79308a56 100644
--- a/account_banking_payment_transfer/model/account_payment.py
+++ b/account_banking_payment_transfer/model/account_payment.py
@@ -104,8 +104,8 @@ class PaymentOrder(models.Model):
"""
res = []
for order in self:
- for order_line in order.line_ids:
- move_line = order_line.transfer_move_line_id
+ for bank_line in order.bank_line_ids:
+ move_line = bank_line.transfer_move_line_id
if move_line:
res.append(move_line)
return res
@@ -141,23 +141,16 @@ class PaymentOrder(models.Model):
@api.multi
def _prepare_move_line_transfer_account(
- self, amount, move, payment_lines, labels):
- if len(payment_lines) == 1:
- partner_id = payment_lines[0].partner_id.id
- name = _('%s line %s') % (labels[self.payment_order_type],
- payment_lines[0].name)
- if payment_lines[0].move_line_id.id and\
- payment_lines[0].move_line_id.move_id.state != 'draft':
- name = "%s (%s)" % (name,
- payment_lines[0].move_line_id.move_id.name)
- elif payment_lines[0].ml_inv_ref.id:
- name = "%s (%s)" % (name,
- payment_lines[0].ml_inv_ref.number)
+ self, amount, move, bank_payment_lines, labels):
+ if len(bank_payment_lines) == 1:
+ partner_id = bank_payment_lines[0].partner_id.id
+ name = _('%s bank line %s') % (labels[self.payment_order_type],
+ bank_payment_lines[0].name)
else:
partner_id = False
name = '%s %s' % (
labels[self.payment_order_type], self.reference)
- date_maturity = payment_lines[0].date
+ date_maturity = bank_payment_lines[0].date
vals = {
'name': name,
'move_id': move.id,
@@ -173,13 +166,12 @@ class PaymentOrder(models.Model):
@api.multi
def _prepare_move_line_partner_account(self, line, move, labels):
- if line.move_line_id:
- account_id = line.move_line_id.account_id.id
+ # TODO : ALEXIS check don't group if move_line_id.account_id
+ # is not the same
+ if self.payment_order_type == 'debit':
+ account_id = line.partner_id.property_account_receivable.id
else:
- if self.payment_order_type == 'debit':
- account_id = line.partner_id.property_account_receivable.id
- else:
- account_id = line.partner_id.property_account_payable.id
+ account_id = line.partner_id.property_account_payable.id
vals = {
'name': _('%s line %s') % (
labels[self.payment_order_type], line.name),
@@ -187,9 +179,9 @@ class PaymentOrder(models.Model):
'partner_id': line.partner_id.id,
'account_id': account_id,
'credit': (self.payment_order_type == 'debit' and
- line.amount or 0.0),
+ line.amount_currency or 0.0),
'debit': (self.payment_order_type == 'payment' and
- line.amount or 0.0),
+ line.amount_currency or 0.0),
}
return vals
@@ -215,12 +207,12 @@ class PaymentOrder(models.Model):
line.write({'transit_move_line_id': partner_move_line.id})
@api.multi
- def _reconcile_payment_lines(self, payment_lines):
- for line in payment_lines:
- if line.move_line_id:
- line.debit_reconcile()
+ def _reconcile_payment_lines(self, bank_payment_lines):
+ for bline in bank_payment_lines:
+ if all([pline.move_line_id for pline in bline.payment_line_ids]):
+ bline.debit_reconcile()
else:
- self.action_sent_no_move_line_hook(line)
+ self.action_sent_no_move_line_hook(bline)
@api.one
def action_sent(self):
@@ -232,8 +224,8 @@ class PaymentOrder(models.Model):
am_obj = self.env['account.move']
aml_obj = self.env['account.move.line']
labels = {
- 'payment': _('Payment order'),
- 'debit': _('Direct debit order'),
+ 'payment': _('Payment'),
+ 'debit': _('Direct debit'),
}
if self.mode.transfer_journal_id and self.mode.transfer_account_id:
# prepare a dict "trfmoves" that can be used when
@@ -242,26 +234,21 @@ class PaymentOrder(models.Model):
# value = [pay_line1, pay_line2, ...]
trfmoves = {}
if self.mode.transfer_move_option == 'line':
- for line in self.line_ids:
+ for line in self.bank_line_ids:
trfmoves[line.id] = [line]
else:
- if self.date_prefered in ('now', 'fixed'):
- trfmoves[True] = []
- for line in self.line_ids:
- trfmoves[True].append(line)
- else: # date_prefered == due
- for line in self.line_ids:
- if line.date in trfmoves:
- trfmoves[line.date].append(line)
- else:
- trfmoves[line.date] = [line]
+ for line in self.bank_line_ids:
+ if line.date in trfmoves:
+ trfmoves[line.date].append(line)
+ else:
+ trfmoves[line.date] = [line]
for identifier, lines in trfmoves.iteritems():
mvals = self._prepare_transfer_move()
move = am_obj.create(mvals)
total_amount = 0
for line in lines:
- total_amount += line.amount
+ total_amount += line.amount_currency
self._create_move_line_partner_account(line, move, labels)
# create the payment/debit move line on the transfer account
trf_ml_vals = self._prepare_move_line_transfer_account(
diff --git a/account_banking_payment_transfer/model/payment_line.py b/account_banking_payment_transfer/model/payment_line.py
index c99c5949b..2eed8de85 100644
--- a/account_banking_payment_transfer/model/payment_line.py
+++ b/account_banking_payment_transfer/model/payment_line.py
@@ -35,29 +35,8 @@ class PaymentLine(models.Model):
'''
_inherit = 'payment.line'
- @api.multi
- def _get_transfer_move_line(self):
- for order_line in self:
- if order_line.transit_move_line_id:
- order_type = order_line.order_id.payment_order_type
- trf_lines = order_line.transit_move_line_id.move_id.line_id
- for move_line in trf_lines:
- if order_type == 'debit' and move_line.debit > 0:
- order_line.transfer_move_line_id = move_line
- elif order_type == 'payment' and move_line.credit > 0:
- order_line.transfer_move_line_id = move_line
-
msg = fields.Char('Message', required=False, readonly=True, default='')
date_done = fields.Date('Date Confirmed', select=True, readonly=True)
- transit_move_line_id = fields.Many2one(
- 'account.move.line', string='Transfer move line', readonly=True,
- help="Move line through which the payment/debit order "
- "pays the invoice")
- transfer_move_line_id = fields.Many2one(
- 'account.move.line', compute='_get_transfer_move_line',
- string='Transfer move line counterpart',
- help="Counterpart move line on the transfer account")
-
"""
Hooks for processing direct debit orders, such as implemented in
account_direct_debit module.
@@ -98,6 +77,31 @@ class PaymentLine(models.Model):
return False
+
+class BankPaymentLine(models.Model):
+ _inherit = 'bank.payment.line'
+
+ transit_move_line_id = fields.Many2one(
+ 'account.move.line', string='Transfer move line', readonly=True,
+ help="Move line through which the payment/debit order "
+ "pays the invoice")
+ transfer_move_line_id = fields.Many2one(
+ 'account.move.line', compute='_get_transfer_move_line',
+ string='Transfer move line counterpart',
+ help="Counterpart move line on the transfer account")
+
+ @api.multi
+ def _get_transfer_move_line(self):
+ for bank_line in self:
+ if bank_line.transit_move_line_id:
+ order_type = bank_line.order_id.payment_order_type
+ trf_lines = bank_line.transit_move_line_id.move_id.line_id
+ for move_line in trf_lines:
+ if order_type == 'debit' and move_line.debit > 0:
+ bank_line.transfer_move_line_id = move_line
+ elif order_type == 'payment' and move_line.credit > 0:
+ bank_line.transfer_move_line_id = move_line
+
@api.one
def debit_reconcile(self):
"""
@@ -111,34 +115,32 @@ class PaymentLine(models.Model):
"""
transit_move_line = self.transit_move_line_id
- torec_move_line = self.move_line_id
- if (not transit_move_line or not torec_move_line):
- raise exceptions.except_orm(
- _('Can not reconcile'),
- _('No move line for line %s') % self.name
- )
- if torec_move_line.reconcile_id:
- raise exceptions.except_orm(
- _('Error'),
- _('Move line %s has already been reconciled') %
- torec_move_line.name
- )
- if (transit_move_line.reconcile_id or
- transit_move_line.reconcile_partial_id):
- raise exceptions.except_orm(
- _('Error'),
- _('Move line %s has already been reconciled') %
- transit_move_line.name
- )
+# if (not transit_move_line or not torec_move_line):
+# raise exceptions.UserError(
+# _('Can not reconcile: no move line for line %s') % self.name
+# )
+# if torec_move_line.reconcile_id:
+# raise exceptions.UserError(
+# _('Move line %s has already been reconciled') %
+# torec_move_line.name
+# )
+# if (transit_move_line.reconcile_id or
+# transit_move_line.reconcile_partial_id):
+# raise exceptions.UserError(
+# _('Move line %s has already been reconciled') %
+# transit_move_line.name
+# )
- line_ids = [transit_move_line.id, torec_move_line.id]
- self.env['account.move.line'].browse(line_ids).reconcile_partial(
- type='auto')
+ lines_to_rec = transit_move_line
+ for payment_line in self.payment_line_ids:
+ lines_to_rec += payment_line.move_line_id
+
+ lines_to_rec.reconcile_partial(type='auto')
# If a bank transaction of a storno was first confirmed
# and now canceled (the invoice is now in state 'debit_denied'
- if torec_move_line.invoice:
- workflow.trg_validate(
- self.env.uid, 'account.invoice', torec_move_line.invoice.id,
- 'undo_debit_denied', self.env.cr)
+# if torec_move_line.invoice:
+# workflow.trg_validate(
+# self.env.uid, 'account.invoice', torec_move_line.invoice.id,
+# 'undo_debit_denied', self.env.cr)
diff --git a/account_direct_debit/models/account_move_line.py b/account_direct_debit/models/account_move_line.py
index 2f10ec351..07608803f 100644
--- a/account_direct_debit/models/account_move_line.py
+++ b/account_direct_debit/models/account_move_line.py
@@ -20,72 +20,12 @@
#
##############################################################################
-from operator import itemgetter
-from openerp.osv import fields, orm
+from openerp import models
-class AccountMoveLine(orm.Model):
+class AccountMoveLine(models.Model):
_inherit = "account.move.line"
- def _amount_to_receive(self, cr, uid, ids, name, arg=None, 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
- account_payment/account_move_line.py
- """
- if not ids:
- return {}
- cr.execute("""SELECT ml.id,
- CASE WHEN ml.amount_currency > 0
- THEN ml.amount_currency
- ELSE ml.debit
- 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 pl.storno is false
- 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_receive_search(self, cr, uid, obj, name, args, context=None):
- """Reverse of account_payment/account_move_line.py:_to_pay_search().
- """
- if not args:
- return []
- line_obj = self.pool.get('account.move.line')
- search_context = dict(context or {}, all_fiscalyear=True)
- query = line_obj._query_get(cr, uid, context=search_context)
- where = ' and '.join(map(lambda x: '''(SELECT
- CASE WHEN l.amount_currency > 0
- THEN l.amount_currency
- ELSE l.debit
- 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 pl.storno is false
- 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=%s AND active)
- AND reconcile_id IS null
- AND debit > 0
- AND ''' + where + ' and ' + query), ('receivable',) + sql_args)
- res = cr.fetchall()
- if not res:
- return [('id', '=', '0')]
- return [('id', 'in', map(lambda x:x[0], res))]
-
def line2bank(self, cr, uid, ids, payment_type=None, context=None):
"""I have to inherit this function for direct debits to fix the
following issue : if the customer invoice has a value for
@@ -112,10 +52,3 @@ class AccountMoveLine(orm.Model):
return line2bank
return super(AccountMoveLine, self).line2bank(
cr, uid, ids, payment_type=pay_mode.id, context=context)
-
- _columns = {
- 'amount_to_receive': fields.function(
- _amount_to_receive, method=True,
- type='float', string='Amount to receive',
- fnct_search=_to_receive_search),
- }
diff --git a/account_direct_debit/views/account_payment.xml b/account_direct_debit/views/account_payment.xml
index 8570789da..016b4bc71 100644
--- a/account_direct_debit/views/account_payment.xml
+++ b/account_direct_debit/views/account_payment.xml
@@ -23,32 +23,27 @@
- payment.order.form
+ direct.debit.payment.order.formpayment.order
-
+
-
-
-
-
+
+ [('payment_order_type', '=', payment_order_type)]
+
diff --git a/account_direct_debit/wizard/payment_order_create.py b/account_direct_debit/wizard/payment_order_create.py
index 3b26562b6..61eea19ca 100644
--- a/account_direct_debit/wizard/payment_order_create.py
+++ b/account_direct_debit/wizard/payment_order_create.py
@@ -33,9 +33,13 @@ class PaymentOrderCreate(models.TransientModel):
super(PaymentOrderCreate, self).extend_payment_order_domain(
payment_order, domain)
if payment_order.payment_order_type == 'debit':
+ # With the new system with bank.payment.line, we want
+ # to be able to have payment lines linked to customer
+ # invoices and payment lines linked to customer refunds
+ # in order to debit the customer of the total of his
+ # invoices minus his refunds
domain += ['|',
('invoice', '=', False),
('invoice.state', '!=', 'debit_denied'),
- ('account_id.type', '=', 'receivable'),
- ('amount_to_receive', '>', 0)]
+ ('account_id.type', '=', 'receivable')]
return True
From adedae3bc2f34abb3e6b4cc8bb15523754970e43 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Thu, 24 Sep 2015 10:00:45 +0200
Subject: [PATCH 03/28] Remove storno, which seems specific to one particular
country.
---
.../model/payment_line.py | 46 -----
account_direct_debit/README.rst | 13 +-
account_direct_debit/__openerp__.py | 1 -
account_direct_debit/models/__init__.py | 4 +-
.../models/account_invoice.py | 165 ------------------
.../models/account_payment.py | 19 --
account_direct_debit/models/payment_line.py | 126 +------------
.../views/account_payment.xml | 12 --
.../workflow/account_invoice.xml | 51 ------
9 files changed, 8 insertions(+), 429 deletions(-)
delete mode 100644 account_direct_debit/models/account_invoice.py
delete mode 100644 account_direct_debit/models/account_payment.py
delete mode 100644 account_direct_debit/workflow/account_invoice.xml
diff --git a/account_banking_payment_transfer/model/payment_line.py b/account_banking_payment_transfer/model/payment_line.py
index 2eed8de85..76262a4b3 100644
--- a/account_banking_payment_transfer/model/payment_line.py
+++ b/account_banking_payment_transfer/model/payment_line.py
@@ -37,45 +37,6 @@ class PaymentLine(models.Model):
msg = fields.Char('Message', required=False, readonly=True, default='')
date_done = fields.Date('Date Confirmed', select=True, readonly=True)
- """
- Hooks for processing direct debit orders, such as implemented in
- account_direct_debit module.
- """
- @api.multi
- def get_storno_account_id(self, amount, currency_id):
- """
- Hook for verifying a match of the payment line with the amount.
- Return the account associated with the storno.
- Used in account_banking interactive mode
- :param payment_line_id: the single payment line id
- :param amount: the (signed) amount debited from the bank account
- :param currency: the bank account's currency *browse object*
- :return: an account if there is a full match, False otherwise
- :rtype: database id of an account.account resource.
- """
-
- return False
-
- @api.multi
- def debit_storno(self, amount, currency_id, storno_retry=True):
- """
- Hook for handling a canceled item of a direct debit order.
- Presumably called from a bank statement import routine.
-
- Decide on the direction that the invoice's workflow needs to take.
- You may optionally return an incomplete reconcile for the caller
- to reconcile the now void payment.
-
- :param payment_line_id: the single payment line id
- :param amount: the (negative) amount debited from the bank account
- :param currency: the bank account's currency *browse object*
- :param boolean storno_retry: whether the storno is considered fatal \
- or not.
- :return: an incomplete reconcile for the caller to fill
- :rtype: database id of an account.move.reconcile resource.
- """
-
- return False
class BankPaymentLine(models.Model):
@@ -137,10 +98,3 @@ class BankPaymentLine(models.Model):
lines_to_rec += payment_line.move_line_id
lines_to_rec.reconcile_partial(type='auto')
-
- # If a bank transaction of a storno was first confirmed
- # and now canceled (the invoice is now in state 'debit_denied'
-# if torec_move_line.invoice:
-# workflow.trg_validate(
-# self.env.uid, 'account.invoice', torec_move_line.invoice.id,
-# 'undo_debit_denied', self.env.cr)
diff --git a/account_direct_debit/README.rst b/account_direct_debit/README.rst
index 1d82305be..337f4a7ad 100644
--- a/account_direct_debit/README.rst
+++ b/account_direct_debit/README.rst
@@ -8,11 +8,8 @@ This module adds support for direct debit orders, analogous to payment orders.
A new entry in the Accounting/Payment menu allow you to create a direct debit
order that helps you to select any customer invoices for you to collect.
-This module explicitely implements direct debit orders as applicable
-in the Netherlands. Debit orders are advanced in total by the bank.
-Amounts that cannot be debited or are canceled by account owners are
-credited afterwards. Such a creditation is called a storno. This style of
-direct debit order may not apply to your country.
+Debit orders are advanced in total by the bank. Amounts that cannot be
+debited or are canceled by account owners are credited afterwards.
Installation
============
@@ -25,12 +22,12 @@ This module is part of the OCA/bank-payment suite.
Configuration
=============
-Please refer to module "Account Banking SEPA Direct Debit"
+Please refer to module *Account Banking SEPA Direct Debit*
Usage
=====
-Please refer to module "Account Banking SEPA Direct Debit"
+Please refer to module *Account Banking SEPA Direct Debit*
For further information, please visit:
@@ -58,7 +55,7 @@ Contributors
* Stefan Rijnhart
* Pedro M. Baeza
-* Alexis de Lattre
+* Alexis de Lattre
* Danimar Ribeiro
* Stéphane Bidoul
* Alexandre Fayolle
diff --git a/account_direct_debit/__openerp__.py b/account_direct_debit/__openerp__.py
index 790dd0896..ace7cda3d 100644
--- a/account_direct_debit/__openerp__.py
+++ b/account_direct_debit/__openerp__.py
@@ -33,7 +33,6 @@
'views/account_invoice.xml',
'views/payment_mode.xml',
'views/payment_mode_type.xml',
- 'workflow/account_invoice.xml',
'data/account_payment_term.xml',
'data/payment_mode_type.xml'
],
diff --git a/account_direct_debit/models/__init__.py b/account_direct_debit/models/__init__.py
index ffb948151..cb28fc53b 100644
--- a/account_direct_debit/models/__init__.py
+++ b/account_direct_debit/models/__init__.py
@@ -1,4 +1,4 @@
-from . import account_payment
+# -*- coding: utf-8 -*-
+
from . import payment_line
from . import account_move_line
-from . import account_invoice
diff --git a/account_direct_debit/models/account_invoice.py b/account_direct_debit/models/account_invoice.py
deleted file mode 100644
index 66c30ac53..000000000
--- a/account_direct_debit/models/account_invoice.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# Copyright (C) 2011 - 2013 Therp BV ().
-#
-# All other contributions are (C) by their respective contributors
-#
-# All Rights Reserved
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#
-##############################################################################
-
-"""
-This module adds support for Direct debit orders as applicable
-in the Netherlands. Debit orders are advanced in total by the bank.
-Amounts that cannot be debited or are canceled by account owners are
-credited afterwards. Such a creditation is called a storno.
-
-Invoice workflow:
-
-1 the sale leads to
- 1300 Debtors 100
- 8000 Sales 100
-
-Balance:
- Debtors 2000 |
- Sales | 2000
-
-2 an external booking takes place
- 1100 Bank 100
- 1300 Debtors 100
- This booking is reconciled with [1]
- The invoice gets set to state 'paid', and 'reconciled' = True
-
-Balance:
- Debtors 1900 |
- Bank 100 |
- Sales | 2000
-
-This module implements the following diversion:
-
-2a the invoice is included in a direct debit order. When the order is
- confirmed, a move is created per invoice:
-
- 2000 Transfer account 100 |
- 1300 Debtors | 100
- Reconciliation takes place between 1 and 2a.
- The invoice gets set to state 'paid', and 'reconciled' = True
-
-Balance:
- Debtors 0 |
- Transfer account 2000 |
- Bank 0 |
- Sales | 2000
-
-3a the direct debit order is booked on the bank account
-
-Balance:
- 1100 Bank 2000 |
- 2000 Transfer account | 2000
- Reconciliation takes place between 3a and 2a
-
-Balance:
- Debtors 0 |
- Transfer account 0 |
- Bank 2000 |
- Sales | 2000
-
-4 a storno from invoice [1] triggers a new booking on the bank account
- 1300 Debtors 100 |
- 1100 Bank | 100
-
-Balance:
- Debtors 100 |
- Transfer account 0 |
- Bank 1900 |
- Sales | 2000
-
- The reconciliation of 2a is undone. The booking of 2a is reconciled
- with the booking of 4 instead.
- The payment line attribute 'storno' is set to True and the invoice
- state is no longer 'paid'.
-
-Two cases need to be distinguisted:
- 1) If the storno is a manual storno from the partner, the invoice is set to
- state 'debit_denied', with 'reconciled' = False
- This module implements this option by allowing the bank module to call
-
- netsvc.LocalService("workflow").trg_validate(
- uid, 'account.invoice', ids, 'debit_denied', cr)
-
- 2) If the storno is an error generated by the bank (assumingly non-fatal),
- the invoice is reopened for the next debit run. This is a call to
- existing
-
- netsvc.LocalService("workflow").trg_validate(
- uid, 'account.invoice', ids, 'open_test', cr)
-
- Should also be adding a log entry on the invoice for tracing purposes
-
- self._log_event(cr, uid, ids, -1.0, 'Debit denied')
-
- If not for that funny comment
- "#TODO: implement messages system" in account/invoice.py
-
- Repeating non-fatal fatal errors need to be dealt with manually by checking
- open invoices with a matured invoice- or due date.
-"""
-
-from openerp.osv import orm
-from openerp.tools.translate import _
-
-
-class AccountInvoice(orm.Model):
- _inherit = "account.invoice"
-
- def _register_hook(self, cr):
- """
- Adding a state to the hardcoded state list of the inherited
- model. The alternative is duplicating the field definition
- in columns but only one module can do that!
-
- Maybe apply a similar trick when overriding the buttons' 'states'
- attributes in the form view, manipulating the xml in fields_view_get().
- """
- self._columns['state'].selection.append(
- ('debit_denied', 'Debit denied'))
- return super(AccountInvoice, self)._register_hook(cr)
-
- def action_debit_denied(self, cr, uid, ids, context=None):
- for invoice_id in ids:
- if self.test_paid(cr, uid, [invoice_id], context):
- number = self.read(
- cr, uid, invoice_id, ['number'], context=context)['number']
- raise orm.except_orm(
- _('Error !'),
- _("You cannot set invoice '%s' to state 'debit "
- "denied', as it is still reconciled.") % number)
- self.write(cr, uid, ids, {'state': 'debit_denied'}, context=context)
- for inv_id, name in self.name_get(cr, uid, ids, context=context):
- message = _("Invoice '%s': direct debit is denied.") % name
- self.log(cr, uid, inv_id, message)
- return True
-
- def test_undo_debit_denied(self, cr, uid, ids, context=None):
- """
- Called from the workflow. Used to unset paid state on
- invoices that were paid with bank transfers which are being cancelled
- """
- for invoice in self.read(cr, uid, ids, ['reconciled'], context):
- if not invoice['reconciled']:
- return False
- return True
diff --git a/account_direct_debit/models/account_payment.py b/account_direct_debit/models/account_payment.py
deleted file mode 100644
index 702477107..000000000
--- a/account_direct_debit/models/account_payment.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from openerp.osv import orm
-
-
-class PaymentOrder(orm.Model):
- _inherit = 'payment.order'
-
- def test_undo_done(self, cr, uid, ids, context=None):
- """Called from the workflow. Used to unset done state on
- payment orders that were reconciled with bank transfers
- which are being cancelled
- """
- for order in self.browse(cr, uid, ids, context=context):
- if order.payment_order_type == 'debit':
- for line in order.line_ids:
- if line.storno:
- return False
- return super(PaymentOrder, self).test_undo_done(
- cr, uid, ids, context=context)
diff --git a/account_direct_debit/models/payment_line.py b/account_direct_debit/models/payment_line.py
index 4fc667daf..120a41145 100644
--- a/account_direct_debit/models/payment_line.py
+++ b/account_direct_debit/models/payment_line.py
@@ -1,134 +1,10 @@
# -*- coding: utf-8 -*-
-from openerp import api, exceptions, models, fields, _, workflow
+from openerp import models, fields
class PaymentLine(models.Model):
_inherit = 'payment.line'
- @api.multi
- def debit_storno(self, amount, currency, storno_retry=True):
- """The processing of a storno is triggered by a debit
- transfer on one of the company's bank accounts.
- This method offers to re-reconcile the original debit
- payment. For this purpose, we have registered that
- payment move on the payment line.
-
- Return the (now incomplete) reconcile id. The caller MUST
- re-reconcile this reconcile with the bank transfer and
- re-open the associated invoice.
-
- :param payment_line_id: the single payment line id
- :param amount: the (signed) amount debited from the bank account
- :param currency: the bank account's currency *browse object*
- :param boolean storno_retry: when True, attempt to reopen the invoice,
- set the invoice to 'Debit denied' otherwise.
- :return: an incomplete reconcile for the caller to fill
- :rtype: database id of an account.move.reconcile resource.
- """
- self.ensure_one()
- reconcile_obj = self.env['account.move.reconcile']
- line = self
- reconcile = reconcile_obj.browse([])
- if (line.transit_move_line_id and not line.storno and
- self.env['res.currency'].is_zero(
- currency, (
- (line.transit_move_line_id.credit or 0.0) -
- (line.transit_move_line_id.debit or 0.0) + amount))):
- # Two different cases, full and partial
- # Both cases differ subtly in the procedure to follow
- # Needs refractoring, but why is this not in the OpenERP API?
- # Actually, given the nature of a direct debit order and storno,
- # we should not need to take partial into account on the side of
- # the transit_move_line.
- if line.transit_move_line_id.reconcile_partial_id:
- reconcile_partial = \
- line.transit_move_line_id.reconcile_partial_id
- reconcile = line.transit_move_line_id.reconcile_id
- if len(reconcile.line_partial_ids) == 2:
- # reuse the simple reconcile for the storno transfer
- reconcile_partial.write({
- 'line_id': [(6, 0, line.transit_move_line_id.id)],
- 'line_partial_ids': [(6, 0, [])]
- })
- else:
- # split up the original reconcile in a partial one
- # and a new one for reconciling the storno transfer
- reconcile_partial.write({
- 'line_partial_ids': [(3, line.transit_move_line_id.id)]
- })
- reconcile = reconcile_obj.create({
- 'type': 'auto',
- 'line_id': [(6, 0, line.transit_move_line_id.id)]
- })
- elif line.transit_move_line_id.reconcile_id:
- reconcile = line.transit_move_line_id.reconcile_id
- if len(line.transit_move_line_id.reconcile_id.line_id) == 2:
- # reuse the simple reconcile for the storno transfer
- reconcile.write({
- 'line_id': [(6, 0, [line.transit_move_line_id.id])],
- })
- else:
- # split up the original reconcile in a partial one
- # and a new one for reconciling the storno transfer
- reconcile = line.transit_move_line_id.reconcile_id
- partial_ids = [x.id for x in reconcile.line_id
- if x.id != line.transit_move_line_id.id]
- reconcile.write({
- 'line_partial_ids': [(6, 0, partial_ids)],
- 'line_id': [(6, 0, [])],
- })
- reconcile = reconcile_obj.create({
- 'type': 'auto',
- 'line_id': [(6, 0, line.transit_move_line_id.id)]
- })
- # mark the payment line for storno processed
- if reconcile:
- self.write({'storno': True})
- # put forth the invoice workflow
- if line.move_line_id.invoice:
- activity = (storno_retry and 'open_test' or
- 'invoice_debit_denied')
- workflow.trg_validate(
- self.env.uid, 'account.invoice',
- line.move_line_id.invoice.id, activity, self.env.cr)
- return reconcile.id
-
- @api.multi
- def get_storno_account_id(self, amount, currency):
- """Check the match of the arguments, and return the account associated
- with the storno.
- Used in account_banking interactive mode
-
- :param payment_line_id: the single payment line id
- :param amount: the (signed) amount debited from the bank account
- :param currency: the bank account's currency *browse object*
- :return: an account if there is a full match, False otherwise
- :rtype: database id of an account.account resource.
- """
- self.ensure_one()
- account_id = False
- if (self.transit_move_line_id and not self.storno and
- self.env['res.currency'].is_zero(
- currency, (
- (self.transit_move_line_id.credit or 0.0) -
- (self.transit_move_line_id.debit or 0.0) + amount))):
- account_id = self.transit_move_line_id.account_id.id
- return account_id
-
- @api.one
- def debit_reconcile(self):
- """Raise if a payment line is passed for which storno is True."""
- if self.storno:
- raise exceptions.except_orm(
- _('Can not reconcile'),
- _('Cancelation of payment line \'%s\' has already been '
- 'processed') % self.name)
- return super(PaymentLine, self).debit_reconcile()
-
- storno = fields.Boolean(
- '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')
diff --git a/account_direct_debit/views/account_payment.xml b/account_direct_debit/views/account_payment.xml
index 016b4bc71..3b0977577 100644
--- a/account_direct_debit/views/account_payment.xml
+++ b/account_direct_debit/views/account_payment.xml
@@ -47,17 +47,5 @@
-
- Payment Lines
- payment.line
-
-
-
-
-
-
-
-
-
diff --git a/account_direct_debit/workflow/account_invoice.xml b/account_direct_debit/workflow/account_invoice.xml
deleted file mode 100644
index d3099e85d..000000000
--- a/account_direct_debit/workflow/account_invoice.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
- debit_denied
- action_debit_denied()
- function
-
-
-
-
-
- invoice_debit_denied
-
-
-
-
-
- invoice_debit_denied
-
-
-
-
-
- test_undo_debit_denied()
- undo_debit_denied
-
-
-
-
-
- open_test
-
-
-
From 0c2aec9eeb243dbd822470dbf7f31c0080b44312 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Thu, 24 Sep 2015 11:38:50 +0200
Subject: [PATCH 04/28] Add a hook to inherit grouping of the transfer account
move line
Use that new hook in SEPA direct debits
Better variable names
---
.../model/__init__.py | 3 +
.../model/account_payment.py | 59 +++++------
.../model/bank_payment_line.py | 97 +++++++++++++++++++
.../model/payment_line.py | 69 ++-----------
.../models/__init__.py | 23 +----
.../models/bank_payment_line.py | 41 ++++++++
6 files changed, 185 insertions(+), 107 deletions(-)
create mode 100644 account_banking_payment_transfer/model/bank_payment_line.py
create mode 100644 account_banking_sepa_direct_debit/models/bank_payment_line.py
diff --git a/account_banking_payment_transfer/model/__init__.py b/account_banking_payment_transfer/model/__init__.py
index 7a8cfda04..09e695000 100644
--- a/account_banking_payment_transfer/model/__init__.py
+++ b/account_banking_payment_transfer/model/__init__.py
@@ -1,4 +1,7 @@
+# -*- coding: utf-8 -*-
+
from . import account_payment
from . import payment_line
+from . import bank_payment_line
from . import payment_mode
from . import account_move_reconcile
diff --git a/account_banking_payment_transfer/model/account_payment.py b/account_banking_payment_transfer/model/account_payment.py
index f79308a56..2fceef2ac 100644
--- a/account_banking_payment_transfer/model/account_payment.py
+++ b/account_banking_payment_transfer/model/account_payment.py
@@ -4,7 +4,7 @@
# Copyright (C) 2009 EduSense BV ().
# (C) 2011 - 2013 Therp BV ().
# (C) 2014 ACSONE SA ().
-# (C) 2014 Akretion (www.akretion.com)
+# (C) 2014-2015 Akretion (www.akretion.com)
#
# All other contributions are (C) by their respective contributors
#
@@ -26,6 +26,7 @@
##############################################################################
from openerp import models, fields, api, _
+from openerp.exceptions import Warning as UserError
class PaymentOrder(models.Model):
@@ -165,23 +166,23 @@ class PaymentOrder(models.Model):
return vals
@api.multi
- def _prepare_move_line_partner_account(self, line, move, labels):
+ def _prepare_move_line_partner_account(self, bank_line, move, labels):
# TODO : ALEXIS check don't group if move_line_id.account_id
# is not the same
if self.payment_order_type == 'debit':
- account_id = line.partner_id.property_account_receivable.id
+ account_id = bank_line.partner_id.property_account_receivable.id
else:
- account_id = line.partner_id.property_account_payable.id
+ account_id = bank_line.partner_id.property_account_payable.id
vals = {
'name': _('%s line %s') % (
- labels[self.payment_order_type], line.name),
+ labels[self.payment_order_type], bank_line.name),
'move_id': move.id,
- 'partner_id': line.partner_id.id,
+ 'partner_id': bank_line.partner_id.id,
'account_id': account_id,
'credit': (self.payment_order_type == 'debit' and
- line.amount_currency or 0.0),
+ bank_line.amount_currency or 0.0),
'debit': (self.payment_order_type == 'payment' and
- line.amount_currency or 0.0),
+ bank_line.amount_currency or 0.0),
}
return vals
@@ -191,20 +192,27 @@ class PaymentOrder(models.Model):
return
@api.multi
- def _create_move_line_partner_account(self, line, move, labels):
+ def _create_move_line_partner_account(self, bank_line, move, labels):
"""This method is designed to be inherited in a custom module"""
-
# TODO: take multicurrency into account
+ company_currency = self.env.user.company_id.currency_id
+ if bank_line.currency != company_currency:
+ raise UserError(_(
+ "Cannot generate the transfer move when "
+ "the currency of the payment (%s) is not the "
+ "same as the currency of the company. This "
+ "is not supported for the moment.")
+ % (bank_line.currency.name, company_currency.name))
aml_obj = self.env['account.move.line']
# create the payment/debit counterpart move line
# on the partner account
partner_ml_vals = self._prepare_move_line_partner_account(
- line, move, labels)
+ bank_line, move, labels)
partner_move_line = aml_obj.create(partner_ml_vals)
# register the payment/debit move line
# on the payment line and call reconciliation on it
- line.write({'transit_move_line_id': partner_move_line.id})
+ bank_line.write({'transit_move_line_id': partner_move_line.id})
@api.multi
def _reconcile_payment_lines(self, bank_payment_lines):
@@ -233,28 +241,25 @@ class PaymentOrder(models.Model):
# key = unique identifier (date or True or line.id)
# value = [pay_line1, pay_line2, ...]
trfmoves = {}
- if self.mode.transfer_move_option == 'line':
- for line in self.bank_line_ids:
- trfmoves[line.id] = [line]
- else:
- for line in self.bank_line_ids:
- if line.date in trfmoves:
- trfmoves[line.date].append(line)
- else:
- trfmoves[line.date] = [line]
+ for bline in self.bank_line_ids:
+ hashcode = bline.move_line_transfer_account_hashcode()
+ if hashcode in trfmoves:
+ trfmoves[hashcode].append(bline)
+ else:
+ trfmoves[hashcode] = [bline]
- for identifier, lines in trfmoves.iteritems():
+ for hashcode, blines in trfmoves.iteritems():
mvals = self._prepare_transfer_move()
move = am_obj.create(mvals)
total_amount = 0
- for line in lines:
- total_amount += line.amount_currency
- self._create_move_line_partner_account(line, move, labels)
+ for bline in blines:
+ total_amount += bline.amount_currency
+ self._create_move_line_partner_account(bline, move, labels)
# create the payment/debit move line on the transfer account
trf_ml_vals = self._prepare_move_line_transfer_account(
- total_amount, move, lines, labels)
+ total_amount, move, blines, labels)
aml_obj.create(trf_ml_vals)
- self._reconcile_payment_lines(lines)
+ self._reconcile_payment_lines(blines)
# consider entry_posted on account_journal
if move.journal_id.entry_posted:
diff --git a/account_banking_payment_transfer/model/bank_payment_line.py b/account_banking_payment_transfer/model/bank_payment_line.py
new file mode 100644
index 000000000..d1b60360c
--- /dev/null
+++ b/account_banking_payment_transfer/model/bank_payment_line.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2009 EduSense BV ().
+# (C) 2011 - 2013 Therp BV ().
+# (C) 2015 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 import models, fields, api
+
+
+class BankPaymentLine(models.Model):
+ _inherit = 'bank.payment.line'
+
+ transit_move_line_id = fields.Many2one(
+ 'account.move.line', string='Transfer move line', readonly=True,
+ help="Move line through which the payment/debit order "
+ "pays the invoice")
+ transfer_move_line_id = fields.Many2one(
+ 'account.move.line', compute='_get_transfer_move_line',
+ string='Transfer move line counterpart',
+ help="Counterpart move line on the transfer account")
+
+ @api.multi
+ def move_line_transfer_account_hashcode(self):
+ """
+ This method is inherited in the module
+ account_banking_sepa_direct_debit
+ """
+ self.ensure_one()
+ if self.order_id.mode.transfer_move_option == 'date':
+ hashcode = self.date
+ else:
+ hashcode = unicode(self.id)
+ return hashcode
+
+ @api.multi
+ def _get_transfer_move_line(self):
+ for bank_line in self:
+ if bank_line.transit_move_line_id:
+ order_type = bank_line.order_id.payment_order_type
+ trf_lines = bank_line.transit_move_line_id.move_id.line_id
+ for move_line in trf_lines:
+ if order_type == 'debit' and move_line.debit > 0:
+ bank_line.transfer_move_line_id = move_line
+ elif order_type == 'payment' and move_line.credit > 0:
+ bank_line.transfer_move_line_id = move_line
+
+ @api.one
+ def debit_reconcile(self):
+ """
+ Reconcile a debit order's payment line with the the move line
+ that it is based on. Called from payment_order.action_sent().
+ As the amount is derived directly from the counterpart move line,
+ we do not expect a write off. Take partial reconciliations into
+ account though.
+
+ :param payment_line_id: the single id of the canceled payment line
+ """
+
+ transit_move_line = self.transit_move_line_id
+
+# if (not transit_move_line or not torec_move_line):
+# raise exceptions.Warning(
+# _('Can not reconcile: no move line for line %s') % self.name
+# )
+# if torec_move_line.reconcile_id:
+# raise exceptions.Warning(
+# _('Move line %s has already been reconciled') %
+# torec_move_line.name
+# )
+# if (transit_move_line.reconcile_id or
+# transit_move_line.reconcile_partial_id):
+# raise exceptions.Warning(
+# _('Move line %s has already been reconciled') %
+# transit_move_line.name
+# )
+
+ lines_to_rec = transit_move_line
+ for payment_line in self.payment_line_ids:
+ lines_to_rec += payment_line.move_line_id
+
+ lines_to_rec.reconcile_partial(type='auto')
diff --git a/account_banking_payment_transfer/model/payment_line.py b/account_banking_payment_transfer/model/payment_line.py
index 76262a4b3..ee0be94b3 100644
--- a/account_banking_payment_transfer/model/payment_line.py
+++ b/account_banking_payment_transfer/model/payment_line.py
@@ -22,8 +22,8 @@
# along with this program. If not, see .
#
##############################################################################
-from openerp import models, fields, workflow, api, exceptions
-from openerp.tools.translate import _
+
+from openerp import models, fields, api
class PaymentLine(models.Model):
@@ -38,63 +38,14 @@ class PaymentLine(models.Model):
msg = fields.Char('Message', required=False, readonly=True, default='')
date_done = fields.Date('Date Confirmed', select=True, readonly=True)
-
-class BankPaymentLine(models.Model):
- _inherit = 'bank.payment.line'
-
- transit_move_line_id = fields.Many2one(
- 'account.move.line', string='Transfer move line', readonly=True,
- help="Move line through which the payment/debit order "
- "pays the invoice")
- transfer_move_line_id = fields.Many2one(
- 'account.move.line', compute='_get_transfer_move_line',
- string='Transfer move line counterpart',
- help="Counterpart move line on the transfer account")
-
@api.multi
- def _get_transfer_move_line(self):
- for bank_line in self:
- if bank_line.transit_move_line_id:
- order_type = bank_line.order_id.payment_order_type
- trf_lines = bank_line.transit_move_line_id.move_id.line_id
- for move_line in trf_lines:
- if order_type == 'debit' and move_line.debit > 0:
- bank_line.transfer_move_line_id = move_line
- elif order_type == 'payment' and move_line.credit > 0:
- bank_line.transfer_move_line_id = move_line
-
- @api.one
- def debit_reconcile(self):
+ def payment_line_hashcode(self):
"""
- Reconcile a debit order's payment line with the the move line
- that it is based on. Called from payment_order.action_sent().
- As the amount is derived directly from the counterpart move line,
- we do not expect a write off. Take partial reconciliations into
- account though.
-
- :param payment_line_id: the single id of the canceled payment line
+ Don't group the payment lines that are attached to the same supplier
+ but to move lines with different accounts (very unlikely),
+ for easier generation/comprehension of the transfer move
"""
-
- transit_move_line = self.transit_move_line_id
-
-# if (not transit_move_line or not torec_move_line):
-# raise exceptions.UserError(
-# _('Can not reconcile: no move line for line %s') % self.name
-# )
-# if torec_move_line.reconcile_id:
-# raise exceptions.UserError(
-# _('Move line %s has already been reconciled') %
-# torec_move_line.name
-# )
-# if (transit_move_line.reconcile_id or
-# transit_move_line.reconcile_partial_id):
-# raise exceptions.UserError(
-# _('Move line %s has already been reconciled') %
-# transit_move_line.name
-# )
-
- lines_to_rec = transit_move_line
- for payment_line in self.payment_line_ids:
- lines_to_rec += payment_line.move_line_id
-
- lines_to_rec.reconcile_partial(type='auto')
+ res = super(PaymentLine, self).payment_line_hashcode()
+ res += '-' + unicode(
+ self.move_line_id and self.move_line_id.account_id or False)
+ return res
diff --git a/account_banking_sepa_direct_debit/models/__init__.py b/account_banking_sepa_direct_debit/models/__init__.py
index 153ab3543..ac7674156 100644
--- a/account_banking_sepa_direct_debit/models/__init__.py
+++ b/account_banking_sepa_direct_debit/models/__init__.py
@@ -1,24 +1,5 @@
-# -*- encoding: utf-8 -*-
-##############################################################################
-#
-# SEPA Direct Debit module for OpenERP
-# Copyright (C) 2013 Akretion (http://www.akretion.com)
-# @author: Alexis de Lattre
-#
-# 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 .
-#
-##############################################################################
+# -*- coding: utf-8 -*-
from . import res_company
from . import account_banking_mandate
+from . import bank_payment_line
diff --git a/account_banking_sepa_direct_debit/models/bank_payment_line.py b/account_banking_sepa_direct_debit/models/bank_payment_line.py
new file mode 100644
index 000000000..9da270e80
--- /dev/null
+++ b/account_banking_sepa_direct_debit/models/bank_payment_line.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# SEPA Direct Debit module for Odoo
+# Copyright (C) 2015 Akretion (http://www.akretion.com)
+# @author: Alexis de Lattre
+#
+# 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 import models, api
+
+
+class BankPaymentLine(models.Model):
+ _inherit = 'bank.payment.line'
+
+ @api.multi
+ def move_line_transfer_account_hashcode(self):
+ """
+ From my experience, even when you ask several direct debits
+ at the same date with enough delay, you will have several credits
+ on your bank statement: one for each mandate types.
+ So we split the transfer move lines by mandate type, so easier
+ reconciliation of the bank statement.
+ """
+ hashcode = super(BankPaymentLine, self).\
+ move_line_transfer_account_hashcode()
+ hashcode += self.mandate_id.type
+ return hashcode
From fc4b88c2dbf2ee5955681f809dd8cff985824b99 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Thu, 24 Sep 2015 11:47:03 +0200
Subject: [PATCH 05/28] Remove dead XML code
---
account_direct_debit/__openerp__.py | 1 -
.../views/account_invoice.xml | 39 -------------------
2 files changed, 40 deletions(-)
delete mode 100644 account_direct_debit/views/account_invoice.xml
diff --git a/account_direct_debit/__openerp__.py b/account_direct_debit/__openerp__.py
index ace7cda3d..7fac10be7 100644
--- a/account_direct_debit/__openerp__.py
+++ b/account_direct_debit/__openerp__.py
@@ -30,7 +30,6 @@
'depends': ['account_banking_payment_export'],
'data': [
'views/account_payment.xml',
- 'views/account_invoice.xml',
'views/payment_mode.xml',
'views/payment_mode_type.xml',
'data/account_payment_term.xml',
diff --git a/account_direct_debit/views/account_invoice.xml b/account_direct_debit/views/account_invoice.xml
deleted file mode 100644
index 76a46e128..000000000
--- a/account_direct_debit/views/account_invoice.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
- account.invoice.form
- account.invoice
-
-
-
-
-
-
-
-
- account.invoice.select direct debit
- account.invoice
- search
-
-
-
-
-
-
-
-
-
From dda5e1ccb5014bb27d4e6faf032e3e9ed9873124 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Thu, 24 Sep 2015 12:29:43 +0200
Subject: [PATCH 06/28] FIX Reading wrong field for sequence type of SEPA DD
Loop on bank payment lines instead of payment lines
---
.../models/bank_payment_line.py | 2 +-
.../wizard/export_sdd.py | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/account_banking_sepa_direct_debit/models/bank_payment_line.py b/account_banking_sepa_direct_debit/models/bank_payment_line.py
index 9da270e80..67a0da3f5 100644
--- a/account_banking_sepa_direct_debit/models/bank_payment_line.py
+++ b/account_banking_sepa_direct_debit/models/bank_payment_line.py
@@ -37,5 +37,5 @@ class BankPaymentLine(models.Model):
"""
hashcode = super(BankPaymentLine, self).\
move_line_transfer_account_hashcode()
- hashcode += self.mandate_id.type
+ hashcode += '-' + unicode(self.mandate_id.recurrent_sequence_type)
return hashcode
diff --git a/account_banking_sepa_direct_debit/wizard/export_sdd.py b/account_banking_sepa_direct_debit/wizard/export_sdd.py
index ff5662c46..53bdd3d10 100644
--- a/account_banking_sepa_direct_debit/wizard/export_sdd.py
+++ b/account_banking_sepa_direct_debit/wizard/export_sdd.py
@@ -368,18 +368,18 @@ class BankingExportSddWizard(models.TransientModel):
to_expire_mandates = abmo.browse([])
first_mandates = abmo.browse([])
all_mandates = abmo.browse([])
- for line in order.line_ids:
- if line.mandate_id in all_mandates:
+ for bline in order.bank_line_ids:
+ if bline.mandate_id in all_mandates:
continue
- all_mandates += line.mandate_id
- if line.mandate_id.type == 'oneoff':
- to_expire_mandates += line.mandate_id
- elif line.mandate_id.type == 'recurrent':
- seq_type = line.mandate_id.recurrent_sequence_type
+ all_mandates += bline.mandate_id
+ if bline.mandate_id.type == 'oneoff':
+ to_expire_mandates += bline.mandate_id
+ elif bline.mandate_id.type == 'recurrent':
+ seq_type = bline.mandate_id.recurrent_sequence_type
if seq_type == 'final':
- to_expire_mandates += line.mandate_id
+ to_expire_mandates += bline.mandate_id
elif seq_type == 'first':
- first_mandates += line.mandate_id
+ first_mandates += bline.mandate_id
all_mandates.write(
{'last_debit_date': fields.Date.context_today(self)})
to_expire_mandates.write({'state': 'expired'})
From 7b62566b29d6fbeb1bf3d7631666228e6d7681af Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Mon, 19 Oct 2015 17:50:53 +0200
Subject: [PATCH 07/28] Forgot to remove a usecase of debit_denied
Add ACL
---
account_direct_debit/wizard/payment_order_create.py | 5 +----
account_payment_partner/security/ir.model.access.csv | 1 +
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/account_direct_debit/wizard/payment_order_create.py b/account_direct_debit/wizard/payment_order_create.py
index 61eea19ca..cd5ee9335 100644
--- a/account_direct_debit/wizard/payment_order_create.py
+++ b/account_direct_debit/wizard/payment_order_create.py
@@ -38,8 +38,5 @@ class PaymentOrderCreate(models.TransientModel):
# invoices and payment lines linked to customer refunds
# in order to debit the customer of the total of his
# invoices minus his refunds
- domain += ['|',
- ('invoice', '=', False),
- ('invoice.state', '!=', 'debit_denied'),
- ('account_id.type', '=', 'receivable')]
+ domain += [('account_id.type', '=', 'receivable')]
return True
diff --git a/account_payment_partner/security/ir.model.access.csv b/account_payment_partner/security/ir.model.access.csv
index b277f0229..ac6d96dfd 100644
--- a/account_payment_partner/security/ir.model.access.csv
+++ b/account_payment_partner/security/ir.model.access.csv
@@ -1,2 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_payment_mode_read,Read access on payment.mode to Employees,account_payment.model_payment_mode,base.group_user,1,0,0,0
+access_payment_mode_type_read,Read access on payment.mode.type to Employees,account_banking_payment_export.model_payment_mode_type,base.group_user,1,0,0,0
From 287c05c4c32be02fb2fd7286375928239c74d33f Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Mon, 9 Nov 2015 23:30:18 +0100
Subject: [PATCH 08/28] Add constraints on BIC length (8 or 11 chars)
---
.../models/__init__.py | 1 +
.../models/res_partner_bank.py | 51 +++++++++++++++++++
2 files changed, 52 insertions(+)
create mode 100644 account_banking_payment_export/models/res_partner_bank.py
diff --git a/account_banking_payment_export/models/__init__.py b/account_banking_payment_export/models/__init__.py
index 738dcdbfd..f9da02f9f 100644
--- a/account_banking_payment_export/models/__init__.py
+++ b/account_banking_payment_export/models/__init__.py
@@ -8,3 +8,4 @@ from . import account_move_line
from . import account_invoice
from . import bank_payment_line
from . import payment_line
+from . import res_partner_bank
diff --git a/account_banking_payment_export/models/res_partner_bank.py b/account_banking_payment_export/models/res_partner_bank.py
new file mode 100644
index 000000000..efa2aba70
--- /dev/null
+++ b/account_banking_payment_export/models/res_partner_bank.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2015 Akretion (http://www.akretion.com)
+# @author Alexis de Lattre
+#
+# 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 import models, api, _
+from openerp.exceptions import ValidationError
+
+
+class ResPartnerBank(models.Model):
+ _inherit = 'res.partner.bank'
+
+ @api.multi
+ @api.constrains('bank_bic')
+ def check_bic_length(self):
+ for pbank in self:
+ if pbank.bank_bic and len(pbank.bank_bic) not in (8, 11):
+ raise ValidationError(_(
+ "A valid BIC contains 8 or 11 caracters. The BIC '%s' "
+ "contains %d caracters, so it is not valid.")
+ % (pbank.bank_bic, len(pbank.bank_bic)))
+
+
+class ResBank(models.Model):
+ _inherit = 'res.bank'
+
+ @api.multi
+ @api.constrains('bic')
+ def check_bic_length(self):
+ for bank in self:
+ if bank.bic and len(bank.bic) not in (8, 11):
+ raise ValidationError(_(
+ "A valid BIC contains 8 or 11 caracters. The BIC '%s' "
+ "contains %d caracters, so it is not valid.")
+ % (bank.bic, len(bank.bic)))
From e881c2aaa1987b99d986cec9903a02d079c3455b Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Mon, 9 Nov 2015 23:34:44 +0100
Subject: [PATCH 09/28] Post transfer account move by default, like for an
invoice
Add sum in bank payment line tree view
---
account_banking_payment_export/views/bank_payment_line.xml | 3 ++-
account_banking_payment_transfer/model/account_payment.py | 6 ++----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/account_banking_payment_export/views/bank_payment_line.xml b/account_banking_payment_export/views/bank_payment_line.xml
index df4a308ba..a159af44d 100644
--- a/account_banking_payment_export/views/bank_payment_line.xml
+++ b/account_banking_payment_export/views/bank_payment_line.xml
@@ -46,7 +46,8 @@
+ options="{'currency_field': 'currency'}"
+ sum="Total Amount"/>
Date: Tue, 10 Nov 2015 10:04:29 +0100
Subject: [PATCH 10/28] Better checks and nice error messages
---
.../model/bank_payment_line.py | 53 +++++++++++++------
1 file changed, 36 insertions(+), 17 deletions(-)
diff --git a/account_banking_payment_transfer/model/bank_payment_line.py b/account_banking_payment_transfer/model/bank_payment_line.py
index d1b60360c..d46fa8d59 100644
--- a/account_banking_payment_transfer/model/bank_payment_line.py
+++ b/account_banking_payment_transfer/model/bank_payment_line.py
@@ -20,7 +20,8 @@
#
##############################################################################
-from openerp import models, fields, api
+from openerp import models, fields, api, _
+from openerp.exceptions import Warning as UserError
class BankPaymentLine(models.Model):
@@ -74,24 +75,42 @@ class BankPaymentLine(models.Model):
transit_move_line = self.transit_move_line_id
-# if (not transit_move_line or not torec_move_line):
-# raise exceptions.Warning(
-# _('Can not reconcile: no move line for line %s') % self.name
-# )
-# if torec_move_line.reconcile_id:
-# raise exceptions.Warning(
-# _('Move line %s has already been reconciled') %
-# torec_move_line.name
-# )
-# if (transit_move_line.reconcile_id or
-# transit_move_line.reconcile_partial_id):
-# raise exceptions.Warning(
-# _('Move line %s has already been reconciled') %
-# transit_move_line.name
-# )
-
+ assert not transit_move_line.reconcile_id,\
+ 'Transit move should not be reconciled'
+ assert not transit_move_line.reconcile_partial_id,\
+ 'Transit move should not be partially reconciled'
lines_to_rec = transit_move_line
for payment_line in self.payment_line_ids:
+
+ if not payment_line.move_line_id:
+ raise UserError(_(
+ "Can not reconcile: no move line for "
+ "payment line %s of partner '%s'.") % (
+ payment_line.name,
+ payment_line.partner_id.name))
+ if payment_line.move_line_id.reconcile_id:
+ raise UserError(_(
+ "Move line '%s' of partner '%s' has already "
+ "been reconciled") % (
+ payment_line.move_line_id.name,
+ payment_line.partner_id.name))
+ if payment_line.move_line_id.reconcile_partial_id:
+ raise UserError(_(
+ "Move line '%s' of partner '%s' has already "
+ "been partially reconciled") % (
+ payment_line.move_line_id.name,
+ payment_line.partner_id.name))
+ if (
+ payment_line.move_line_id.account_id !=
+ transit_move_line.account_id):
+ raise UserError(_(
+ "For partner '%s', the account of the account "
+ "move line to pay (%s) is different from the "
+ "account of of the transit move line (%s).") % (
+ payment_line.move_line_id.partner_id.name,
+ payment_line.move_line_id.account_id.code,
+ transit_move_line.account_id.code))
+
lines_to_rec += payment_line.move_line_id
lines_to_rec.reconcile_partial(type='auto')
From 4f3f094370aa9a485f44b0f7391cadb988e7a6e3 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Wed, 11 Nov 2015 01:09:30 +0100
Subject: [PATCH 11/28] FIX better handling of account_id in transfer move
---
.../model/account_payment.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/account_banking_payment_transfer/model/account_payment.py b/account_banking_payment_transfer/model/account_payment.py
index 0748c79c6..42a1c1d14 100644
--- a/account_banking_payment_transfer/model/account_payment.py
+++ b/account_banking_payment_transfer/model/account_payment.py
@@ -169,10 +169,15 @@ class PaymentOrder(models.Model):
def _prepare_move_line_partner_account(self, bank_line, move, labels):
# TODO : ALEXIS check don't group if move_line_id.account_id
# is not the same
- if self.payment_order_type == 'debit':
- account_id = bank_line.partner_id.property_account_receivable.id
+ if bank_line.payment_line_ids[0].move_line_id:
+ account_id =\
+ bank_line.payment_line_ids[0].move_line_id.account_id.id
else:
- account_id = bank_line.partner_id.property_account_payable.id
+ if self.payment_order_type == 'debit':
+ account_id =\
+ bank_line.partner_id.property_account_receivable.id
+ else:
+ account_id = bank_line.partner_id.property_account_payable.id
vals = {
'name': _('%s line %s') % (
labels[self.payment_order_type], bank_line.name),
From f9bde4af355ee102146303d0459f7f144d431c57 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Tue, 24 Nov 2015 21:38:13 +0100
Subject: [PATCH 12/28] Add bank_line_count field and display it in view
Display date_sent field in view
---
.../models/account_payment.py | 8 ++++++++
.../views/account_payment.xml | 13 ++++++++++++-
.../view/account_payment.xml | 17 ++++++++++++++++-
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/account_banking_payment_export/models/account_payment.py b/account_banking_payment_export/models/account_payment.py
index 74ea5108c..13a7c1a9d 100644
--- a/account_banking_payment_export/models/account_payment.py
+++ b/account_banking_payment_export/models/account_payment.py
@@ -47,12 +47,20 @@ class PaymentOrder(models.Model):
'bank.payment.line', 'order_id', string="Bank Payment Lines",
readonly=True)
total = fields.Float(compute='_compute_total', store=True)
+ bank_line_count = fields.Integer(
+ compute='_bank_line_count', string='Number of Bank Lines')
@api.depends('line_ids', 'line_ids.amount')
@api.one
def _compute_total(self):
self.total = sum(self.mapped('line_ids.amount') or [0.0])
+ @api.multi
+ @api.depends('bank_line_ids')
+ def _bank_line_count(self):
+ for order in self:
+ order.bank_line_count = len(order.bank_line_ids)
+
@api.multi
def launch_wizard(self):
"""Search for a wizard to launch according to the type.
diff --git a/account_banking_payment_export/views/account_payment.xml b/account_banking_payment_export/views/account_payment.xml
index 0e9340e1e..8884061a8 100644
--- a/account_banking_payment_export/views/account_payment.xml
+++ b/account_banking_payment_export/views/account_payment.xml
@@ -14,7 +14,8 @@
-
+
+ {
@@ -91,6 +92,16 @@
+
+ account_banking_payment_export.payment.order.tree
+
+ payment.order
+
+
+
+
+
+
diff --git a/account_banking_payment_transfer/view/account_payment.xml b/account_banking_payment_transfer/view/account_payment.xml
index 8bb537622..4ed6b9c62 100644
--- a/account_banking_payment_transfer/view/account_payment.xml
+++ b/account_banking_payment_transfer/view/account_payment.xml
@@ -4,7 +4,7 @@
account.payment.order.form (account_banking_payment_transfer)payment.order
-
+
+
+
+
+
+
+ account_banking_payment_transfer.payment.order.tree
+ payment.order
+
+
+
+
+
+
+
+
From 32470c37056aa8dd402a3175df4483df9a4aa494 Mon Sep 17 00:00:00 2001
From: Alexis de Lattre
Date: Tue, 1 Dec 2015 16:39:58 +0100
Subject: [PATCH 13/28] Better filters on payment.order.create wizard
Add default values for those filters on payment.mode
---
.../models/payment_mode.py | 11 ++++
.../views/payment_mode.xml | 6 ++
.../wizard/payment_order_create.py | 40 ++++++++++---
.../wizard/payment_order_create_view.xml | 9 +++
account_payment_partner/__openerp__.py | 2 +
account_payment_partner/models/__init__.py | 23 +------
.../models/payment_mode.py | 32 ++++++++++
.../views/payment_mode.xml | 20 +++++++
.../wizard/payment_order_create.py | 60 ++++++++++---------
.../wizard/payment_order_create_view.xml | 25 ++++++++
10 files changed, 171 insertions(+), 57 deletions(-)
create mode 100644 account_payment_partner/models/payment_mode.py
create mode 100644 account_payment_partner/views/payment_mode.xml
create mode 100644 account_payment_partner/wizard/payment_order_create_view.xml
diff --git a/account_banking_payment_export/models/payment_mode.py b/account_banking_payment_export/models/payment_mode.py
index a0084f114..dff0071e1 100644
--- a/account_banking_payment_export/models/payment_mode.py
+++ b/account_banking_payment_export/models/payment_mode.py
@@ -108,3 +108,14 @@ class PaymentMode(models.Model):
purchase_ok = fields.Boolean(string='Selectable on purchase operations',
default=True)
note = fields.Text(string="Note", translate=True)
+ # Default options for the "payment.order.create" wizard
+ default_journal_ids = fields.Many2many(
+ 'account.journal', string="Journals Filter")
+ default_invoice = fields.Boolean(
+ string='Linked to an Invoice or Refund', default=True)
+ default_date_type = fields.Selection([
+ ('due', 'Due'),
+ ('move', 'Move'),
+ ], default='due', string="Type of Date Filter")
+ default_populate_results = fields.Boolean(
+ string='Populate Results Directly')
diff --git a/account_banking_payment_export/views/payment_mode.xml b/account_banking_payment_export/views/payment_mode.xml
index 5441bb428..cdc5a33c1 100644
--- a/account_banking_payment_export/views/payment_mode.xml
+++ b/account_banking_payment_export/views/payment_mode.xml
@@ -17,6 +17,12 @@
\n"
+" A SEPA Direct Debit Mandate is a document signed by your customer that gives you the autorization to do one or several direct debits on his bank account.\n"
+"
\n"
+" "
msgstr "
\n"
-" Pulse para crear un nuevo mandato de adeudo directo SEPA.\n"
-"
\n"
-" Un mandato de adeudo directo SEPA es un documento firmado por su cliente que le autoriza a realizar uno o más cobros directos en su cuenta bancaria, también conocidas como domiciliaciones.\n"
-"
\n"
-" "
+" Pulse para crear un nuevo mandato bancario.\n"
+"
\n"
+" Un mandato bancario es un documento firmado por su cliente que le da la autorización para hacer una o varias operaciones en su cuenta bancaria.\n"
+"