[14.0][ADD] repair_type

This commit is contained in:
Bernat Puig Font
2021-10-11 11:16:10 +02:00
parent 29873b2558
commit 544c79d7d5
17 changed files with 431 additions and 0 deletions

1
repair_type/__init__.py Normal file
View File

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

View 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,
}

View File

@@ -0,0 +1,2 @@
from . import repair
from . import repair_type

View 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

View 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.",
)

View File

@@ -0,0 +1 @@
No configuration needed for this module.

View File

@@ -0,0 +1,3 @@
* `ForgeFlow <https://forgeflow.com>`_:
* Bernat Puig <bernat.puig@forgeflow.com>

View 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.

View 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.

View 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.

View 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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 type_repair.stock_manager type_repair.stock_manager model_repair_type stock.group_stock_manager 1 1 1 1

View 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

View 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,
)

View 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>

View 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>

View File

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

View File

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