mirror of
https://github.com/ForgeFlow/stock-rma.git
synced 2025-01-21 12:57:49 +02:00
Revert "[17.0][MIG] rma"
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
from . import rma_order
|
||||
from . import rma_order_line
|
||||
from . import rma_operation
|
||||
from . import stock_move
|
||||
from . import stock_warehouse
|
||||
from . import product
|
||||
from . import product_category
|
||||
from . import procurement_group
|
||||
from . import stock_rule
|
||||
from . import res_partner
|
||||
from . import res_company
|
||||
from . import res_config_settings
|
||||
@@ -1,37 +0,0 @@
|
||||
# Copyright (C) 2017-22 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ProcurementGroup(models.Model):
|
||||
_inherit = "procurement.group"
|
||||
|
||||
rma_id = fields.Many2one(
|
||||
comodel_name="rma.order", string="RMA", ondelete="set null"
|
||||
)
|
||||
rma_line_id = fields.Many2one(
|
||||
comodel_name="rma.order.line", string="RMA line", ondelete="set null"
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _get_rule(self, product_id, location_id, values):
|
||||
"""Ensure that the selected rule is valid for RMAs"""
|
||||
res = super()._get_rule(product_id, location_id, values)
|
||||
rma_route_check = self.env.context.get("rma_route_check")
|
||||
if rma_route_check:
|
||||
if res and not res.route_id.rma_selectable:
|
||||
raise ValidationError(
|
||||
_(
|
||||
"No rule found for this product %(product)s and "
|
||||
"location %(location)s that is valid for RMA operations."
|
||||
)
|
||||
% {
|
||||
"product": product_id.default_code or product_id.name,
|
||||
"location": location_id.complete_name,
|
||||
}
|
||||
)
|
||||
# Don't enforce check on any chained moves
|
||||
rma_route_check.clear()
|
||||
return res
|
||||
@@ -1,22 +0,0 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = "product.template"
|
||||
|
||||
rma_customer_operation_id = fields.Many2one(
|
||||
company_dependent=True,
|
||||
comodel_name="rma.operation",
|
||||
string="Default RMA Customer Operation",
|
||||
)
|
||||
rma_supplier_operation_id = fields.Many2one(
|
||||
company_dependent=True,
|
||||
comodel_name="rma.operation",
|
||||
string="Default RMA Supplier Operation",
|
||||
)
|
||||
rma_approval_policy = fields.Selection(
|
||||
related="categ_id.rma_approval_policy", readonly=True
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
# Copyright 2017 ForgeFlow
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ProductCategory(models.Model):
|
||||
_inherit = "product.category"
|
||||
|
||||
rma_approval_policy = fields.Selection(
|
||||
selection=[("one_step", "One step"), ("two_step", "Two steps")],
|
||||
string="RMA Approval Policy",
|
||||
required=True,
|
||||
default="one_step",
|
||||
help="Options: \n "
|
||||
"* One step: Always auto-approve RMAs that only contain "
|
||||
"products within categories with this policy.\n"
|
||||
"* Two steps: A RMA containing a product within a category with "
|
||||
"this policy will request the RMA manager approval.",
|
||||
)
|
||||
rma_customer_operation_id = fields.Many2one(
|
||||
company_dependent=True,
|
||||
comodel_name="rma.operation",
|
||||
string="Default RMA Customer Operation",
|
||||
)
|
||||
rma_supplier_operation_id = fields.Many2one(
|
||||
company_dependent=True,
|
||||
comodel_name="rma.operation",
|
||||
string="Default RMA Supplier Operation",
|
||||
)
|
||||
@@ -1,14 +0,0 @@
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
group_rma_delivery_address = fields.Boolean(
|
||||
string="RMA addresses",
|
||||
help="Display 3 fields on rma: partner, invoice address, delivery address",
|
||||
)
|
||||
|
||||
group_rma_lines = fields.Boolean(
|
||||
string="Use RMA groups", help="Group RMA lines in one RMA group"
|
||||
)
|
||||
@@ -1,22 +0,0 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
group_rma_delivery_address = fields.Boolean(
|
||||
related="company_id.group_rma_delivery_address",
|
||||
implied_group="rma.group_rma_delivery_invoice_address",
|
||||
readonly=False,
|
||||
)
|
||||
|
||||
group_rma_lines = fields.Boolean(
|
||||
related="company_id.group_rma_lines",
|
||||
readonly=False,
|
||||
implied_group="rma.group_rma_groups",
|
||||
)
|
||||
|
||||
module_rma_account = fields.Boolean(string="RMA invoicing")
|
||||
@@ -1,27 +0,0 @@
|
||||
# Copyright 2017-22 ForgeFlow
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
def _compute_rma_line_count(self):
|
||||
for rec in self:
|
||||
rec.rma_line_count = len(rec.rma_line_ids)
|
||||
|
||||
rma_line_ids = fields.One2many(
|
||||
comodel_name="rma.order.line", string="RMAs", inverse_name="partner_id"
|
||||
)
|
||||
rma_line_count = fields.Integer(
|
||||
compute="_compute_rma_line_count", compute_sudo=True
|
||||
)
|
||||
|
||||
def action_open_partner_rma(self):
|
||||
action = self.env.ref("rma.action_rma_customer_lines")
|
||||
result = action.sudo().read()[0]
|
||||
result["context"] = {"search_default_partner_id": self.id}
|
||||
result["domain"] = []
|
||||
result["display_name"] = "Partner RMAs"
|
||||
return result
|
||||
@@ -1,96 +0,0 @@
|
||||
# Copyright 2017-18 ForgeFlow
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class RmaOperation(models.Model):
|
||||
_name = "rma.operation"
|
||||
_description = "RMA Operation"
|
||||
|
||||
@api.model
|
||||
def _default_warehouse_id(self):
|
||||
company_id = self.env.user.company_id.id
|
||||
warehouse = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", company_id)], limit=1
|
||||
)
|
||||
return warehouse
|
||||
|
||||
@api.model
|
||||
def _default_customer_location_id(self):
|
||||
return self.env.ref("stock.stock_location_customers") or False
|
||||
|
||||
@api.model
|
||||
def _default_supplier_location_id(self):
|
||||
return self.env.ref("stock.stock_location_suppliers") or False
|
||||
|
||||
@api.model
|
||||
def _default_routes(self):
|
||||
op_type = self.env.context.get("default_type")
|
||||
if op_type == "customer":
|
||||
return self.env.ref("rma.route_rma_customer")
|
||||
elif op_type == "supplier":
|
||||
return self.env.ref("rma.route_rma_supplier")
|
||||
|
||||
name = fields.Char("Description", required=True)
|
||||
code = fields.Char(required=True)
|
||||
active = fields.Boolean(default=True)
|
||||
receipt_policy = fields.Selection(
|
||||
[
|
||||
("no", "Not required"),
|
||||
("ordered", "Based on Ordered Quantities"),
|
||||
("delivered", "Based on Delivered Quantities"),
|
||||
],
|
||||
default="no",
|
||||
)
|
||||
delivery_policy = fields.Selection(
|
||||
[
|
||||
("no", "Not required"),
|
||||
("ordered", "Based on Ordered Quantities"),
|
||||
("received", "Based on Received Quantities"),
|
||||
],
|
||||
default="no",
|
||||
)
|
||||
in_route_id = fields.Many2one(
|
||||
comodel_name="stock.route",
|
||||
string="Inbound Route",
|
||||
domain=[("rma_selectable", "=", True)],
|
||||
default=lambda self: self._default_routes(),
|
||||
)
|
||||
out_route_id = fields.Many2one(
|
||||
comodel_name="stock.route",
|
||||
string="Outbound Route",
|
||||
domain=[("rma_selectable", "=", True)],
|
||||
default=lambda self: self._default_routes(),
|
||||
)
|
||||
customer_to_supplier = fields.Boolean(
|
||||
string="The customer will send to the supplier"
|
||||
)
|
||||
supplier_to_customer = fields.Boolean(
|
||||
string="The supplier will send to the customer"
|
||||
)
|
||||
in_warehouse_id = fields.Many2one(
|
||||
comodel_name="stock.warehouse",
|
||||
string="Inbound Warehouse",
|
||||
default=lambda self: self._default_warehouse_id(),
|
||||
)
|
||||
out_warehouse_id = fields.Many2one(
|
||||
comodel_name="stock.warehouse",
|
||||
string="Outbound Warehouse",
|
||||
default=lambda self: self._default_warehouse_id(),
|
||||
)
|
||||
location_id = fields.Many2one("stock.location", "Send To This Company Location")
|
||||
type = fields.Selection(
|
||||
[("customer", "Customer"), ("supplier", "Supplier")],
|
||||
string="Used in RMA of this type",
|
||||
required=True,
|
||||
)
|
||||
rma_line_ids = fields.One2many(
|
||||
comodel_name="rma.order.line", inverse_name="operation_id", string="RMA lines"
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
string="Company",
|
||||
required=True,
|
||||
default=lambda self: self.env.user.company_id,
|
||||
)
|
||||
@@ -1,322 +0,0 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class RmaOrder(models.Model):
|
||||
_name = "rma.order"
|
||||
_description = "RMA Group"
|
||||
_inherit = ["mail.thread"]
|
||||
_order = "id desc"
|
||||
|
||||
@api.model
|
||||
def _get_default_type(self):
|
||||
if "supplier" in self.env.context:
|
||||
return "supplier"
|
||||
return "customer"
|
||||
|
||||
def _compute_in_shipment_count(self):
|
||||
for rec in self:
|
||||
pickings = self.env["stock.picking"]
|
||||
for line in rec.rma_line_ids:
|
||||
pickings |= line._get_in_pickings()
|
||||
rec.in_shipment_count = len(pickings)
|
||||
|
||||
def _compute_out_shipment_count(self):
|
||||
for rec in self:
|
||||
pickings = self.env["stock.picking"]
|
||||
for line in rec.rma_line_ids:
|
||||
pickings |= line._get_out_pickings()
|
||||
rec.out_shipment_count = len(pickings)
|
||||
|
||||
def _compute_supplier_line_count(self):
|
||||
self.supplier_line_count = len(
|
||||
self.rma_line_ids.filtered(lambda r: r.supplier_rma_line_ids)
|
||||
)
|
||||
|
||||
def _compute_line_count(self):
|
||||
for rec in self:
|
||||
rec.line_count = len(rec._get_valid_lines())
|
||||
|
||||
@api.depends("rma_line_ids", "rma_line_ids.state")
|
||||
def _compute_state(self):
|
||||
for rec in self:
|
||||
rma_line_done = self.env["rma.order.line"].search_count(
|
||||
[("id", "in", rec.rma_line_ids.ids), ("state", "=", "done")]
|
||||
)
|
||||
rma_line_approved = self.env["rma.order.line"].search_count(
|
||||
[("id", "in", rec.rma_line_ids.ids), ("state", "=", "approved")]
|
||||
)
|
||||
rma_line_to_approve = self.env["rma.order.line"].search_count(
|
||||
[("id", "in", rec.rma_line_ids.ids), ("state", "=", "to_approve")]
|
||||
)
|
||||
if rma_line_done != 0:
|
||||
state = "done"
|
||||
elif rma_line_approved != 0:
|
||||
state = "approved"
|
||||
elif rma_line_to_approve != 0:
|
||||
state = "to_approve"
|
||||
else:
|
||||
state = "draft"
|
||||
rec.state = state
|
||||
|
||||
@api.model
|
||||
def _default_date_rma(self):
|
||||
return datetime.now()
|
||||
|
||||
@api.model
|
||||
def _default_warehouse_id(self):
|
||||
warehouse = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", self.env.company.id)], limit=1
|
||||
)
|
||||
return warehouse
|
||||
|
||||
name = fields.Char(string="Group Number", index=True, copy=False)
|
||||
type = fields.Selection(
|
||||
[("customer", "Customer"), ("supplier", "Supplier")],
|
||||
required=True,
|
||||
default=lambda self: self._get_default_type(),
|
||||
readonly=True,
|
||||
)
|
||||
reference = fields.Char(
|
||||
string="Partner Reference", help="The partner reference of this RMA order."
|
||||
)
|
||||
description = fields.Text()
|
||||
comment = fields.Text("Additional Information")
|
||||
date_rma = fields.Datetime(
|
||||
compute="_compute_date_rma",
|
||||
inverse="_inverse_date_rma",
|
||||
string="Order Date",
|
||||
index=True,
|
||||
default=lambda self: self._default_date_rma(),
|
||||
)
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name="res.partner", string="Partner", required=True
|
||||
)
|
||||
rma_line_ids = fields.One2many("rma.order.line", "rma_id", string="RMA lines")
|
||||
in_shipment_count = fields.Integer(
|
||||
compute="_compute_in_shipment_count", string="# of Shipments"
|
||||
)
|
||||
out_shipment_count = fields.Integer(
|
||||
compute="_compute_out_shipment_count", string="# of Outgoing Shipments"
|
||||
)
|
||||
line_count = fields.Integer(compute="_compute_line_count", string="# of RMA lines")
|
||||
supplier_line_count = fields.Integer(
|
||||
compute="_compute_supplier_line_count", string="# of Supplier RMAs"
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
"res.company",
|
||||
string="Company",
|
||||
required=True,
|
||||
default=lambda self: self.env.company,
|
||||
)
|
||||
assigned_to = fields.Many2one(
|
||||
comodel_name="res.users",
|
||||
tracking=True,
|
||||
default=lambda self: self.env.uid,
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
comodel_name="res.users",
|
||||
tracking=True,
|
||||
default=lambda self: self.env.uid,
|
||||
)
|
||||
in_route_id = fields.Many2one(
|
||||
"stock.route",
|
||||
string="Inbound Route",
|
||||
domain=[("rma_selectable", "=", True)],
|
||||
)
|
||||
out_route_id = fields.Many2one(
|
||||
"stock.route",
|
||||
string="Outbound Route",
|
||||
domain=[("rma_selectable", "=", True)],
|
||||
)
|
||||
in_warehouse_id = fields.Many2one(
|
||||
comodel_name="stock.warehouse",
|
||||
string="Inbound Warehouse",
|
||||
required=False,
|
||||
default=_default_warehouse_id,
|
||||
)
|
||||
out_warehouse_id = fields.Many2one(
|
||||
comodel_name="stock.warehouse",
|
||||
string="Outbound Warehouse",
|
||||
required=False,
|
||||
default=_default_warehouse_id,
|
||||
)
|
||||
location_id = fields.Many2one(
|
||||
comodel_name="stock.location",
|
||||
string="Send To This Company Location",
|
||||
)
|
||||
customer_to_supplier = fields.Boolean("The customer will send to the supplier")
|
||||
supplier_to_customer = fields.Boolean("The supplier will send to the customer")
|
||||
supplier_address_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
string="Supplier Address",
|
||||
help="Address of the supplier in case of Customer RMA operation " "dropship.",
|
||||
)
|
||||
customer_address_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
string="Customer Address",
|
||||
help="Address of the customer in case of Supplier RMA operation " "dropship.",
|
||||
)
|
||||
state = fields.Selection(
|
||||
compute=_compute_state,
|
||||
selection=[
|
||||
("draft", "Draft"),
|
||||
("to_approve", "To Approve"),
|
||||
("approved", "Approved"),
|
||||
("done", "Done"),
|
||||
],
|
||||
default="draft",
|
||||
store=True,
|
||||
)
|
||||
operation_default_id = fields.Many2one(
|
||||
comodel_name="rma.operation",
|
||||
required=False,
|
||||
string="Default Operation Type",
|
||||
)
|
||||
|
||||
@api.onchange(
|
||||
"operation_default_id",
|
||||
)
|
||||
def _onchange_operation(self):
|
||||
if self.operation_default_id:
|
||||
self.in_warehouse_id = self.operation_default_id.in_warehouse_id
|
||||
self.out_warehouse_id = self.operation_default_id.out_warehouse_id
|
||||
self.location_id = (
|
||||
self.operation_default_id.location_id or self.in_warehouse_id.lot_rma_id
|
||||
)
|
||||
self.customer_to_supplier = self.operation_default_id.customer_to_supplier
|
||||
self.supplier_to_customer = self.operation_default_id.supplier_to_customer
|
||||
self.in_route_id = self.operation_default_id.in_route_id
|
||||
self.out_route_id = self.operation_default_id.out_route_id
|
||||
|
||||
@api.depends("rma_line_ids.date_rma")
|
||||
def _compute_date_rma(self):
|
||||
"""If all order line have same date set date_rma.
|
||||
If no lines, respect value given by the user.
|
||||
"""
|
||||
for rma in self:
|
||||
if rma.rma_line_ids:
|
||||
date_rma = rma.rma_line_ids[0].date_rma or False
|
||||
for rma_line in rma.rma_line_ids:
|
||||
if rma_line.date_rma != date_rma:
|
||||
date_rma = False
|
||||
break
|
||||
rma.date_rma = date_rma
|
||||
|
||||
def _inverse_date_rma(self):
|
||||
"""When set date_rma set date_rma on all order lines"""
|
||||
for po in self:
|
||||
if po.date_rma:
|
||||
po.rma_line_ids.write({"date_rma": po.date_rma})
|
||||
|
||||
@api.constrains("partner_id", "rma_line_ids")
|
||||
def _check_partner_id(self):
|
||||
if self.rma_line_ids and self.partner_id != self.mapped(
|
||||
"rma_line_ids.partner_id"
|
||||
):
|
||||
raise UserError(_("Group partner and RMA's partner must be the same."))
|
||||
if len(self.mapped("rma_line_ids.partner_id")) > 1:
|
||||
raise UserError(_("All grouped RMA's should have same partner."))
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if self.env.context.get("supplier") or vals.get("type") == "supplier":
|
||||
vals["name"] = self.env["ir.sequence"].next_by_code(
|
||||
"rma.order.supplier"
|
||||
)
|
||||
else:
|
||||
vals["name"] = self.env["ir.sequence"].next_by_code(
|
||||
"rma.order.customer"
|
||||
)
|
||||
return super().create(vals_list)
|
||||
|
||||
def _view_shipments(self, result, shipments):
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) > 1:
|
||||
result["domain"] = [("id", "in", shipments.ids)]
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref("stock.view_picking_form", False)
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = shipments.ids[0]
|
||||
return result
|
||||
|
||||
def action_view_in_shipments(self):
|
||||
action = self.env.ref("stock.action_picking_tree_all")
|
||||
result = action.sudo().read()[0]
|
||||
shipments = self.env["stock.picking"]
|
||||
for line in self.rma_line_ids:
|
||||
shipments |= line._get_in_pickings()
|
||||
return self._view_shipments(result, shipments)
|
||||
|
||||
def action_view_out_shipments(self):
|
||||
action = self.env.ref("stock.action_picking_tree_all")
|
||||
result = action.sudo().read()[0]
|
||||
shipments = self.env["stock.picking"]
|
||||
for line in self.rma_line_ids:
|
||||
shipments |= line._get_out_pickings()
|
||||
return self._view_shipments(result, shipments)
|
||||
|
||||
def _get_valid_lines(self):
|
||||
""":return: A recordset of rma lines."""
|
||||
self.ensure_one()
|
||||
return self.rma_line_ids
|
||||
|
||||
def action_view_lines(self):
|
||||
if self.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]
|
||||
lines = self._get_valid_lines()
|
||||
# choose the view_mode accordingly
|
||||
if len(lines.ids) != 1:
|
||||
result["domain"] = [("id", "in", lines.ids)]
|
||||
else:
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = lines.id
|
||||
result["context"] = {}
|
||||
return result
|
||||
|
||||
def action_view_supplier_lines(self):
|
||||
action = self.env.ref("rma.action_rma_supplier_lines")
|
||||
result = action.sudo().read()[0]
|
||||
lines = self.rma_line_ids
|
||||
for line_id in lines:
|
||||
related_lines = [line.id for line in line_id.supplier_rma_line_ids]
|
||||
# choose the view_mode accordingly
|
||||
if len(related_lines) != 1:
|
||||
result["domain"] = [("id", "in", related_lines)]
|
||||
else:
|
||||
res = self.env.ref("rma.view_rma_line_supplier_form", False)
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = related_lines[0]
|
||||
return result
|
||||
|
||||
@api.onchange("in_warehouse_id")
|
||||
def _onchange_in_warehouse_id(self):
|
||||
if self.in_warehouse_id and self.rma_line_ids:
|
||||
for rma_line in self.rma_line_ids:
|
||||
rma_line.in_warehouse_id = self.in_warehouse_id.id
|
||||
rma_line.location_id = self.in_warehouse_id.lot_rma_id.id
|
||||
|
||||
@api.onchange("customer_to_supplier", "supplier_address_id")
|
||||
def _onchange_customer_to_supplier(self):
|
||||
if self.type == "customer" and self.rma_line_ids:
|
||||
for rma_line in self.rma_line_ids:
|
||||
rma_line.customer_to_supplier = self.customer_to_supplier
|
||||
rma_line.supplier_address_id = self.supplier_address_id.id
|
||||
|
||||
@api.onchange("supplier_to_customer", "customer_address_id")
|
||||
def _onchange_supplier_to_customer(self):
|
||||
if self.type == "supplier" and self.rma_line_ids:
|
||||
for rma_line in self.rma_line_ids:
|
||||
rma_line.supplier_to_customer = self.supplier_to_customer
|
||||
rma_line.customer_address_id = self.customer_address_id.id
|
||||
@@ -1,807 +0,0 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
import operator
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
|
||||
ops = {"=": operator.eq, "!=": operator.ne}
|
||||
|
||||
|
||||
class RmaOrderLine(models.Model):
|
||||
_name = "rma.order.line"
|
||||
_description = "RMA"
|
||||
_inherit = ["mail.thread"]
|
||||
_order = "id desc"
|
||||
|
||||
@api.model
|
||||
def _get_default_type(self):
|
||||
if "supplier" in self.env.context:
|
||||
return "supplier"
|
||||
return "customer"
|
||||
|
||||
@api.model
|
||||
def _default_warehouse_id(self):
|
||||
rma_id = self.env.context.get("default_rma_id", False)
|
||||
warehouse = self.env["stock.warehouse"]
|
||||
if rma_id:
|
||||
rma = self.env["rma.order"].browse(rma_id)
|
||||
warehouse = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", rma.company_id.id)], limit=1
|
||||
)
|
||||
return warehouse
|
||||
|
||||
@api.model
|
||||
def _default_location_id(self):
|
||||
wh = self._default_warehouse_id()
|
||||
return wh.lot_rma_id
|
||||
|
||||
@api.onchange("partner_id")
|
||||
def _onchange_delivery_address(self):
|
||||
self.delivery_address_id = self.env["res.partner"].browse(
|
||||
self.partner_id.address_get(["delivery"])["delivery"]
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _get_in_pickings(self):
|
||||
# We consider an in move one where the first origin is outside
|
||||
# of the company and the final destination is outside. In case
|
||||
# of 2 or 3 step pickings, we should categorize as in shipments
|
||||
# even when they are technically internal transfers.
|
||||
pickings = self.env["stock.picking"]
|
||||
for move in self.move_ids:
|
||||
first_usage = move._get_first_usage()
|
||||
last_usage = move._get_last_usage()
|
||||
if last_usage == "internal" and first_usage != "internal":
|
||||
pickings |= move.picking_id
|
||||
elif last_usage == "supplier" and first_usage == "customer":
|
||||
pickings |= move.picking_id
|
||||
return pickings
|
||||
|
||||
@api.model
|
||||
def _get_in_moves(self):
|
||||
moves = self.env["stock.move"]
|
||||
for move in self.move_ids:
|
||||
first_usage = move._get_first_usage()
|
||||
last_usage = move._get_last_usage()
|
||||
if last_usage == "internal" and first_usage != "internal":
|
||||
moves |= move
|
||||
elif last_usage == "supplier" and first_usage == "customer":
|
||||
moves |= move
|
||||
return moves
|
||||
|
||||
@api.model
|
||||
def _get_out_pickings(self):
|
||||
pickings = self.env["stock.picking"]
|
||||
for move in self.move_ids:
|
||||
first_usage = move._get_first_usage()
|
||||
last_usage = move._get_last_usage()
|
||||
if first_usage in ("internal", "production") and last_usage in (
|
||||
"customer",
|
||||
"supplier",
|
||||
):
|
||||
pickings |= move.picking_id
|
||||
elif last_usage == "customer" and first_usage == "supplier":
|
||||
pickings |= move.picking_id
|
||||
return pickings
|
||||
|
||||
def _compute_in_shipment_count(self):
|
||||
for line in self:
|
||||
pickings = line._get_in_pickings()
|
||||
line.in_shipment_count = len(pickings)
|
||||
|
||||
def _compute_out_shipment_count(self):
|
||||
for line in self:
|
||||
pickings = line._get_out_pickings()
|
||||
line.out_shipment_count = len(pickings)
|
||||
|
||||
def _get_rma_move_qty(self, states, direction="in"):
|
||||
for rec in self:
|
||||
product_obj = self.env["uom.uom"]
|
||||
qty = 0.0
|
||||
if direction == "in":
|
||||
moves = rec.move_ids.filtered(
|
||||
lambda m: m.state in states
|
||||
and (
|
||||
m.location_id.usage == "supplier"
|
||||
or m.location_id.usage == "customer"
|
||||
)
|
||||
and (
|
||||
m.location_dest_id.usage == "internal"
|
||||
or m.location_dest_id.usage == "supplier"
|
||||
)
|
||||
)
|
||||
elif direction == "out":
|
||||
moves = rec.move_ids.filtered(
|
||||
lambda m: m.state in states
|
||||
and (
|
||||
m.location_dest_id.usage == "supplier"
|
||||
or m.location_dest_id.usage == "customer"
|
||||
)
|
||||
and (
|
||||
m.location_id.usage == "internal"
|
||||
or m.location_id.usage == "supplier"
|
||||
)
|
||||
)
|
||||
for move in moves:
|
||||
# If the move is part of a chain don't count it
|
||||
if direction == "out" and move.move_orig_ids:
|
||||
continue
|
||||
elif direction == "in" and move.move_dest_ids:
|
||||
continue
|
||||
qty += product_obj._compute_quantity(move.product_uom_qty, rec.uom_id)
|
||||
return qty
|
||||
|
||||
@api.depends(
|
||||
"move_ids",
|
||||
"move_ids.state",
|
||||
"qty_received",
|
||||
"receipt_policy",
|
||||
"product_qty",
|
||||
"type",
|
||||
)
|
||||
def _compute_qty_to_receive(self):
|
||||
for rec in self:
|
||||
rec.qty_to_receive = 0.0
|
||||
if rec.receipt_policy == "ordered":
|
||||
rec.qty_to_receive = rec.product_qty - rec.qty_received
|
||||
elif rec.receipt_policy == "delivered":
|
||||
rec.qty_to_receive = rec.qty_delivered - rec.qty_received
|
||||
|
||||
@api.depends(
|
||||
"move_ids",
|
||||
"move_ids.state",
|
||||
"delivery_policy",
|
||||
"product_qty",
|
||||
"type",
|
||||
"qty_delivered",
|
||||
"qty_received",
|
||||
)
|
||||
def _compute_qty_to_deliver(self):
|
||||
for rec in self:
|
||||
rec.qty_to_deliver = 0.0
|
||||
if rec.delivery_policy == "ordered":
|
||||
rec.qty_to_deliver = rec.product_qty - rec.qty_delivered
|
||||
elif rec.delivery_policy == "received":
|
||||
rec.qty_to_deliver = rec.qty_received - rec.qty_delivered
|
||||
|
||||
@api.depends("move_ids", "move_ids.state", "type")
|
||||
def _compute_qty_incoming(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty(
|
||||
("draft", "confirmed", "assigned"), direction="in"
|
||||
)
|
||||
rec.qty_incoming = qty
|
||||
|
||||
@api.depends("move_ids", "move_ids.state", "type")
|
||||
def _compute_qty_received(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty("done", direction="in")
|
||||
rec.qty_received = qty
|
||||
|
||||
@api.depends("move_ids", "move_ids.state", "type")
|
||||
def _compute_qty_outgoing(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty(
|
||||
("draft", "confirmed", "assigned"), direction="out"
|
||||
)
|
||||
rec.qty_outgoing = qty
|
||||
|
||||
@api.depends("move_ids", "move_ids.state", "type")
|
||||
def _compute_qty_delivered(self):
|
||||
for rec in self:
|
||||
qty = rec._get_rma_move_qty("done", direction="out")
|
||||
rec.qty_delivered = qty
|
||||
|
||||
@api.model
|
||||
def _get_supplier_rma_qty(self):
|
||||
return sum(
|
||||
self.supplier_rma_line_ids.filtered(lambda r: r.state != "cancel").mapped(
|
||||
"product_qty"
|
||||
)
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
"customer_to_supplier",
|
||||
"supplier_rma_line_ids",
|
||||
"move_ids",
|
||||
"move_ids.state",
|
||||
"qty_received",
|
||||
"receipt_policy",
|
||||
"product_qty",
|
||||
"type",
|
||||
)
|
||||
def _compute_qty_supplier_rma(self):
|
||||
for rec in self:
|
||||
if rec.customer_to_supplier:
|
||||
supplier_rma_qty = rec._get_supplier_rma_qty()
|
||||
rec.qty_to_supplier_rma = rec.product_qty - supplier_rma_qty
|
||||
rec.qty_in_supplier_rma = supplier_rma_qty
|
||||
else:
|
||||
rec.qty_to_supplier_rma = 0.0
|
||||
rec.qty_in_supplier_rma = 0.0
|
||||
|
||||
def _compute_rma_line_count(self):
|
||||
for rec in self.filtered(lambda r: r.type == "customer"):
|
||||
rec.rma_line_count = len(rec.supplier_rma_line_ids)
|
||||
for rec in self.filtered(lambda r: r.type == "supplier"):
|
||||
rec.rma_line_count = len(rec.customer_rma_id)
|
||||
|
||||
@api.model
|
||||
def _default_date_rma(self):
|
||||
return fields.Datetime.now()
|
||||
|
||||
delivery_address_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
string="Partner delivery address",
|
||||
help="This address will be used to deliver repaired or replacement "
|
||||
"products.",
|
||||
)
|
||||
rma_id = fields.Many2one(
|
||||
comodel_name="rma.order",
|
||||
string="RMA Group",
|
||||
tracking=True,
|
||||
readonly=True,
|
||||
)
|
||||
name = fields.Char(
|
||||
string="Reference",
|
||||
required=True,
|
||||
default="/",
|
||||
help="Add here the supplier RMA #. Otherwise an internal code is" " assigned.",
|
||||
copy=False,
|
||||
)
|
||||
description = fields.Text()
|
||||
conditions = fields.Html(string="Terms and conditions")
|
||||
origin = fields.Char(
|
||||
string="Source Document",
|
||||
help="Reference of the document that produced this rma.",
|
||||
)
|
||||
date_rma = fields.Datetime(
|
||||
string="Order Date", index=True, default=lambda self: self._default_date_rma()
|
||||
)
|
||||
state = fields.Selection(
|
||||
selection=[
|
||||
("draft", "Draft"),
|
||||
("to_approve", "To Approve"),
|
||||
("approved", "Approved"),
|
||||
("done", "Done"),
|
||||
("canceled", "Canceled"),
|
||||
],
|
||||
default="draft",
|
||||
tracking=True,
|
||||
)
|
||||
operation_id = fields.Many2one(
|
||||
comodel_name="rma.operation",
|
||||
required=True,
|
||||
readonly=False,
|
||||
tracking=True,
|
||||
)
|
||||
assigned_to = fields.Many2one(
|
||||
comodel_name="res.users",
|
||||
tracking=True,
|
||||
default=lambda self: self.env.uid,
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
comodel_name="res.users",
|
||||
tracking=True,
|
||||
default=lambda self: self.env.uid,
|
||||
)
|
||||
partner_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
required=True,
|
||||
store=True,
|
||||
tracking=True,
|
||||
)
|
||||
sequence = fields.Integer(
|
||||
default=10, help="Gives the sequence of this line when displaying the rma."
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
comodel_name="product.product",
|
||||
ondelete="restrict",
|
||||
required=True,
|
||||
)
|
||||
product_tracking = fields.Selection(related="product_id.tracking")
|
||||
lot_id = fields.Many2one(
|
||||
comodel_name="stock.lot",
|
||||
string="Lot/Serial Number",
|
||||
)
|
||||
product_qty = fields.Float(
|
||||
string="Return Qty",
|
||||
copy=False,
|
||||
default=1.0,
|
||||
digits="Product Unit of Measure",
|
||||
)
|
||||
uom_id = fields.Many2one(
|
||||
comodel_name="uom.uom",
|
||||
string="Unit of Measure",
|
||||
required=True,
|
||||
compute="_compute_uom_id",
|
||||
precompute=True,
|
||||
store=True,
|
||||
)
|
||||
price_unit = fields.Monetary(
|
||||
string="Unit cost",
|
||||
help="Unit cost of the items under RMA",
|
||||
)
|
||||
in_shipment_count = fields.Integer(
|
||||
compute="_compute_in_shipment_count", string="# of Shipments"
|
||||
)
|
||||
out_shipment_count = fields.Integer(
|
||||
compute="_compute_out_shipment_count", string="# of Deliveries"
|
||||
)
|
||||
move_ids = fields.One2many(
|
||||
"stock.move", "rma_line_id", string="Stock Moves", readonly=True, copy=False
|
||||
)
|
||||
reference_move_id = fields.Many2one(
|
||||
comodel_name="stock.move",
|
||||
string="Originating Stock Move",
|
||||
copy=False,
|
||||
)
|
||||
currency_id = fields.Many2one(
|
||||
"res.currency",
|
||||
default=lambda self: self.env.company.currency_id,
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
required=True,
|
||||
default=lambda self: self.env.company,
|
||||
)
|
||||
type = fields.Selection(
|
||||
selection=[("customer", "Customer"), ("supplier", "Supplier")],
|
||||
required=True,
|
||||
default=lambda self: self._get_default_type(),
|
||||
readonly=True,
|
||||
)
|
||||
customer_to_supplier = fields.Boolean(
|
||||
"The customer will send to the supplier",
|
||||
)
|
||||
supplier_to_customer = fields.Boolean(
|
||||
"The supplier will send to the customer",
|
||||
)
|
||||
receipt_policy = fields.Selection(
|
||||
[
|
||||
("no", "Not required"),
|
||||
("ordered", "Based on Ordered Quantities"),
|
||||
("delivered", "Based on Delivered Quantities"),
|
||||
],
|
||||
required=True,
|
||||
default="no",
|
||||
readonly=False,
|
||||
)
|
||||
delivery_policy = fields.Selection(
|
||||
[
|
||||
("no", "Not required"),
|
||||
("ordered", "Based on Ordered Quantities"),
|
||||
("received", "Based on Received Quantities"),
|
||||
],
|
||||
required=True,
|
||||
default="no",
|
||||
readonly=False,
|
||||
ondelete="cascade",
|
||||
)
|
||||
in_route_id = fields.Many2one(
|
||||
"stock.route",
|
||||
string="Inbound Route",
|
||||
required=True,
|
||||
domain=[("rma_selectable", "=", True)],
|
||||
compute="_compute_in_route_id",
|
||||
precompute=True,
|
||||
store=True,
|
||||
)
|
||||
out_route_id = fields.Many2one(
|
||||
"stock.route",
|
||||
string="Outbound Route",
|
||||
required=True,
|
||||
domain=[("rma_selectable", "=", True)],
|
||||
compute="_compute_out_route_id",
|
||||
precompute=True,
|
||||
store=True,
|
||||
)
|
||||
in_warehouse_id = fields.Many2one(
|
||||
comodel_name="stock.warehouse",
|
||||
string="Inbound Warehouse",
|
||||
required=True,
|
||||
default=lambda self: self._default_warehouse_id(),
|
||||
)
|
||||
out_warehouse_id = fields.Many2one(
|
||||
comodel_name="stock.warehouse",
|
||||
string="Outbound Warehouse",
|
||||
required=True,
|
||||
default=lambda self: self._default_warehouse_id(),
|
||||
)
|
||||
location_id = fields.Many2one(
|
||||
comodel_name="stock.location",
|
||||
string="Send To This Company Location",
|
||||
required=True,
|
||||
default=lambda self: self._default_location_id(),
|
||||
)
|
||||
customer_rma_id = fields.Many2one(
|
||||
"rma.order.line", string="Customer RMA line", ondelete="cascade"
|
||||
)
|
||||
supplier_rma_line_ids = fields.One2many("rma.order.line", "customer_rma_id")
|
||||
rma_line_count = fields.Integer(
|
||||
compute="_compute_rma_line_count", string="# of RMA lines associated"
|
||||
)
|
||||
supplier_address_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
string="Supplier Address",
|
||||
help="Address of the supplier in case of Customer RMA operation " "dropship.",
|
||||
)
|
||||
customer_address_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
string="Customer Address",
|
||||
help="Address of the customer in case of Supplier RMA operation " "dropship.",
|
||||
)
|
||||
qty_to_receive = fields.Float(
|
||||
digits="Product Unit of Measure",
|
||||
compute="_compute_qty_to_receive",
|
||||
store=True,
|
||||
)
|
||||
qty_incoming = fields.Float(
|
||||
string="Incoming Qty",
|
||||
copy=False,
|
||||
readonly=True,
|
||||
digits="Product Unit of Measure",
|
||||
compute="_compute_qty_incoming",
|
||||
store=True,
|
||||
)
|
||||
qty_received = fields.Float(
|
||||
copy=False,
|
||||
digits="Product Unit of Measure",
|
||||
compute="_compute_qty_received",
|
||||
store=True,
|
||||
)
|
||||
qty_to_deliver = fields.Float(
|
||||
copy=False,
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
compute="_compute_qty_to_deliver",
|
||||
store=True,
|
||||
)
|
||||
qty_outgoing = fields.Float(
|
||||
string="Outgoing Qty",
|
||||
copy=False,
|
||||
readonly=True,
|
||||
digits="Product Unit of Measure",
|
||||
compute="_compute_qty_outgoing",
|
||||
store=True,
|
||||
)
|
||||
qty_delivered = fields.Float(
|
||||
copy=False,
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
compute="_compute_qty_delivered",
|
||||
store=True,
|
||||
)
|
||||
qty_to_supplier_rma = fields.Float(
|
||||
string="Qty to send to Supplier RMA",
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
compute="_compute_qty_supplier_rma",
|
||||
store=True,
|
||||
)
|
||||
qty_in_supplier_rma = fields.Float(
|
||||
string="Qty in Supplier RMA",
|
||||
digits="Product Unit of Measure",
|
||||
readonly=True,
|
||||
compute="_compute_qty_supplier_rma",
|
||||
store=True,
|
||||
)
|
||||
under_warranty = fields.Boolean(string="Under Warranty?")
|
||||
|
||||
def _prepare_rma_line_from_stock_move(self, sm, lot=False):
|
||||
if not self.type:
|
||||
self.type = self._get_default_type()
|
||||
if self.type == "customer":
|
||||
operation = (
|
||||
sm.product_id.rma_customer_operation_id
|
||||
or sm.product_id.categ_id.rma_customer_operation_id
|
||||
)
|
||||
else:
|
||||
operation = (
|
||||
sm.product_id.rma_supplier_operation_id
|
||||
or sm.product_id.categ_id.rma_supplier_operation_id
|
||||
)
|
||||
|
||||
if not operation:
|
||||
operation = self.env["rma.operation"].search(
|
||||
[("type", "=", self.type)], limit=1
|
||||
)
|
||||
if not operation:
|
||||
raise ValidationError(_("Please define an operation first."))
|
||||
|
||||
if not operation.in_route_id or not operation.out_route_id:
|
||||
route = self.env["stock.route"].search(
|
||||
[("rma_selectable", "=", True)], limit=1
|
||||
)
|
||||
if not route:
|
||||
raise ValidationError(_("Please define an RMA route."))
|
||||
|
||||
if (
|
||||
not operation.in_warehouse_id
|
||||
or not operation.out_warehouse_id
|
||||
or not (
|
||||
operation.in_warehouse_id.lot_rma_id
|
||||
or operation.out_warehouse_id.lot_rma_id
|
||||
)
|
||||
):
|
||||
warehouse = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", self.company_id.id), ("lot_rma_id", "!=", False)],
|
||||
limit=1,
|
||||
)
|
||||
if not warehouse:
|
||||
raise ValidationError(
|
||||
_("Please define a warehouse with a default RMA location.")
|
||||
)
|
||||
|
||||
data = {
|
||||
"product_id": sm.product_id.id,
|
||||
"lot_id": lot and lot.id or False,
|
||||
"origin": sm.picking_id.name or sm.name,
|
||||
"uom_id": sm.product_uom.id,
|
||||
"product_qty": sm.product_uom_qty,
|
||||
"delivery_address_id": sm.picking_id.partner_id.id,
|
||||
"operation_id": operation.id,
|
||||
"receipt_policy": operation.receipt_policy,
|
||||
"delivery_policy": operation.delivery_policy,
|
||||
"in_warehouse_id": operation.in_warehouse_id.id or warehouse.id,
|
||||
"out_warehouse_id": operation.out_warehouse_id.id or warehouse.id,
|
||||
"in_route_id": operation.in_route_id.id or route.id,
|
||||
"out_route_id": operation.out_route_id.id or route.id,
|
||||
"location_id": (
|
||||
operation.location_id.id
|
||||
or operation.in_warehouse_id.lot_rma_id.id
|
||||
or operation.out_warehouse_id.lot_rma_id.id
|
||||
or warehouse.lot_rma_id.id
|
||||
),
|
||||
}
|
||||
return data
|
||||
|
||||
@api.onchange("reference_move_id")
|
||||
def _onchange_reference_move_id(self):
|
||||
self.ensure_one()
|
||||
sm = self.reference_move_id
|
||||
if not sm:
|
||||
return
|
||||
if sm.move_line_ids.lot_id:
|
||||
if len(sm.move_line_ids.lot_id) > 1:
|
||||
raise UserError(_("To manage lots use RMA groups."))
|
||||
else:
|
||||
data = self._prepare_rma_line_from_stock_move(
|
||||
sm, lot=sm.move_line_ids.lot_id[0]
|
||||
)
|
||||
self.update(data)
|
||||
else:
|
||||
data = self._prepare_rma_line_from_stock_move(sm, lot=False)
|
||||
self.update(data)
|
||||
self._remove_other_data_origin("reference_move_id")
|
||||
|
||||
@api.constrains("reference_move_id", "partner_id")
|
||||
def _check_move_partner(self):
|
||||
for rec in self:
|
||||
if (
|
||||
rec.reference_move_id
|
||||
and rec.reference_move_id.picking_id.partner_id != rec.partner_id
|
||||
):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"RMA customer and originating stock move customer "
|
||||
"doesn't match."
|
||||
)
|
||||
)
|
||||
|
||||
def _remove_other_data_origin(self, exception):
|
||||
if not exception == "reference_move_id":
|
||||
self.reference_move_id = False
|
||||
return True
|
||||
|
||||
def _check_lot_assigned(self):
|
||||
for rec in self:
|
||||
if rec.product_id.tracking == "serial" and rec.product_qty != 1:
|
||||
raise ValidationError(
|
||||
_(
|
||||
"Product %s has serial tracking configuration, "
|
||||
"quantity to receive should be 1"
|
||||
)
|
||||
% (rec.product_id.display_name)
|
||||
)
|
||||
|
||||
def action_rma_to_approve(self):
|
||||
self._check_lot_assigned()
|
||||
self.write({"state": "to_approve"})
|
||||
for rec in self:
|
||||
if rec.product_id.rma_approval_policy == "one_step":
|
||||
rec.action_rma_approve()
|
||||
return True
|
||||
|
||||
def action_rma_draft(self):
|
||||
self.write({"state": "draft"})
|
||||
return True
|
||||
|
||||
def action_rma_approve(self):
|
||||
self.write({"state": "approved"})
|
||||
return True
|
||||
|
||||
def action_rma_done(self):
|
||||
self.write({"state": "done"})
|
||||
return True
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if not vals.get("name") or vals.get("name") == "/":
|
||||
if self.env.context.get("supplier"):
|
||||
vals["name"] = self.env["ir.sequence"].next_by_code(
|
||||
"rma.order.line.supplier"
|
||||
)
|
||||
else:
|
||||
vals["name"] = self.env["ir.sequence"].next_by_code(
|
||||
"rma.order.line.customer"
|
||||
)
|
||||
return super().create(vals_list)
|
||||
|
||||
def check_cancel(self):
|
||||
for move in self.move_ids:
|
||||
if move.state == "done":
|
||||
raise UserError(
|
||||
_("Unable to cancel %s as some receptions have already been done.")
|
||||
% (self.name)
|
||||
)
|
||||
|
||||
def action_rma_cancel(self):
|
||||
for order in self:
|
||||
order.check_cancel()
|
||||
order.write({"state": "canceled"})
|
||||
order.move_ids._action_cancel()
|
||||
shipments = order._get_in_pickings()
|
||||
shipments |= order._get_out_pickings()
|
||||
for ship in shipments:
|
||||
ship.action_cancel()
|
||||
return True
|
||||
|
||||
def _get_price_unit(self):
|
||||
"""The price unit corresponds to the cost of that product"""
|
||||
self.ensure_one()
|
||||
if self.reference_move_id:
|
||||
price_unit = self.reference_move_id.price_unit
|
||||
else:
|
||||
price_unit = self.product_id.with_company(self.company_id).standard_price
|
||||
return price_unit
|
||||
|
||||
@api.onchange("product_id")
|
||||
def _onchange_product_id(self):
|
||||
result = {}
|
||||
if not self.product_id:
|
||||
return result
|
||||
self.uom_id = self.product_id.uom_id.id
|
||||
if not self.type:
|
||||
self.type = self._get_default_type()
|
||||
self.price_unit = self._get_price_unit()
|
||||
if self.type == "customer":
|
||||
self.operation_id = (
|
||||
self.product_id.rma_customer_operation_id
|
||||
or self.product_id.categ_id.rma_customer_operation_id
|
||||
)
|
||||
else:
|
||||
self.operation_id = (
|
||||
self.product_id.rma_supplier_operation_id
|
||||
or self.product_id.categ_id.rma_supplier_operation_id
|
||||
)
|
||||
if self.lot_id.product_id != self.product_id:
|
||||
self.lot_id = False
|
||||
return result
|
||||
|
||||
@api.onchange("operation_id")
|
||||
def _onchange_operation_id(self):
|
||||
result = {}
|
||||
if not self.operation_id:
|
||||
return result
|
||||
self.receipt_policy = self.operation_id.receipt_policy
|
||||
self.delivery_policy = self.operation_id.delivery_policy
|
||||
self.customer_to_supplier = (
|
||||
self.rma_id.customer_to_supplier or self.operation_id.customer_to_supplier
|
||||
)
|
||||
self.supplier_to_customer = (
|
||||
self.rma_id.supplier_to_customer or self.operation_id.supplier_to_customer
|
||||
)
|
||||
self.in_warehouse_id = (
|
||||
self.rma_id.in_warehouse_id or self.operation_id.in_warehouse_id
|
||||
)
|
||||
self.out_warehouse_id = (
|
||||
self.rma_id.out_warehouse_id or self.operation_id.out_warehouse_id
|
||||
)
|
||||
self.location_id = (
|
||||
self.rma_id.location_id
|
||||
or self.operation_id.location_id
|
||||
or self.in_warehouse_id.lot_rma_id
|
||||
)
|
||||
self.in_route_id = self.rma_id.in_route_id or self.operation_id.in_route_id
|
||||
self.out_route_id = self.rma_id.out_route_id or self.operation_id.out_route_id
|
||||
return result
|
||||
|
||||
@api.depends("operation_id")
|
||||
def _compute_in_route_id(self):
|
||||
for rec in self:
|
||||
rec.in_route_id = rec.operation_id.in_route_id
|
||||
|
||||
@api.depends("operation_id")
|
||||
def _compute_out_route_id(self):
|
||||
for rec in self:
|
||||
rec.out_route_id = rec.operation_id.out_route_id
|
||||
|
||||
@api.onchange("customer_to_supplier", "type")
|
||||
def _onchange_receipt_policy(self):
|
||||
if self.type == "supplier" and self.customer_to_supplier:
|
||||
self.receipt_policy = "no"
|
||||
elif self.type == "customer" and self.supplier_to_customer:
|
||||
self.delivery_policy = "no"
|
||||
|
||||
@api.onchange("lot_id")
|
||||
def _onchange_lot_id(self):
|
||||
product = self.lot_id.product_id
|
||||
if product:
|
||||
self.product_id = product
|
||||
|
||||
@api.depends("product_id")
|
||||
def _compute_uom_id(self):
|
||||
for rec in self:
|
||||
if rec.product_id:
|
||||
rec.uom_id = rec.product_id.uom_id
|
||||
|
||||
def action_view_in_shipments(self):
|
||||
action = self.env.ref("stock.action_picking_tree_all")
|
||||
result = action.sudo().read()[0]
|
||||
shipments = self.env["stock.picking"]
|
||||
for line in self:
|
||||
shipments |= line._get_in_pickings()
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
result["domain"] = "[('id', 'in', " + str(shipments.ids) + ")]"
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref("stock.view_picking_form", False)
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = shipments.ids[0]
|
||||
return result
|
||||
|
||||
def action_view_out_shipments(self):
|
||||
action = self.env.ref("stock.action_picking_tree_all")
|
||||
result = action.sudo().read()[0]
|
||||
shipments = self.env["stock.picking"]
|
||||
for line in self:
|
||||
shipments |= line._get_out_pickings()
|
||||
# choose the view_mode accordingly
|
||||
if len(shipments) != 1:
|
||||
result["domain"] = "[('id', 'in', " + str(shipments.ids) + ")]"
|
||||
elif len(shipments) == 1:
|
||||
res = self.env.ref("stock.view_picking_form", False)
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = shipments.ids[0]
|
||||
return result
|
||||
|
||||
def action_view_rma_lines(self):
|
||||
if self.type == "customer":
|
||||
# from customer we link to supplier rma
|
||||
action = self.env.ref("rma.action_rma_supplier_lines")
|
||||
rma_lines = self.supplier_rma_line_ids.ids
|
||||
res = self.env.ref("rma.view_rma_line_supplier_form", False)
|
||||
else:
|
||||
# from supplier we link to customer rma
|
||||
action = self.env.ref("rma.action_rma_customer_lines")
|
||||
rma_lines = self.customer_rma_id.ids
|
||||
res = self.env.ref("rma.view_rma_line_form", False)
|
||||
result = action.sudo().read()[0]
|
||||
# choose the view_mode accordingly
|
||||
if rma_lines and len(rma_lines) != 1:
|
||||
result["domain"] = rma_lines.ids
|
||||
elif len(rma_lines) == 1:
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = rma_lines[0]
|
||||
return result
|
||||
|
||||
@api.constrains("partner_id", "rma_id")
|
||||
def _check_partner_id(self):
|
||||
if self.rma_id and self.partner_id != self.rma_id.partner_id:
|
||||
raise ValidationError(
|
||||
_("Group partner and RMA's partner must be the same.")
|
||||
)
|
||||
@@ -1,107 +0,0 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = "stock.move"
|
||||
|
||||
rma_line_id = fields.Many2one(
|
||||
"rma.order.line", string="RMA line", ondelete="restrict"
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get("group_id"):
|
||||
group = self.env["procurement.group"].browse(vals["group_id"])
|
||||
if group.rma_line_id:
|
||||
vals["rma_line_id"] = group.rma_line_id.id
|
||||
return super().create(vals_list)
|
||||
|
||||
def _action_assign(self, force_qty=False):
|
||||
res = super()._action_assign(force_qty=force_qty)
|
||||
for move in self:
|
||||
if move.rma_line_id:
|
||||
move.partner_id = move.rma_line_id.partner_id.id or False
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _get_first_usage(self):
|
||||
if self.move_orig_ids:
|
||||
# We assume here that all origin moves come from the same place
|
||||
return self.move_orig_ids[0]._get_first_usage()
|
||||
else:
|
||||
return self.location_id.usage
|
||||
|
||||
@api.model
|
||||
def _get_last_usage(self):
|
||||
if self.move_dest_ids:
|
||||
# We assume here that all origin moves come from the same place
|
||||
return self.move_dest_ids[0]._get_last_usage()
|
||||
else:
|
||||
return self.location_dest_id.usage
|
||||
|
||||
def _should_bypass_reservation(self, forced_location=False):
|
||||
res = super()._should_bypass_reservation(forced_location=forced_location)
|
||||
if self.env.context.get("force_no_bypass_reservation"):
|
||||
return False
|
||||
return res
|
||||
|
||||
def _get_available_quantity(
|
||||
self,
|
||||
location_id,
|
||||
lot_id=None,
|
||||
package_id=None,
|
||||
owner_id=None,
|
||||
strict=False,
|
||||
allow_negative=False,
|
||||
):
|
||||
if (
|
||||
not lot_id
|
||||
and self.rma_line_id.lot_id
|
||||
and self.location_id.usage == "internal"
|
||||
):
|
||||
# In supplier RMA deliveries we can only send the RMA lot/serial.
|
||||
lot_id = self.rma_line_id.lot_id
|
||||
return super()._get_available_quantity(
|
||||
location_id,
|
||||
lot_id=lot_id,
|
||||
package_id=package_id,
|
||||
owner_id=owner_id,
|
||||
strict=strict,
|
||||
allow_negative=allow_negative,
|
||||
)
|
||||
|
||||
def _update_reserved_quantity(
|
||||
self,
|
||||
need,
|
||||
location_id,
|
||||
quant_ids=None,
|
||||
lot_id=None,
|
||||
package_id=None,
|
||||
owner_id=None,
|
||||
strict=True,
|
||||
):
|
||||
if (
|
||||
not lot_id
|
||||
and self.rma_line_id.lot_id
|
||||
and self.location_id.usage == "internal"
|
||||
):
|
||||
# In supplier RMA deliveries we can only send the RMA lot/serial.
|
||||
lot_id = self.rma_line_id.lot_id
|
||||
return super()._update_reserved_quantity(
|
||||
need,
|
||||
location_id,
|
||||
quant_ids=quant_ids,
|
||||
lot_id=lot_id,
|
||||
package_id=package_id,
|
||||
owner_id=owner_id,
|
||||
strict=strict,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _prepare_merge_moves_distinct_fields(self):
|
||||
res = super()._prepare_merge_moves_distinct_fields()
|
||||
return res + ["rma_line_id"]
|
||||
@@ -1,40 +0,0 @@
|
||||
# Copyright (C) 2017-22 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 "rma_line_id" in values:
|
||||
line = values.get("rma_line_id")
|
||||
line = self.env["rma.order.line"].browse([line])
|
||||
res["rma_line_id"] = line.id
|
||||
if line.delivery_address_id:
|
||||
res["partner_id"] = line.delivery_address_id.id
|
||||
elif line.rma_id.partner_id:
|
||||
res["partner_id"] = line.rma_id.partner_id.id
|
||||
res["price_unit"] = line._get_price_unit()
|
||||
return res
|
||||
@@ -1,270 +0,0 @@
|
||||
# Copyright (C) 2017-20 ForgeFlow S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
|
||||
|
||||
from odoo import _, fields, models
|
||||
|
||||
|
||||
class StockWarehouse(models.Model):
|
||||
_inherit = "stock.warehouse"
|
||||
|
||||
lot_rma_id = fields.Many2one(
|
||||
comodel_name="stock.location", string="RMA Location"
|
||||
) # not readonly to have the possibility to edit location and
|
||||
# propagate to rma rules (add a auto-update when writing this field?)
|
||||
rma_cust_out_type_id = fields.Many2one(
|
||||
comodel_name="stock.picking.type", string="RMA Customer out Type", readonly=True
|
||||
)
|
||||
rma_sup_out_type_id = fields.Many2one(
|
||||
comodel_name="stock.picking.type", string="RMA Supplier out Type", readonly=True
|
||||
)
|
||||
rma_cust_in_type_id = fields.Many2one(
|
||||
comodel_name="stock.picking.type", string="RMA Customer in Type", readonly=True
|
||||
)
|
||||
rma_sup_in_type_id = fields.Many2one(
|
||||
comodel_name="stock.picking.type", string="RMA Supplier in Type", readonly=True
|
||||
)
|
||||
rma_in_this_wh = fields.Boolean(
|
||||
string="RMA in this Warehouse",
|
||||
help="If set, it will create RMA location, picking types and routes "
|
||||
"for this warehouse.",
|
||||
)
|
||||
rma_customer_in_pull_id = fields.Many2one(
|
||||
comodel_name="stock.rule", string="RMA Customer In Rule"
|
||||
)
|
||||
rma_customer_out_pull_id = fields.Many2one(
|
||||
comodel_name="stock.rule", string="RMA Customer Out Rule"
|
||||
)
|
||||
rma_supplier_in_pull_id = fields.Many2one(
|
||||
comodel_name="stock.rule", string="RMA Supplier In Rule"
|
||||
)
|
||||
rma_supplier_out_pull_id = fields.Many2one(
|
||||
comodel_name="stock.rule", string="RMA Supplier Out Rule"
|
||||
)
|
||||
|
||||
def _get_rma_types(self):
|
||||
return [
|
||||
self.rma_cust_out_type_id,
|
||||
self.rma_sup_out_type_id,
|
||||
self.rma_cust_in_type_id,
|
||||
self.rma_sup_in_type_id,
|
||||
]
|
||||
|
||||
def _rma_types_available(self):
|
||||
self.ensure_one()
|
||||
rma_types = self._get_rma_types()
|
||||
for r_type in rma_types:
|
||||
if not r_type:
|
||||
return False
|
||||
return True
|
||||
|
||||
def write(self, vals):
|
||||
if "rma_in_this_wh" in vals:
|
||||
if vals.get("rma_in_this_wh"):
|
||||
for wh in self:
|
||||
# RMA location:
|
||||
if not wh.lot_rma_id:
|
||||
wh.lot_rma_id = self.env["stock.location"].create(
|
||||
{
|
||||
"name": "RMA",
|
||||
"usage": "internal",
|
||||
"location_id": wh.view_location_id.id,
|
||||
"company_id": wh.company_id.id,
|
||||
"return_location": True,
|
||||
}
|
||||
)
|
||||
# RMA types
|
||||
if not wh._rma_types_available():
|
||||
wh._create_rma_picking_types()
|
||||
else:
|
||||
for r_type in wh._get_rma_types():
|
||||
if r_type:
|
||||
r_type.active = True
|
||||
# RMA rules:
|
||||
wh._create_or_update_rma_pull()
|
||||
else:
|
||||
for wh in self:
|
||||
for r_type in wh._get_rma_types():
|
||||
if r_type:
|
||||
r_type.active = False
|
||||
# Unlink rules:
|
||||
self.mapped("rma_customer_in_pull_id").unlink()
|
||||
self.mapped("rma_customer_out_pull_id").unlink()
|
||||
self.mapped("rma_supplier_in_pull_id").unlink()
|
||||
self.mapped("rma_supplier_out_pull_id").unlink()
|
||||
return super().write(vals)
|
||||
|
||||
def _create_rma_picking_types(self):
|
||||
picking_type_obj = self.env["stock.picking.type"]
|
||||
customer_loc, supplier_loc = self._get_partner_locations()
|
||||
for wh in self:
|
||||
other_pick_type = picking_type_obj.search(
|
||||
[("warehouse_id", "=", wh.id)], order="sequence desc", limit=1
|
||||
)
|
||||
color = other_pick_type.color if other_pick_type else 0
|
||||
max_sequence = other_pick_type and other_pick_type.sequence or 0
|
||||
# create rma_cust_out_type_id:
|
||||
rma_cust_out_type_id = picking_type_obj.create(
|
||||
{
|
||||
"name": _("Customer RMA Deliveries"),
|
||||
"warehouse_id": wh.id,
|
||||
"code": "outgoing",
|
||||
"use_create_lots": True,
|
||||
"use_existing_lots": False,
|
||||
"sequence_id": self.env.ref("rma.seq_picking_type_rma_cust_out").id,
|
||||
"default_location_src_id": wh.lot_rma_id.id,
|
||||
"default_location_dest_id": customer_loc.id,
|
||||
"sequence": max_sequence,
|
||||
"color": color,
|
||||
"sequence_code": "RMA → Customer",
|
||||
}
|
||||
)
|
||||
# create rma_sup_out_type_id:
|
||||
rma_sup_out_type_id = picking_type_obj.create(
|
||||
{
|
||||
"name": _("Supplier RMA Deliveries"),
|
||||
"warehouse_id": wh.id,
|
||||
"code": "outgoing",
|
||||
"use_create_lots": True,
|
||||
"use_existing_lots": False,
|
||||
"sequence_id": self.env.ref("rma.seq_picking_type_rma_sup_out").id,
|
||||
"default_location_src_id": wh.lot_rma_id.id,
|
||||
"default_location_dest_id": supplier_loc.id,
|
||||
"sequence": max_sequence,
|
||||
"color": color,
|
||||
"sequence_code": "Customer → RMA",
|
||||
}
|
||||
)
|
||||
# create rma_cust_in_type_id:
|
||||
rma_cust_in_type_id = picking_type_obj.create(
|
||||
{
|
||||
"name": _("Customer RMA Receipts"),
|
||||
"warehouse_id": wh.id,
|
||||
"code": "incoming",
|
||||
"use_create_lots": True,
|
||||
"use_existing_lots": False,
|
||||
"sequence_id": self.env.ref("rma.seq_picking_type_rma_cust_in").id,
|
||||
"default_location_src_id": customer_loc.id,
|
||||
"default_location_dest_id": wh.lot_rma_id.id,
|
||||
"sequence": max_sequence,
|
||||
"color": color,
|
||||
"sequence_code": "RMA -> Supplier",
|
||||
}
|
||||
)
|
||||
# create rma_sup_in_type_id:
|
||||
rma_sup_in_type_id = picking_type_obj.create(
|
||||
{
|
||||
"name": _("Supplier RMA Receipts"),
|
||||
"warehouse_id": wh.id,
|
||||
"code": "incoming",
|
||||
"use_create_lots": True,
|
||||
"use_existing_lots": False,
|
||||
"sequence_id": self.env.ref("rma.seq_picking_type_rma_sup_in").id,
|
||||
"default_location_src_id": supplier_loc.id,
|
||||
"default_location_dest_id": wh.lot_rma_id.id,
|
||||
"sequence": max_sequence,
|
||||
"color": color,
|
||||
"sequence_code": "Supplier -> RMA",
|
||||
}
|
||||
)
|
||||
wh.write(
|
||||
{
|
||||
"rma_cust_out_type_id": rma_cust_out_type_id.id,
|
||||
"rma_sup_out_type_id": rma_sup_out_type_id.id,
|
||||
"rma_cust_in_type_id": rma_cust_in_type_id.id,
|
||||
"rma_sup_in_type_id": rma_sup_in_type_id.id,
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
def get_rma_rules_dict(self):
|
||||
self.ensure_one()
|
||||
rma_rules = dict()
|
||||
customer_loc, supplier_loc = self._get_partner_locations()
|
||||
rma_rules["rma_customer_in"] = {
|
||||
"name": self._format_rulename(self, customer_loc, self.lot_rma_id.name),
|
||||
"action": "pull",
|
||||
"warehouse_id": self.id,
|
||||
"company_id": self.company_id.id,
|
||||
"location_src_id": customer_loc.id,
|
||||
"location_dest_id": self.lot_rma_id.id,
|
||||
"procure_method": "make_to_stock",
|
||||
"route_id": self.env.ref("rma.route_rma_customer").id,
|
||||
"picking_type_id": self.rma_cust_in_type_id.id,
|
||||
"active": True,
|
||||
}
|
||||
rma_rules["rma_customer_out"] = {
|
||||
"name": self._format_rulename(self, self.lot_rma_id, customer_loc.name),
|
||||
"action": "pull",
|
||||
"warehouse_id": self.id,
|
||||
"company_id": self.company_id.id,
|
||||
"location_src_id": self.lot_rma_id.id,
|
||||
"location_dest_id": customer_loc.id,
|
||||
"procure_method": "make_to_stock",
|
||||
"route_id": self.env.ref("rma.route_rma_customer").id,
|
||||
"picking_type_id": self.rma_cust_out_type_id.id,
|
||||
"active": True,
|
||||
}
|
||||
rma_rules["rma_supplier_in"] = {
|
||||
"name": self._format_rulename(self, supplier_loc, self.lot_rma_id.name),
|
||||
"action": "pull",
|
||||
"warehouse_id": self.id,
|
||||
"company_id": self.company_id.id,
|
||||
"location_src_id": supplier_loc.id,
|
||||
"location_dest_id": self.lot_rma_id.id,
|
||||
"procure_method": "make_to_stock",
|
||||
"route_id": self.env.ref("rma.route_rma_supplier").id,
|
||||
"picking_type_id": self.rma_sup_in_type_id.id,
|
||||
"active": True,
|
||||
}
|
||||
rma_rules["rma_supplier_out"] = {
|
||||
"name": self._format_rulename(self, self.lot_rma_id, supplier_loc.name),
|
||||
"action": "pull",
|
||||
"warehouse_id": self.id,
|
||||
"company_id": self.company_id.id,
|
||||
"location_src_id": self.lot_rma_id.id,
|
||||
"location_dest_id": supplier_loc.id,
|
||||
"procure_method": "make_to_stock",
|
||||
"route_id": self.env.ref("rma.route_rma_supplier").id,
|
||||
"picking_type_id": self.rma_sup_out_type_id.id,
|
||||
"active": True,
|
||||
}
|
||||
return rma_rules
|
||||
|
||||
def _create_or_update_rma_pull(self):
|
||||
rule_obj = self.env["stock.rule"]
|
||||
for wh in self:
|
||||
rules_dict = wh.get_rma_rules_dict()
|
||||
if wh.rma_customer_in_pull_id:
|
||||
wh.rma_customer_in_pull_id.write(rules_dict["rma_customer_in"])
|
||||
else:
|
||||
wh.rma_customer_in_pull_id = rule_obj.create(
|
||||
rules_dict["rma_customer_in"]
|
||||
)
|
||||
|
||||
if wh.rma_customer_out_pull_id:
|
||||
wh.rma_customer_out_pull_id.write(rules_dict["rma_customer_out"])
|
||||
else:
|
||||
wh.rma_customer_out_pull_id = rule_obj.create(
|
||||
rules_dict["rma_customer_out"]
|
||||
)
|
||||
|
||||
if wh.rma_supplier_in_pull_id:
|
||||
wh.rma_supplier_in_pull_id.write(rules_dict["rma_supplier_in"])
|
||||
else:
|
||||
wh.rma_supplier_in_pull_id = rule_obj.create(
|
||||
rules_dict["rma_supplier_in"]
|
||||
)
|
||||
|
||||
if wh.rma_supplier_out_pull_id:
|
||||
wh.rma_supplier_out_pull_id.write(rules_dict["rma_supplier_out"])
|
||||
else:
|
||||
wh.rma_supplier_out_pull_id = rule_obj.create(
|
||||
rules_dict["rma_supplier_out"]
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
class StockLocationRoute(models.Model):
|
||||
_inherit = "stock.route"
|
||||
|
||||
rma_selectable = fields.Boolean(string="Selectable on RMA Lines")
|
||||
Reference in New Issue
Block a user