bemade_fsm: major refactoring of unit tests completed. Integration tests need rework.

This commit is contained in:
Marc Durepos 2023-07-14 13:39:30 -04:00
parent 1e050584a5
commit 3771c36899
8 changed files with 232 additions and 318 deletions

View file

@ -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: <a href=# data-oe-model=sale.order data-oe-id=%d>%s</a> (%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

View file

@ -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

View file

@ -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:

View file

@ -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',

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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')