[ADD] repair_picking

This commit is contained in:
Joan Sisquella
2023-05-04 11:07:23 +02:00
committed by Lois Rilo
parent 1ee992a8e4
commit cf662b87cb
17 changed files with 942 additions and 0 deletions

View File

View File

@@ -0,0 +1,2 @@
from . import models
from . import tests

View File

@@ -0,0 +1,20 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Repair Picking",
"version": "14.0.1.0.0",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"category": "Repair",
"website": "https://github.com/OCA/manufacture",
"summary": "Enhanced repair order management with pickings "
"for adding and removing components",
"depends": ["repair", "stock_move_forced_lot", "repair_stock_move"],
"data": [
"views/stock_warehouse_views.xml",
"views/repair_order_view.xml",
],
"license": "LGPL-3",
"installable": True,
"auto_install": False,
}

View File

@@ -0,0 +1,3 @@
from . import stock_warehouse
from . import repair
from . import stock_rule

View File

@@ -0,0 +1,231 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
from odoo.exceptions import UserError
class RepairOrder(models.Model):
_inherit = "repair.order"
@api.model
def _get_default_location_id(self):
warehouse = self.env["stock.warehouse"].search(
[("company_id", "=", self.env.company.id)], limit=1
)
return (
warehouse.repair_location_id.id
if warehouse and warehouse.repair_location_id
else False
)
# Changing default value on existing field
location_id = fields.Many2one(
default=_get_default_location_id,
)
picking_ids = fields.Many2many(
comodel_name="stock.picking",
compute="_compute_picking_ids",
copy=False,
string="Pickings associated to this repair order",
)
picking_count = fields.Integer(
string="Transfers", copy=False, compute="_compute_picking_ids"
)
procurement_group_id = fields.Many2one(
"procurement.group", "Procurement Group", copy=False
)
def action_view_pickings(self):
self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id(
"stock.action_picking_tree_all"
)
action["domain"] = [("id", "in", self.picking_ids.ids)]
return action
def _compute_picking_ids(self):
for order in self:
moves = self.env["stock.move"].search(
[("repair_line_id", "in", order.operations.ids)]
)
order.picking_ids = moves.mapped("picking_id")
order.picking_count = len(moves.mapped("picking_id"))
def action_repair_cancel(self):
res = super().action_repair_cancel()
for picking in self.picking_ids:
if picking.state not in ["cancel", "done"]:
picking.action_cancel()
return res
def _action_launch_stock_rule(self, repair_lines):
for line in repair_lines:
self._run_procurement_repair(line)
return True
def _run_procurement_repair(self, line):
procurements = []
errors = []
procurement = self._prepare_procurement_repair(line)
procurements.append(procurement)
try:
self.env["procurement.group"].run(procurements)
except UserError as error:
errors.append(error.args[0])
if errors:
raise UserError("\n".join(errors))
return True
@api.model
def _get_procurement_data_repair(self, line):
warehouse = self.location_id.get_warehouse()
if not self.procurement_group_id:
group_id = self.env["procurement.group"].create({"name": self.name})
self.procurement_group_id = group_id
procurement_data = {
"name": self.name,
"group_id": self.procurement_group_id,
"origin": self.name,
"date_planned": fields.Datetime.now(),
"product_id": line.product_id.id,
"product_qty": line.product_uom_qty,
"product_uom": line.product_uom.id,
"company_id": self.company_id,
"warehouse_id": warehouse,
"repair_line_id": line.id,
}
if line.lot_id:
procurement_data["lot_id"] = line.lot_id.id
if line.type == "remove":
procurement_data[
"source_repair_location_id"
] = line.repair_id.location_id.id
return procurement_data
@api.model
def _prepare_procurement_repair(self, line):
values = self._get_procurement_data_repair(line)
warehouse = self.location_id.get_warehouse()
location = (
self.location_id
if line.type == "add"
else warehouse.remove_c_type_id.default_location_dest_id
)
procurement = self.env["procurement.group"].Procurement(
line.product_id,
line.product_uom_qty,
line.product_uom,
location,
values.get("origin"),
values.get("origin"),
self.company_id,
values,
)
return procurement
def _update_stock_moves_and_picking_state(self):
for repair in self:
for picking in repair.picking_ids:
if picking.location_dest_id.id == self.location_id.id:
for move_line in picking.move_ids_without_package:
stock_moves = repair.stock_move_ids.filtered(
lambda m: m.product_id.id
== repair.operations.filtered(
lambda l: l.type == "add"
and l.product_id.id == m.product_id.id
).product_id.id
and m.location_id.id == self.location_id.id
)
if stock_moves:
stock_moves[0].write(
{
"move_orig_ids": [(4, move_line.id)],
"state": "waiting",
}
)
if picking.location_id.id == self.location_id.id:
for move_line in picking.move_ids_without_package:
stock_moves = repair.stock_move_ids.filtered(
lambda m: m.product_id.id
== repair.operations.filtered(
lambda l: l.type == "remove"
and l.product_id.id == m.product_id.id
).product_id.id
and m.location_dest_id.id == self.location_id.id
)
if stock_moves:
move_line.write(
{
"move_orig_ids": [(4, stock_moves[0].id)],
"state": "waiting",
}
)
# We are using write here because
# the repair_stock_move module does not use stock rules.
# As a result, we manually link the stock moves
# and then recompute the state of the picking.
picking._compute_state()
def action_repair_confirm(self):
res = super().action_repair_confirm()
for repair in self:
warehouse = repair.location_id.get_warehouse()
if warehouse.repair_steps in ["2_steps", "3_steps"]:
repair._action_launch_stock_rule(
repair.operations.filtered(lambda l: l.type == "add"),
)
if warehouse.repair_steps == "3_steps":
repair._action_launch_stock_rule(
repair.operations.filtered(lambda l: l.type == "remove"),
)
repair._update_stock_moves_and_picking_state()
return res
@api.onchange("location_id")
def _onchange_location_id(self):
warehouse = self.location_id.get_warehouse()
for line in self.operations:
if line.type == "add":
line.location_id = self.location_id
elif line.type == "remove" and warehouse.repair_steps == "3_steps":
line.location_dest_id = self.location_id
class RepairLine(models.Model):
_inherit = "repair.line"
@api.onchange("type", "product_id")
def onchange_operation_type(self):
super().onchange_operation_type()
production_location = self.env["stock.location"].search(
[("usage", "=", "production")], limit=1
)
warehouse = self.repair_id.location_id.get_warehouse()
if self.type == "add":
self.write(
{
"location_id": self.repair_id.location_id.id,
"location_dest_id": production_location.id,
}
)
elif self.type == "remove":
self.write({"location_id": production_location.id})
if warehouse.repair_steps in ["1_step", "2_steps"]:
scrap_location = self.env["stock.location"].search(
[
("scrap_location", "=", True),
("company_id", "=", warehouse.company_id.id),
],
limit=1,
)
self.write({"location_dest_id": scrap_location.id})
else:
self.write({"location_dest_id": self.repair_id.location_id.id})
def create(self, vals):
line = super().create(vals)
if line.repair_id.state in ["confirmed", "under_repair", "ready"]:
line.repair_id._action_launch_stock_rule(line)
return line

View File

@@ -0,0 +1,27 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, models
class StockRule(models.Model):
_inherit = "stock.rule"
def _get_custom_move_fields(self):
fields = super(StockRule, self)._get_custom_move_fields()
# Fields is added on `repair_stock_move` module.
fields += ["repair_line_id"]
return fields
class ProcurementGroup(models.Model):
_inherit = "procurement.group"
@api.model
def _get_rule_domain(self, location, values):
domain = super(ProcurementGroup, self)._get_rule_domain(location, values)
if values.get("source_repair_location_id"):
domain.append(
("location_src_id", "=", values.get("source_repair_location_id"))
)
return domain

View File

@@ -0,0 +1,184 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class StockWarehouse(models.Model):
_inherit = "stock.warehouse"
repair_steps = fields.Selection(
[
("1_step", "Repair"),
("2_steps", "Pick component, repair"),
("3_steps", "Pick component, repair, store removed component"),
],
string="Repair Steps",
default="1_step",
)
add_c_type_id = fields.Many2one(
"stock.picking.type", string="Add Component to Repair"
)
remove_c_type_id = fields.Many2one(
"stock.picking.type", string="Remove component from Repair"
)
repair_route_id = fields.Many2one("stock.location.route", string="Repair Route")
repair_location_id = fields.Many2one("stock.location", string="Repair Location")
def update_picking_types(self, repair_steps, repair_location_id):
if repair_steps in ["2_steps", "3_steps"]:
self.add_c_type_id.active = True
if repair_steps == "1_step":
self.add_c_type_id.active = False
if repair_steps == "3_steps":
self.remove_c_type_id.active = True
if repair_steps in ["1_step", "2_steps"]:
self.remove_c_type_id.active = False
if repair_location_id:
self.add_c_type_id.write({"default_location_dest_id": repair_location_id})
self.remove_c_type_id.write({"default_location_src_id": repair_location_id})
def update_repair_routes(self, repair_steps, repair_location_id):
if repair_steps == "2_steps" or repair_steps == "3_steps":
self.repair_route_id.active = True
existing_rule = (
self.env["stock.rule"]
.with_context(active_test=False)
.search(
[
("picking_type_id", "=", self.add_c_type_id.id),
("route_id", "=", self.repair_route_id.id),
],
limit=1,
)
)
existing_rule.active = True
if repair_steps == "1_step":
for rule in self.repair_route_id.rule_ids:
rule.active = False
self.repair_route_id.active = False
if repair_location_id:
self.repair_route_id.rule_ids.filtered(
lambda r: r.picking_type_id == self.add_c_type_id
).write({"location_id": repair_location_id})
self.repair_route_id.rule_ids.filtered(
lambda r: r.picking_type_id == self.remove_c_type_id
).write({"location_src_id": repair_location_id})
if repair_steps in ["1_step", "2_steps"]:
self.repair_route_id.rule_ids.filtered(
lambda r: r.picking_type_id == self.remove_c_type_id
).active = False
def write(self, vals):
res = super(StockWarehouse, self).write(vals)
for warehouse in self:
repair_steps = vals.get("repair_steps")
repair_location_id = vals.get("repair_location_id")
if repair_steps:
if repair_steps in ["3_steps", "2_steps"]:
warehouse._create_repair_picking_types()
warehouse._create_repair_route()
if repair_steps == "3_steps":
warehouse._create_remove_rule()
if repair_steps or repair_location_id:
warehouse.update_picking_types(repair_steps, repair_location_id)
warehouse.update_repair_routes(repair_steps, repair_location_id)
return res
def _create_repair_picking_types(self):
for warehouse in self:
repair_location_id = (
warehouse.repair_location_id.id or warehouse.lot_stock_id.id
)
if not warehouse.add_c_type_id:
pbr_type = self.env["stock.picking.type"].create(
{
"name": "Add Component to Repair",
"code": "internal",
"sequence_code": "ACR",
"warehouse_id": warehouse.id,
"default_location_src_id": warehouse.lot_stock_id.id,
"default_location_dest_id": repair_location_id,
"company_id": warehouse.company_id.id,
}
)
warehouse.add_c_type_id = pbr_type.id
else:
warehouse.add_c_type_id.write(
{"default_location_dest_id": repair_location_id}
)
if not warehouse.remove_c_type_id:
par_type = self.env["stock.picking.type"].create(
{
"name": "Remove component from Repair",
"code": "internal",
"sequence_code": "RCR",
"warehouse_id": warehouse.id,
"default_location_src_id": repair_location_id,
"default_location_dest_id": warehouse.view_location_id.id,
"company_id": warehouse.company_id.id,
}
)
warehouse.remove_c_type_id = par_type.id
else:
warehouse.remove_c_type_id.write(
{"default_location_src_id": repair_location_id}
)
def _create_repair_route(self):
for warehouse in self:
if not warehouse.repair_route_id:
route = self.env["stock.location.route"].create(
{
"name": "Repair Route for %s" % warehouse.name,
"warehouse_selectable": True,
"product_selectable": False,
"warehouse_ids": [(6, 0, warehouse.ids)],
"company_id": warehouse.company_id.id,
}
)
warehouse.repair_route_id = route.id
self.env["stock.rule"].create(
{
"name": "Add Component to Repair",
"picking_type_id": warehouse.add_c_type_id.id,
"route_id": route.id,
"location_src_id": warehouse.lot_stock_id.id,
"location_id": warehouse.repair_location_id.id
or warehouse.view_location_id.id,
"action": "pull",
"company_id": warehouse.company_id.id,
"warehouse_id": warehouse.id,
}
)
def _create_remove_rule(self):
for warehouse in self:
existing_rule = (
self.env["stock.rule"]
.with_context(active_test=False)
.search(
[
("picking_type_id", "=", warehouse.remove_c_type_id.id),
("route_id", "=", warehouse.repair_route_id.id),
],
limit=1,
)
)
if not existing_rule:
self.env["stock.rule"].create(
{
"name": "Remove component from Repair",
"picking_type_id": warehouse.remove_c_type_id.id,
"route_id": warehouse.repair_route_id.id,
"location_src_id": warehouse.repair_location_id.id
or warehouse.view_location_id.id,
"location_id": warehouse.view_location_id.id,
"action": "pull",
"company_id": warehouse.company_id.id,
"warehouse_id": warehouse.id,
"active": True,
}
)
else:
existing_rule.active = True

View File

@@ -0,0 +1 @@
* Joan Sisquella <joan.sisquella@forgeflow.com>

View File

@@ -0,0 +1,12 @@
Repair Management Extension for Odoo
=====================================
This module extends the repair management functionality in Odoo, providing additional options for handling the repair process in a more customizable and efficient way. It allows the configuration of repair steps based on specific business requirements and adds new picking types for managing component addition and removal in repair orders.
Main Features:
--------------
- Customize repair steps: Choose between a 1-step, 2-step, or 3-step repair process.
- Add and remove components during the repair process using separate picking types.
- Associate repair orders with pickings for improved traceability.
- Automatic creation of pickings and procurement routes based on the selected repair steps.
- Manage repair locations and routes more efficiently with warehouse settings.

View File

@@ -0,0 +1,23 @@
Getting Started
===============
1. Install the module in your Odoo instance.
2. Navigate to Inventory > Configuration > Warehouses, and select a warehouse.
3. In the "Repair Steps" field, choose between "Repair", "Pick component, repair", or "Pick component, repair, store removed component" to define the repair process.
4. Define the "Repair Location", "Add Component to Repair" picking type, "Remove component from Repair" picking type, and "Repair Route" as needed.
Using the Repair Management Extension
=====================================
1. Navigate to Repair > Repair Orders and create a new repair order.
2. In the Operations tab, add components to be added or removed during the repair process.
3. Confirm the repair order. This will automatically generate the necessary pickings based on the configured repair steps.
4. Process the pickings as required during the repair process.
5. If the repair order needs to be canceled, all associated pickings that are not in "cancel" or "done" state will also be canceled automatically.

View File

@@ -0,0 +1,2 @@
from . import test_stock_repair_warehouse
from . import test_stock_repair_order

View File

@@ -0,0 +1,266 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests import common
class TestStockRepairOrder(common.SavepointCase):
@classmethod
def setUp(cls):
super(TestStockRepairOrder, cls).setUpClass()
cls.repair_model = cls.env["repair.order"]
cls.repair_line_model = cls.env["repair.line"]
cls.product_model = cls.env["product.product"]
cls.stock_location_model = cls.env["stock.location"]
cls.warehouse_model = cls.env["stock.warehouse"]
cls.company = cls.env["res.company"].create(
{
"name": "My Test Company",
}
)
cls.warehouse = cls.warehouse_model.create(
{
"name": "Test Warehouse",
"code": "TW",
"company_id": cls.company.id,
}
)
cls.product1 = cls.product_model.create(
{
"name": "Product 1",
"type": "product",
"company_id": cls.company.id,
}
)
cls.product2 = cls.product_model.create(
{
"name": "Product 2",
"type": "product",
"company_id": cls.company.id,
}
)
cls.repair_location = cls.stock_location_model.create(
{
"name": "Repair Location",
"usage": "internal",
"location_id": cls.warehouse.view_location_id.id,
"company_id": cls.company.id,
}
)
cls.production_location = cls.stock_location_model.create(
{
"name": "Production Location",
"usage": "production",
"company_id": cls.company.id,
}
)
cls.env["stock.quant"].create(
{
"product_id": cls.product1.id,
"location_id": cls.repair_location.id,
"quantity": 10,
}
)
cls.env["stock.quant"].create(
{
"product_id": cls.product2.id,
"location_id": cls.warehouse.lot_stock_id.id,
"quantity": 10,
}
)
def test_1step_repair_order_flow(self):
self.warehouse.write(
{
"repair_steps": "1_step",
"repair_location_id": self.repair_location.id,
}
)
repair_order = self.repair_model.create(
{
"product_id": self.product1.id,
"product_uom": self.product1.uom_id.id,
"location_id": self.repair_location.id,
"company_id": self.company.id,
}
)
self.repair_line_model.create(
{
"name": "Repair Line 1",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "add",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.repair_location.id,
"location_dest_id": self.production_location.id,
}
)
repair_order.action_repair_confirm()
self.assertEqual(repair_order.state, "confirmed")
repair_order.action_repair_ready()
self.assertEqual(repair_order.state, "ready")
def test_2steps_repair_order_flow(self):
self.warehouse.write(
{
"repair_steps": "2_steps",
"repair_location_id": self.repair_location.id,
}
)
self.product2.write(
{"route_ids": [(6, 0, [self.warehouse.repair_route_id.id])]}
)
repair_order = self.repair_model.create(
{
"product_id": self.product1.id,
"product_uom": self.product1.uom_id.id,
"location_id": self.repair_location.id,
"company_id": self.company.id,
}
)
self.repair_line_model.create(
{
"name": "Repair Line 2",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "add",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.repair_location.id,
"location_dest_id": self.production_location.id,
}
)
repair_order.action_repair_confirm()
self.assertEqual(repair_order.state, "confirmed")
self.assertTrue(repair_order.picking_ids)
self.assertEqual(len(repair_order.picking_ids), 1)
def test_3steps_repair_order_flow(self):
self.warehouse.write(
{
"repair_steps": "3_steps",
"repair_location_id": self.repair_location.id,
}
)
self.product2.write(
{"route_ids": [(6, 0, [self.warehouse.repair_route_id.id])]}
)
repair_order = self.repair_model.create(
{
"product_id": self.product1.id,
"product_uom": self.product1.uom_id.id,
"location_id": self.repair_location.id,
"company_id": self.company.id,
}
)
self.repair_line_model.create(
{
"name": "Repair Line 3",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "add",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.repair_location.id,
"location_dest_id": self.production_location.id,
}
)
self.repair_line_model.create(
{
"name": "Repair Line 4",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "remove",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.production_location.id,
"location_dest_id": self.repair_location.id,
}
)
repair_order.action_repair_confirm()
self.assertEqual(repair_order.state, "confirmed")
self.assertTrue(repair_order.picking_ids)
self.assertEqual(len(repair_order.picking_ids), 2)
repair_order.action_repair_cancel()
self.assertEqual(repair_order.state, "cancel")
for picking in repair_order.picking_ids:
self.assertEqual(picking.state, "cancel")
def test_update_related_pickings(self):
self.warehouse.write(
{
"repair_steps": "3_steps",
"repair_location_id": self.repair_location.id,
}
)
self.product2.write(
{"route_ids": [(6, 0, [self.warehouse.repair_route_id.id])]}
)
repair_order = self.repair_model.create(
{
"product_id": self.product1.id,
"product_uom": self.product1.uom_id.id,
"location_id": self.repair_location.id,
"company_id": self.company.id,
}
)
self.repair_line_model.create(
{
"name": "Repair Line 3",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "add",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.repair_location.id,
"location_dest_id": self.production_location.id,
}
)
repair_order.action_repair_confirm()
self.assertEqual(repair_order.state, "confirmed")
self.assertTrue(repair_order.picking_ids)
self.assertEqual(len(repair_order.picking_ids), 1)
self.assertEqual(len(repair_order.picking_ids.move_ids_without_package), 1)
self.assertEqual(
repair_order.picking_ids.move_ids_without_package.product_uom_qty, 1
)
self.repair_line_model.create(
{
"name": "Repair Line Add",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "add",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.repair_location.id,
"location_dest_id": self.production_location.id,
}
)
self.assertEqual(len(repair_order.picking_ids), 1)
self.assertEqual(len(repair_order.picking_ids.move_ids_without_package), 1)
self.assertEqual(
repair_order.picking_ids.move_ids_without_package.product_uom_qty, 2
)
self.repair_line_model.create(
{
"name": "Repair Line Remove",
"repair_id": repair_order.id,
"product_id": self.product2.id,
"type": "remove",
"product_uom_qty": 1,
"product_uom": self.product2.uom_id.id,
"price_unit": 1,
"location_id": self.production_location.id,
"location_dest_id": self.repair_location.id,
}
)
self.assertEqual(len(repair_order.picking_ids), 2)

View File

@@ -0,0 +1,116 @@
# Copyright 2023 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests import common
class TestStockRepairWarehouse(common.SavepointCase):
@classmethod
def setUpClass(cls):
super(TestStockRepairWarehouse, cls).setUpClass()
cls.warehouse_obj = cls.env["stock.warehouse"]
cls.product_obj = cls.env["product.product"]
cls.product_1 = cls.product_obj.create(
{
"name": "Product 1",
"type": "product",
}
)
cls.warehouse_1 = cls.warehouse_obj.create(
{
"name": "Test Warehouse",
"code": "TWH",
"repair_steps": "1_step",
}
)
def test_01_warehouse_creation(self):
self.assertEqual(self.warehouse_1.repair_steps, "1_step")
def test_02_update_repair_steps(self):
self.warehouse_1.repair_steps = "2_steps"
self.assertEqual(self.warehouse_1.repair_steps, "2_steps")
self.assertTrue(self.warehouse_1.add_c_type_id.active)
self.assertFalse(self.warehouse_1.remove_c_type_id.active)
self.assertTrue(self.warehouse_1.repair_route_id.active)
def test_03_update_repair_steps_to_3_steps(self):
self.warehouse_1.repair_steps = "3_steps"
self.assertEqual(self.warehouse_1.repair_steps, "3_steps")
self.assertTrue(self.warehouse_1.add_c_type_id.active)
self.assertTrue(self.warehouse_1.remove_c_type_id.active)
self.assertTrue(self.warehouse_1.repair_route_id.active)
def test_04_reverse_and_update_repair_steps(self):
self.warehouse_1.repair_steps = "1_step"
self.warehouse_1.repair_steps = "2_steps"
self.assertEqual(self.warehouse_1.repair_steps, "2_steps")
self.assertTrue(self.warehouse_1.add_c_type_id.active)
self.assertFalse(self.warehouse_1.remove_c_type_id.active)
self.assertTrue(self.warehouse_1.repair_route_id.active)
add_rule = self.env["stock.rule"].search(
[
("picking_type_id", "=", self.warehouse_1.add_c_type_id.id),
("route_id", "=", self.warehouse_1.repair_route_id.id),
]
)
self.assertTrue(add_rule.active)
remove_rule = self.env["stock.rule"].search(
[
("picking_type_id", "=", self.warehouse_1.remove_c_type_id.id),
("route_id", "=", self.warehouse_1.repair_route_id.id),
]
)
self.assertFalse(remove_rule)
self.warehouse_1.repair_steps = "3_steps"
self.assertEqual(self.warehouse_1.repair_steps, "3_steps")
self.assertTrue(self.warehouse_1.add_c_type_id.active)
self.assertTrue(self.warehouse_1.remove_c_type_id.active)
self.assertTrue(self.warehouse_1.repair_route_id.active)
add_rule = self.env["stock.rule"].search(
[
("picking_type_id", "=", self.warehouse_1.add_c_type_id.id),
("route_id", "=", self.warehouse_1.repair_route_id.id),
]
)
self.assertTrue(add_rule.active)
remove_rule = self.env["stock.rule"].search(
[
("picking_type_id", "=", self.warehouse_1.remove_c_type_id.id),
("route_id", "=", self.warehouse_1.repair_route_id.id),
]
)
self.assertTrue(remove_rule.active)
self.warehouse_1.repair_steps = "2_steps"
self.assertEqual(self.warehouse_1.repair_steps, "2_steps")
self.assertTrue(self.warehouse_1.add_c_type_id.active)
self.assertFalse(self.warehouse_1.remove_c_type_id.active)
self.assertTrue(self.warehouse_1.repair_route_id.active)
add_rule = self.env["stock.rule"].search(
[
("picking_type_id", "=", self.warehouse_1.add_c_type_id.id),
("route_id", "=", self.warehouse_1.repair_route_id.id),
]
)
self.assertTrue(add_rule.active)
remove_rule = self.env["stock.rule"].search(
[
("picking_type_id", "=", self.warehouse_1.remove_c_type_id.id),
("route_id", "=", self.warehouse_1.repair_route_id.id),
]
)
self.assertFalse(remove_rule)
self.warehouse_1.repair_steps = "1_step"
self.assertFalse(self.warehouse_1.add_c_type_id.active)
self.assertFalse(self.warehouse_1.remove_c_type_id.active)
self.assertFalse(self.warehouse_1.repair_route_id.active)

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_repair_order_form_repair_stock_move_inherited" model="ir.ui.view">
<field name="name">repair.order.form - repair_stock_move - custom</field>
<field name="model">repair.order</field>
<field name="inherit_id" ref="repair_stock_move.view_repair_order_form" />
<field name="arch" type="xml">
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
<button
name="action_view_pickings"
type="object"
class="oe_stat_button"
icon="fa-truck"
attrs="{'invisible': [('picking_count', '=', 0)]}"
help="Transfers associated with this repair order"
>
<field name="picking_count" widget="statinfo" string="Transfers" />
</button>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_warehouse_inherit_repair" model="ir.ui.view">
<field name="name">Stock Warehouse Inherit Repair</field>
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="stock.view_warehouse" />
<field name="arch" type="xml">
<xpath expr="//field[@name='resupply_wh_ids']" position="before">
<field name="repair_steps" widget="radio" />
</xpath>
<xpath expr="//field[@name='wh_output_stock_loc_id']" position="after">
<field name="repair_location_id" />
</xpath>
<xpath expr="//field[@name='out_type_id']" position="after">
<field
name="add_c_type_id"
attrs="{'invisible': [('repair_steps', 'not in', ['2_steps', '3_steps'])]}"
/>
<field
name="remove_c_type_id"
attrs="{'invisible': [('repair_steps', '!=', '3_steps')]}"
/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
../../../../repair_picking

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)