From 04279a120ee1b9680c28044e295d9994f1fd4baa Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Sat, 12 May 2018 14:11:37 -0700 Subject: [PATCH 1/4] Initial commit `account_invoice_change` and `account_invoice_change_analytic` for 11.0 --- account_invoice_change/__init__.py | 1 + account_invoice_change/__manifest__.py | 30 ++++++++++ account_invoice_change/tests/__init__.py | 1 + .../tests/test_invoice_change.py | 60 +++++++++++++++++++ account_invoice_change/wizard/__init__.py | 1 + .../wizard/invoice_change.py | 56 +++++++++++++++++ .../wizard/invoice_change_views.xml | 48 +++++++++++++++ 7 files changed, 197 insertions(+) create mode 100644 account_invoice_change/__init__.py create mode 100644 account_invoice_change/__manifest__.py create mode 100644 account_invoice_change/tests/__init__.py create mode 100644 account_invoice_change/tests/test_invoice_change.py create mode 100644 account_invoice_change/wizard/__init__.py create mode 100644 account_invoice_change/wizard/invoice_change.py create mode 100644 account_invoice_change/wizard/invoice_change_views.xml diff --git a/account_invoice_change/__init__.py b/account_invoice_change/__init__.py new file mode 100644 index 00000000..40272379 --- /dev/null +++ b/account_invoice_change/__init__.py @@ -0,0 +1 @@ +from . import wizard diff --git a/account_invoice_change/__manifest__.py b/account_invoice_change/__manifest__.py new file mode 100644 index 00000000..7cb8459d --- /dev/null +++ b/account_invoice_change/__manifest__.py @@ -0,0 +1,30 @@ +{ + 'name': 'Account Invoice Change', + 'author': 'Hibou Corp. ', + 'version': '11.0.1.0.0', + 'category': 'Accounting', + 'sequence': 95, + 'summary': 'Technical foundation for changing invoices.', + 'description': """ +Technical foundation for changing invoices. + +Creates wizard and permissions for making invoice changes that can be +handled by other individual modules. + +This module implements, as examples, how to change the Salesperson and Date fields. + +Abstractly, individual 'changes' should come from specific 'fields' or capability +modules that handle the consequences of changing that field in whatever state the +the invoice is currently in. + + """, + 'website': 'https://hibou.io/', + 'depends': [ + 'account', + ], + 'data': [ + 'wizard/invoice_change_views.xml', + ], + 'installable': True, + 'application': False, +} diff --git a/account_invoice_change/tests/__init__.py b/account_invoice_change/tests/__init__.py new file mode 100644 index 00000000..defd2696 --- /dev/null +++ b/account_invoice_change/tests/__init__.py @@ -0,0 +1 @@ +from . import test_invoice_change diff --git a/account_invoice_change/tests/test_invoice_change.py b/account_invoice_change/tests/test_invoice_change.py new file mode 100644 index 00000000..3809241c --- /dev/null +++ b/account_invoice_change/tests/test_invoice_change.py @@ -0,0 +1,60 @@ +from odoo.addons.account.tests.account_test_users import AccountTestUsers +from odoo import fields + +class TestInvoiceChange(AccountTestUsers): + + def test_invoice_change_basic(self): + self.account_invoice_obj = self.env['account.invoice'] + self.payment_term = self.env.ref('account.account_payment_term_advance') + self.journalrec = self.env['account.journal'].search([('type', '=', 'sale')])[0] + self.partner3 = self.env.ref('base.res_partner_3') + account_user_type = self.env.ref('account.data_account_type_receivable') + self.account_rec1_id = self.account_model.sudo(self.account_manager.id).create(dict( + code="cust_acc", + name="customer account", + user_type_id=account_user_type.id, + reconcile=True, + )) + invoice_line_data = [ + (0, 0, + { + 'product_id': self.env.ref('product.product_product_5').id, + 'quantity': 10.0, + 'account_id': self.env['account.account'].search( + [('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id, + 'name': 'product test 5', + 'price_unit': 100.00, + } + ) + ] + self.invoice_basic = self.account_invoice_obj.sudo(self.account_user.id).create(dict( + name="Test Customer Invoice", + reference_type="none", + payment_term_id=self.payment_term.id, + journal_id=self.journalrec.id, + partner_id=self.partner3.id, + account_id=self.account_rec1_id.id, + invoice_line_ids=invoice_line_data + )) + self.assertEqual(self.invoice_basic.state, 'draft') + self.invoice_basic.action_invoice_open() + self.assertEqual(self.invoice_basic.state, 'open') + self.assertEqual(self.invoice_basic.date, fields.Date.today()) + self.assertEqual(self.invoice_basic.user_id, self.account_user) + self.assertEqual(self.invoice_basic.move_id.date, fields.Date.today()) + self.assertEqual(self.invoice_basic.move_id.line_ids[0].date, fields.Date.today()) + + ctx = {'active_model': 'account.invoice', 'active_ids': [self.invoice_basic.id]} + change = self.env['account.invoice.change'].with_context(ctx).create({}) + self.assertEqual(change.date, self.invoice_basic.date) + self.assertEqual(change.user_id, self.invoice_basic.user_id) + + change_date = '2018-01-01' + change_user = self.env.user + change.write({'user_id': change_user.id, 'date': change_date}) + + change.affect_change() + self.assertEqual(self.invoice_basic.date, change_date) + self.assertEqual(self.invoice_basic.user_id, change_user) + self.assertEqual(self.invoice_basic.move_id.date, change_date) + self.assertEqual(self.invoice_basic.move_id.line_ids[0].date, change_date) diff --git a/account_invoice_change/wizard/__init__.py b/account_invoice_change/wizard/__init__.py new file mode 100644 index 00000000..8ec5d6da --- /dev/null +++ b/account_invoice_change/wizard/__init__.py @@ -0,0 +1 @@ +from . import invoice_change \ No newline at end of file diff --git a/account_invoice_change/wizard/invoice_change.py b/account_invoice_change/wizard/invoice_change.py new file mode 100644 index 00000000..def9583f --- /dev/null +++ b/account_invoice_change/wizard/invoice_change.py @@ -0,0 +1,56 @@ +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +class InvoiceChangeWizard(models.TransientModel): + _name = 'account.invoice.change' + _description = 'Invoice Change' + + invoice_id = fields.Many2one('account.invoice', string='Invoice', readonly=True, required=True) + invoice_company_id = fields.Many2one('res.company', readonly=True, related='invoice_id.company_id') + user_id = fields.Many2one('res.users', string='Salesperson') + date = fields.Date(string='Accounting Date') + + @api.model + def default_get(self, fields): + rec = super(InvoiceChangeWizard, self).default_get(fields) + context = dict(self._context or {}) + active_model = context.get('active_model') + active_ids = context.get('active_ids') + + # Checks on context parameters + if not active_model or not active_ids: + raise UserError( + _("Programmation error: wizard action executed without active_model or active_ids in context.")) + if active_model != 'account.invoice': + raise UserError(_( + "Programmation error: the expected model for this action is 'account.invoice'. 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({ + 'invoice_id': invoice.id, + 'user_id': invoice.user_id.id, + 'date': invoice.date, + }) + return rec + + def _new_invoice_vals(self): + vals = {} + if self.invoice_id.user_id != self.user_id: + vals['user_id'] = self.user_id.id + if self.invoice_id.date != self.date: + vals['date'] = self.date + return vals + + @api.multi + def affect_change(self): + self.ensure_one() + vals = self._new_invoice_vals() + if vals: + self.invoice_id.write(vals) + if 'date' in vals and self.invoice_id.move_id: + self.invoice_id.move_id.write({'date': vals['date']}) + return True diff --git a/account_invoice_change/wizard/invoice_change_views.xml b/account_invoice_change/wizard/invoice_change_views.xml new file mode 100644 index 00000000..5852570c --- /dev/null +++ b/account_invoice_change/wizard/invoice_change_views.xml @@ -0,0 +1,48 @@ + + + + Invoice Change + account.invoice.change + +
+ + + + + + + + + +
+
+ +
+
+ + + Invoice Change Wizard + ir.actions.act_window + account.invoice.change + form + form + new + + + + account.invoice.form.inherit + account.invoice + + + +