Code refactoring of module account_payment_line_cancel

This commit is contained in:
Emanuel Cino
2017-12-19 17:25:41 +01:00
parent 1cb2028db8
commit ee04fcfa42
22 changed files with 344 additions and 426 deletions

View File

@@ -1,29 +0,0 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3
======================
Cancel account payment
======================
This module allow you to automaticly cancel en remove a payment from a payment
order when the payment need to be cancel (for exemple from a when a payment is
rejected). The module allow you to free invoice and automaticly put
the invoice in a new payment order.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://odoo-community.org/logo.png>`_.
Contributors
------------
* Marco Monzione
* Emanuel Cino
Do not contact contributors directly about support or help with
technical issues.

View File

@@ -1,2 +0,0 @@
from . import models

View File

@@ -1,21 +0,0 @@
{
'name': 'Account payment cancel',
'version': '10.0.1.0.0',
'license': 'AGPL-3',
'author': 'Monzione Marco',
'website': 'https://www.compassion.ch',
'category': 'Banking addons',
'depends': [
'account_payment_order',
],
'data': [
'views/invoice_view.xml',
],
'demo': [
'res/test_data.yml',
],
'test': [
],
'installable': True,
}

View File

@@ -1,3 +0,0 @@
from . import account_payment_cancel
from . import invoice_free_wizard
from . import invoice

View File

@@ -1,130 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2017 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
#
# The licence is in the file __manifest__.py
#
##############################################################################
from odoo import models
class AccountCancelPayment(models.AbstractModel):
_name = 'account.payment.cancel'
def cancel_payment(self, payment_order, bank_payment_line,
data_supp):
"""
This method proceed to call private methods to remove payment
from payment order
:param payment_order: The order where to remove the payment
:param bank_payment_line: The payment to remove
:param data_supp: additional information used in the message
:return: -
"""
if payment_order and bank_payment_line:
# Retrieve all account_payment_line associated to the
# current bank_payment_line
account_payment_lines = self.env['account.payment.line'].search(
[('bank_line_id', '=', bank_payment_line.id)])
if account_payment_lines:
self._process_invoice_remove(
account_payment_lines, payment_order, data_supp)
def _process_invoice_remove(self, account_payment_lines, payment_order,
data_supp):
"""
This method unreconcile the given move lines and remove the payment.
:param account_payment_lines: The payment to remove
:param payment_order: The payment order where to remove the payment
:param data_supp: additional information used in the message
:return: -
"""
# Retrieve all account_move_line(s) associated with the previous
# account_payment_line(s).
all_account_move_lines = account_payment_lines.mapped(
'move_line_id')
full_reconcile_id = all_account_move_lines.mapped(
'full_reconcile_id').id
if full_reconcile_id:
# Retrieve the counterpart of the previous move_line(s).
# The counter parth should always be unique.
account_move_line_counterpart = self.env['account.move.line'].\
search([('full_reconcile_id', '=', full_reconcile_id),
('id', 'not in', all_account_move_lines.ids)], limit=1)
# Keep only the move lines that belong to the desired payment order
filtered_move_lines_counterpart = account_move_line_counterpart.\
filtered(lambda l: l.move_id.payment_order_id == payment_order)
account_move_counterpart = filtered_move_lines_counterpart.move_id
# All the move lines with the same reconcile id are unreconciled.
filtered_move_lines_counterpart.remove_move_reconcile()
# unpost and delete the move from the journal.
account_move_counterpart.button_cancel()
account_move_counterpart.unlink()
# Delete the payment line in the payment order.
account_payment_lines.unlink()
# Search if there is something left in the payment order.
account_payment_line = self.env['account.payment.line'].search(
[('order_id', '=', payment_order.id)])
if len(account_payment_line) == 0 and \
payment_order.state == 'uploaded':
payment_order.action_done_cancel()
# Add the message to the invoice and to the payment order
self._post_message(data_supp, all_account_move_lines, payment_order)
def _post_message(self, data_supp, account_move_lines, payment_order):
"""
This method is used to post message on the invoices that have been
deleted from the payment order and it post a message too on the
payment order for each deleted invoice.
:param data_supp: additional information used in the message
:param account_move_lines: used to find the invoices where to post
the message
:param payment_order: used to post the message for each
deleted invoices
:return: -
"""
for account_move_line in account_move_lines:
# Create a link to the invoice that was removed
url = '<a href="web#id={}&view_type=form&model=' \
'account.invoice">{}</a>'. \
format(account_move_line.invoice_id.id,
account_move_line.invoice_id.move_name)
if data_supp and 'add_tl_inf' in data_supp:
# Add a message to the invoice
account_move_line.invoice_id.message_post(
"The invoice has been removed from the payment "
"order because: " +
data_supp['add_tl_inf'])
# Add a message to the payment order
payment_order.message_post(
url + " has been removed because : " + data_supp[
'add_tl_inf'])
else:
# Add a message to the invoice
account_move_line.invoice_id.message_post(
"The invoice has been removed from the payment order,"
" no reason given.")
# Add a message to the payment order
payment_order.message_post(
url + " has been removed no reason given.")

View File

@@ -1,49 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2017 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
#
# The licence is in the file __manifest__.py
#
##############################################################################
from odoo import models, api, _, exceptions
class AccountInvoice(models.Model):
''' Inherit invoice to add invoice freeing functionality. It's about
moving related payment line in a new cancelled payment order. This
way, the invoice (properly, invoice's move lines) can be used again
in another payment order.
'''
_inherit = 'account.invoice'
@api.multi
def cancel_payment_lines(self):
''' This function simply finds related payment lines and move them
in a new payment order.
'''
mov_line_obj = self.env['account.move.line']
pay_line_obj = self.env['account.payment.line']
account_payment_cancel = self.env['account.payment.cancel']
move_ids = self.mapped('move_id.id')
move_line_ids = mov_line_obj.search([('move_id', 'in', move_ids)]).ids
payment_lines = pay_line_obj.search([
('move_line_id', 'in', move_line_ids)
])
if not payment_lines:
raise exceptions.UserError(_('No payment line found !'))
bank_payment_lines = payment_lines.mapped('bank_line_id')
# It should have only one payment order
old_pay_order = payment_lines.mapped('order_id')
for bank_payment_line in bank_payment_lines:
account_payment_cancel.cancel_payment(old_pay_order,
bank_payment_line,
None)

View File

@@ -1,48 +0,0 @@
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Create partner
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
!record {model: res.partner, id: customer, view: False}:
name: "pain000 test"
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Create bank
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
!record {model: res.bank, id: bank_post, view: False}:
name: 'Postfinance AG'
bic: 'POFICHBEXXX'
street: 'Postfinance'
zip: '3030'
city: 'Bern'
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Create partner bank
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
!record {model: res.partner.bank, id: company_bank_post, view: False}:
acc_type: 'postal'
acc_number: '25-9778-2'
partner_id: base.main_partner #YourCompany
bank_id: bank_post
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Create journal
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
!record {model: account.journal, id: lsv_account_journal, view: False}:
name: '2017/1013'
type: bank
bank_account_id: company_bank_post
update_posted: True
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Create payment mode
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
!record {model: account.payment.mode, id: dd_pay_mode, view: False}:
bank_account_link: variable
name: 'DD'
active: True
payment_method_id: !ref {model: account.payment.method,search: "[('id','=','2')]"}
payment_order_ok: True
transfer_journal_id: !ref {model: account.journal, search: "[('type','=','bank')]"}
transfer_account_id: !ref {model: account.account, search: "[('code','=','1090')]"}
offsetting_account: 'transfer_account'

View File

@@ -1 +0,0 @@
from . import test_payment_cancel

View File

@@ -1,127 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2017 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
#
# The licence is in the file __manifest__.py
#
##############################################################################
from odoo.tests import TransactionCase
from odoo import fields
class TestPaymentCancel(TransactionCase):
def setUp(self):
super(TestPaymentCancel, self).setUp()
self.invoice_name = 'test invoice pain000'
self.invoice_line_name = 'test invoice line pain000'
self.order_name = '2017/1013'
self.journal_name = '2017/1013'
self.payment_line_name = 'Ltest'
# Create invoice
self.invoice = self.env['account.invoice'].create({
'company_id': self.env['res.company'].search([
('name', '=', 'YourCompany')
]).id,
'move_name': self.invoice_name,
'journal_id': self.env['account.journal'].search([
('name', '=', self.journal_name)
]).id,
'currency_id': self.env['res.currency'].search([
('name', '=', 'CHF')
]).id,
'account_id': self.env['account.account'].search([
('code', '=', '1100')
]).id,
'type': 'in_invoice',
'partner_id': self.env['res.partner'].search([
('name', '=', 'pain000 test')
]).id,
'date_invoice': fields.Datetime.now(),
'partner_bank_id': self.env['res.partner.bank'].search([
('acc_number', '=', '25-9778-2')
]).id,
'payment_mode_id': self.env['account.payment.mode'].search([
('name', '=', 'DD')
]).id
})
# Add an invoice line to our invoice.
self.env['account.invoice.line'].create({
'account_id': self.env['account.account'].search([
('code', '=', '3200')
]).id,
'name': 'test invoice line pain000',
'price_unit': 600.0,
'quantity': 1.0,
'product_id': self.env['product.product'].search([
('default_code', '=', 'E-COM09')
]).id,
'invoice_id': self.invoice.id
})
# Validate the invoice
self.invoice.action_invoice_open()
# Create a payment order
action = self.invoice.create_account_payment_line()
payment_order_id = action['res_id']
payment_order = self.env['account.payment.order'].search(
[('id', '=', payment_order_id)])
partner_bank = self.env['account.journal'].search(
[('name', '=', self.journal_name)])
bank = self.env['account.journal'].search([('name', '=', 'Bank')])
payment_order.name = self.order_name
bank.update_posted = True
payment_order.journal_id = partner_bank.id
# Confirm payment order
payment_order.draft2open()
# Generate payment file
payment_order.open2generated()
# File successfully uploaded
payment_order.generated2uploaded()
payment_line = self.env['bank.payment.line'].search(
[('order_id', '=', payment_order.id)])
payment_line.name = self.payment_line_name
def test_free_invoice(self):
self._invoice_free()
# Test if the move related to the invoice are deleted after the invoice
# is freed.
payment_order = self.env['account.payment.order'].search(
[('name', '=', self.order_name)])
account_move = self.env['account.move'].search(
[('payment_order_id', '=', payment_order.id)])
self.assertFalse(account_move)
# Test if the order is in cancel state.
payment_order = self.env['account.payment.order'].search(
[('name', '=', self.order_name)])
self.assertEqual(payment_order.state, 'cancel')
# Test if the invoice is in open state.
self.assertEqual(self.invoice.state, 'open')
def _invoice_free(self):
invoice = self.env['account.invoice'].search(
[('move_name', '=', self.invoice_name)])
free_wizard = self.env['account.invoice.free'].with_context(
active_ids=invoice.ids).create({})
free_wizard.invoice_free()

View File

@@ -0,0 +1,80 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3
===================
Cancel payment line
===================
This module allows you to cancel and remove a payment line from a payment order when the payment needs to be cancelled (for example when a payment is rejected).
The module allows you as well to free an invoice that was imported in a payment order and automatically cancel the payment lines that were generated.
Usage
=====
To use this module, you need to:
#. Go in payment orders
#. Click on the cancel button of a payment line, to remove it from the payment order.
Or :
#. Go to invoices
#. Select a few invoices from the tree view
#. Use the "Free invoices" entry to remove selected invoices from payment orders
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/173/10.0
Known issues / Roadmap
======================
* Nothing
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/bank-payment/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://odoo-community.org/logo.png>`_.
Contributors
------------
* Marco Monzione <marco.mon@windowslive.com>
* Emanuel Cino <ecino@compassion.ch>
* Cyril Sester <cyril.sester@outlook.com>
Do not contact contributors directly about support or help with technical issues.
Funders
-------
The development of this module has been financially supported by:
* Compassion Switzerland
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models
from . import wizards

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Copyright 2017-2018 Compassion CH (http://www.compassion.ch)
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
'name': 'Account payment line cancel',
'version': '10.0.1.0.0',
'license': 'AGPL-3',
'author': 'Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/bank-payment',
'category': 'Banking addons',
'depends': [
'account_payment_order',
'account_cancel',
],
'data': [
'views/invoice_view.xml',
'views/payment_line_view.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import account_payment_line
from . import invoice

View File

@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Compassion CH (http://www.compassion.ch)
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models, fields, _
class AccountCancelPayment(models.Model):
_inherit = 'account.payment.line'
cancel_reason = fields.Char()
def cancel_line(self):
"""
This method proceed to call private methods to remove payment lines
from payment order
A cancel reason can be put in the cancel_reason field.
:return: True
"""
# Retrieve all account_move_line(s) associated with the previous
# account_payment_line(s).
all_account_move_lines = self.mapped('move_line_id')
# Add the message to the invoice and to the payment order
self._post_cancel_message()
# Unreconcile transfer journal entries
full_reconcile_ids = all_account_move_lines.mapped(
'full_reconcile_id.id')
payment_orders = self.mapped('order_id')
if full_reconcile_ids:
# Retrieve the counterparts of the previous move_lines.
# The counter part should always be unique.
account_move_line_counterpart = self.env[
'account.move.line'].search([
('full_reconcile_id', 'in', full_reconcile_ids),
('id', 'not in', all_account_move_lines.ids),
('move_id.payment_order_id', 'in', payment_orders.ids)])
# All the move lines with the same reconcile id are unreconciled.
account_move_line_counterpart.remove_move_reconcile()
# unpost and delete the moves from the journal.
account_move_counterpart = account_move_line_counterpart.mapped(
'move_id')
account_move_counterpart.button_cancel()
account_move_counterpart.unlink()
# Remove bank.payment.line
self.mapped('bank_line_id').with_context(force_unlink=True).unlink()
# Search if there is something left in the payment order.
for payment_order in payment_orders:
other_lines = self.search_count([
('order_id', '=', payment_order.id),
('id', 'not in', self.ids)
])
if not other_lines:
payment_order.action_done_cancel()
# Delete the payment line in the payment order.
res = self.unlink()
# Force recomputation of total
payment_orders._compute_total()
if self.env.context.get('cancel_line_from_payment_order'):
# to see that the state of the order has changed, we need
# to update the whole view. Do that only if necessary.
res = {
'type': 'ir.actions.client',
'tag': 'reload',
}
return res
def _post_cancel_message(self):
"""
This method is used to post message on the invoices that have been
deleted from the payment order and it post a message too on the
payment order for each deleted invoice.
"""
for payment_line in self:
cancel_reason = payment_line.cancel_reason or _(
u"no reason given.")
# Create a link to the invoice that was removed
invoice = payment_line.move_line_id.invoice_id
order = payment_line.order_id
invoice_url = u'<a href="web#id={}&view_type=form&model=' \
u'account.invoice">{}</a>'.format(invoice.id,
invoice.move_name)
payment_order_url = u'<a href="web#id={}&view_type=form&model=' \
u'account.payment.order">{}</a>'.format(order.id, order.name)
# Add a message to the invoice
invoice.message_post(
_(u"The invoice has been removed from ") + u"{}, {}"
.format(payment_order_url, cancel_reason)
)
# Add a message to the payment order
payment_line.order_id.message_post(
invoice_url + _(u" has been removed, ") + cancel_reason)

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Compassion CH (http://www.compassion.ch)
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models, api, _, exceptions
class AccountInvoice(models.Model):
""" Inherit invoice to add invoice freeing functionality. It's about
cancelling related payment line. This
way, the invoice (properly, invoice's move lines) can be used again
in another payment order.
"""
_inherit = 'account.invoice'
@api.multi
def cancel_payment_lines(self):
""" This function simply finds related payment lines and cancel them.
"""
mov_line_obj = self.env['account.move.line']
pay_line_obj = self.env['account.payment.line']
move_ids = self.mapped('move_id.id')
move_line_ids = mov_line_obj.search([('move_id', 'in', move_ids)]).ids
payment_lines = pay_line_obj.search([
('move_line_id', 'in', move_line_ids)
])
if not payment_lines:
raise exceptions.UserError(_('No payment line found !'))
payment_lines.cancel_line()

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import test_payment_cancel

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Compassion CH (http://www.compassion.ch)
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import tools, fields
from odoo.tests import TransactionCase
from odoo.modules.module import get_resource_path
class TestPaymentCancel(TransactionCase):
def _load(self, module, *args):
tools.convert_file(
self.cr, 'account_asset',
get_resource_path(module, *args),
{}, 'init', False, 'test', self.registry._assertion_report)
def test_free_invoice(self):
self._load('account', 'test', 'account_minimal_test.xml')
journal = self.env['account.journal'].search([
('code', '=', 'TEXJ')], limit=1)
account = self.env['account.account'].search([
('code', '=', 'X1012')], limit=1)
product = self.env.ref('product.product_product_24')
account_line = self.env['account.account'].search([
('code', '=', 'X2020')], limit=1)
# Create invoice
invoice = self.env['account.invoice'].create({
'journal_id': journal.id,
'currency_id': self.env.ref('base.USD').id,
'account_id': account.id,
'type': 'in_invoice',
'partner_id': self.env.ref('base.res_partner_address_31').id,
'date_invoice': fields.Datetime.now(),
'invoice_line_ids': [(0, 0, {
'product_id': product.id,
'name': product.name,
'account_id': account_line.id,
'quantity': 1,
'price_unit': product.standard_price
})]
})
invoice.action_invoice_open()
payorder_id = invoice.create_account_payment_line().get('res_id')
payment_order = self.env['account.payment.order'].browse(payorder_id)
payment_order.journal_id = journal
# Confirm payment order
payment_order.draft2open()
# Generate payment file
payment_order.open2generated()
# File successfully uploaded
payment_order.generated2uploaded()
# The invoice should be paid
self.assertEquals(invoice.state, 'paid')
# Make journal cancellable
journal.update_posted = True
wizard = self.env['account.invoice.free'].with_context(
active_ids=invoice.ids).create({})
wizard.invoice_free()
# Test if the move related to the invoice are deleted after the invoice
# is freed.
account_move = self.env['account.move'].search(
[('payment_order_id', '=', payment_order.id)])
self.assertFalse(account_move)
# Test if the order is in cancel state.
self.assertEqual(payment_order.state, 'cancel')
# Test if the invoice is in open state.
self.assertEqual(invoice.state, 'open')

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_payment_line_cancel_view" model="ir.ui.view">
<field name="name">account.payment.line.cancel.tree</field>
<field name="model">account.payment.line</field>
<field name="inherit_id" ref="account_payment_order.account_payment_line_tree"/>
<field name="arch" type="xml">
<field name="payment_type" position="after">
<button name="cancel_line" type="object" icon="fa-undo" context="{'cancel_line_from_payment_order': 1}"/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import invoice_free_wizard

View File

@@ -1,13 +1,7 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2017 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
#
# The licence is in the file __manifest__.py
#
##############################################################################
# Copyright 2017 Compassion CH (http://www.compassion.ch)
# @author: Marco Monzione <marco.mon@windowslive.com>, Emanuel Cino
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models, api
@@ -17,6 +11,7 @@ class AccountInvoiceFree(models.TransientModel):
payment order.
'''
_name = 'account.invoice.free'
_description = 'Free invoice wizard'
@api.multi
def invoice_free(self):

View File

@@ -158,11 +158,12 @@ class BankPaymentLine(models.Model):
@api.multi
def unlink(self):
for line in self:
order_state = line.order_id.state
if order_state == 'uploaded':
raise UserError(_(
'Cannot delete a payment order line whose payment order is'
' in state \'%s\'. You need to cancel it first.')
% order_state)
if not self.env.context.get('force_unlink'):
for line in self:
order_state = line.order_id.state
if order_state == 'uploaded':
raise UserError(_(
'Cannot delete a payment order line whose payment '
'order is in state \'%s\'. You need to cancel it '
'first.') % order_state)
return super(BankPaymentLine, self).unlink()