diff --git a/replace_invoicing_user/__init__.py b/replace_invoicing_user/__init__.py new file mode 100644 index 0000000..9b42961 --- /dev/null +++ b/replace_invoicing_user/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/replace_invoicing_user/__manifest__.py b/replace_invoicing_user/__manifest__.py new file mode 100644 index 0000000..d07f703 --- /dev/null +++ b/replace_invoicing_user/__manifest__.py @@ -0,0 +1,33 @@ +# +# Bemade Inc. +# +# Copyright (C) 2023-June Bemade Inc. (). +# Author: Marc Durepos (Contact : marc@bemade.org) +# +# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1) +# It is forbidden to publish, distribute, sublicense, or sell copies of the Software +# or modified copies of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +{ + 'name': 'Current User as Invoice User', + 'version': '18.0.1.0.0', + 'summary': 'Instead of the salesperson, use the currently logged in user as the responsible user on invoice.', + 'category': 'Accounting', + 'author': 'Bemade Inc.', + 'website': 'http://www.bemade.org', + 'license': 'OPL-1', + 'depends': ['sale', 'account'], + 'data': [ + 'views/res_config_settings_views.xml', + ], + 'installable': True, + 'auto_install': False, +} diff --git a/replace_invoicing_user/models/__init__.py b/replace_invoicing_user/models/__init__.py new file mode 100644 index 0000000..0deb68c --- /dev/null +++ b/replace_invoicing_user/models/__init__.py @@ -0,0 +1 @@ +from . import res_config_settings diff --git a/replace_invoicing_user/models/res_config_settings.py b/replace_invoicing_user/models/res_config_settings.py new file mode 100644 index 0000000..8b2bd28 --- /dev/null +++ b/replace_invoicing_user/models/res_config_settings.py @@ -0,0 +1,18 @@ +from odoo import fields, models + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + # Configuration fields + use_current_user = fields.Boolean( + string='Use Current User as Invoice User', + config_parameter='current_user_as_invoice_user.use_current_user', + default=True, + help='If checked, the current user will be set as the invoice user. Otherwise, a specific user will be used.' + ) + specific_invoice_user_id = fields.Many2one( + 'res.users', + string='Specific Invoice User', + config_parameter='current_user_as_invoice_user.specific_user_id', + help='User to be set as invoice user when not using current user' + ) diff --git a/replace_invoicing_user/tests/__init__.py b/replace_invoicing_user/tests/__init__.py new file mode 100644 index 0000000..26d6dc6 --- /dev/null +++ b/replace_invoicing_user/tests/__init__.py @@ -0,0 +1 @@ +from . import test_current_user_as_invoice_user diff --git a/replace_invoicing_user/tests/test_current_user_as_invoice_user.py b/replace_invoicing_user/tests/test_current_user_as_invoice_user.py new file mode 100644 index 0000000..7e8744d --- /dev/null +++ b/replace_invoicing_user/tests/test_current_user_as_invoice_user.py @@ -0,0 +1,52 @@ +from odoo.tests import TransactionCase, Form, tagged +from odoo.addons.sale.tests.common import TestSaleCommon +from odoo import Command + + +@tagged("-at_install", "post_install") +class TestSaleOrder(TestSaleCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + Partner = cls.env['res.partner'] + groups = [ + cls.env.ref('base.group_user').id, + cls.env.ref('base.group_system').id, + cls.env.ref('account.group_account_invoice').id, + cls.env.ref('sales_team.group_sale_manager').id, + ] + cls.user = cls.env['res.users'].create({ + 'partner_id': Partner.create({'name': 'user1'}).id, + 'login': 'test_user', + 'password': 'test_user', + 'groups_id': [Command.set(groups)] + }) + cls.product = cls.env['product.product'].create({ + 'name': 'Test Product', + 'default_code': 'TEST', + 'price': 10.0, + 'invoice_policy': 'order', + }) + cls.sale_order = cls.env['sale.order'].with_user(cls.user).create({ + 'partner_id': cls.partner_a.id, + }) + so_form = Form(cls.sale_order) + with so_form.order_line.new() as line: + line.product_id = cls.product + line.product_uom_qty = 2 + so_form.save() + cls.sale_order.action_confirm() + + def test_invoice_wizard_does_not_set_so_responsible_as_invoice_follower(self): + so = self.sale_order + admin = self.env.ref('base.user_root') + wiz = self.env['sale.advance.payment.inv'].with_user(admin).with_context({ + 'active_ids': so.ids, + 'active_model': 'sale.order', + }).create({}) + wiz.with_user(admin).create_invoices() + invoice = so.invoice_ids[0] + self.assertEqual(invoice.invoice_user_id, admin) + self.assertFalse(self.user in invoice.message_follower_ids.mapped('partner_id').mapped('user_ids')) + + diff --git a/replace_invoicing_user/views/res_config_settings_views.xml b/replace_invoicing_user/views/res_config_settings_views.xml new file mode 100644 index 0000000..e9fbb24 --- /dev/null +++ b/replace_invoicing_user/views/res_config_settings_views.xml @@ -0,0 +1,28 @@ + + + + res.config.settings.view.form.inherit.invoice.user + res.config.settings + + + +
+
+ +
+
+
+
+
+
+
+
diff --git a/replace_invoicing_user/wizard/__init__.py b/replace_invoicing_user/wizard/__init__.py new file mode 100644 index 0000000..90fe27c --- /dev/null +++ b/replace_invoicing_user/wizard/__init__.py @@ -0,0 +1,2 @@ +from . import sale_make_invoice_advance +from . import sale_order diff --git a/replace_invoicing_user/wizard/sale_make_invoice_advance.py b/replace_invoicing_user/wizard/sale_make_invoice_advance.py new file mode 100644 index 0000000..0577e07 --- /dev/null +++ b/replace_invoicing_user/wizard/sale_make_invoice_advance.py @@ -0,0 +1,29 @@ +from odoo import models + + +class SaleMakeInvoiceAdvance(models.TransientModel): + _inherit = "sale.advance.payment.inv" + + def _prepare_invoice_values(self, order, so_line): + invoice_vals = super()._prepare_invoice_values(order, so_line) + + # Get configuration parameters + use_current_user = self.env['ir.config_parameter'].sudo().get_param( + 'current_user_as_invoice_user.use_current_user', 'True' + ).lower() == 'true' + + specific_user_id = int(self.env['ir.config_parameter'].sudo().get_param( + 'current_user_as_invoice_user.specific_user_id', '0' + )) + + # Determine which user to use + if use_current_user: + user_id = self.env.user.id + else: + user_id = specific_user_id if specific_user_id else self.env.user.id + + invoice_vals.update({ + 'invoice_user_id': user_id, + 'user_id': user_id, + }) + return invoice_vals diff --git a/replace_invoicing_user/wizard/sale_order.py b/replace_invoicing_user/wizard/sale_order.py new file mode 100644 index 0000000..c1d16e2 --- /dev/null +++ b/replace_invoicing_user/wizard/sale_order.py @@ -0,0 +1,29 @@ +from odoo import models, fields, api, _ + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + def _prepare_invoice(self): + invoice_vals = super()._prepare_invoice() + + # Get configuration parameters + use_current_user = self.env['ir.config_parameter'].sudo().get_param( + 'current_user_as_invoice_user.use_current_user', 'True' + ).lower() == 'true' + + specific_user_id = int(self.env['ir.config_parameter'].sudo().get_param( + 'current_user_as_invoice_user.specific_user_id', '0' + )) + + # Determine which user to use + if use_current_user: + user_id = self.env.user.id + else: + user_id = specific_user_id if specific_user_id else self.env.user.id + + invoice_vals.update({ + 'invoice_user_id': user_id, + 'user_id': user_id, + }) + return invoice_vals \ No newline at end of file