From 3771c368996c0fe966b5b17ab6e6c6f6d4604e3c Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Fri, 14 Jul 2023 13:39:30 -0400 Subject: [PATCH] bemade_fsm: major refactoring of unit tests completed. Integration tests need rework. --- bemade_fsm/models/sale_order.py | 7 +- bemade_fsm/tests/__init__.py | 1 - bemade_fsm/tests/test_bemade_fsm_common.py | 52 +++-- bemade_fsm/tests/test_equipment.py | 1 + bemade_fsm/tests/test_fsm_contact_setting.py | 147 ++++++------- bemade_fsm/tests/test_fsm_visit.py | 75 ++----- bemade_fsm/tests/test_sale_order.py | 208 ++++++++++--------- bemade_fsm/tests/test_so_task_contacts.py | 59 ------ 8 files changed, 232 insertions(+), 318 deletions(-) delete mode 100644 bemade_fsm/tests/test_so_task_contacts.py diff --git a/bemade_fsm/models/sale_order.py b/bemade_fsm/models/sale_order.py index 7b8b988..4e879be 100644 --- a/bemade_fsm/models/sale_order.py +++ b/bemade_fsm/models/sale_order.py @@ -114,7 +114,8 @@ class SaleOrderLine(models.Model): vals['user_ids'] = template.assignees.ids vals['tag_ids'] = template.tags.ids vals['planned_hours'] = template.planned_hours - vals['equipment_ids'] = [Command.set([template.equipment_id.id])] + if template.equipment_id: + vals['equipment_ids'] = [Command.set([template.equipment_id.id])] return vals tmpl = self.product_id.task_template_id @@ -128,8 +129,8 @@ class SaleOrderLine(models.Model): "This task has been created from: %s (%s)") % ( self.order_id.id, self.order_id.name, self.product_id.name) task.message_post(body=task_msg) - if not task.equipment_ids: - task.write({'equipment_ids': [Command.set(self.order_id.equipment_id)]}) + if not task.equipment_ids and self.order_id.equipment_id: + task.write({'equipment_ids': [Command.set([self.order_id.equipment_id.id])]}) task.name = _generate_task_name(tmpl) return task diff --git a/bemade_fsm/tests/__init__.py b/bemade_fsm/tests/__init__.py index e838478..381536f 100644 --- a/bemade_fsm/tests/__init__.py +++ b/bemade_fsm/tests/__init__.py @@ -3,5 +3,4 @@ from . import test_task_template from . import test_sale_order from . import test_equipment from . import test_fsm_contact_setting -from . import test_so_task_contacts from . import test_fsm_visit diff --git a/bemade_fsm/tests/test_bemade_fsm_common.py b/bemade_fsm/tests/test_bemade_fsm_common.py index 94de29c..e186410 100644 --- a/bemade_fsm/tests/test_bemade_fsm_common.py +++ b/bemade_fsm/tests/test_bemade_fsm_common.py @@ -5,13 +5,6 @@ from odoo import Command @tagged("-at_install", "post_install") class BemadeFSMBaseTest(TransactionCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.user = cls._generate_project_manager_user('Project Manager', 'misterpm') - cls.user_limited = cls._generate_project_user('Project User', 'mruser') - cls.env.ref("industry_fsm.fsm_project").write({'allow_subtasks': True}) - @classmethod def _generate_project_manager_user(cls, name, login): user_group_employee = cls.env.ref('base.group_user') @@ -47,7 +40,8 @@ class BemadeFSMBaseTest(TransactionCase): user.write({'groups_id': [Command.unlink(cls.env.ref('industry_fsm.group_fsm_manager'))]}) @classmethod - def _generate_partner(cls, name: str = 'Test Company', company_type: str = 'company', parent=None): + def _generate_partner(cls, name: str = 'Test Company', company_type: str = 'company', parent=None, + location_type='other'): """ Generates a partner with basic address filled in. :param name: The partner's name. @@ -59,24 +53,26 @@ class BemadeFSMBaseTest(TransactionCase): 'city': 'Montreal', 'state_id': cls.env.ref('base.state_ca_qc').id, 'country_id': cls.env.ref('base.ca').id, - 'parent_id': parent and parent.id, + 'parent_id': parent and parent.id or False, + 'type': location_type, }) @classmethod - def _generate_sale_order(cls, partner, client_order_ref='Test Order', equipment=None): + def _generate_sale_order(cls, partner=None, client_order_ref='Test Order', equipment=None): + partner = partner or cls._generate_partner() return cls.env['sale.order'].create({ 'partner_id': partner.id, 'client_order_ref': client_order_ref, - 'equipment_id': equipment.id, + 'equipment_id': equipment and equipment.id or False, }) @classmethod - def _generate_sale_order_line(cls, sale_order, product, project, qty=1.0, uom=None, price=100.0, tax_id=False): + def _generate_sale_order_line(cls, sale_order, product, qty=1.0, uom=None, price=100.0, tax_id=False): return cls.env['sale.order.line'].create({ 'order_id': sale_order.id, 'product_id': product.id, 'product_uom_qty': qty, - 'product_uom': uom or cls.env.ref("uom.product_uom_hour"), + 'product_uom': uom and uom.id or cls.env.ref("uom.product_uom_hour").id, 'price_unit': price, 'tax_id': tax_id, }) @@ -85,7 +81,7 @@ class BemadeFSMBaseTest(TransactionCase): def _generate_equipment(cls, name='test equipment', partner=None): return cls.env['bemade_fsm.equipment'].create({ 'name': name, - 'partner_location_id': partner and partner.id, + 'partner_location_id': partner and partner.id or False, }) @classmethod @@ -93,14 +89,14 @@ class BemadeFSMBaseTest(TransactionCase): project=None, task_template=None, service_policy='delivered_manual', uom=None): if 'project' in service_tracking and not project: project = cls.env.ref("industry_fsm.fsm_project") - uom_id = uom and uom.id or cls.env.ref("uom.product_uom_hour").id + uom_id = uom and uom.id or cls.env.ref("uom.product_uom_hour").id or False return cls.env['product.product'].create({ 'name': name, 'type': product_type, 'service_tracking': service_tracking, - 'project_id': service_tracking in ('task_global_project', 'project_only') and project.id, - 'project_template_id': service_tracking == 'task_in_project' and project.id, - 'task_template_id': task_template and task_template.id, + 'project_id': service_tracking in ('task_global_project', 'project_only') and project.id or False, + 'project_template_id': service_tracking == 'task_in_project' and project.id or False, + 'task_template_id': task_template and task_template.id or False, 'service_policy': service_policy, 'uom_id': uom_id, 'uom_po_id': uom_id, @@ -119,20 +115,32 @@ class BemadeFSMBaseTest(TransactionCase): }) @classmethod - def _generate_task_template(cls, parent=None, structure=[], names=['Test Task Template']): + def _generate_task_template(cls, parent=None, structure=None, names=None, planned_hours=1, + equipment=None): """ Generates a task template with the specified structure and naming. + :param parent: The parent task template for the top-level task template being generated :param structure: A list of integers describing the number of tasks for each level of descendants. An empty - list represents only one top-level task template. + list represents only one top-level task template. If no structure is given, an empty list + will be used in its place. :param names: The name prefixes to be given to the task templates at each level. Each prefix will be followed - by a sequential integer for its level. Child 1, Child 2, Grandchild 1, etc.""" + by a sequential integer for its level. Child 1, Child 2, Grandchild 1, etc. If no names argument + is passed, a default ['Task Template'] argument will be used. + :param planned_hours: The number of planned hours for the top-level task template being generated. + :param equipment: The equipment to add as linked equipment to the task template.""" + if not names: + names = ['Task Template'] + if not structure: + structure = [] if len(structure) != len(names) - 1: raise ValueError("The length of the structure argument must contain exactly one element less than the " "names argument.") name = names.pop(0) template = cls.env['project.task.template'].create({ 'name': name, - 'parent': parent and parent.id, + 'parent': parent and parent.id or False, + 'planned_hours': planned_hours, + 'equipment_id': equipment and equipment.id or False, }) parent = template while structure: diff --git a/bemade_fsm/tests/test_equipment.py b/bemade_fsm/tests/test_equipment.py index 65fba3c..934c370 100644 --- a/bemade_fsm/tests/test_equipment.py +++ b/bemade_fsm/tests/test_equipment.py @@ -29,6 +29,7 @@ class TestEquipmentTours(HttpCase, BemadeFSMBaseTest): cls._generate_partner() cls._generate_partner('Site Contact', 'person', cls.partner_company) cls._generate_equipment('Test Equipment 1', cls.partner_company) + cls.user = cls._generate_project_manager_user() def test_equipment_base_tour(self): self.start_tour('/web', 'equipment_base_tour', diff --git a/bemade_fsm/tests/test_fsm_contact_setting.py b/bemade_fsm/tests/test_fsm_contact_setting.py index 0c097ab..b613aef 100644 --- a/bemade_fsm/tests/test_fsm_contact_setting.py +++ b/bemade_fsm/tests/test_fsm_contact_setting.py @@ -3,110 +3,87 @@ from odoo import Command from .test_bemade_fsm_common import BemadeFSMBaseTest -def create_base_contacts(cls): - Partner = cls.env['res.partner'] - cls.parent_co = Partner.create({ - 'name': 'Parent Co', - 'company_type': 'company', - }) - cls.contact_1 = Partner.create({ - 'name': 'Contact 1', - 'company_type': 'person', - 'parent_id': cls.parent_co.id, - }) - cls.contact_2 = Partner.create({ - 'name': 'Contact 2', - 'company_type': 'person', - 'parent_id': cls.parent_co.id, - }) - - @tagged("-at_install", "post_install") class SaleOrderFSMContactsCase(BemadeFSMBaseTest): - @classmethod - def setUpClass(cls): - super().setUpClass() - create_base_contacts(cls) - def test_site_contacts(self): + parent_co = self._generate_partner('Parent Co') + contact_1 = self._generate_partner('Contact 1', 'person', parent_co) + contact_2 = self._generate_partner('Contact 2', 'person', parent_co) + # Make sure the SO pulls the defaults from the partner correctly - self.parent_co.write({'site_contacts': [Command.set([self.contact_1.id, self.contact_2.id])]}) - so = self.env['sale.order'].create({ - 'partner_id': self.parent_co.id, - }) - self.assertTrue(so.site_contacts == self.parent_co.site_contacts) + parent_co.write({'site_contacts': [Command.set([contact_1.id, contact_2.id])]}) + so = self._generate_sale_order(parent_co) + self.assertTrue(so.site_contacts == parent_co.site_contacts) + # Make sure updating the site contacts on the SO doesn't feed back to the partner - so.write({'site_contacts': [Command.set([self.contact_1.id])]}) - self.assertTrue(self.contact_1 in so.site_contacts) - self.assertTrue(self.contact_2 not in so.site_contacts) + so.write({'site_contacts': [Command.set([contact_1.id])]}) + self.assertTrue(contact_1 in so.site_contacts) + self.assertTrue(contact_2 not in so.site_contacts) self.assertTrue(so.site_contacts != so.partner_id.site_contacts and len(so.partner_id.site_contacts) == 2) def test_default_workorder_contacts(self): + parent_co = self._generate_partner('Parent Co') + contact_1 = self._generate_partner('Contact 1', 'person', parent_co) + contact_2 = self._generate_partner('Contact 2', 'person', parent_co) + # Make sure the SO pulls the defaults from the partner correctly - self.parent_co.write({'work_order_contacts': [Command.set([self.contact_1.id, self.contact_2.id])]}) - so = self.env['sale.order'].create({ - 'partner_id': self.parent_co.id, - }) - self.assertTrue(self.contact_1 in self.parent_co.work_order_contacts) - self.assertTrue(self.contact_2 in self.parent_co.work_order_contacts) - self.assertTrue(self.contact_1 in so.work_order_contacts) - self.assertTrue(self.contact_2 in so.work_order_contacts) + parent_co.write({'work_order_contacts': [Command.set([contact_1.id, contact_2.id])]}) + so = self._generate_sale_order(parent_co) + self.assertTrue(contact_1 in parent_co.work_order_contacts) + self.assertTrue(contact_2 in parent_co.work_order_contacts) + self.assertTrue(contact_1 in so.work_order_contacts) + self.assertTrue(contact_2 in so.work_order_contacts) + # Make sure setting the work order contacts on the SO doesn't feed back to the partner - so.write({'work_order_contacts': [Command.set([self.contact_1.id])]}) - self.assertTrue(self.contact_1 in so.work_order_contacts) - self.assertTrue(self.contact_2 not in so.work_order_contacts) + so.write({'work_order_contacts': [Command.set([contact_1.id])]}) + self.assertTrue(contact_1 in so.work_order_contacts) + self.assertTrue(contact_2 not in so.work_order_contacts) self.assertTrue( so.work_order_contacts != so.partner_id.work_order_contacts and len(so.partner_id.work_order_contacts) == 2) - -class SaleOrderMultiLocationContactsTest(BemadeFSMBaseTest): - @classmethod - def setUpClass(cls): - super().setUpClass() - create_base_contacts(cls) - cls.shipping_location = cls.env['res.partner'].create({ - 'name': 'Shipping location', - 'company_type': 'company', - 'type': 'delivery', - 'parent_id': cls.parent_co.id, - }) - cls.site_contact1 = cls.env['res.partner'].create({ - 'name': 'Site Contact One', - 'company_type': 'person', - 'type': 'contact', - 'parent_id': cls.shipping_location.id, - }) - cls.site_contact2 = cls.env['res.partner'].create({ - 'name': 'Site Contact Two', - 'company_type': 'person', - 'type': 'contact', - 'parent_id': cls.shipping_location.id, - }) - cls.shipping_location.write({ - 'work_order_contacts': [Command.set([cls.contact_1.id, cls.contact_2.id])], - 'site_contacts': [Command.set([cls.site_contact1.id, cls.site_contact2.id])], - }) - def test_multilayer_site_contacts(self): - so = self.env['sale.order'].create({ - 'partner_id': self.parent_co.id, - 'partner_shipping_id': self.shipping_location.id}) - self.assertEqual(so.partner_shipping_id, self.shipping_location) - self.assertEqual(so.site_contacts, self.shipping_location.site_contacts) - self.assertEqual(so.work_order_contacts, self.shipping_location.work_order_contacts) + parent_co = self._generate_partner('Parent Co') + shipping_location = self._generate_partner('Shipping Location', 'company', parent_co, 'delivery') + wo_contact_1 = self._generate_partner('WO Contact 1', 'person', shipping_location) + wo_contact_2 = self._generate_partner('WO Contact 2', 'person', shipping_location) + site_contact_1 = self._generate_partner('Site Contact 1', 'person', shipping_location) + site_contact_2 = self._generate_partner('Site Contact 2', 'person', shipping_location) + shipping_location.write({ + 'work_order_contacts': [Command.set([wo_contact_1.id, wo_contact_2.id])], + 'site_contacts': [Command.set([site_contact_1.id, site_contact_2.id])] + }) + + so = self._generate_sale_order(parent_co) + so.write({'partner_shipping_id': shipping_location.id}) + + self.assertEqual(so.site_contacts, shipping_location.site_contacts) + self.assertEqual(so.work_order_contacts, shipping_location.work_order_contacts) def test_onchange_shipping_address(self): - so = self.env['sale.order'].create({ - 'partner_id': self.parent_co.id, - 'partner_shipping_id': self.parent_co.id, + parent_co = self._generate_partner('Parent Co') + shipping_location = self._generate_partner('Shipping Location', 'company', parent_co, 'delivery') + wo_contact_1 = self._generate_partner('WO Contact 1', 'person', shipping_location) + wo_contact_2 = self._generate_partner('WO Contact 2', 'person', shipping_location) + site_contact_1 = self._generate_partner('Site Contact 1', 'person', shipping_location) + site_contact_2 = self._generate_partner('Site Contact 2', 'person', shipping_location) + shipping_location.write({ + 'work_order_contacts': [Command.set([wo_contact_1.id, wo_contact_2.id])], + 'site_contacts': [Command.set([site_contact_1.id, site_contact_2.id])] }) + + so = self._generate_sale_order(parent_co) + + # Set back to a location without site or work order contacts + form = Form(so) + form.partner_shipping_id = parent_co + form.save() + # Make sure the contacts were reset on the SO self.assertFalse(so.work_order_contacts) self.assertFalse(so.site_contacts) - form = Form(so) - form.partner_shipping_id = self.shipping_location + # Now set back to the location with the FSM contacts and make sure they get set on the SO + form.partner_shipping_id = shipping_location form.save() - - self.assertEqual(so.work_order_contacts, self.shipping_location.work_order_contacts) - self.assertEqual(so.site_contacts, self.shipping_location.site_contacts) + self.assertEqual(so.work_order_contacts, shipping_location.work_order_contacts) + self.assertEqual(so.site_contacts, shipping_location.site_contacts) diff --git a/bemade_fsm/tests/test_fsm_visit.py b/bemade_fsm/tests/test_fsm_visit.py index eca8e2c..cf01c1e 100644 --- a/bemade_fsm/tests/test_fsm_visit.py +++ b/bemade_fsm/tests/test_fsm_visit.py @@ -1,24 +1,22 @@ from odoo.tests import TransactionCase, tagged, Form +from .test_bemade_fsm_common import BemadeFSMBaseTest @tagged('-at_install', 'post_install') -class FSMVisitTest(TransactionCase): - @classmethod - def setUpClass(cls): - super().setUpClass() +class FSMVisitTest(BemadeFSMBaseTest): def test_create_visit_sets_name_on_section(self): - so = self.generate_sale_order() - self.add_service_so_line(so) + so = self._generate_sale_order() + self._add_service_so_line(so) - visit = self.generate_visit(so) + visit = self._generate_visit(so) self.assertTrue(visit.so_section_id) self.assertEqual(visit.so_section_id.name, visit.label) def test_change_visit_section_name(self): - so = self.generate_sale_order() - visit = self.generate_visit(so, label="First Label") + so = self._generate_sale_order() + visit = self._generate_visit(so, label="First Label") line = visit.so_section_id line.name = "Second Label" @@ -26,8 +24,8 @@ class FSMVisitTest(TransactionCase): self.assertEqual(visit.label, "Second Label") def test_change_visit_label_changes_section_name(self): - so = self.generate_sale_order() - visit = self.generate_visit(so, label="First Label") + so = self._generate_sale_order() + visit = self._generate_visit(so, label="First Label") line = visit.so_section_id visit.label = "Second Label" @@ -35,9 +33,9 @@ class FSMVisitTest(TransactionCase): self.assertEqual(line.name, "Second Label") def test_visit_completes_when_task_completes(self): - so = self.generate_sale_order() - visit = self.generate_visit(so) - sol = self.add_service_so_line(so, task=True) + so = self._generate_sale_order() + visit = self._generate_visit(so) + self._add_service_so_line(so, task=True) so.action_confirm() task = so.order_line.filtered(lambda l: l.task_id).task_id @@ -46,65 +44,36 @@ class FSMVisitTest(TransactionCase): self.assertTrue(visit.is_completed) def test_visit_shows_invoiced_when_invoiced(self): - so = self.generate_sale_order() - visit = self.generate_visit(so) - self.add_service_so_line(so, task=True) + so = self._generate_sale_order() + visit = self._generate_visit(so) + self._add_service_so_line(so, task=True) so.action_confirm() task = so.order_line.filtered(lambda l: l.task_id).task_id task.action_fsm_validate() - self.invoice_sale_order(so) + self._invoice_sale_order(so) self.assertTrue(visit.is_invoiced) - def invoice_sale_order(self, so): + def _invoice_sale_order(self, so): wiz = self.env['sale.advance.payment.inv'].with_context({'active_ids': [so.id]}).create({}) wiz.create_invoices() inv = so.invoice_ids[-1] inv.action_post() return inv - def generate_visit(self, sale_order, label="Test Label"): + def _generate_visit(self, sale_order, label="Test Label"): return self.env['bemade_fsm.visit'].create([{ 'sale_order_id': sale_order.id, 'label': label, }]) - def generate_sale_order(self, partner_id=None): - so = self.env['sale.order'].create({ - 'partner_id': partner_id or self.generate_partner().id, - 'client_order_ref': 'Test', - }) - return so - - def add_service_so_line(self, sale_order, task: bool = False): + def _add_service_so_line(self, sale_order, task: bool = False): """ Generates a sales order line for a service product. :param sale_order: The sales order to which the new line is to be added :param task: If true, the created line will be for a product with service_tracking=task_global_project """ - if not task: - service_tracking = 'no' - project = False - else: - project = self.env.ref("industry_fsm.fsm_project") - service_tracking = 'task_global_project' - product = self.env['product.product'].create({ - 'name': 'Test Product', - 'type': 'service', - 'service_tracking': service_tracking, - 'project_id': project and project.id, - 'price': 100.0, - 'sale_ok': True, - }) - return self.env['sale.order.line'].create({ - 'product_id': product.id, - 'order_id': sale_order.id, - }) - - def generate_partner(self): - partner = self.env['res.partner'].create({ - 'name': 'Test Partner', - 'company_type': 'company', - }) - return partner + service_tracking = 'task_global_project' if task else 'no' + product = self._generate_product(service_tracking=service_tracking) + return self._generate_sale_order_line(sale_order, product) diff --git a/bemade_fsm/tests/test_sale_order.py b/bemade_fsm/tests/test_sale_order.py index ae558f7..eaab2f0 100644 --- a/bemade_fsm/tests/test_sale_order.py +++ b/bemade_fsm/tests/test_sale_order.py @@ -1,123 +1,93 @@ from .test_task_template import TestTaskTemplateCommon -from odoo.tests.common import tagged, HttpCase +from odoo.tests.common import tagged, HttpCase, Form +from odoo import Command @tagged("-at_install", "post_install") class TestSalesOrder(TestTaskTemplateCommon): - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.partner = cls.env['res.partner'].create({ - 'name': 'Test Partner', - }) - cls.equipment = TestSalesOrder._generate_equipment() - cls.so_equipment = TestSalesOrder._generate_equipment('test equipment 2') - - cls.sale_order1 = TestSalesOrder._generate_equipment(partner=cls.partner, client_order_ref='TEST ORDER 1', - equipment=cls.so_equipment) - cls.sol_serv_order = TestSalesOrder._generate_sale_order_line(product, project, ) - 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_order1.id, - 'tax_id': False, - }) - cls.sol_serv_order_task_in_project = cls.env['sale.order.line'].create({ - 'name': cls.product_task_in_project.name, - 'product_id': cls.product_task_in_project.id, - 'product_uom_qty': 1, - 'product_uom': cls.product_task_in_project.uom_id.id, - 'price_unit': 150.0, - 'order_id': cls.sale_order1.id, - 'tax_id': False, - }) - cls.sale_order2 = cls.env['sale.order'].create({ - 'partner_id': cls.partner.id, - 'client_order_ref': 'TEST ORDER 2', - 'state': 'draft', - }) - cls.sol_tree_order = cls.env['sale.order.line'].create({ - 'name': cls.product_task_tree_global_project.name, - 'product_id': cls.product_task_tree_global_project.id, - 'product_uom_qty': 1, - 'product_uom': cls.product_task_tree_global_project.uom_id.id, - 'price_unit': 120.0, - 'order_id': cls.sale_order2.id, - 'tax_id': False, - }) - cls.sol_serv_order_task_in_project = cls.env['sale.order.line'].create({ - 'name': cls.product_task_tree_in_project.name, - 'product_id': cls.product_task_tree_in_project.id, - 'product_uom_qty': 1, - 'product_uom': cls.product_task_tree_in_project.uom_id.id, - 'price_unit': 150.0, - 'order_id': cls.sale_order2.id, - 'tax_id': False, - }) - - @tagged('-at_install', 'post_install') def test_order_confirmation_simple_template(self): - """ Confirming the order should create a task in the global project. """ - so = self.sale_order1 + """ Confirming the order should create a task in the global project based on the task template. """ + partner = self._generate_partner() + so = self._generate_sale_order(partner=partner) + task_template = self._generate_task_template(planned_hours=8) + product = self._generate_product(task_template=task_template) + sol = self._generate_sale_order_line(so, product=product) + so.action_confirm() - sol1 = so.order_line[0] - sol2 = so.order_line[1] - task1 = sol1.task_id - task2 = sol2.task_id - self.assertTrue(task1) - self.assertTrue(task2) - self.assertTrue(self.task1.name in task1.name) - self.assertTrue(self.task1.name in task2.name) - self.assertTrue(self.task1.planned_hours == task1.planned_hours) + + task = sol.task_id + self.assertTrue(task) + self.assertTrue(task_template.name in task.name) + self.assertTrue(task_template.planned_hours == task.planned_hours) def test_order_confirmation_tree_template(self): - def assert_structure(sol): - self.assertTrue(sol.task_id.child_ids and len(sol.task_id.child_ids) == 2) - self.assertTrue(self.parent_task.name in sol.task_id.name) - self.assertTrue(self.child_task_1.name in sol.task_id.child_ids[0].name) - self.assertTrue(self.child_task_2.name in sol.task_id.child_ids[1].name) - self.assertTrue(sol.task_id.child_ids[1].child_ids and len(sol.task_id.child_ids.child_ids) == 1) - self.assertTrue(self.grandchild_task.name in sol.task_id.child_ids.child_ids[0].name) + partner = self._generate_partner() + so = self._generate_sale_order(partner=partner) + task_template = self._generate_task_template(structure=[2, 1], + names=['Parent Template', 'Child Template', + 'Grandchild Template']) + product = self._generate_product(task_template=task_template) + sol = self._generate_sale_order_line(so, product=product) - so = self.sale_order2 so.action_confirm() - sol1 = so.order_line[0] - sol2 = so.order_line[1] - assert_structure(sol1) - assert_structure(sol2) + + self.assertTrue(sol.task_id.child_ids and len(sol.task_id.child_ids) == 2) + self.assertTrue(self.parent_task.name in sol.task_id.name) + self.assertTrue(self.child_task_1.name in sol.task_id.child_ids[0].name) + self.assertTrue(self.child_task_2.name in sol.task_id.child_ids[1].name) + self.assertTrue(sol.task_id.child_ids[0].child_ids and len(sol.task_id.child_ids[0].child_ids) == 1) + self.assertTrue(self.grandchild_task.name in sol.task_id.child_ids.child_ids[0].name) def test_order_confirmation_equipment(self): - so = self.sale_order1 - self.assertEqual(so.equipment_id, so.equipment_id) - self.assertFalse(so.order_line[0].product_id.task_template_id.equipment_id) + """ The equipment selected on the SO should transfer to the task.""" + partner = self._generate_partner() + equipment = self._generate_equipment(partner=partner) + so = self._generate_sale_order(partner=partner, equipment=equipment) + task_template = self._generate_task_template(planned_hours=8) + product1 = self._generate_product(task_template=task_template) + product2 = self._generate_product() + sol1 = self._generate_sale_order_line(so, product=product1) + sol2 = self._generate_sale_order_line(so, product=product2) + so.action_confirm() - task = so.order_line.filtered(lambda l: not l.product_id.task_template_id.equipment_id).task_id - self.assertEqual(task.equipment_id, self.so_equipment) + + task1 = sol1.task_id + task2 = sol2.task_id + self.assertEqual(task1.equipment_ids[0], equipment) + self.assertEqual(task2.equipment_ids[0], equipment) def test_task_template_with_equipment_flow(self): - so = self.sale_order1 - self.product_task_global_project.task_template_id.equipment_id = self.equipment + """ The equipment selected on a task template should flow down to the task created on SO confirmation.""" + partner = self._generate_partner() + equipment = self._generate_equipment(partner=partner) + so = self._generate_sale_order(partner=partner) + task_template = self._generate_task_template(equipment=equipment) + product = self._generate_product(task_template=task_template) + sol = self._generate_sale_order_line(so, product=product) + so.action_confirm() - task = so.order_line.filtered(lambda l: l.product_id.task_template_id.equipment_id).task_id - self.assertEqual(task.equipment_id, self.equipment) + + self.assertEqual(sol.task_id.equipment_ids[0], equipment) def test_task_mark_done(self): - so = self.sale_order2 + """ Marking the task linked to an SO line should mark the line delivered. Marking sub-tasks done should not.""" + partner = self._generate_partner() + so = self._generate_sale_order(partner=partner) + task_template = self._generate_task_template(structure=[2], names=["Parent Task", "Subtask"]) + product = self._generate_product(task_template=task_template) + sol = self._generate_sale_order_line(so, product=product) so.action_confirm() - sol = so.order_line[0] parent_task = sol.task_id - child_task = parent_task.child_ids[0] + subtasks = parent_task._get_all_subtasks() + + # Marking the subtasks done should not increment delivered quantity + subtasks.action_fsm_validate() + self.assertEqual(sol.qty_delivered, 0) + # Marking the top-level tasks done should set the delivered quantity to some non-zero value based on the UOM parent_task.action_fsm_validate() - # sol._compute_qty_delivered() self.assertTrue(sol.qty_delivered != 0) - # Marking a child task done should not create a sale order - child_task.action_fsm_validate() - self.assertFalse(child_task.sale_order_id) @tagged("-at_install", "post_install", "slow") @@ -138,3 +108,51 @@ class TestSaleOrderTour(HttpCase, TestSalesOrder): sol = so.order_line.filtered(lambda l: 'Test Product 3' in l.name) self.start_tour('/web', 'sale_order_tour', login='misterpm') self.assertTrue(sol.qty_delivered != 0) + + def test_task_contacts_through_sale_order(self): + """ Make sure the site contacts and work order contacts transfer correctly from the SO to the task.""" + + partner = self._generate_partner() + contact1 = self._generate_partner('Site contact', 'person', partner) + contact2 = self._generate_partner('Work order contact', 'person', partner) + partner.write({ + 'site_contacts': [Command.set([contact1.id])], + 'work_order_contacts': [Command.set([contact2.id])], + }) + so = self._generate_sale_order(partner) + product = self._generate_product() + sol = self._generate_sale_order_line(product=product) + + so.action_confirm() + + self.assertEqual(so.work_order_contacts, partner.work_order_contacts) + self.assertEqual(so.site_contacts, partner.site_contacts) + self.assertEqual(sol.task_id.work_order_contacts, partner.work_order_contacts) + self.assertEqual(sol.task_id.site_contacts, partner.site_contacts) + + def test_changing_task_contacts_mirrors_with_sale_order(self): + partner = self._generate_partner() + contact = self._generate_partner("Contact", "person", partner) + so = self._generate_sale_order(partner) + product = self._generate_product() + sol = self._generate_sale_order_line(so, product) + so.action_confirm() + task = sol.task_id + task_form = Form(task) + + # Now change the site/work order contact on the task and make sure it feeds back to the sales order + task_form.site_contacts.add(contact) + task_form.work_order_contacts.add(contact) + task_form.save() + + self.assertEqual(task.site_contacts, so.site_contacts) + self.assertEqual(task.work_order_contacts, so.work_order_contacts) + + # Test changing it on the SO feeds back to the task as well + f = Form(so) + f.work_order_contacts.remove(contact.id) + f.site_contacts.remove(contact.id) + f.save() + + self.assertEqual(task.site_contacts, so.site_contacts) + self.assertEqual(task.work_order_contacts, so.work_order_contacts) diff --git a/bemade_fsm/tests/test_so_task_contacts.py b/bemade_fsm/tests/test_so_task_contacts.py deleted file mode 100644 index d0f1453..0000000 --- a/bemade_fsm/tests/test_so_task_contacts.py +++ /dev/null @@ -1,59 +0,0 @@ -from .test_sale_order import TestSalesOrder -from odoo import Command -from odoo.tests.common import Form, tagged - - -@tagged("-at_install", "post_install") -class TestSaleOrderTaskContacts(TestSalesOrder): - @classmethod - def setUpClass(cls): - super().setUpClass() - Partner = cls.env['res.partner'] - cls.partner2 = Partner.create({ - 'name': 'New Partner', - 'company_type': 'company', - }) - cls.contact = Partner.create({ - 'name': 'Contact', - 'company_type': 'person', - 'parent_id': cls.partner2.id, - }) - cls.contact2 = cls.env['res.partner'].create({ - 'name': 'Contact 2', - 'company_type': 'person', - 'parent_id': cls.partner2.id, - }) - - def _test_task_contacts_from_so(self, field): - """ Shorthand function for testing both work_order_contacts and site_contacts fields on SOs and tasks.""" - def ga(obj): - return getattr(obj, field) - # Add the default site/work order contact to the partner, create an SO with the partner - self.partner2.write({field: [Command.set([self.contact.id])]}) - self.sale_order1.write( - {'partner_id': self.partner2.id, field: [Command.set(ga(self.partner2).ids)]}) - so = self.sale_order1 - self.assertTrue(ga(so)) - # Confirm the SO and check that the task got the default carried over - so.action_confirm() - task = so.order_line[0].task_id - self.assertTrue(ga(task)) - self.assertTrue(ga(task) == ga(so)) - # Now change the site/work order contact on the task and make sure it feeds back to the sales order - f = Form(task) - ga(f).add(self.contact2) - f.save() - self.assertTrue(ga(so) == ga(task)) - # Test changing it on the SO feeds back to the task as well - f = Form(so) - ga(f).remove(self.contact.id) - f.save() - self.assertTrue(ga(so) == ga(task)) - - def test_work_order_contacts_on_task(self): - # Make sure work order contacts on the sales order transfer to the task on order confirmation - self._test_task_contacts_from_so('work_order_contacts') - - def test_site_contacts_on_task(self): - # Make sure site contacts from the sales order transfer to the task on order confirmation - self._test_task_contacts_from_so('site_contacts')