mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[14.0][ADD] repair_type
This commit is contained in:
1
repair_type/__init__.py
Normal file
1
repair_type/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
21
repair_type/__manifest__.py
Normal file
21
repair_type/__manifest__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# Copyright 2021 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
"name": "Repair Type",
|
||||
"version": "14.0.1.0.0",
|
||||
"author": "ForgeFlow, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/manufacture",
|
||||
"summary": "Repair type",
|
||||
"category": "Repair",
|
||||
"depends": ["repair"],
|
||||
"data": [
|
||||
"views/repair.xml",
|
||||
"views/repair_type.xml",
|
||||
"security/ir.model.access.csv",
|
||||
],
|
||||
"installable": True,
|
||||
"development_status": "Alpha",
|
||||
"license": "AGPL-3",
|
||||
"application": False,
|
||||
}
|
||||
2
repair_type/models/__init__.py
Normal file
2
repair_type/models/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import repair
|
||||
from . import repair_type
|
||||
71
repair_type/models/repair.py
Normal file
71
repair_type/models/repair.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# Copyright (C) 2021 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class Repair(models.Model):
|
||||
_inherit = "repair.order"
|
||||
|
||||
repair_type_id = fields.Many2one(comodel_name="repair.type")
|
||||
location_id = fields.Many2one(
|
||||
compute="_compute_location_id", store=True, readonly=False
|
||||
)
|
||||
|
||||
@api.depends("repair_type_id")
|
||||
def _compute_location_id(self):
|
||||
for rec in self:
|
||||
if rec.repair_type_id.source_location_id:
|
||||
rec.location_id = rec.repair_type_id.source_location_id
|
||||
|
||||
|
||||
class RepairLine(models.Model):
|
||||
_inherit = "repair.line"
|
||||
|
||||
location_id = fields.Many2one(
|
||||
compute="_compute_location_id", store=True, readonly=False
|
||||
)
|
||||
location_dest_id = fields.Many2one(
|
||||
compute="_compute_location_id", store=True, readonly=False
|
||||
)
|
||||
|
||||
@api.depends("type", "repair_id.repair_type_id")
|
||||
def _compute_location_id(self):
|
||||
for rec in self:
|
||||
if (
|
||||
rec.type == "add"
|
||||
and rec.repair_id.repair_type_id.source_location_add_part_id
|
||||
):
|
||||
rec.location_id = (
|
||||
rec.repair_id.repair_type_id.source_location_add_part_id
|
||||
)
|
||||
if (
|
||||
rec.type == "add"
|
||||
and rec.repair_id.repair_type_id.destination_location_add_part_id
|
||||
):
|
||||
rec.location_dest_id = (
|
||||
rec.repair_id.repair_type_id.destination_location_add_part_id
|
||||
)
|
||||
if (
|
||||
rec.type == "remove"
|
||||
and rec.repair_id.repair_type_id.source_location_remove_part_id
|
||||
):
|
||||
rec.location_id = (
|
||||
rec.repair_id.repair_type_id.source_location_remove_part_id
|
||||
)
|
||||
if (
|
||||
rec.type == "remove"
|
||||
and rec.repair_id.repair_type_id.destination_location_remove_part_id
|
||||
):
|
||||
rec.location_dest_id = (
|
||||
rec.repair_id.repair_type_id.destination_location_remove_part_id
|
||||
)
|
||||
|
||||
@api.onchange("type")
|
||||
def onchange_operation_type(self):
|
||||
# this onchange was overriding the changes from the compute
|
||||
# method `_compute_location_id`, we ensure that the locations
|
||||
# in the types have more priority by explicit calling the compute.
|
||||
res = super().onchange_operation_type()
|
||||
self._compute_location_id()
|
||||
return res
|
||||
41
repair_type/models/repair_type.py
Normal file
41
repair_type/models/repair_type.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# Copyright (C) 2021 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class RepairType(models.Model):
|
||||
_name = "repair.type"
|
||||
_description = "Repair Type"
|
||||
|
||||
name = fields.Char("Repair Type Name", copy=False, required=True)
|
||||
source_location_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Source Location",
|
||||
help="This is the location where the product to repair is located.",
|
||||
)
|
||||
destination_location_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Destination Location",
|
||||
help="This is the location where the product repaired will be located.",
|
||||
)
|
||||
source_location_add_part_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Source Location Add Component",
|
||||
help="This is the location where the part of the product to add is located.",
|
||||
)
|
||||
destination_location_add_part_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Destination Location Add Component",
|
||||
help="This is the location where the part of the product to add is located.",
|
||||
)
|
||||
source_location_remove_part_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Source Location Remove Component",
|
||||
help="This is the location where the part of the product to remove is located.",
|
||||
)
|
||||
destination_location_remove_part_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Destination Location Remove Component",
|
||||
help="This is the location where the part of the product to remove is located.",
|
||||
)
|
||||
1
repair_type/readme/CONFIGURE.rst
Normal file
1
repair_type/readme/CONFIGURE.rst
Normal file
@@ -0,0 +1 @@
|
||||
No configuration needed for this module.
|
||||
3
repair_type/readme/CONTRIBUTORS.rst
Normal file
3
repair_type/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
* `ForgeFlow <https://forgeflow.com>`_:
|
||||
|
||||
* Bernat Puig <bernat.puig@forgeflow.com>
|
||||
1
repair_type/readme/DESCRIPTION.rst
Normal file
1
repair_type/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1 @@
|
||||
This module adds the type to a repair order. If we select a type on a Repair Order, Odoo will automatically fill some fields of the order.
|
||||
5
repair_type/readme/ROADMAP.rst
Normal file
5
repair_type/readme/ROADMAP.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
Possible improvements for future versions:
|
||||
|
||||
* Destination Location of the product to repair is not used currently,
|
||||
so that's why is invisible. We still save the field for future new
|
||||
module implementations.
|
||||
1
repair_type/readme/USAGE.rst
Normal file
1
repair_type/readme/USAGE.rst
Normal file
@@ -0,0 +1 @@
|
||||
Go to Configuration>Repair Types and create a new repair type. Afterwards selecting a type on a Repair Order will automatically fill some fields.
|
||||
2
repair_type/security/ir.model.access.csv
Normal file
2
repair_type/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
type_repair.stock_manager,type_repair.stock_manager,model_repair_type,stock.group_stock_manager,1,1,1,1
|
||||
|
4
repair_type/tests/__init__.py
Normal file
4
repair_type/tests/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Copyright (C) 2021 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from . import test_repair_type
|
||||
199
repair_type/tests/test_repair_type.py
Normal file
199
repair_type/tests/test_repair_type.py
Normal file
@@ -0,0 +1,199 @@
|
||||
# Copyright (C) 2021 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestRepairType(TransactionCase):
|
||||
def setUp(self, *args, **kwargs):
|
||||
super(TestRepairType, self).setUp(*args, **kwargs)
|
||||
|
||||
# First of all we create a repair to work with
|
||||
self.repair_r1 = self.env.ref("repair.repair_r1")
|
||||
|
||||
# Now we will create a location scrap for the destination location of removed components
|
||||
stock_location_locations_virtual = self.env["stock.location"].create(
|
||||
{"name": "Virtual Locations", "usage": "view", "posz": 1}
|
||||
)
|
||||
self.scrapped_location = self.env["stock.location"].create(
|
||||
{
|
||||
"name": "Scrapped",
|
||||
"location_id": stock_location_locations_virtual.id,
|
||||
"scrap_location": True,
|
||||
"usage": "inventory",
|
||||
}
|
||||
)
|
||||
|
||||
# Then, we create a repair type to know the source and destination locations
|
||||
self.repair_type_1 = self.env["repair.type"].create(
|
||||
{
|
||||
"name": "Repairings Office 1",
|
||||
"source_location_id": self.env.ref("stock.stock_location_stock").id,
|
||||
"destination_location_id": self.env.ref(
|
||||
"stock.stock_location_customers"
|
||||
).id,
|
||||
"source_location_add_part_id": self.env.ref(
|
||||
"stock.stock_location_components"
|
||||
).id,
|
||||
"destination_location_add_part_id": self.env.ref(
|
||||
"stock.stock_location_customers"
|
||||
).id,
|
||||
"source_location_remove_part_id": self.env.ref(
|
||||
"stock.stock_location_stock"
|
||||
).id,
|
||||
"destination_location_remove_part_id": self.scrapped_location.id,
|
||||
}
|
||||
)
|
||||
self.repair_type_2 = self.env["repair.type"].create(
|
||||
{
|
||||
"name": "Repairings Office 2",
|
||||
"source_location_id": self.env.ref(
|
||||
"stock.stock_location_components"
|
||||
).id,
|
||||
"destination_location_id": self.env.ref(
|
||||
"stock.stock_location_stock"
|
||||
).id,
|
||||
"source_location_add_part_id": self.env.ref(
|
||||
"stock.location_refrigerator_small"
|
||||
).id,
|
||||
"destination_location_add_part_id": self.env.ref(
|
||||
"stock.stock_location_14"
|
||||
).id,
|
||||
"source_location_remove_part_id": self.env.ref(
|
||||
"stock.stock_location_stock"
|
||||
).id,
|
||||
"destination_location_remove_part_id": self.scrapped_location.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Finally we add two line components to the repair order,
|
||||
# one adding a component and the other one removing
|
||||
self.add_component = self.env["repair.line"].create(
|
||||
{
|
||||
"name": "Add Component 1",
|
||||
"repair_id": 1,
|
||||
"price_unit": 2.0,
|
||||
"type": "add",
|
||||
"product_id": self.env.ref("product.product_product_3").id,
|
||||
"product_uom": self.env.ref("product.product_product_3").uom_id.id,
|
||||
"product_uom_qty": 1.0,
|
||||
"location_id": self.env.ref("stock.stock_location_14").id,
|
||||
"location_dest_id": self.env.ref(
|
||||
"product.product_product_3"
|
||||
).property_stock_production.id,
|
||||
"company_id": self.env.company.id,
|
||||
}
|
||||
)
|
||||
self.remove_component = self.env["repair.line"].create(
|
||||
{
|
||||
"name": "Add Component 2",
|
||||
"repair_id": 1,
|
||||
"price_unit": 2.0,
|
||||
"type": "remove",
|
||||
"product_id": self.env.ref("product.product_product_11").id,
|
||||
"product_uom": self.env.ref("product.product_product_11").uom_id.id,
|
||||
"product_uom_qty": 1.0,
|
||||
"location_id": self.env.ref("stock.stock_location_14").id,
|
||||
"location_dest_id": self.env.ref(
|
||||
"product.product_product_11"
|
||||
).property_stock_production.id,
|
||||
"company_id": self.env.company.id,
|
||||
}
|
||||
)
|
||||
self.repair_r1.operations |= self.add_component
|
||||
self.repair_r1.operations |= self.remove_component
|
||||
|
||||
def test_compute_location_id(self):
|
||||
# First we associate the repair with the repair type
|
||||
self.repair_r1.repair_type_id = self.repair_type_1
|
||||
|
||||
# Afterwards we will assert the source and
|
||||
# destination of the product in the repair order
|
||||
self.assertEqual(
|
||||
self.repair_r1.location_id, self.repair_type_1.source_location_id
|
||||
)
|
||||
|
||||
# Next we assert if the source and destination locations of the components are correct
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_id,
|
||||
self.repair_type_1.source_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_dest_id,
|
||||
self.repair_type_1.destination_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[1].location_id,
|
||||
self.repair_type_1.source_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[1].location_dest_id,
|
||||
self.repair_type_1.destination_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[2].location_id,
|
||||
self.repair_type_1.source_location_remove_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[2].location_dest_id,
|
||||
self.repair_type_1.destination_location_remove_part_id,
|
||||
)
|
||||
|
||||
# We change the repair type to repair_type_2 and check if all the locations changed
|
||||
self.repair_r1.repair_type_id = self.repair_type_2
|
||||
|
||||
self.assertEqual(
|
||||
self.repair_r1.location_id, self.repair_type_2.source_location_id
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_id,
|
||||
self.repair_type_2.source_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_dest_id,
|
||||
self.repair_type_2.destination_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[1].location_id,
|
||||
self.repair_type_2.source_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[1].location_dest_id,
|
||||
self.repair_type_2.destination_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[2].location_id,
|
||||
self.repair_type_2.source_location_remove_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[2].location_dest_id,
|
||||
self.repair_type_2.destination_location_remove_part_id,
|
||||
)
|
||||
|
||||
def test_compute_location_id_2(self):
|
||||
# First we will assert the source and destination
|
||||
# of the component product in the repair order
|
||||
self.repair_r1.repair_type_id = self.repair_type_1
|
||||
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_id,
|
||||
self.repair_type_1.source_location_add_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_dest_id,
|
||||
self.repair_type_1.destination_location_add_part_id,
|
||||
)
|
||||
|
||||
# Then we change the type of operation
|
||||
self.repair_r1.operations[0].type = "remove"
|
||||
|
||||
# And finally we assert that the locations of that operation changed
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_id,
|
||||
self.repair_type_1.source_location_remove_part_id,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.repair_r1.operations[0].location_dest_id,
|
||||
self.repair_type_1.destination_location_remove_part_id,
|
||||
)
|
||||
13
repair_type/views/repair.xml
Normal file
13
repair_type/views/repair.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="repair_type_form_inherit" model="ir.ui.view">
|
||||
<field name="name">repair.type.inherit</field>
|
||||
<field name="model">repair.order</field>
|
||||
<field name="inherit_id" ref="repair.view_repair_order_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="repair_type_id" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
59
repair_type/views/repair_type.xml
Normal file
59
repair_type/views/repair_type.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id='repair_type_action' model='ir.actions.act_window'>
|
||||
<field name="name">Repair Types</field>
|
||||
<field name="res_model">repair.type</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Repair Types"
|
||||
id="repair_type_menu"
|
||||
parent="repair.repair_menu_config"
|
||||
action="repair_type_action"
|
||||
groups="stock.group_stock_manager"
|
||||
/>
|
||||
|
||||
<record id="repair_type_view_form" model="ir.ui.view">
|
||||
<field name="name">Repair Types Form</field>
|
||||
<field name="model">repair.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet string="Repair types">
|
||||
<label for="name" />
|
||||
<h1>
|
||||
<field name="name" />
|
||||
</h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="source_location_id" />
|
||||
<field name="destination_location_id" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="source_location_add_part_id" />
|
||||
<field name="destination_location_add_part_id" />
|
||||
<field name="source_location_remove_part_id" />
|
||||
<field name="destination_location_remove_part_id" />
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="repair_type_view_tree" model="ir.ui.view">
|
||||
<field name="name">Repair Types List</field>
|
||||
<field name="model">repair.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
<field name="source_location_id" />
|
||||
<field name="destination_location_id" invisible="1" />
|
||||
<field name="source_location_add_part_id" />
|
||||
<field name="destination_location_add_part_id" />
|
||||
<field name="source_location_remove_part_id" />
|
||||
<field name="destination_location_remove_part_id" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
1
setup/repair_type/odoo/addons/repair_type
Symbolic link
1
setup/repair_type/odoo/addons/repair_type
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../repair_type
|
||||
6
setup/repair_type/setup.py
Normal file
6
setup/repair_type/setup.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
||||
Reference in New Issue
Block a user