Files
enterprise-addons/industry_fsm_sale/tests/test_industry_fsm_task.py
T

251 lines
11 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details
from odoo import Command
from odoo.tests import tagged, Form
from .common import TestFsmFlowSaleCommon
@tagged('-at_install', 'post_install')
class TestIndustryFsmTask(TestFsmFlowSaleCommon):
def test_partner_id_follows_so_shipping_address(self):
""" For fsm tasks linked to a sale order, the partner_id should be the same as
the partner_shipping_id set on the sale sale order.
"""
self.env.user.group_ids += self.env.ref('account.group_delivery_invoice_address')
so = self.env['sale.order'].create([{
'name': 'Test SO linked to fsm task',
'partner_id': self.partner_1.id,
}])
sol = self.env['sale.order.line'].create([{
'name': 'Test SOL linked to a fsm tasl',
'order_id': so.id,
'task_id': self.task.id,
'product_id': self.service_product_delivered.id,
'product_uom_qty': 3,
}])
self.task.sale_line_id = sol
partner_2 = self.env['res.partner'].create({'name': 'A Test Partner 2'})
# 1. Modyfing shipping address on SO should update the customer on the task
self.assertEqual(so.partner_id, self.partner_1)
self.assertEqual(so.partner_shipping_id, self.partner_1)
self.assertEqual(self.task.partner_id, self.partner_1)
so.partner_shipping_id = partner_2
self.assertEqual(so.partner_id, self.partner_1)
self.assertEqual(so.partner_shipping_id, partner_2)
self.assertEqual(self.task.partner_id, partner_2,
"Modifying the shipping partner on a sale order linked to a fsm task should update the partner of this task accordingly")
# 2. partner_id should be False for task not billable
self.task.project_id.allow_billable = False
so.partner_shipping_id = partner_2
self.assertFalse(self.task.partner_id, "Partner id should be set to False for non-billable tasks")
def test_fsm_task_under_warranty(self):
""" Ensure that the product price is zero in the sales order line for task is under warranty.
Test Case:
=========
1. Create a task and add timesheet line to it
2. Set the task under warranty
3. Validate the task
4. Check the price unit of the sale order line
"""
self.task.write({'under_warranty': True, 'partner_id': self.partner_1.id})
self.env['account.analytic.line'].create({
'name': 'Timesheet',
'task_id': self.task.id,
'unit_amount': 0.25,
'date': '2024-04-22',
'employee_id': self.employee_user2.id,
})
self.task.action_fsm_validate()
self.assertEqual(self.task.sale_line_id.price_unit, 0.0, "If task is under warranty, the price of the sale order line should be 0.0")
def test_fsm_task_sale_line_id(self):
"""Ensure that no Sale Order is generated on task if task is under warranty
and there are timesheets but no product on the task.
Test Case:
=========
1. Create a task and add timesheet line to it
2. Set the task under warranty
3. Validate the task without any product
4. Sale order should not be generated
"""
self.task.write({'under_warranty': True, 'partner_id': self.partner_1.id})
self.env['account.analytic.line'].create({
'name': 'Timesheet',
'task_id': self.task.id,
'unit_amount': 0.50,
'date': '2024-07-07',
'employee_id': self.employee_user2.id,
})
self.task.action_fsm_validate()
self.assertFalse(self.task.sale_order_id, 'Sale order should not be generated on the task.')
self.assertFalse(self.task.timesheet_ids.so_line, 'The timesheet should not be linked to a SOL.')
def test_read_timesheet_product_id_portal_user(self):
portal_user = self._create_new_portal_user()
self.task.project_id.write({
'collaborator_ids': [
Command.create({'partner_id': portal_user.partner_id.id}),
],
})
self.assertTrue(
Form(
self.task.with_user(portal_user),
view="industry_fsm_sale.project_sharing_project_task_inherit_view_form",
)
)
def test_under_warranty_copied_when_creating_task_from_template(self):
template_task = self.env["project.task"].create({
"name": "Template",
"project_id": self.fsm_project.id,
"is_template": True,
"under_warranty": True,
"description": "Template description",
})
task_id = template_task.action_create_from_template()
task = self.env["project.task"].browse(task_id)
self.assertTrue(task.under_warranty, "The 'under_warranty' is not copied from the template task.")
def test_under_warranty_copied_when_creating_project_from_project_template(self):
fsm_project = self.env['project.project'].create({
'name': 'Field Service',
'is_fsm': True,
'allow_billable': True,
'allow_timesheets': True,
'is_template': True,
'company_id': self.env.company.id,
})
self.env["project.task"].create({
'name': 'Template',
'project_id': fsm_project.id,
'is_template': True,
'under_warranty': True,
'description': 'Template description',
})
project_id = fsm_project.action_create_from_template()
self.assertTrue(project_id.task_ids.under_warranty, "The 'under_warranty' is not copied from the template task.")
def test_fsm_task_timesheet_uses_customer_pricelist(self):
"""Test that the timesheet service line uses the fixed price from the customer's assigned pricelist.
Steps to reproduce:
- Create a fixed-price pricelist that applies to all products.
- Assign the pricelist to the customer.
- Create a task linked to that customer.
- Add a timesheet entry to the task.
- Mark the task as done.
- Verify that the price of the timesheet service line in the sale order matches the fixed price from the pricelist.
"""
pricelist = self.env['product.pricelist'].create({
'name': 'Price List',
'currency_id': self.env.company.currency_id.id,
'item_ids': [Command.create({
'applied_on': '3_global',
'compute_price': 'fixed',
'fixed_price': 0.0,
})],
})
self.partner.property_product_pricelist = pricelist
self.task.partner_id = self.partner
self.env['account.analytic.line'].create({
'employee_id': self.employee_user2.id,
'task_id': self.task.id,
'unit_amount': 2.0,
'date': '2025-06-17',
})
self.task.action_fsm_validate()
self.assertEqual(
self.task.sale_line_id.price_unit,
pricelist.item_ids[0].fixed_price,
"The service price does not match the fixed price defined in the customer's pricelist."
)
def test_warranty_status_updates_sale_order_line_price(self):
"""
Ensure that the product price is zero in the sales order line
when the task is under warranty.
Test Case:
==========
1. Create a sales order linked to the customer.
2. Assign a customer (partner) to the task and link the task to the sales order.
3. Create a sales order line for a product and link it to the task.
4. Verify the price unit matches the product's list price by default.
5. Set the task as under warranty.
6. Verify the price unit is set to 0.0 in the sales order line.
7. Unset the warranty status.
8. Verify the price unit returns to the product's list price.
"""
so = self.env['sale.order'].create([{
'name': 'Test SO linked to fsm task',
'partner_id': self.partner_1.id,
}])
self.task.write({'partner_id': self.partner_1.id, 'sale_order_id': so})
sol = self.env['sale.order.line'].create([{
'name': 'Test SOL linked to a fsm tasl',
'order_id': so.id,
'task_id': self.task.id,
'product_id': self.consu_product_delivered.id,
'product_uom_qty': 3,
}])
self.assertEqual(sol.price_unit, self.consu_product_delivered.list_price,
"The price should match the product's listed price.")
self.task.under_warranty = True
self.assertEqual(sol.price_unit, 0.0,
"If task is under warranty, the price of the sale order line should be 0.0")
self.task.under_warranty = False
self.assertEqual(sol.price_unit, self.consu_product_delivered.list_price,
"The price should match the product's listed price.")
def test_no_double_discount_for_fsm_task(self):
"""
Test that the timesheet service line only gives discount
once from the customer's assigned pricelist.
Steps to reproduce:
- Enable discounts
- Create a discount pricelist that applies to all products.
- Assign the pricelist to the customer.
- Create a task linked to that customer.
- Add a timesheet entry to the task.
- Mark the task as done.
- Verify that the price of the timesheet service line
in the sale order does not have discount applied twice.
"""
self.env['res.config.settings'].create({'group_discount_per_so_line': True}).execute()
pricelist = self.env['product.pricelist'].create({
'name': 'Price List',
'item_ids': [Command.create({
'applied_on': '3_global',
'compute_price': 'percentage',
'percent_price': 10,
})],
})
self.partner.property_product_pricelist = pricelist
self.task.partner_id = self.partner
analytic_line = self.env['account.analytic.line'].create({
'employee_id': self.employee_user2.id,
'task_id': self.task.id,
'unit_amount': 1.0,
'date': '2025-06-17',
})
self.task.action_fsm_validate()
discounted_price = pricelist._get_product_price(
self.task.timesheet_product_id, analytic_line.unit_amount
)
self.assertEqual(self.task.sale_line_id.price_subtotal, discounted_price)