Skip to content

Commit

Permalink
Merge commit 'refs/pull/174/head' of https://github.com/ForgeFlow/sto…
Browse files Browse the repository at this point in the history
…ck-rma into fko/14.0.1.0.0
  • Loading branch information
max3903 committed Sep 7, 2021
2 parents c2d3807 + 2483daf commit b9cca9b
Show file tree
Hide file tree
Showing 11 changed files with 494 additions and 0 deletions.
67 changes: 67 additions & 0 deletions rma_recall/README.rst
@@ -0,0 +1,67 @@
===========
RMA Recalls
===========

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3

|badge1| |badge2|

This module allows you to manage recalls, find where the compromised product/lot is
located and create the corresponding document to track the status:

* scrap order if the product is located in a warehouse
* RMA order if the product has already been shipped to a customer

The module supports compromised products used as a component in a manufacturing order
and creates a recall line for the finished good.

**Table of contents**

.. contents::
:local:

Usage
=====

* Go to RMA
* Create a recall
* Select the lot/serial number
* Click on "Search"
* For each of the line, create a scrap order or RMA order

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/ForgeFlow/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
=======

Authors
-------

* Open Source Integrators <contact@opensourceintegrators.com>

Contributors
------------
* Open Source Integrators <contact@opensourceintegrators.com>

* Melody Fetterly <mfetterly@opensourceintegrators.com>
* Raphael Lee <rlee@opensourceintegrators.com>
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
* Vimal Patel <vpatel@opensourceintegrators.com>

Maintainers
-----------

This module is maintained by ForgeFlow.

This module is part of the `ForgeFlow/stock-rma <https://github.com/ForgeFlow/stock-rma>`_ project on GitHub.
4 changes: 4 additions & 0 deletions rma_recall/__init__.py
@@ -0,0 +1,4 @@
# Copyright (C) 2021 Open Source Integrators (https://www.opensourceintegrators.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import models
19 changes: 19 additions & 0 deletions rma_recall/__manifest__.py
@@ -0,0 +1,19 @@
# Copyright (C) 2021 Open Source Integrators (https://www.opensourceintegrators.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "RMA Recall",
"version": "14.0.1.0.0",
"license": "LGPL-3",
"category": "RMA",
"summary": "To track inventory items by lot number",
"author": "Open Source Integrators, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/https://github.com/ForgeFlow/stock-rma",
"depends": ["rma"],
"data": [
"security/ir.model.access.csv",
"data/data.xml",
"views/rma_recall_view.xml",
],
"installable": True,
}
12 changes: 12 additions & 0 deletions rma_recall/data/data.xml
@@ -0,0 +1,12 @@
<odoo>

<record id="rma_recall_seq" model="ir.sequence">
<field name="name">RMA Recall Sequence</field>
<field name="code">rma.recall</field>
<field name="padding">5</field>
<field name="prefix">RECALL/%(year)s/</field>
<field eval="1" name="number_next" />
<field eval="1" name="number_increment" />
</record>

</odoo>
4 changes: 4 additions & 0 deletions rma_recall/models/__init__.py
@@ -0,0 +1,4 @@
# Copyright (C) 2021 Open Source Integrators (https://www.opensourceintegrators.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import rma_recall
195 changes: 195 additions & 0 deletions rma_recall/models/rma_recall.py
@@ -0,0 +1,195 @@
# Copyright (C) 2021 Open Source Integrators (https://www.opensourceintegrators.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models


class RmaRecall(models.Model):
_name = "rma.recall"
_inherit = ["mail.thread", "mail.activity.mixin"]
_description = "RMA Recall"

name = fields.Char(
"Name",
required=True,
copy=False,
readonly=True,
states={"new": [("readonly", False)]},
default=lambda self: _("New"),
)
lot_id = fields.Many2one(
"stock.production.lot",
"Lot/Serial",
required=True,
index=True,
states={"new": [("readonly", False)]},
)
product_id = fields.Many2one(
related="lot_id.product_id", string="Product", store=True
)
rma_date = fields.Date("Date", default=fields.Date.today())
origin = fields.Char("Origin", copy=False, states={"new": [("readonly", False)]})
state = fields.Selection(
[
("new", "New"),
("in_progress", "In Progress"),
("done", "Done"),
("cancelled", "Cancelled"),
],
readonly=True,
index=True,
copy=False,
default="new",
tracking=True,
)
line_ids = fields.One2many("rma.recall.line", "recall_id", "Lines", readonly=True)

@api.model
def create(self, vals):
if vals.get("name", _("New")) == _("New"):
vals["name"] = self.env["ir.sequence"].next_by_code("rma.recall") or _(
"New"
)
return super().create(vals)

def _valid_field_parameter(self, field, name):
# I can't even
return name == "tracking" or super()._valid_field_parameter(field, name)

def action_search(self):
MoveLine = self.env["stock.move.line"]
TraceabilityReport = self.env["stock.traceability.report"]
for rec in self:
lines = MoveLine.search(
[
("lot_id", "=", rec.lot_id.id),
("state", "=", "done"),
]
)
recall_lines = []
stock_locations = lines.mapped("location_dest_id")
for stock_location in stock_locations:
for move_line in lines.filtered(
lambda l: l.location_dest_id == stock_location
)[-1]:
res_model, res_id, ref = TraceabilityReport._get_reference(
move_line
)
picking = False
if res_model == "stock.picking":
picking = self.env[res_model].browse(res_id)
vals = {
"location_id": stock_location.id,
"partner_id": picking and picking.partner_id.id or False,
"picking_id": res_id,
"product_id": move_line.product_id.id,
"qty": move_line.qty_done,
"uom_id": move_line.product_uom_id.id
or move_line.product_id.uom_id.id,
}
recall_lines.append((0, 0, vals))
rec.write(
{
"line_ids": recall_lines,
"state": "in_progress",
}
)

def action_done(self):
self.write({"state": "done"})

def action_cancel(self):
self.write({"state": "cancelled"})


class RmaRecallLine(models.Model):
_name = "rma.recall.line"
_description = "RMA Recall Lines"

def _compute_state(self):
for rec in self:
state_value = False
if rec.scrap_id:
state_value = dict(rec.scrap_id._fields["state"].selection).get(
rec.scrap_id.state
)
elif rec.rma_id:
state_value = dict(rec.rma_id._fields["state"].selection).get(
rec.rma_id.state
)
rec.state = state_value

location_id = fields.Many2one("stock.location", "Inventory Location")
recall_id = fields.Many2one(
"rma.recall", "Recall", required=True, ondelete="cascade"
)
partner_id = fields.Many2one("res.partner", "Contact")
rma_id = fields.Many2one("rma.order.line", "RMA")
scrap_id = fields.Many2one("stock.scrap", "Scrap")
picking_id = fields.Many2one("stock.picking", "Transfer")
product_id = fields.Many2one("product.product", "Product")
qty = fields.Float("Quantity")
uom_id = fields.Many2one(related="product_id.uom_id", string="UoM")
state = fields.Char("State", compute="_compute_state")

def button_rma_order(self):
RmaOrderLine = self.env["rma.order.line"]
for rec in self:
if not rec.rma_id and rec.partner_id:
partner_type = "customer"
operation = self.env.ref("rma.rma_operation_customer_replace")
if rec.picking_id.picking_type_code == "incoming":
partner_type = "supplier"
operation = self.env.ref("rma.rma_operation_supplier_replace")
vals = {
"partner_id": rec.partner_id.id,
"product_id": rec.product_id.id,
"lot_id": rec.recall_id.lot_id.id,
"type": partner_type,
"operation_id": operation.id,
"origin": rec.recall_id.name,
}
rma_order_line_new = RmaOrderLine.new(vals)
vals.update(rma_order_line_new.default_get(rma_order_line_new._fields))
rma_order_line_new._onchange_operation_id()
rma_order_line_new._onchange_product_id()
vals.update(
rma_order_line_new.sudo()._convert_to_write(
{
name: rma_order_line_new[name]
for name in rma_order_line_new._cache
}
)
)
vals.update({"operation_id": operation.id})
rma_line = RmaOrderLine.create(vals)
rec.rma_id = rma_line.id

def button_scrap_order(self):
StockScrap = self.env["stock.scrap"]
for rec in self:
if not rec.scrap_id:
vals = {"product_id": rec.product_id.id}
new_scrap_order_new = StockScrap.new(vals)
vals.update(
new_scrap_order_new.default_get(new_scrap_order_new._fields)
)
new_scrap_order_new._onchange_product_id()
vals.update(
new_scrap_order_new.sudo()._convert_to_write(
{
name: new_scrap_order_new[name]
for name in new_scrap_order_new._cache
}
)
)
vals.update(
{
"lot_id": rec.recall_id.lot_id.id,
"location_id": rec.location_id.id,
"origin": rec.recall_id.name,
"scrap_qty": rec.qty,
}
)
scrap_order = StockScrap.create(vals)
rec.scrap_id = scrap_order.id
3 changes: 3 additions & 0 deletions rma_recall/security/ir.model.access.csv
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_rma_recall,access_rma_recall_all_employee,rma_recall.model_rma_recall,,1,1,1,1
access_rma_recall_line,access_rma_recall_line_all_employee,rma_recall.model_rma_recall_line,,1,1,1,1
Binary file added rma_recall/static/description/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b9cca9b

Please sign in to comment.