diff --git a/account_payment_cancel/README.rst b/account_payment_cancel/README.rst deleted file mode 100644 index d61f9d04d..000000000 --- a/account_payment_cancel/README.rst +++ /dev/null @@ -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 `_. - -Contributors ------------- - -* Marco Monzione -* Emanuel Cino - -Do not contact contributors directly about support or help with -technical issues. \ No newline at end of file diff --git a/account_payment_cancel/__init__.py b/account_payment_cancel/__init__.py deleted file mode 100644 index 24c19d687..000000000 --- a/account_payment_cancel/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - -from . import models \ No newline at end of file diff --git a/account_payment_cancel/__manifest__.py b/account_payment_cancel/__manifest__.py deleted file mode 100644 index 98f0f1319..000000000 --- a/account_payment_cancel/__manifest__.py +++ /dev/null @@ -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, -} diff --git a/account_payment_cancel/models/__init__.py b/account_payment_cancel/models/__init__.py deleted file mode 100644 index 41796f99a..000000000 --- a/account_payment_cancel/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import account_payment_cancel -from . import invoice_free_wizard -from . import invoice diff --git a/account_payment_cancel/models/account_payment_cancel.py b/account_payment_cancel/models/account_payment_cancel.py deleted file mode 100644 index 556134933..000000000 --- a/account_payment_cancel/models/account_payment_cancel.py +++ /dev/null @@ -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 , 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 = '{}'. \ - 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.") diff --git a/account_payment_cancel/models/invoice.py b/account_payment_cancel/models/invoice.py deleted file mode 100644 index 0dd381e0a..000000000 --- a/account_payment_cancel/models/invoice.py +++ /dev/null @@ -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 , 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) diff --git a/account_payment_cancel/res/test_data.yml b/account_payment_cancel/res/test_data.yml deleted file mode 100644 index 54a5aa027..000000000 --- a/account_payment_cancel/res/test_data.yml +++ /dev/null @@ -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' \ No newline at end of file diff --git a/account_payment_cancel/tests/__init__.py b/account_payment_cancel/tests/__init__.py deleted file mode 100644 index 85bb03d15..000000000 --- a/account_payment_cancel/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import test_payment_cancel diff --git a/account_payment_cancel/tests/test_payment_cancel.py b/account_payment_cancel/tests/test_payment_cancel.py deleted file mode 100644 index 41cdd0e38..000000000 --- a/account_payment_cancel/tests/test_payment_cancel.py +++ /dev/null @@ -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 , 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() diff --git a/account_payment_line_cancel/README.rst b/account_payment_line_cancel/README.rst new file mode 100644 index 000000000..2ff826551 --- /dev/null +++ b/account_payment_line_cancel/README.rst @@ -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 +`_. 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 `_. + +Contributors +------------ + +* Marco Monzione +* Emanuel Cino +* Cyril Sester + +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. diff --git a/account_payment_line_cancel/__init__.py b/account_payment_line_cancel/__init__.py new file mode 100644 index 000000000..8e5f8868b --- /dev/null +++ b/account_payment_line_cancel/__init__.py @@ -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 diff --git a/account_payment_line_cancel/__manifest__.py b/account_payment_line_cancel/__manifest__.py new file mode 100644 index 000000000..d98edc364 --- /dev/null +++ b/account_payment_line_cancel/__manifest__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2017-2018 Compassion CH (http://www.compassion.ch) +# @author: Marco Monzione , 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, +} diff --git a/account_payment_line_cancel/models/__init__.py b/account_payment_line_cancel/models/__init__.py new file mode 100644 index 000000000..8772d8d7c --- /dev/null +++ b/account_payment_line_cancel/models/__init__.py @@ -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 diff --git a/account_payment_line_cancel/models/account_payment_line.py b/account_payment_line_cancel/models/account_payment_line.py new file mode 100644 index 000000000..0a78ddb41 --- /dev/null +++ b/account_payment_line_cancel/models/account_payment_line.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Compassion CH (http://www.compassion.ch) +# @author: Marco Monzione , 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'{}'.format(invoice.id, + invoice.move_name) + payment_order_url = u'{}'.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) diff --git a/account_payment_line_cancel/models/invoice.py b/account_payment_line_cancel/models/invoice.py new file mode 100644 index 000000000..7344724d8 --- /dev/null +++ b/account_payment_line_cancel/models/invoice.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Compassion CH (http://www.compassion.ch) +# @author: Marco Monzione , 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() diff --git a/account_payment_line_cancel/tests/__init__.py b/account_payment_line_cancel/tests/__init__.py new file mode 100644 index 000000000..2b2b058dd --- /dev/null +++ b/account_payment_line_cancel/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import test_payment_cancel diff --git a/account_payment_line_cancel/tests/test_payment_cancel.py b/account_payment_line_cancel/tests/test_payment_cancel.py new file mode 100644 index 000000000..b9da3edb8 --- /dev/null +++ b/account_payment_line_cancel/tests/test_payment_cancel.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Compassion CH (http://www.compassion.ch) +# @author: Marco Monzione , 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') diff --git a/account_payment_cancel/views/invoice_view.xml b/account_payment_line_cancel/views/invoice_view.xml similarity index 100% rename from account_payment_cancel/views/invoice_view.xml rename to account_payment_line_cancel/views/invoice_view.xml diff --git a/account_payment_line_cancel/views/payment_line_view.xml b/account_payment_line_cancel/views/payment_line_view.xml new file mode 100644 index 000000000..6ed0ccb41 --- /dev/null +++ b/account_payment_line_cancel/views/payment_line_view.xml @@ -0,0 +1,13 @@ + + + + account.payment.line.cancel.tree + account.payment.line + + + +