[14.0][IMP]rma_put_away: allows to do stock moves from rma

This commit is contained in:
DavidJForgeFlow
2022-06-14 09:54:55 +02:00
parent 6b84bef6a2
commit 491f20b09c
16 changed files with 453 additions and 0 deletions

View File

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

View File

@@ -0,0 +1,16 @@
{
"name": "RMA Free of Charge True",
"summary": "Make the field free of charge true by default",
"version": "14.0.1.1.0",
"author": "ForgeFlow, " "Odoo Community Association (OCA)",
"website": "https://github.com/ForgeFlow/stock-rma",
"category": "RMA",
"depends": ["account_move_line_rma_order_line"],
"license": "AGPL-3",
"data": [
],
"installable": True,
"maintainers": ["DavidJForgeFlow"],
"development_status": "Beta",
}

View File

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

View File

@@ -0,0 +1,7 @@
from odoo import fields, models
class RmaLineMakePurchaseOrderItem(models.TransientModel):
_inherit = "rma.order.line.make.purchase.order.item"
free_of_charge = fields.Boolean(default="True")

2
rma_put_away/__init__.py Normal file
View File

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

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 recieved products"
"in odoo",
"author": "ForgeFlow",
"website": "https://github.com/ForgeFlow/stock-rma",
"depends": ["rma"],
"data": [
"views/rma_put_away_view.xml",
"views/rma_operation_view.xml",
"views/rma_order_view.xml",
"views/rma_order_line_view.xml",
],
"installable": True,
}

View File

@@ -0,0 +1,2 @@
from . import rma_order_line
from . import rma_operation

View File

@@ -0,0 +1,33 @@
# Copyright 2020 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class RmaOperation(models.Model):
_inherit = "rma.operation"
put_away_policy = fields.Selection(
selection=[
("no", "Not required"),
("ordered", "Based on Ordered Quantities"),
("received", "Based on Received Quantities"),
],
string="Put Away Policy",
default="no",
)
internal_route_id = fields.Many2one(
comodel_name="stock.location.route",
string="Internal Route",
domain=[("rma_selectable", "=", True)],
default=lambda self: self._default_routes(),
)
internal_warehouse_id = fields.Many2one(
comodel_name="stock.warehouse",
string="Internal Destination Warehouse",
default=lambda self: self._default_warehouse_id(),
)

View File

@@ -0,0 +1,52 @@
from odoo import _, api, fields, models
class RmaOrderLine(models.Model):
_inherit = "rma.order.line"
qty_to_put_away = fields.Float(
string="Qty To Put Away",
digits="Product Unit of Measure",
compute="_compute_qty_to_put_away",
store=True,
)
qty_put_away = fields.Float(
string="Qty Put Away",
copy=False,
digits="Product Unit of Measure",
readonly=True,
compute="_compute_qty_put_away",
store=True,
help="Quantity Put Away.",
)
put_away_policy = fields.Selection(
selection=[
("no", "Not required"),
("ordered", "Based on Ordered Quantities"),
("received", "Based on Received Quantities"),
],
string="Put Away Policy",
default="no",
required=True,
)
def _compute_qty_to_put_away(self):
for rec in self:
rec.qty_to_put_away = 0.0
if rec.put_away_policy == "ordered":
rec.qty_to_put_away = rec.product_qty - rec.qty_put_away
elif rec.put_away_policy == "received":
rec.qty_to_put_away = rec.qty_received - rec.qty_put_away
def _compute_qty_put_away(self):
for rec in self:
rec.qty_put_away = 0.0
@api.onchange("operation_id")
def _onchange_operation_id(self):
result = super(RmaOrderLine, self)._onchange_operation_id()
if self.operation_id:
self.put_away_policy = self.operation_id.put_away_policy or "no"
return result

View File

@@ -0,0 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_rma_put_away_wizard,rma.order.manager,model_rma_make_put_away.wizard,group_rma_manager,1,1,1,1
access_rma_put_away_wizard_customer,rma.order.manager,model_rma_make_put_away.wizard,group_rma_customer_user,1,1,1,1
access_rma_put_away_wizard_supplier,rma.order.manager,model_rma_make_put_away.wizard,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_put_away_wizard rma.order.manager model_rma_make_put_away.wizard group_rma_manager 1 1 1 1
3 access_rma_put_away_wizard_customer rma.order.manager model_rma_make_put_away.wizard group_rma_customer_user 1 1 1 1
4 access_rma_put_away_wizard_supplier rma.order.manager model_rma_make_put_away.wizard group_rma_supplier_user 1 1 1 1

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="rma_operation_tree" model="ir.ui.view">
<field name="name">rma.operation.tree - rma_put_away</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="put_away_policy" />
</field>
</field>
</record>
<record id="rma_operation_form" model="ir.ui.view">
<field name="name">rma.operation.form - rma_put_away</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="put_away_policy" />
</field>
<group name="outbound" position="after">
<group name="internal" string="Internal">
<field name="internal_route_id"/>
<field name="internal_warehouse_id"/>
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?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 - rma_put_away</field>
<field name="model">rma.order.line</field>
<field name="inherit_id" ref="rma.view_rma_line_form" />
<field name="arch" type="xml">
<field name="delivery_policy" position="after">
<field name="put_away_policy" />
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_rma_form" model="ir.ui.view">
<field name="name">rma.order.form - rma_put_away</field>
<field name="model">rma.order</field>
<field name="inherit_id" ref="rma.view_rma_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='rma_line_ids']/tree" position="inside">
<field name="put_away_policy" invisible="True" />
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" ?>
<odoo>
<record id="view_rma_put_away" model="ir.ui.view">
<field name="name">Create Put Away</field>
<field name="model">rma_make_put_away.wizard</field>
<field name="arch" type="xml">
<form string="Select lines for picking" name="lines">
<separator string="Select lines for put away" />
<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="line_id" invisible="1" />
<field name="uom_id" groups="uom.group_uom" />
</tree>
</field>
<footer>
<button
string="Confirm"
name="action_create_put_away"
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_put_away" model="ir.actions.act_window">
<field name="name">Create Put Away</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma_make_put_away.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="view_id" ref="view_rma_put_away" />
<field name="groups_id" eval="[(4, ref('stock.group_stock_user'))]" />
<field name="context">{'picking_type': 'internal'}</field>
<field name="binding_model_id" ref="rma.model_rma_order_line" />
</record>
<record id="view_rma_line_button_put_away_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_put_away)d"
string="Create Put Away"
class="oe_highlight"
attrs="{'invisible':['|', ('qty_to_put_away', '=', 0), ('state', '!=', 'approved')]}"
type="action"
/>
<button
name="%(action_rma_put_away)d"
string="Create Put Away"
attrs="{'invisible':['|', ('qty_to_put_away', '!=', 0), ('state', '!=', 'approved')]}"
type="action"
/>
<field
name="qty_to_put_away"
widget="statinfo"
string="PutAwayQty"
/>
</header>
</field>
</record>
</odoo>

View File

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

View File

@@ -0,0 +1,177 @@
import time
from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT_FORMAT
class RmaMakePutAway(models.TransientModel):
_name = "rma_make_put_away.wizard"
_description = "Wizard to create put away from rma lines"
item_ids = fields.One2many("rma_make_picking.wizard.item", "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,
"uom_id": line.uom_id.id,
"qty_to_receive": line.qty_to_receive,
"qty_to_deliver": line.qty_to_deliver,
"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):
"""Default values for wizard, if there is more than one supplier on
lines the supplier field is empty otherwise is the unique line
supplier.
"""
context = self._context.copy()
res = super(RmaMakePutAway, 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)
if len(lines.mapped("partner_id")) > 1:
raise ValidationError(
_(
"Only RMA lines from the same partner can be processed at "
"the same time"
)
)
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_put_away(self):
"""Method called when the user clicks on create picking"""
picking_type = "internal"
procurements = []
for item in self.item_ids:
line = item.line_id
if line.state != "approved":
raise ValidationError(_("RMA %s is not approved") % line.name)
if line.receipt_policy == "no" and picking_type == "incoming":
raise ValidationError(_("No shipments needed for this operation"))
if line.delivery_policy == "no" and picking_type == "outgoing":
raise ValidationError(_("No deliveries needed for this operation"))
procurement = self._create_procurement(item, picking_type)
procurements.extend(procurement)
return procurements
def action_create_put_away(self):
self._create_put_away()
action = self.item_ids.line_id.action_view_in_shipments()
return action
@api.model
def _get_address(self, item):
if item.line_id.customer_to_supplier:
delivery_address = item.line_id.supplier_address_id
elif item.line_id.supplier_to_customer:
delivery_address = item.line_id.customer_address_id
elif item.line_id.delivery_address_id:
delivery_address = item.line_id.delivery_address_id
elif item.line_id.partner_id:
delivery_address = item.line_id.partner_id
else:
raise ValidationError(_("Unknown delivery address"))
return delivery_address
@api.model
def _get_address_location(self, delivery_address_id, a_type):
if a_type == "supplier":
return delivery_address_id.property_stock_supplier
elif a_type == "customer":
return delivery_address_id.property_stock_customer
@api.model
def _get_procurement_data(self, item, group, qty, picking_type):
line = item.line_id
delivery_address_id = self._get_address(item)
location = self._get_address_location(delivery_address_id, line.type)
warehouse = line.out_warehouse_id
route = line.out_route_id
if not route:
raise ValidationError(_("No route specified"))
if not warehouse:
raise ValidationError(_("No warehouse specified"))
procurement_data = {
"name": line.rma_id and line.rma_id.name or line.name,
"group_id": group,
"origin": line.name,
"warehouse_id": warehouse,
"date_planned": time.strftime(DT_FORMAT),
"product_id": item.product_id,
"product_qty": qty,
"partner_id": delivery_address_id.id,
"product_uom": line.product_id.product_tmpl_id.uom_id.id,
"location_id": location,
"rma_line_id": line.id,
"route_ids": route,
}
return procurement_data
@api.model
def _create_procurement(self, item, picking_type):
errors = []
group = self.find_procurement_group(item)
if not group:
pg_data = self._get_procurement_group_data(item)
group = self.env["procurement.group"].create(pg_data)
qty = item.product_qty
values = self._get_procurement_data(item, group, qty, picking_type)
values = dict(values, rma_line_id=item.line_id, rma_id=item.line_id.rma_id)
# create picking
procurements = []
try:
procurement = group.Procurement(
item.line_id.product_id,
qty,
item.line_id.product_id.product_tmpl_id.uom_id,
values.get("location_id"),
values.get("origin"),
values.get("origin"),
self.env.company,
values,
)
procurements.append(procurement)
self.env["procurement.group"].run(procurements)
except UserError as error:
errors.append(error.name)
if errors:
raise UserError("\n".join(errors))
return procurements
def find_procurement_group(self, item):
if item.line_id.rma_id:
return self.env["procurement.group"].search(
[("rma_id", "=", item.line_id.rma_id.id)]
)
else:
return self.env["procurement.group"].search(
[("rma_line_id", "=", item.line_id.id)]
)
def _get_procurement_group_data(self, item):
group_data = {
"partner_id": item.line_id.partner_id.id,
"name": item.line_id.rma_id.name or item.line_id.name,
"rma_id": item.line_id.rma_id and item.line_id.rma_id.id or False,
"rma_line_id": item.line_id.id if not item.line_id.rma_id else False,
}
return group_data