diff --git a/__manifest__.py b/__manifest__.py index a49a539..ce4ee88 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -14,7 +14,7 @@ ], 'assets': { 'web.assets_tests': [ - 'durpro_fsm/static/tests/tours/task_template_tour.js', + 'bemade_fsm/static/tests/tours/task_template_tour.js', ], }, 'installable': True, diff --git a/__pycache__/__init__.cpython-310.pyc b/__pycache__/__init__.cpython-310.pyc index b5c96a5..c093db2 100644 Binary files a/__pycache__/__init__.cpython-310.pyc and b/__pycache__/__init__.cpython-310.pyc differ diff --git a/models/__pycache__/__init__.cpython-310.pyc b/models/__pycache__/__init__.cpython-310.pyc index 894c59b..1c58b7f 100644 Binary files a/models/__pycache__/__init__.cpython-310.pyc and b/models/__pycache__/__init__.cpython-310.pyc differ diff --git a/models/__pycache__/product_template.cpython-310.pyc b/models/__pycache__/product_template.cpython-310.pyc index dcb03c9..9398263 100644 Binary files a/models/__pycache__/product_template.cpython-310.pyc and b/models/__pycache__/product_template.cpython-310.pyc differ diff --git a/models/__pycache__/sale_order.cpython-310.pyc b/models/__pycache__/sale_order.cpython-310.pyc index 9f6b12a..29c5013 100644 Binary files a/models/__pycache__/sale_order.cpython-310.pyc and b/models/__pycache__/sale_order.cpython-310.pyc differ diff --git a/models/__pycache__/task_template.cpython-310.pyc b/models/__pycache__/task_template.cpython-310.pyc index 35d4aa6..7334f4c 100644 Binary files a/models/__pycache__/task_template.cpython-310.pyc and b/models/__pycache__/task_template.cpython-310.pyc differ diff --git a/models/task_template.py b/models/task_template.py index b02f763..128edbd 100644 --- a/models/task_template.py +++ b/models/task_template.py @@ -14,7 +14,7 @@ class TaskTemplate(models.Model): customer = fields.Many2one("res.partner", string="Default Customer", help="Default customer for tasks created from this template.") project = fields.Many2one("project.project", string="Default Project", help="Default project for tasks created from this template.") tags = fields.Many2many("project.tags", string="Default Tags", help="Default tags for tasks created from this template.") - parent = fields.Many2one("project.task.template", string="Parent Task Template") + parent = fields.Many2one("project.task.template", string="Parent Task Template", ondelete='cascade') subtasks = fields.One2many("project.task.template", inverse_name="parent", string="Subtask Templates") sequence = fields.Integer(string="Sequence") company_id = fields.Many2one("res.company", string="Company", index=1, default=_current_company) diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index 52439aa..e48e8e7 100644 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -1,3 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_durpro_fsm_task_template,durpro_fsm_task_template,model_project_task_template,project.group_project_manager,1,1,1,1 -access_durpro_fsm_task_template,durpro_fsm_task_template,model_project_task_template,project.group_project_user,1,1,1,1 \ No newline at end of file +access_bemade_fsm_task_template,bemade_fsm_task_template,model_project_task_template,project.group_project_manager,1,1,1,1 +access_bemade_fsm_task_template,bemade_fsm_task_template,model_project_task_template,project.group_project_user,1,1,1,1 \ No newline at end of file diff --git a/static/tests/tours/task_template_tour.js b/static/tests/tours/task_template_tour.js index f1bf5d9..549803d 100644 --- a/static/tests/tours/task_template_tour.js +++ b/static/tests/tours/task_template_tour.js @@ -10,7 +10,7 @@ tour.register('task_template_tour', { trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', }, { content: 'Open the task templates list view.', - trigger: '.o_nav_entry[data-menu-xmlid="durpro_fsm.task_template_menu"]', + trigger: '.o_nav_entry[data-menu-xmlid="bemade_fsm.task_template_menu"]', }, { content: 'Open the existing task template.', trigger: '.o_data_cell:contains("Template 1"):parent()', diff --git a/tests/__pycache__/__init__.cpython-310.pyc b/tests/__pycache__/__init__.cpython-310.pyc index 3928a60..abb4558 100644 Binary files a/tests/__pycache__/__init__.cpython-310.pyc and b/tests/__pycache__/__init__.cpython-310.pyc differ diff --git a/tests/__pycache__/test_task_template.cpython-310.pyc b/tests/__pycache__/test_task_template.cpython-310.pyc index ff546e6..f0e0da4 100644 Binary files a/tests/__pycache__/test_task_template.cpython-310.pyc and b/tests/__pycache__/test_task_template.cpython-310.pyc differ diff --git a/tests/test_task_template.py b/tests/test_task_template.py index abdf09c..62813fd 100644 --- a/tests/test_task_template.py +++ b/tests/test_task_template.py @@ -1,5 +1,8 @@ from odoo.tests.common import TransactionCase, HttpCase, tagged -from odoo.exceptions import UserError +from odoo.tools import mute_logger +from odoo.exceptions import MissingError +from odoo import Command +from psycopg2.errors import ForeignKeyViolation class TestTaskTemplateCommon(TransactionCase): @@ -55,19 +58,43 @@ class TestTaskTemplateCommon(TransactionCase): 'uom_po_id': hours_uom.id, 'uom_id': hours_uom.id, }) - cls.partner = cls.env['res.partner'].create({'name': 'Test Partner'}) - cls.sale_order = cls.env['sale.order'].create({ - 'partner_id': cls.partner.id, - 'client_order_ref': 'TEST ORDER', + + # Set up a task template tree with 2 children and 1 grandchild + cls.parent_task = cls.env['project.task.template'].create({ + 'name': 'Parent Template', }) - cls.sol_serv_order = cls.env['sale.order.line'].create({ - 'name': cls.product_task_global_project.name, - 'product_id': cls.product_task_global_project.id, - 'product_uom_qty': 1, - 'product_uom': cls.product_task_global_project.uom_id.id, - 'price_unit': 120.0, - 'order_id': cls.sale_order.id, - 'tax_id': False, + cls.child_task_1 = cls.env['project.task.template'].create({ + 'name': 'Child Template 1', + 'parent': cls.parent_task.id, + }) + cls.child_task_2 = cls.env['project.task.template'].create({ + 'name': 'Child Template 2', + 'parent': cls.parent_task.id, + }) + cls.parent_task.write({'subtasks': [Command.set([cls.child_task_1.id, cls.child_task_2.id])]}) + cls.grandchild_task = cls.env['project.task.template'].create({ + 'name': 'Grandchild Template', + 'parent': cls.child_task_2.id + }) + cls.child_task_2.write({'subtasks': [Command.set([cls.grandchild_task.id])]}) + + # Create products using the task tree we just created + cls.product_task_tree_global_project = cls.env['product.product'].create({ + 'name': 'Test Product 3', + 'type': 'service', + 'service_tracking': 'task_global_project', + 'project_id': cls.project.id, + 'task_template_id': cls.parent_task.id, + 'uom_id': hours_uom.id, + 'uom_po_id': hours_uom.id, + }) + cls.product_task_tree_in_project = cls.env['product.product'].create({ + 'name': 'Test Product 2', + 'type': 'service', + 'service_tracking': 'task_in_project', + 'task_template_id': cls.parent_task.id, + 'uom_po_id': hours_uom.id, + 'uom_id': hours_uom.id, }) @@ -76,17 +103,16 @@ class TestTaskTemplate(TestTaskTemplateCommon): def test_delete_task_template(self): """User should never be able to delete a task template used on a product""" - with self.assertRaises(UserError): + with self.assertRaises(ForeignKeyViolation): self.task1.unlink() - def test_order_confirmation_single_task(self): - """ Confirming the order should create a task in the global project. """ - self.sale_order.action_confirm() - so = self.sale_order - sol = self.sale_order.order_line[0] - task = sol.task_id - self.assertTrue(task) - + def test_delete_subtask_template(self): + """ Deletion of a child task should be OK even if the parent is on a product. Children of the deleted + subtask should be deleted.""" + self.child_task_2.unlink() + # Reading deleted child's name field should be impossible + with self.assertRaises(MissingError): + test = self.grandchild_task.name @tagged('-at_install', 'post_install')