bemade-addons/bemade_fsm/tests/test_bemade_fsm_common.py
2025-05-29 21:35:47 -04:00

284 lines
10 KiB
Python

from odoo.tests.common import TransactionCase, tagged
from odoo import Command
@tagged("-at_install", "post_install")
class BemadeFSMBaseTest(TransactionCase):
@classmethod
def _generate_project_manager_user(cls, name, login):
group_ids = cls.__get_user_groups()
user_group_project_manager = cls.env.ref("project.group_project_manager")
user_group_fsm_manager = cls.env.ref("industry_fsm.group_fsm_manager")
group_ids.append(user_group_fsm_manager.id)
group_ids.append(user_group_project_manager.id)
return cls.__generate_user(name, login, group_ids)
@classmethod
def _generate_project_user(cls, name, login):
group_ids = cls.__get_user_groups()
return cls.__generate_user(name, login, group_ids)
@classmethod
def __generate_user(cls, name, login, group_ids):
return (
cls.env["res.users"]
.with_context(no_reset_password=True)
.create(
{
"name": name,
"login": login,
"password": login,
"email": f"{login}@test.co",
"groups_id": [Command.set(group_ids)],
}
)
)
@classmethod
def __get_user_groups(cls):
user_group_employee = cls.env.ref("base.group_user")
user_group_project_user = cls.env.ref("project.group_project_user")
user_group_fsm_user = cls.env.ref("industry_fsm.group_fsm_user")
user_group_sales_user = cls.env.ref("sales_team.group_sale_salesman")
user_group_sales_manager = cls.env.ref("sales_team.group_sale_manager")
user_product_customer = cls.env.ref(
"customer_product_code.group_product_customer_code_user",
raise_if_not_found=False,
)
group_ids = [
user_group_employee.id,
user_group_project_user.id,
user_group_fsm_user.id,
user_group_sales_manager.id,
user_group_sales_user.id,
]
if user_product_customer:
group_ids.append(user_product_customer.id)
return group_ids
@classmethod
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.
:param company_type: The type of partner, either 'company' or 'person' are
accepted.
"""
return cls.env["res.partner"].create(
{
"name": name,
"company_type": company_type,
"street": "123 Street St.",
"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 or False,
"type": location_type,
}
)
@classmethod
def _generate_sale_order(
cls,
partner=None,
client_order_ref="Test Order",
equipment=None,
shipping_location=None,
):
partner = partner or cls._generate_partner()
vals = {"partner_id": partner.id, "client_order_ref": client_order_ref}
if equipment:
vals.update({"default_equipment_ids": [Command.set([equipment.id])]})
if shipping_location:
vals.update({"partner_shipping_id": shipping_location.id})
return cls.env["sale.order"].create(vals)
@classmethod
def _generate_sale_order_line(
cls, sale_order, product=None, qty=1.0, uom=None, price=100.0, tax_id=False
):
if not product:
product = cls._generate_product()
return cls.env["sale.order.line"].create(
{
"order_id": sale_order.id,
"product_id": product.id,
"product_uom_qty": qty,
"product_uom": uom and uom.id or cls.env.ref("uom.product_uom_hour").id,
"price_unit": price,
"tax_id": tax_id,
}
)
@classmethod
def _generate_equipment(cls, name="test equipment", partner=None):
return cls.env["fsm.equipment"].create(
{
"name": name,
"partner_id": partner and partner.id or False,
}
)
@classmethod
def _generate_product(
cls,
name="Test Product",
product_type="service",
service_tracking="task_global_project",
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 or False
return cls.env["product.product"].create(
{
"name": name,
"type": product_type,
"service_tracking": service_tracking,
"service_type": "timesheet",
"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,
}
)
@classmethod
def _generate_fsm_project(cls, name="Test Project"):
return cls.env["project.project"].create(
{
"name": name,
"allow_material": True,
"allow_timesheets": True,
"allow_quotations": True,
"allow_worksheets": True,
"is_fsm": True,
}
)
@classmethod
def _generate_task_template(
cls,
parent=None,
structure=None,
names=None,
planned_hours=1,
equipment=None,
customer=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. 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. 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 or False,
"planned_hours": planned_hours,
"equipment_ids": [Command.set(equipment and [equipment.id] or [])],
"customer": customer and customer.id or False,
}
)
parent = template
while structure:
subtasks = []
for i in range(0, structure[0]):
subtasks.append(
cls.env["project.task.template"].create(
{
"parent": parent.id,
"name": names[0] + f" {i}",
}
)
)
structure.pop(0)
names.pop(0)
parent = subtasks[0]
return template
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"):
return self.env["bemade_fsm.visit"].create(
[
{
"sale_order_id": sale_order.id,
"label": label,
}
]
)
def _generate_so_with_one_visit_two_lines(self):
so = self._generate_sale_order()
visit = self._generate_visit(sale_order=so)
sol1 = self._generate_sale_order_line(sale_order=so)
sol2 = self._generate_sale_order_line(sale_order=so)
visit.so_section_id.sequence = 1
sol1.sequence = 2
sol2.sequence = 3
return so, visit, sol1, sol2
def _generate_so_with_one_visit_two_lines_and_descendants(self):
so = self._generate_sale_order()
visit = self._generate_visit(sale_order=so)
task_template = self._generate_task_template(
structure=[2, 2, 2],
names=["Parent", "Child", "Grandchild", "Great-grandchild"],
)
product = self._generate_product(task_template=task_template)
sol1 = self._generate_sale_order_line(sale_order=so, product=product)
sol2 = self._generate_sale_order_line(sale_order=so, product=product)
visit.so_section_id.sequence = 1
sol1.sequence = 2
sol2.sequence = 3
return so, visit, sol1, sol2