Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[11.0][MIG] account_invoice_update_wizard #75

Open
wants to merge 9 commits into
base: 11.0
Choose a base branch
from
39 changes: 39 additions & 0 deletions account_invoice_update_wizard/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

Account Invoice Update Wizard
=============================

This module adds a button *Update Invoice* on Customer and Supplier invoices in
Open or Paid state. This button starts a wizard which allows the user to update
non-legal fields of the invoice:

* Source Document
* Reference/Description
* Payment terms (update allowed only to a payment term with same number of terms
of the same amount and on invoices without any payment)
* Bank Account
* Salesman
* Notes
* Description of invoice lines
* Analytic account
* Analytic tags

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/akretion/odoo-usability/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.

Contributors
------------

* Alexis de Lattre <[email protected]>
* Florian da Costa <[email protected]>
* Matthieu Dietrich <[email protected]>
* Yannick Vaucher <[email protected]>
* Mykhailo Panarin <[email protected]>
* Artem Kostyuk <[email protected]>
1 change: 1 addition & 0 deletions account_invoice_update_wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import wizard
20 changes: 20 additions & 0 deletions account_invoice_update_wizard/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2017 Akretion (Alexis de Lattre <[email protected]>)
# Copyright 2018 Camptocamp
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
'name': 'Account Invoice Update Wizard',
'version': '11.0.1.0.0',
'category': 'Accounting & Finance',
'license': 'AGPL-3',
'summary': 'Wizard to update non-legal fields of an open/paid invoice',
'author': 'Akretion',
'website': 'http://github.com/akretion/odoo-usability',
'depends': [
'account',
],
'data': [
'wizard/account_invoice_update_view.xml',
'views/account_invoice.xml',
],
}
1 change: 1 addition & 0 deletions account_invoice_update_wizard/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_account_invoice_update_wizard
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Copyright 2018 Camptocamp
# License AGPL-3.0 or later (https://gnu.org/licenses/agpl).

from odoo.tests.common import SavepointCase
from odoo.exceptions import UserError


class TestAccountInvoiceUpdateWizard(SavepointCase):

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(
cls.env.context,
tracking_disable=True,
))
cls.customer12 = cls.env.ref('base.res_partner_12')
cls.product16 = cls.env.ref('product.product_product_16')
cls.product24 = cls.env.ref('product.product_product_24')
uom_unit = cls.env.ref('product.product_uom_categ_unit')

cls.invoice1 = cls.env['account.invoice'].create({
'name': 'Test invoice',
'partner_id': cls.customer12.id,
})
cls.inv_line1 = cls.env['account.invoice.line'].create({
'invoice_id': cls.invoice1.id,
'name': "Line1",
'product_id': cls.product16.id,
'product_uom_id': uom_unit.id,
'account_id': cls.invoice1.account_id.id,
'price_unit': 42.0,
})
cls.inv_line2 = cls.env['account.invoice.line'].create({
'invoice_id': cls.invoice1.id,
'name': "Line2",
'product_id': cls.product24.id,
'product_uom_id': uom_unit.id,
'account_id': cls.invoice1.account_id.id,
'price_unit': 1111.1,
})

cls.aa1 = cls.env.ref('analytic.analytic_partners_camp_to_camp')
cls.aa2 = cls.env.ref('analytic.analytic_nebula')
cls.atag1 = cls.env.ref('analytic.tag_contract')
cls.atag2 = cls.env['account.analytic.tag'].create({
'name': 'の',
})

def create_wizard(self):
UpdateWizard = self.env['account.invoice.update'].with_context(
active_model='account.invoice',
active_id=self.invoice1.id)
self.wiz = UpdateWizard.create({})

def test_add_analytic_account_line1(self):
""" Add analytic account on an invoice line
after the invoice has been approved.

This will:
- update the move line
- create a new analytic line.
"""
self.invoice1.action_invoice_open()
self.create_wizard()

wiz_line = self.wiz.line_ids.filtered(
lambda rec: rec.invoice_line_id == self.inv_line1)
wiz_line.account_analytic_id = self.aa1
self.wiz.run()

related_ml = self.invoice1.move_id.line_ids.filtered(
lambda rec: rec.product_id == self.product16)
self.assertEqual(related_ml.analytic_account_id, self.aa1)
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)

def test_change_analytic_account_line1(self):
""" Change analytic account on an invoice line
after the invoice has been approved.

This will:
- update the move line
- update the existing analytic line."""
self.inv_line1.account_analytic_id = self.aa2

self.invoice1.action_invoice_open()
self.create_wizard()

wiz_line = self.wiz.line_ids.filtered(
lambda rec: rec.invoice_line_id == self.inv_line1)
wiz_line.account_analytic_id = self.aa1
self.wiz.run()

related_ml = self.invoice1.move_id.line_ids.filtered(
lambda rec: rec.product_id == self.product16)
self.assertEqual(related_ml.analytic_account_id, self.aa1)
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)

def test_error_grouped_move_lines(self):
""" Change analytic account on an invoice line
after the invoice has been approved where both
lines were grouped in the same move line.

This will raise an error.
"""
self.invoice1.journal_id.group_invoice_lines = True

self.inv_line2.product_id = self.product16
self.inv_line2.unit_price = 42.0

self.invoice1.action_invoice_open()
self.create_wizard()

line1 = self.wiz.line_ids[0]
line1.account_analytic_id = self.aa1
with self.assertRaises(UserError):
self.wiz.run()

def test_add_analytic_tags_line1(self):
""" Add analytic tags on an invoice line
after the invoice has been approved.

This will update move line.
"""
self.invoice1.action_invoice_open()
self.create_wizard()

wiz_line = self.wiz.line_ids.filtered(
lambda rec: rec.invoice_line_id == self.inv_line1)
wiz_line.analytic_tag_ids = self.atag2
self.wiz.run()

related_ml = self.invoice1.move_id.line_ids.filtered(
lambda rec: rec.product_id == self.product16)
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
self.assertFalse(related_ml.analytic_line_ids)

def test_change_analytic_tags_line1(self):
""" Change analytic tags on an invoice line
after the invoice has been approved.

It will update move line and analytic line
"""
self.inv_line1.account_analytic_id = self.aa2
self.inv_line1.analytic_tag_ids = self.atag1

self.invoice1.action_invoice_open()
self.create_wizard()

wiz_line = self.wiz.line_ids.filtered(
lambda rec: rec.invoice_line_id == self.inv_line1)
wiz_line.analytic_tag_ids = self.atag2
self.wiz.run()

related_ml = self.invoice1.move_id.line_ids.filtered(
lambda rec: rec.product_id == self.product16)
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)

def test_add_analytic_info_line1(self):
""" Add analytic account and tags on an invoice line
after the invoice has been approved.

This will:
- update move line
- create an analytic line
"""
self.invoice1.action_invoice_open()
self.create_wizard()

wiz_line = self.wiz.line_ids.filtered(
lambda rec: rec.invoice_line_id == self.inv_line1)
wiz_line.account_analytic_id = self.aa1
wiz_line.analytic_tag_ids = self.atag2
self.wiz.run()

related_ml = self.invoice1.move_id.line_ids.filtered(
lambda rec: rec.product_id == self.product16)
self.assertEqual(related_ml.analytic_account_id, self.aa1)
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)

def test_empty_analytic_account_line1(self):
""" Remove analytic account
after the invoice has been approved.

This will raise an error as it is not implemented.
"""
self.inv_line1.account_analytic_id = self.aa2

self.invoice1.action_invoice_open()
self.create_wizard()

wiz_line = self.wiz.line_ids.filtered(
lambda rec: rec.invoice_line_id == self.inv_line1)
wiz_line.account_analytic_id = False
self.wiz.run()
related_ml = self.invoice1.move_id.line_ids.filtered(
lambda rec: rec.product_id == self.product16)
self.assertFalse(related_ml.analytic_account_id)
self.assertFalse(related_ml.analytic_line_ids)
29 changes: 29 additions & 0 deletions account_invoice_update_wizard/views/account_invoice.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Akretion (Alexis de Lattre <[email protected]>)
License AGPL-3.0 or later (https://gnu.org/licenses/agpl).
-->

<odoo>

<record id="invoice_supplier_form" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="arch" type="xml">
<button name="action_invoice_cancel" position="before">
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
</button>
</field>
</record>

<record id="invoice_form" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<button name="action_invoice_cancel" position="before">
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
</button>
</field>
</record>

</odoo>
1 change: 1 addition & 0 deletions account_invoice_update_wizard/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import account_invoice_update
Loading