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 e2c362bd..ddf53741 100644 --- a/account_invoice_change/tests/test_invoice_change.py +++ b/account_invoice_change/tests/test_invoice_change.py @@ -1,10 +1,12 @@ -from odoo.addons.account.tests.account_test_users import AccountTestUsers from odoo import fields +from odoo.exceptions import UserError +from odoo.tests import tagged, Form +from odoo.addons.account.tests.account_test_users import AccountTestUsers -class TestInvoiceChange(AccountTestUsers): - - def test_invoice_change_basic(self): +class InvoiceChangeCommon(AccountTestUsers): + def setUp(self): + super().setUp() self.account_invoice_obj = self.env['account.move'] self.payment_term = self.env.ref('account.account_payment_term_advance') self.journalrec = self.env['account.journal'].search([('type', '=', 'sale')])[0] @@ -16,7 +18,7 @@ class TestInvoiceChange(AccountTestUsers): 'journal_id': self.journalrec.id, 'partner_id': self.partner3.id, # account_id=self.account_rec1_id.id, - 'line_ids': [(0, 0, { + 'invoice_line_ids': [(0, 0, { 'product_id': self.env.ref('product.product_product_5').id, 'quantity': 10.0, 'account_id': self.env['account.account'].search( @@ -25,6 +27,11 @@ class TestInvoiceChange(AccountTestUsers): 'price_unit': 100.00, })], }) + + +@tagged('post_install', '-at_install') +class TestInvoiceChange(InvoiceChangeCommon): + def test_invoice_change_basic(self): self.assertEqual(self.invoice_basic.state, 'draft') self.invoice_basic.action_post() self.assertEqual(self.invoice_basic.state, 'posted') @@ -49,3 +56,65 @@ class TestInvoiceChange(AccountTestUsers): 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 5e233688..c15c94eb 100644 --- a/account_invoice_change/wizard/invoice_change_views.xml +++ b/account_invoice_change/wizard/invoice_change_views.xml @@ -7,11 +7,15 @@
- + + - - - + + + + + + @@ -39,8 +43,7 @@