[14.0][ADD] rma_scrap

This commit is contained in:
DavidJForgeFlow
2022-11-03 10:53:57 +01:00
committed by JasminSForgeFlow
parent 14401983a8
commit a98271f31a
19 changed files with 783 additions and 0 deletions

45
rma_scrap/README.rst Normal file
View File

@@ -0,0 +1,45 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License LGPL-3
============
RMA Scrap
============
This module allows you to put scrap the products.
Configuration
=============
Go to *RMA / Configuration / Customer Operations* and define there:
#. The Scrap Policy
#. The default scrap destination location .
Usage
=====
#. Go to a Customer RMA.
#. Click on *Scrap*.
#. Indicate the quantity that you want to scrap.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/Eficent/stock-rma/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Contributors
------------
* David Jimenez <david.jimenez@ForgeFlow.com>
Maintainer
----------
This module is maintained by ForgeFlow

2
rma_scrap/__init__.py Normal file
View File

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

18
rma_scrap/__manifest__.py Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "RMA Put Away",
"version": "14.0.1.0.0",
"license": "LGPL-3",
"category": "RMA",
"summary": "Allows to put away the received products in odoo",
"author": "ForgeFlow",
"website": "https://github.com/ForgeFlow/stock-rma",
"depends": ["rma"],
"data": [
"security/ir.model.access.csv",
"views/rma_operation_view.xml",
"views/rma_order_line_view.xml",
"views/rma_order_view.xml",
"wizards/rma_scrap_view.xml",
],
"installable": True,
}

View File

@@ -0,0 +1,6 @@
from . import rma_operation
from . import stock_move
from . import stock_rule
from . import rma_order_line
from . import rma_order
from . import stock_scrap

View File

@@ -0,0 +1,24 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html).
from odoo import fields, models
class RmaOperation(models.Model):
_inherit = "rma.operation"
scrap_policy = fields.Selection(
selection=[
("no", "Not required"),
("ordered", "Based on Ordered Quantities"),
("received", "Based on Received Quantities"),
],
string="Scrap Policy",
default="no",
)
scrap_location_id = fields.Many2one(
comodel_name="stock.location",
string="Scrap Destination Location",
domain="[('scrap_location', '=', True), ('company_id', 'in', [company_id, False])]",
)

View File

@@ -0,0 +1,31 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import fields, models
class RmaOrder(models.Model):
_inherit = "rma.order"
def _compute_scrap_count(self):
for order in self:
moves = (
order.mapped("rma_line_ids.move_ids")
.filtered(lambda m: m.is_rma_scrap)
.move_line_ids
)
order.scrap_count = len(moves)
scrap_count = fields.Integer(compute="_compute_scrap_count", string="# Scrap")
def action_view_scrap_transfers(self):
self.ensure_one()
action = self.env.ref("stock.action_stock_scrap")
result = action.sudo().read()[0]
scraps = self.env["stock.scrap"].search([("origin", "=", self.name)])
if len(scraps) > 1:
result["domain"] = [("id", "in", scraps.ids)]
elif len(scraps) == 1:
res = self.env.ref("stock.stock_scrap_form_view", False)
result["views"] = [(res and res.id or False, "form")]
result["res_id"] = scraps.ids[0]
return result

View File

@@ -0,0 +1,106 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import api, fields, models
class RmaOrderLine(models.Model):
_inherit = "rma.order.line"
@api.depends(
"move_ids",
"move_ids.state",
"move_ids.is_rma_scrap",
"qty_scrap",
"scrap_policy",
"product_qty",
)
def _compute_qty_to_scrap(self):
for rec in self:
rec.qty_to_scrap = 0.0
if rec.scrap_policy == "ordered":
rec.qty_to_scrap = rec.product_qty - rec.qty_scrap
elif rec.scrap_policy == "received":
rec.qty_to_scrap = rec.qty_received - rec.qty_scrap
@api.depends("move_ids", "move_ids.state", "move_ids.is_rma_scrap")
def _compute_qty_in_scrap(self):
product_obj = self.env["uom.uom"]
for rec in self:
qty = 0.0
for move in self.env["stock.scrap"].search(
[("origin", "=", rec.name), ("state", "=", "draft")]
):
qty += product_obj._compute_quantity(move.scrap_qty, rec.uom_id)
rec.qty_in_scrap = qty
@api.depends("move_ids", "move_ids.state", "move_ids.is_rma_scrap")
def _compute_qty_scrap(self):
product_obj = self.env["uom.uom"]
for rec in self:
qty = 0.0
for move in rec.move_ids.filtered(
lambda m: m.state in ["done"] and m.is_rma_scrap
):
qty += product_obj._compute_quantity(move.product_uom_qty, rec.uom_id)
rec.qty_scrap = qty
def _compute_scrap_count(self):
for line in self:
scraps = self.env["stock.scrap"].search([("origin", "=", line.name)])
line.scrap_count = len(scraps)
qty_to_scrap = fields.Float(
string="Qty To Scrap",
copy=False,
digits="Product Unit of Measure",
readonly=True,
compute="_compute_qty_to_scrap",
store=True,
)
qty_in_scrap = fields.Float(
string="Qty In Scrap",
copy=False,
digits="Product Unit of Measure",
readonly=True,
compute="_compute_qty_in_scrap",
store=True,
)
qty_scrap = fields.Float(
string="Qty Scrap",
copy=False,
digits="Product Unit of Measure",
readonly=True,
compute="_compute_qty_scrap",
store=True,
)
scrap_policy = fields.Selection(
selection=[
("no", "Not required"),
("ordered", "Based on Ordered Quantities"),
("received", "Based on Received Quantities"),
],
string="Scrap Policy",
default="no",
required=True,
readonly=False,
)
scrap_count = fields.Integer(compute="_compute_scrap_count", string="# Scraps")
@api.onchange("operation_id")
def _onchange_operation_id(self):
res = super(RmaOrderLine, self)._onchange_operation_id()
if self.operation_id:
self.scrap_policy = self.operation_id.scrap_policy or "no"
return res
def action_view_scrap_transfers(self):
action = self.env.ref("stock.action_stock_scrap")
result = action.sudo().read()[0]
scraps = self.env["stock.scrap"].search([("origin", "=", self.name)])
if len(scraps) > 1:
result["domain"] = [("id", "in", scraps.ids)]
elif len(scraps) == 1:
res = self.env.ref("stock.stock_scrap_form_view", False)
result["views"] = [(res and res.id or False, "form")]
result["res_id"] = scraps.ids[0]
return result

View File

@@ -0,0 +1,20 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import fields, models
class StockMove(models.Model):
_inherit = "stock.move"
is_rma_scrap = fields.Boolean(
string="Is RMA Scrap",
copy=False,
help="This Stock Move has been created from a Scrap operation in " "the RMA.",
)
def _is_in_out_rma_move(self, op, states, location_type):
res = super(StockMove, self)._is_in_out_rma_move(op, states, location_type)
if self.is_rma_scrap:
return False
return res

View File

@@ -0,0 +1,33 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import models
class StockRule(models.Model):
_inherit = "stock.rule"
def _get_stock_move_values(
self,
product_id,
product_qty,
product_uom,
location_id,
name,
origin,
company_id,
values,
):
res = super()._get_stock_move_values(
product_id,
product_qty,
product_uom,
location_id,
name,
origin,
company_id,
values,
)
if "is_rma_scrap" in values:
res["is_rma_scrap"] = values.get("is_rma_scrap")
return res

View File

@@ -0,0 +1,23 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html).
from odoo import fields, models
class StockScrap(models.Model):
_inherit = "stock.scrap"
rma_line_id = fields.Many2one("rma.order.line", string="RMA order Line")
is_rma_scrap = fields.Boolean(
string="Is RMA Scrap",
default=False,
copy=False,
help="This Stock Move has been created from a Scrap operation in " "the RMA.",
)
def do_scrap(self):
super(StockScrap, self).do_scrap()
if self.is_rma_scrap:
self.move_id.is_rma_scrap = True
self.rma_line_id.move_ids |= self.move_id

View File

@@ -0,0 +1,7 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_rma_scrap_wizard,rma.order.manager,model_rma_make_scrap_wizard,rma.group_rma_manager,1,1,1,1
access_rma_scrap_wizard_customer,rma.order.manager,model_rma_make_scrap_wizard,rma.group_rma_customer_user,1,1,1,1
access_rma_scrap_wizard_supplier,rma.order.manager,model_rma_make_scrap_wizard,rma.group_rma_supplier_user,1,1,1,1
access_rma_scrap_item_wizard,rma.order.manager,model_rma_make_scrap_item_wizard,rma.group_rma_manager,1,1,1,1
access_rma_scrap_item_wizard_customer,rma.order.manager,model_rma_make_scrap_item_wizard,rma.group_rma_customer_user,1,1,1,1
access_rma_scrap_item_wizard_supplier,rma.order.manager,model_rma_make_scrap_item_wizard,rma.group_rma_supplier_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_rma_scrap_wizard rma.order.manager model_rma_make_scrap_wizard rma.group_rma_manager 1 1 1 1
3 access_rma_scrap_wizard_customer rma.order.manager model_rma_make_scrap_wizard rma.group_rma_customer_user 1 1 1 1
4 access_rma_scrap_wizard_supplier rma.order.manager model_rma_make_scrap_wizard rma.group_rma_supplier_user 1 1 1 1
5 access_rma_scrap_item_wizard rma.order.manager model_rma_make_scrap_item_wizard rma.group_rma_manager 1 1 1 1
6 access_rma_scrap_item_wizard_customer rma.order.manager model_rma_make_scrap_item_wizard rma.group_rma_customer_user 1 1 1 1
7 access_rma_scrap_item_wizard_supplier rma.order.manager model_rma_make_scrap_item_wizard rma.group_rma_supplier_user 1 1 1 1

View File

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

View File

@@ -0,0 +1,172 @@
from odoo.tests import common
class TestRmaScrap(common.SingleTransactionCase):
@classmethod
def setUpClass(cls):
super(TestRmaScrap, cls).setUpClass()
cls.rma_obj = cls.env["rma.order"]
cls.rma_line_obj = cls.env["rma.order.line"]
cls.rma_op_obj = cls.env["rma.operation"]
cls.rma_make_picking = cls.env["rma_make_picking.wizard"]
cls.rma_make_scrap_wiz = cls.env["rma_make_scrap.wizard"]
cls.product_obj = cls.env["product.product"]
cls.partner_obj = cls.env["res.partner"]
cls.rma_route_cust = cls.env.ref("rma.route_rma_customer")
cls.cust_loc = cls.env.ref("stock.stock_location_customers")
# Create customer
cls.customer1 = cls.partner_obj.create({"name": "Customer 1"})
# Create products
cls.product_1 = cls.product_obj.create(
{"name": "Test Product 1", "type": "product", "list_price": 100.0}
)
cls.product_2 = cls.product_obj.create(
{
"name": "Test Product 2",
"type": "product",
"list_price": 150.0,
"tracking": "lot",
}
)
cls.lot = cls.env["stock.production.lot"].create(
{
"name": "Lot for tests",
"product_id": cls.product_2.id,
"company_id": cls.env.ref("base.main_company").id,
}
)
cls.wh = cls.env.ref("stock.warehouse0")
cls.stock_rma_location = cls.wh.lot_rma_id
cls.scrap_loc = cls.env["stock.location"].create(
{
"name": "WH Scrap Location",
"location_id": cls.wh.view_location_id.id,
"scrap_location": True,
}
)
# Create RMA group and operation:
cls.rma_group = cls.rma_obj.create({"partner_id": cls.customer1.id})
cls.operation_1 = cls.rma_op_obj.create(
{
"code": "TEST1",
"name": "Operation 1",
"type": "customer",
"receipt_policy": "ordered",
"scrap_policy": "received",
"scrap_location_id": cls.scrap_loc.id,
"in_route_id": cls.rma_route_cust.id,
"out_route_id": cls.rma_route_cust.id,
}
)
cls.operation_2 = cls.rma_op_obj.create(
{
"code": "TEST2",
"name": "Operation 2",
"type": "customer",
"receipt_policy": "ordered",
"scrap_policy": "ordered",
"scrap_location_id": cls.scrap_loc.id,
"in_route_id": cls.rma_route_cust.id,
"out_route_id": cls.rma_route_cust.id,
}
)
def test_01_rma_scrap_received(self):
rma = self.rma_line_obj.create(
{
"partner_id": self.customer1.id,
"product_id": self.product_1.id,
"operation_id": self.operation_1.id,
"uom_id": self.product_1.uom_id.id,
"in_route_id": self.operation_1.in_route_id.id,
"out_route_id": self.operation_1.out_route_id.id,
"in_warehouse_id": self.operation_1.in_warehouse_id.id,
"out_warehouse_id": self.operation_1.out_warehouse_id.id,
"location_id": self.stock_rma_location.id,
}
)
rma._onchange_operation_id()
rma.action_rma_to_approve()
wizard = self.rma_make_picking.with_context(
{
"active_ids": rma.id,
"active_model": "rma.order.line",
"picking_type": "incoming",
"active_id": 1,
}
).create({})
wizard._create_picking()
rma._compute_qty_to_scrap()
wizard = self.rma_make_scrap_wiz.with_context(
{
"active_ids": rma.id,
"active_model": "rma.order.line",
"item_ids": [
0,
0,
{
"line_id": rma.id,
"product_id": rma.product_id.id,
"product_qty": rma.product_qty,
"location_id": rma.location_id,
"qty_to_scrap": rma.qty_to_scrap,
"uom_id": rma.uom_id.id,
},
],
}
).create({})
action = wizard.action_create_scrap()
scrap = self.env["stock.scrap"].browse([action["res_id"]])
self.assertEqual(scrap.location_id.id, self.stock_rma_location.id)
self.assertEqual(scrap.move_id.id, False)
scrap.action_validate()
move = scrap.move_id
self.assertEqual(move.product_id.id, self.product_1.id)
def test_02_rma_scrap_ordered(self):
rma = self.rma_line_obj.create(
{
"partner_id": self.customer1.id,
"product_id": self.product_1.id,
"operation_id": self.operation_2.id,
"uom_id": self.product_1.uom_id.id,
"in_route_id": self.operation_2.in_route_id.id,
"out_route_id": self.operation_2.out_route_id.id,
"in_warehouse_id": self.operation_2.in_warehouse_id.id,
"out_warehouse_id": self.operation_2.out_warehouse_id.id,
"location_id": self.stock_rma_location.id,
}
)
rma._onchange_operation_id()
rma.action_rma_to_approve()
rma._compute_qty_to_scrap()
wizard = self.rma_make_scrap_wiz.with_context(
{
"active_ids": rma.id,
"active_model": "rma.order.line",
"item_ids": [
0,
0,
{
"line_id": rma.id,
"product_id": rma.product_id.id,
"product_qty": rma.product_qty,
"location_id": rma.location_id,
"qty_to_scrap": rma.qty_to_scrap,
"uom_id": rma.uom_id.id,
},
],
}
).create({})
action = wizard.action_create_scrap()
scrap = self.env["stock.scrap"].browse([action["res_id"]])
self.assertEqual(scrap.location_id.id, self.stock_rma_location.id)
self.assertEqual(scrap.move_id.id, False)
self.assertTrue(scrap.action_validate())

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="rma_operation_tree" model="ir.ui.view">
<field name="name">rma.operation.tree</field>
<field name="model">rma.operation</field>
<field name="inherit_id" ref="rma.rma_operation_tree" />
<field name="arch" type="xml">
<field name="delivery_policy" position="after">
<field name="scrap_policy" />
</field>
</field>
</record>
<record id="rma_operation_form" model="ir.ui.view">
<field name="name">rma.operation.form - rma_scrap</field>
<field name="model">rma.operation</field>
<field name="inherit_id" ref="rma.rma_operation_form" />
<field name="arch" type="xml">
<field name="delivery_policy" position="after">
<field name="scrap_policy" />
</field>
<group name="outbound" position="after">
<group name="scrap" string="Scrap">
<field
name="scrap_location_id"
string="Destination Scrap Location"
/>
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_rma_line_form" model="ir.ui.view">
<field name="name">rma.order.line.form</field>
<field name="model">rma.order.line</field>
<field name="inherit_id" ref="rma.view_rma_line_form" />
<field name="arch" type="xml">
<button name='action_view_out_shipments' position="after">
<button
type="object"
name="action_view_scrap_transfers"
class="oe_stat_button"
icon="fa-truck"
groups="stock.group_stock_user"
attrs="{'invisible':['|', ('scrap_count', '=', 0), ('state', '=', 'draft')]}"
>
<field name="scrap_count" widget="statinfo" string="Scraps" />
</button>
</button>
<group name="quantities" position="inside">
<group>
<field name="qty_to_scrap" />
<field name="qty_in_scrap" />
<field name="qty_scrap" />
</group>
</group>
<field name="delivery_policy" position="after">
<field name="scrap_policy" />
</field>
</field>
</record>
<record id="view_rma_rma_line_filter" model="ir.ui.view">
<field name="name">rma.order.line.select - rma_scrap</field>
<field name="model">rma.order.line</field>
<field name="inherit_id" ref="rma.view_rma_rma_line_filter" />
<field name="arch" type="xml">
<group name="stock_quantities" position="after">
<group name="scrap_quantities" groups="stock.group_stock_user">
<filter
domain="[('state','!=', 'done'),('qty_to_scrap','>',0.0)]"
help="To Scrap"
name="to_scrap"
/>
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_rma_form" model="ir.ui.view">
<field name="name">rma.order.form</field>
<field name="model">rma.order</field>
<field name="inherit_id" ref="rma.view_rma_form" />
<field name="arch" type="xml">
<button name="action_view_out_shipments" position="after">
<button
type="object"
name="action_view_scrap_transfers"
class="oe_stat_button"
icon="fa-truck"
groups="stock.group_stock_user"
attrs="{'invisible': [('scrap_count', '=', 0)]}"
>
<field name="scrap_count" widget="statinfo" string="Scraps" />
</button>
</button>
<xpath expr="//field[@name='rma_line_ids']/tree" position="inside">
<field name="scrap_policy" invisible="True" />
</xpath>
</field>
</record>
</odoo>

View File

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

View File

@@ -0,0 +1,112 @@
# Copyright 2022 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class RmaMakeScrap(models.TransientModel):
_name = "rma_make_scrap.wizard"
_description = "Wizard to create scrap from rma lines"
item_ids = fields.One2many(
comodel_name="rma_make_scrap_item.wizard",
inverse_name="wiz_id",
string="Items",
)
@api.returns("rma.order.line")
def _prepare_item(self, line):
values = {
"product_id": line.product_id.id,
"product_qty": line.product_qty,
"location_id": line.location_id.id,
"uom_id": line.uom_id.id,
"qty_to_scrap": line.qty_to_scrap,
"line_id": line.id,
"rma_id": line.rma_id and line.rma_id.id or False,
}
return values
@api.model
def default_get(self, fields_list):
context = self._context.copy()
res = super(RmaMakeScrap, self).default_get(fields_list)
rma_line_obj = self.env["rma.order.line"]
rma_line_ids = self.env.context["active_ids"] or []
active_model = self.env.context["active_model"]
if not rma_line_ids:
return res
assert active_model == "rma.order.line", "Bad context propagation"
items = []
lines = rma_line_obj.browse(rma_line_ids)
for line in lines:
items.append([0, 0, self._prepare_item(line)])
res["item_ids"] = items
context.update({"items_ids": items})
return res
def _create_scrap(self):
scraps = []
for item in self.item_ids:
line = item.line_id
if line.state != "approved":
raise ValidationError(_("RMA %s is not approved") % line.name)
scrap = self._prepare_scrap(item)
scraps.append(scrap)
return scraps
def action_create_scrap(self):
self._create_scrap()
self.item_ids[0].line_id._compute_qty_in_scrap()
return self.item_ids[0].line_id.action_view_scrap_transfers()
@api.model
def _prepare_scrap(self, item):
line = item.line_id
scrap = self.env["stock.scrap"].create(
{
"name": line.rma_id.id and line.rma_id.name or line.name,
"origin": line.name,
"product_id": item.line_id.product_id.id,
"scrap_qty": item.qty_to_scrap,
"product_uom_id": item.line_id.product_id.product_tmpl_id.uom_id.id,
"scrap_location_id": line.operation_id.scrap_location_id.id,
"rma_line_id": line.id,
"create_date": fields.Datetime.now(),
"company_id": line.company_id.id,
"is_rma_scrap": True,
"location_id": line.location_id.id,
}
)
return scrap
class RmaMakeScrapItem(models.TransientModel):
_name = "rma_make_scrap_item.wizard"
_description = "Items to Scrap"
wiz_id = fields.Many2one("rma_make_scrap.wizard", string="Wizard", required=True)
line_id = fields.Many2one(
"rma.order.line", string="RMA order Line", ondelete="cascade"
)
rma_id = fields.Many2one("rma.order", related="line_id.rma_id", string="RMA Group")
product_id = fields.Many2one("product.product", string="Product")
product_qty = fields.Float(
related="line_id.product_qty",
string="Quantity Ordered",
copy=False,
digits="Product Unit of Measure",
)
location_id = fields.Many2one(
"stock.location",
string="Scrap Location",
domain="[('scrap_location', '=', True)]",
)
qty_to_scrap = fields.Float(
string="Quantity To Scrap", digits="Product Unit of Measure"
)
uom_id = fields.Many2one("uom.uom", string="Unit of Measure")

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" ?>
<odoo>
<record id="view_rma_scrap" model="ir.ui.view">
<field name="name">Create Scrap</field>
<field name="model">rma_make_scrap.wizard</field>
<field name="arch" type="xml">
<form string="Select lines for picking" name="lines">
<separator string="Select lines for Scrap" />
<field name="item_ids">
<tree string="RMA Lines" editable="bottom" create="false">
<field name="rma_id" groups="rma.group_rma_groups" />
<field name="product_id" />
<field name="product_qty" />
<field name="qty_to_scrap" />
<field name="location_id" />
<field name="line_id" invisible="1" />
<field name="uom_id" groups="uom.group_uom" />
</tree>
</field>
<footer>
<button
string="Confirm"
name="action_create_scrap"
type="object"
class="oe_highlight"
/>
or
<button
name="action_cancel"
string="Cancel"
class="oe_link"
special="cancel"
/>
</footer>
</form>
</field>
</record>
<record id="action_rma_scrap" model="ir.actions.act_window">
<field name="name">Create Scrap</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma_make_scrap.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="view_id" ref="view_rma_scrap" />
<field name="groups_id" eval="[(4, ref('stock.group_stock_user'))]" />
<field name="binding_model_id" ref="rma.model_rma_order_line" />
</record>
<record id="view_rma_line_button_scrap_form" model="ir.ui.view">
<field name="name">rma.order.line.form</field>
<field name="model">rma.order.line</field>
<field name="inherit_id" ref="rma.view_rma_line_button_form" />
<field name="arch" type="xml">
<header position="inside">
<button
name="%(action_rma_scrap)d"
string="Scrap"
class="oe_highlight"
attrs="{'invisible':['|', ('qty_to_scrap', '=', 0), ('state', '!=', 'approved')]}"
type="action"
/>
<button
name="%(action_rma_scrap)d"
string="Scrap"
attrs="{'invisible':['|', ('qty_to_scrap', '!=', 0), ('state', '!=', 'approved')]}"
type="action"
/>
</header>
</field>
</record>
</odoo>