Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[17.0][MIG] rma_scrap #514

Open
wants to merge 6 commits into
base: 17.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions rma_scrap/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.. 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
------------

* Jordi Ballester Alomar <[email protected]>
* David Jimenez <[email protected]>


Maintainer
----------

This module is maintained by ForgeFlow
2 changes: 2 additions & 0 deletions rma_scrap/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import wizards
from . import models
19 changes: 19 additions & 0 deletions rma_scrap/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "RMA Scrap",
"version": "17.0.1.0.0",
"license": "LGPL-3",
"category": "RMA",
"summary": "Allows to scrap the received/ordered products in odoo",
"author": "ForgeFlow",
"website": "https://github.com/ForgeFlow",
"depends": ["rma"],
"data": [
"security/ir.model.access.csv",
"views/rma_operation_view.xml",
"views/rma_order_line_view.xml",
"views/rma_order_view.xml",
"views/stock_scrap_view.xml",
"wizards/rma_scrap_view.xml",
],
"installable": True,
}
6 changes: 6 additions & 0 deletions rma_scrap/models/__init__.py
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions rma_scrap/models/rma_operation.py
Original file line number Diff line number Diff line change
@@ -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"),
],
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])]",
)
27 changes: 27 additions & 0 deletions rma_scrap/models/rma_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 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:
scraps = order.mapped("rma_line_ids.scrap_ids")
order.scrap_count = len(scraps)

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
109 changes: 109 additions & 0 deletions rma_scrap/models/rma_order_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# 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",
"scrap_ids",
"scrap_ids.state",
"scrap_ids.is_rma_scrap",
)
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",
"scrap_ids",
"scrap_ids.state",
"scrap_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.scrap_ids.filtered(lambda m: m.state in ["draft"]):
qty += product_obj._compute_quantity(move.scrap_qty, rec.uom_id)
rec.qty_in_scrap = qty

@api.depends("scrap_ids", "scrap_ids.state", "scrap_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.quantity, rec.uom_id)
rec.qty_scrap = qty

def _compute_scrap_count(self):
for line in self:
line.scrap_count = len(self.scrap_ids)

qty_to_scrap = fields.Float(
copy=False,
digits="Product Unit of Measure",
readonly=True,
compute="_compute_qty_to_scrap",
store=True,
)
qty_in_scrap = fields.Float(
copy=False,
digits="Product Unit of Measure",
readonly=True,
compute="_compute_qty_in_scrap",
store=True,
)
qty_scrap = fields.Float(
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"),
],
default="no",
required=True,
readonly=False,
)
scrap_count = fields.Integer(compute="_compute_scrap_count", string="# Scraps")
scrap_ids = fields.One2many("stock.scrap", "rma_line_id")

@api.onchange("operation_id")
def _onchange_operation_id(self):
res = super()._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]
if len(self.scrap_ids) > 1:
result["domain"] = [("id", "in", self.scrap_ids.ids)]
elif len(self.scrap_ids) == 1:
res = self.env.ref("stock.stock_scrap_form_view", False)
result["views"] = [(res and res.id or False, "form")]
result["res_id"] = self.scrap_ids.ids[0]
return result
14 changes: 14 additions & 0 deletions rma_scrap/models/stock_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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.",
)
33 changes: 33 additions & 0 deletions rma_scrap/models/stock_rule.py
Original file line number Diff line number Diff line change
@@ -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
96 changes: 96 additions & 0 deletions rma_scrap/models/stock_scrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# 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
from odoo.exceptions import UserError
from odoo.tools import float_compare, float_is_zero


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):
res = super().do_scrap()
if self.is_rma_scrap:
self.move_ids.is_rma_scrap = True
self.rma_line_id.move_ids |= self.move_ids
return res

def _prepare_move_values(self):
res = super()._prepare_move_values()
res["rma_line_id"] = self.rma_line_id.id
return res

def action_view_rma_line(self):
if self.rma_line_id.type == "customer":
action = self.env.ref("rma.action_rma_customer_lines")
res = self.env.ref("rma.view_rma_line_form", False)
else:
action = self.env.ref("rma.action_rma_supplier_lines")
res = self.env.ref("rma.view_rma_line_supplier_form", False)
result = action.sudo().read()[0]
# choose the view_mode accordingly
result["views"] = [(res and res.id or False, "form")]
result["res_id"] = self.rma_line_id.id
return result

def action_validate(self):
self.ensure_one()
if float_is_zero(
self.scrap_qty, precision_rounding=self.product_uom_id.rounding
):
raise UserError(_("You can only enter positive quantities."))
if self.product_id.type != "product":
return self.do_scrap()
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
available_qty = sum(
self.env["stock.quant"]
._gather(
self.product_id,
self.location_id,
self.lot_id,
self.package_id,
self.owner_id,
strict=True,
)
.mapped("quantity")
)
scrap_qty = self.product_uom_id._compute_quantity(
self.scrap_qty, self.product_id.uom_id
)
if float_compare(available_qty, scrap_qty, precision_digits=precision) >= 0:
return self.do_scrap()
else:
ctx = dict(self.env.context)
ctx.update(
{
"default_product_id": self.product_id.id,
"default_location_id": self.location_id.id,
"default_scrap_id": self.id,
"default_quantity": scrap_qty,
"default_product_uom_name": self.product_id.uom_name,
}
)
return {
"name": self.product_id.display_name
+ _(": Insufficient Quantity To Scrap"),
"view_mode": "form",
"res_model": "stock.warn.insufficient.qty.scrap",
"view_id": self.env.ref(
"stock.stock_warn_insufficient_qty_scrap_form_view"
).id,
"type": "ir.actions.act_window",
"context": ctx,
"target": "new",
}
3 changes: 3 additions & 0 deletions rma_scrap/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
7 changes: 7 additions & 0 deletions rma_scrap/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions rma_scrap/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_rma_scrap
Loading
Loading