mirror of
https://github.com/bringout/oca-workflow-process.git
synced 2026-04-19 12:32:03 +02:00
356 lines
16 KiB
Python
356 lines
16 KiB
Python
# Copyright 2022-2025 Tecnativa - Víctor Martínez
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
from odoo import fields
|
|
from odoo.tests import Form
|
|
from odoo.tests.common import users
|
|
from odoo.tools import mute_logger
|
|
|
|
from .common import TestProjectStockBase
|
|
|
|
|
|
class TestProjectStock(TestProjectStockBase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls._create_stock_quant(cls, cls.product_a, cls.location, 2)
|
|
cls._create_stock_quant(cls, cls.product_b, cls.location, 1)
|
|
cls._create_stock_quant(cls, cls.product_c, cls.location, 1)
|
|
cls.task = cls._create_task(cls, [(cls.product_a, 2), (cls.product_b, 1)])
|
|
cls.move_product_a = cls.task.move_ids.filtered(
|
|
lambda x: x.product_id == cls.product_a
|
|
)
|
|
cls.move_product_b = cls.task.move_ids.filtered(
|
|
lambda x: x.product_id == cls.product_b
|
|
)
|
|
cls.env.ref("base.user_admin").write(
|
|
{
|
|
"groups_id": [
|
|
(4, cls.env.ref("analytic.group_analytic_accounting").id),
|
|
],
|
|
}
|
|
)
|
|
|
|
def _create_stock_quant(self, product, location, qty):
|
|
self.env["stock.quant"].create(
|
|
{"product_id": product.id, "location_id": location.id, "quantity": qty}
|
|
)
|
|
|
|
def test_project_task_misc(self):
|
|
self.assertTrue(self.task.group_id)
|
|
self.assertEqual(self.task.picking_type_id, self.picking_type)
|
|
self.assertEqual(self.task.location_id, self.location)
|
|
self.assertEqual(self.task.location_dest_id, self.location_dest)
|
|
self.assertEqual(self.move_product_a.name, self.task.name)
|
|
self.assertEqual(self.move_product_a.group_id, self.task.group_id)
|
|
self.assertEqual(self.move_product_a.reference, self.task.name)
|
|
self.assertEqual(self.move_product_a.location_id, self.location)
|
|
self.assertEqual(self.move_product_a.location_dest_id, self.location_dest)
|
|
self.assertEqual(self.move_product_a.picking_type_id, self.picking_type)
|
|
self.assertEqual(self.move_product_a.raw_material_task_id, self.task)
|
|
self.assertEqual(self.move_product_b.group_id, self.task.group_id)
|
|
self.assertEqual(self.move_product_b.location_id, self.location)
|
|
self.assertEqual(self.move_product_b.location_dest_id, self.location_dest)
|
|
self.assertEqual(self.move_product_b.picking_type_id, self.picking_type)
|
|
self.assertEqual(self.move_product_b.raw_material_task_id, self.task)
|
|
|
|
def _test_task_analytic_lines_from_task(self, amount):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
# Prevent error when hr_timesheet addon is installed.
|
|
stock_analytic_lines = self.task.sudo().stock_analytic_line_ids
|
|
self.assertEqual(len(stock_analytic_lines), 2)
|
|
self.assertEqual(sum(stock_analytic_lines.mapped("unit_amount")), 3)
|
|
self.assertEqual(sum(stock_analytic_lines.mapped("amount")), amount)
|
|
self.assertIn(
|
|
self.analytic_account,
|
|
stock_analytic_lines.mapped("account_id"),
|
|
)
|
|
# Prevent incoherence when hr_timesheet addon is installed.
|
|
if "project_id" in self.task.stock_analytic_line_ids._fields:
|
|
self.assertFalse(self.task.stock_analytic_line_ids.project_id)
|
|
|
|
def test_project_task_without_analytic_account(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
# Prevent error when hr_timesheet addon is installed.
|
|
if "allow_timesheets" in self.task.project_id._fields:
|
|
self.task.project_id.allow_timesheets = False
|
|
self.task.project_id.analytic_account_id = False
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.task.action_done()
|
|
self.assertFalse(self.task.stock_analytic_line_ids)
|
|
|
|
def test_project_task_picking_done_analytic_items(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.task.action_assign()
|
|
picking = self.task.move_ids.picking_id
|
|
for move in picking.move_ids:
|
|
move.quantity_done = move.product_uom_qty
|
|
picking.button_validate()
|
|
self.assertEqual(picking.state, "done")
|
|
self._test_task_analytic_lines_from_task(-40)
|
|
self.assertEqual(
|
|
fields.first(self.task.stock_analytic_line_ids).date,
|
|
fields.Date.from_string("1990-01-01"),
|
|
)
|
|
|
|
@users("manager-user")
|
|
def test_project_task_without_analytic_account_manager_user(self):
|
|
self.test_project_task_without_analytic_account()
|
|
|
|
def test_project_task_user_access_without_stock_group(self):
|
|
self.basic_user.write(
|
|
{
|
|
"groups_id": [(6, 0, [self.env.ref("project.group_project_user").id])],
|
|
}
|
|
)
|
|
task_form = Form(self.task.with_user(self.basic_user))
|
|
self.assertEqual(task_form.project_id, self.project)
|
|
|
|
def test_project_task_analytic_lines_without_tags(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.task.action_done()
|
|
self._test_task_analytic_lines_from_task(-40)
|
|
self.assertEqual(
|
|
fields.first(self.task.stock_analytic_line_ids).date,
|
|
fields.Date.from_string("1990-01-01"),
|
|
)
|
|
|
|
@users("manager-user")
|
|
def test_project_task_analytic_lines_without_tags_manager_user(self):
|
|
self.test_project_task_analytic_lines_without_tags()
|
|
|
|
def test_project_task_analytic_lines_with_tag_1(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.task.write(
|
|
{
|
|
"stock_analytic_date": "1991-01-01",
|
|
}
|
|
)
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.task.action_done()
|
|
self._test_task_analytic_lines_from_task(-40)
|
|
self.assertEqual(
|
|
fields.first(self.task.stock_analytic_line_ids).date,
|
|
fields.Date.from_string("1991-01-01"),
|
|
)
|
|
|
|
@users("manager-user")
|
|
def test_project_task_analytic_lines_with_tag_1_manager_user(self):
|
|
self.task.stock_analytic_distribution = {self.analytic_account.id: 100}
|
|
self.test_project_task_analytic_lines_with_tag_1()
|
|
|
|
def test_project_task_analytic_lines_with_tag_2(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.task.project_id.stock_analytic_date = False
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.task.action_done()
|
|
self._test_task_analytic_lines_from_task(-40)
|
|
self.assertEqual(
|
|
fields.first(self.task.stock_analytic_line_ids).date, fields.date.today()
|
|
)
|
|
|
|
@users("manager-user")
|
|
def test_project_task_analytic_lines_with_tag_2_manager_user(self):
|
|
self.task.stock_analytic_distribution = {
|
|
self.analytic_account.id: 50,
|
|
self.analytic_account_2.id: 50,
|
|
}
|
|
self.test_project_task_analytic_lines_with_tag_2()
|
|
|
|
def test_project_task_process_done(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.assertEqual(self.move_product_a.state, "draft")
|
|
self.assertEqual(self.move_product_b.state, "draft")
|
|
# Change task stage (auto-confirm + auto-assign)
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.assertEqual(self.move_product_a.state, "assigned")
|
|
self.assertEqual(self.move_product_b.state, "assigned")
|
|
self.assertEqual(self.move_product_a.reserved_availability, 2)
|
|
self.assertEqual(self.move_product_b.reserved_availability, 1)
|
|
self.assertTrue(self.task.stock_moves_is_locked)
|
|
self.task.action_toggle_stock_moves_is_locked()
|
|
self.assertFalse(self.task.stock_moves_is_locked)
|
|
# Add new stock_move
|
|
self.task.write({"stage_id": self.stage_in_progress.id})
|
|
task_form = Form(self.task)
|
|
with task_form.move_ids.new() as move_form:
|
|
move_form.product_id = self.product_c
|
|
move_form.product_uom_qty = 1
|
|
task_form.save()
|
|
move_product_c = self.task.move_ids.filtered(
|
|
lambda x: x.product_id == self.product_c
|
|
)
|
|
self.assertEqual(move_product_c.group_id, self.task.group_id)
|
|
self.assertEqual(move_product_c.state, "draft")
|
|
self.task.action_assign()
|
|
self.assertEqual(move_product_c.state, "assigned")
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
# action_done
|
|
self.task.action_done()
|
|
self.assertEqual(self.move_product_a.state, "done")
|
|
self.assertEqual(self.move_product_b.state, "done")
|
|
self.assertEqual(self.move_product_a.quantity_done, 2)
|
|
self.assertEqual(self.move_product_b.quantity_done, 1)
|
|
self.assertEqual(move_product_c.quantity_done, 1)
|
|
|
|
@users("basic-user")
|
|
def test_project_task_process_done_basic_user(self):
|
|
self.test_project_task_process_done()
|
|
|
|
@mute_logger("odoo.models.unlink")
|
|
def test_project_task_process_cancel(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.assertEqual(self.move_product_a.state, "draft")
|
|
self.assertEqual(self.move_product_b.state, "draft")
|
|
# Change task stage
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.assertEqual(self.move_product_a.state, "assigned")
|
|
self.assertEqual(self.move_product_b.state, "assigned")
|
|
# action_done
|
|
self.task.action_done()
|
|
self.assertEqual(self.move_product_a.state, "done")
|
|
self.assertEqual(self.move_product_b.state, "done")
|
|
self.assertEqual(self.move_product_a.quantity_done, 2)
|
|
self.assertEqual(self.move_product_b.quantity_done, 1)
|
|
self.assertTrue(self.task.sudo().stock_analytic_line_ids)
|
|
# action_cancel
|
|
self.task.action_cancel()
|
|
self.assertEqual(self.move_product_a.state, "done")
|
|
self.assertEqual(self.move_product_b.state, "done")
|
|
self.assertEqual(self.move_product_a.quantity_done, 0)
|
|
self.assertEqual(self.move_product_b.quantity_done, 0)
|
|
self.assertFalse(self.task.stock_analytic_line_ids)
|
|
quant_a = self.product_a.stock_quant_ids.filtered(
|
|
lambda x: x.location_id == self.location
|
|
)
|
|
quant_b = self.product_b.stock_quant_ids.filtered(
|
|
lambda x: x.location_id == self.location
|
|
)
|
|
quant_c = self.product_c.stock_quant_ids.filtered(
|
|
lambda x: x.location_id == self.location
|
|
)
|
|
self.assertEqual(quant_a.quantity, 2)
|
|
self.assertEqual(quant_b.quantity, 1)
|
|
self.assertEqual(quant_c.quantity, 1)
|
|
|
|
@users("manager-user")
|
|
def test_project_task_process_cancel_manager_user(self):
|
|
self.test_project_task_process_cancel()
|
|
|
|
@mute_logger("odoo.models.unlink")
|
|
def test_project_task_process_unreserve(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.assertEqual(self.move_product_a.state, "draft")
|
|
self.assertEqual(self.move_product_b.state, "draft")
|
|
# Change task stage (auto-confirm + auto-assign)
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.assertTrue(self.move_product_a.move_line_ids)
|
|
self.assertEqual(self.move_product_a.move_line_ids.task_id, self.task)
|
|
self.assertEqual(self.move_product_a.state, "assigned")
|
|
self.assertEqual(self.move_product_b.state, "assigned")
|
|
self.assertEqual(self.move_product_a.reserved_availability, 2)
|
|
self.assertEqual(self.move_product_b.reserved_availability, 1)
|
|
self.assertTrue(self.task.unreserve_visible)
|
|
# button_unreserve
|
|
self.task.button_unreserve()
|
|
self.assertEqual(self.move_product_a.state, "confirmed")
|
|
self.assertEqual(self.move_product_b.state, "confirmed")
|
|
self.assertEqual(self.move_product_a.reserved_availability, 0)
|
|
self.assertEqual(self.move_product_b.reserved_availability, 0)
|
|
self.assertFalse(self.task.unreserve_visible)
|
|
|
|
@mute_logger("odoo.models.unlink")
|
|
def test_project_task_process_01(self):
|
|
"""Product A move cancel + Product B move OK."""
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.move_product_b.unlink()
|
|
self.assertEqual(self.move_product_a.state, "draft")
|
|
# Confirm + Edit to qty=0
|
|
self.task.action_confirm()
|
|
self.assertEqual(self.move_product_a.state, "assigned")
|
|
self.move_product_a.product_uom_qty = 0
|
|
self.task.action_done()
|
|
self.assertEqual(self.move_product_a.state, "cancel")
|
|
# Add extra line
|
|
task_form = Form(self.task)
|
|
with task_form.move_ids.new() as move_form:
|
|
move_form.product_id = self.product_b
|
|
move_form.product_uom_qty = 1
|
|
task_form.save()
|
|
self.move_product_b = self.task.move_ids.filtered(
|
|
lambda x: x.product_id == self.product_b
|
|
)
|
|
self.task.action_confirm()
|
|
self.assertEqual(self.move_product_b.state, "assigned")
|
|
self.task.action_done()
|
|
self.assertEqual(self.move_product_b.state, "done")
|
|
|
|
def test_project_task_process_02(self):
|
|
self.task.action_confirm()
|
|
self.assertEqual(self.move_product_a.state, "assigned")
|
|
self.assertEqual(self.move_product_b.state, "assigned")
|
|
self.task.action_done()
|
|
self.assertEqual(self.move_product_a.state, "done")
|
|
self.assertEqual(self.move_product_b.state, "done")
|
|
self.assertEqual(len(self.task.stock_analytic_line_ids), 2)
|
|
self.task.action_done()
|
|
self.assertEqual(len(self.task.stock_analytic_line_ids), 2)
|
|
|
|
@users("basic-user")
|
|
def test_project_task_process_unreserve_basic_user(self):
|
|
self.test_project_task_process_unreserve()
|
|
|
|
def test_project_task_action_cancel(self):
|
|
self.assertTrue(self.env["project.task"].browse(self.task.id).action_cancel())
|
|
|
|
@users("basic-user")
|
|
def test_project_task_action_cancel_basic_user(self):
|
|
self.test_project_task_action_cancel()
|
|
|
|
def test_project_task_action_done(self):
|
|
self.task = self.env["project.task"].browse(self.task.id)
|
|
self.task.write({"stage_id": self.stage_done.id})
|
|
self.task.action_done()
|
|
self.assertTrue(self.task.sudo().stock_analytic_line_ids)
|
|
|
|
@users("basic-user")
|
|
def test_project_task_action_done_basic_user(self):
|
|
self.test_project_task_action_done()
|
|
|
|
@mute_logger("odoo.models.unlink")
|
|
def test_project_task_unlink(self):
|
|
self.assertTrue(self.env["project.task"].browse(self.task.id).unlink())
|
|
|
|
@users("basic-user")
|
|
def test_project_task_unlink_basic_user(self):
|
|
self.test_project_task_unlink()
|
|
|
|
@mute_logger("odoo.models.unlink")
|
|
def test_project_project_onchange(self):
|
|
new_type = self.env.ref("stock.picking_type_out")
|
|
self.project.write({"picking_type_id": new_type.id})
|
|
self.project._onchange_picking_type_id()
|
|
self.assertEqual(self.project.location_id, new_type.default_location_src_id)
|
|
self.assertEqual(
|
|
self.project.location_dest_id, new_type.default_location_dest_id
|
|
)
|
|
self.task.do_unreserve()
|
|
self.task.write({"picking_type_id": new_type.id})
|
|
self.task._onchange_picking_type_id()
|
|
self.assertEqual(self.task.location_id, new_type.default_location_src_id)
|
|
self.assertEqual(self.task.location_dest_id, new_type.default_location_dest_id)
|
|
move = fields.first(self.task.move_ids)
|
|
self.assertEqual(move.location_id, new_type.default_location_src_id)
|
|
|
|
def test_project_task_scrap(self):
|
|
move = fields.first(self.task.move_ids)
|
|
scrap = self.env["stock.scrap"].create(
|
|
{
|
|
"product_id": move.product_id.id,
|
|
"product_uom_id": move.product_id.uom_id.id,
|
|
"scrap_qty": 1,
|
|
"task_id": self.task.id,
|
|
}
|
|
)
|
|
scrap.do_scrap()
|
|
self.assertEqual(scrap.move_id.raw_material_task_id, self.task)
|