diff --git a/account_invoice_change/__manifest__.py b/account_invoice_change/__manifest__.py
index 952b2e59..ac07226a 100644
--- a/account_invoice_change/__manifest__.py
+++ b/account_invoice_change/__manifest__.py
@@ -23,6 +23,7 @@ the invoice is currently in.
'account',
],
'data': [
+ 'data/server_actions.xml',
'wizard/invoice_change_views.xml',
],
'installable': True,
diff --git a/account_invoice_change/data/server_actions.xml b/account_invoice_change/data/server_actions.xml
new file mode 100644
index 00000000..036fc97f
--- /dev/null
+++ b/account_invoice_change/data/server_actions.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ Change Invoice
+
+
+ list
+ code
+
+
+if records:
+ action = env['ir.actions.act_window'].for_xml_id('account_invoice_change', 'action_view_account_invoice_change')
+ action['context'] = {
+ 'active_model': model._name,
+ 'active_ids': records.ids,
+ }
+
+
+
+
+
diff --git a/account_invoice_change/tests/test_invoice_change.py b/account_invoice_change/tests/test_invoice_change.py
index da433052..ddf53741 100644
--- a/account_invoice_change/tests/test_invoice_change.py
+++ b/account_invoice_change/tests/test_invoice_change.py
@@ -1,5 +1,6 @@
from odoo import fields
-from odoo.tests import tagged
+from odoo.exceptions import UserError
+from odoo.tests import tagged, Form
from odoo.addons.account.tests.account_test_users import AccountTestUsers
@@ -55,3 +56,65 @@ class TestInvoiceChange(InvoiceChangeCommon):
self.assertEqual(str(self.invoice_basic.invoice_date), change_invoice_date)
self.assertEqual(self.invoice_basic.invoice_user_id, change_user)
self.assertEqual(str(self.invoice_basic.line_ids[0].date), change_date)
+
+ def _create_journal_entry(self):
+ revenue_account = self.env['account.account'].search([
+ ('company_id', '=', self.main_company.id),
+ ('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)
+ ], limit=1)
+ expense_account = self.env['account.account'].search([
+ ('company_id', '=', self.main_company.id),
+ ('user_type_id', '=', self.env.ref('account.data_account_type_expenses').id)
+ ], limit=1)
+ return self.env['account.move'].create({
+ 'type': 'entry',
+ 'date': '2019-01-01',
+ 'line_ids': [
+ (0, 0, {
+ 'name': 'line_debit',
+ 'account_id': revenue_account.id,
+ }),
+ (0, 0, {
+ 'name': 'line_credit',
+ 'account_id': expense_account.id,
+ }),
+ ],
+ })
+
+ def test_invoice_change_multiple(self):
+ journal_entry = self._create_journal_entry()
+ ctx = {'active_model': 'account.move', 'active_ids': [self.invoice_basic.id, journal_entry.id]}
+ with self.assertRaises(UserError):
+ change = Form(self.env['account.invoice.change'].with_context(ctx))
+
+ other_invoice = self.invoice_basic.copy()
+ ctx = {'active_model': 'account.move', 'active_ids': [self.invoice_basic.id, other_invoice.id]}
+ with self.assertRaises(UserError):
+ change = Form(self.env['account.invoice.change'].with_context(ctx))
+
+ self.invoice_basic.action_post()
+ other_invoice.action_post()
+ change = Form(self.env['account.invoice.change'].with_context(ctx))
+ self.assertFalse(change.date)
+ self.assertFalse(change.invoice_date)
+ self.assertFalse(change.invoice_user_id)
+
+ change_date = '2018-01-01'
+ change_invoice_date = '2019-01-01'
+ change_user = self.env.user
+ change.set_invoice_user_id = True
+ change.set_date = True
+ change.set_invoice_date = True
+ change.invoice_user_id = change_user
+ change.date = change_date
+ change.invoice_date = change_invoice_date
+
+ change.save().affect_change()
+ self.assertEqual(str(self.invoice_basic.date), change_date)
+ self.assertEqual(str(self.invoice_basic.invoice_date), change_invoice_date)
+ self.assertEqual(self.invoice_basic.invoice_user_id, change_user)
+ self.assertEqual(str(self.invoice_basic.line_ids[0].date), change_date)
+ self.assertEqual(str(other_invoice.date), change_date)
+ self.assertEqual(str(other_invoice.invoice_date), change_invoice_date)
+ self.assertEqual(other_invoice.invoice_user_id, change_user)
+ self.assertEqual(str(other_invoice.line_ids[0].date), change_date)
diff --git a/account_invoice_change/wizard/invoice_change.py b/account_invoice_change/wizard/invoice_change.py
index 63baae08..ccb4117d 100644
--- a/account_invoice_change/wizard/invoice_change.py
+++ b/account_invoice_change/wizard/invoice_change.py
@@ -6,11 +6,15 @@ class InvoiceChangeWizard(models.TransientModel):
_name = 'account.invoice.change'
_description = 'Invoice Change'
- move_id = fields.Many2one('account.move', string='Invoice', readonly=True, required=True)
- move_company_id = fields.Many2one('res.company', readonly=True, related='move_id.company_id')
+ move_ids = fields.Many2many('account.move', string='Invoice', readonly=True, required=True)
+ is_single_move = fields.Boolean(compute='_compute_move_company_id')
+ move_company_id = fields.Many2one('res.company', readonly=True, compute='_compute_move_company_id')
invoice_user_id = fields.Many2one('res.users', string='Salesperson')
+ set_invoice_user_id = fields.Boolean()
date = fields.Date(string='Accounting Date')
+ set_date = fields.Boolean()
invoice_date = fields.Date(string='Invoice Date')
+ set_invoice_date = fields.Boolean()
@api.model
def default_get(self, fields):
@@ -28,24 +32,40 @@ class InvoiceChangeWizard(models.TransientModel):
"Programmation error: the expected model for this action is 'account.move'. The provided one is '%d'.") % active_model)
# Checks on received invoice records
- invoice = self.env[active_model].browse(active_ids)
- if len(invoice) != 1:
- raise UserError(_("Invoice Change expects only one invoice."))
- rec.update({
- 'move_id': invoice.id,
- 'invoice_user_id': invoice.invoice_user_id.id,
- 'date': invoice.date,
- 'invoice_date': invoice.invoice_date,
- })
+ invoices = self.env[active_model].browse(active_ids)
+ if invoices.filtered(lambda i: not i.is_invoice()):
+ raise UserError(_('Only invoices can be updated.'))
+ if invoices.filtered(lambda i: i.state in ('draft', 'cancel')):
+ raise UserError(_('Only posted invoices can be updated.'))
+ if len(invoices.company_id) > 1:
+ raise UserError(_('Selected invoices must be in the same company.'))
+ rec['move_ids'] = [(6, 0, invoices.ids)]
+ if len(invoices) == 1:
+ rec.update({
+ 'set_invoice_user_id': True,
+ 'set_date': True,
+ 'set_invoice_date': True,
+ 'invoice_user_id': invoices.invoice_user_id.id,
+ 'date': invoices.date,
+ 'invoice_date': invoices.invoice_date,
+ })
return rec
+
+ @api.depends('move_ids')
+ def _compute_move_company_id(self):
+ for wiz in self:
+ company = wiz.move_ids.company_id
+ company.ensure_one()
+ wiz.move_company_id = company
+ wiz.is_single_move = len(wiz.move_ids) == 1
def _new_move_vals(self):
vals = {}
- if self.move_id.invoice_user_id != self.invoice_user_id:
+ if self.set_invoice_user_id:
vals['invoice_user_id'] = self.invoice_user_id.id
- if self.move_id.date != self.date:
+ if self.set_date:
vals['date'] = self.date
- if self.move_id.invoice_date != self.invoice_date:
+ if self.set_invoice_date:
vals['invoice_date'] = self.invoice_date
return vals
@@ -53,5 +73,5 @@ class InvoiceChangeWizard(models.TransientModel):
self.ensure_one()
vals = self._new_move_vals()
if vals:
- self.move_id.write(vals)
+ self.move_ids.write(vals)
return True
diff --git a/account_invoice_change/wizard/invoice_change_views.xml b/account_invoice_change/wizard/invoice_change_views.xml
index 460ee944..c15c94eb 100644
--- a/account_invoice_change/wizard/invoice_change_views.xml
+++ b/account_invoice_change/wizard/invoice_change_views.xml
@@ -7,11 +7,15 @@