[IMP] rma_sale: prepare kits integration

When a sale line has a phantom product (mrp kits) the RMA would not be
possible as the wizard couldn't pair the components moves with the
product in the line. With this approach, we can at least return the
spare components of the original kit line.

We also need some hooks to intervine in the main methods, like in
invoicing.
This commit is contained in:
david
2020-11-16 17:26:06 +01:00
parent 0493b315d2
commit 6378647d1c
8 changed files with 90 additions and 32 deletions

View File

@@ -9,14 +9,13 @@ from odoo.tools import float_compare
class AccountMove(models.Model):
_inherit = "account.move"
def post(self):
""" Avoids to validate a refund with less quantity of product than
quantity in the linked RMA.
"""
def _check_rma_invoice_lines_qty(self):
"""We can't refund a different qty than the stated in the RMA.
Extend to change criteria """
precision = self.env["decimal.precision"].precision_get(
"Product Unit of Measure"
)
if (
return (
self.sudo()
.mapped("invoice_line_ids")
.filtered(
@@ -26,7 +25,13 @@ class AccountMove(models.Model):
< 0
)
)
):
)
def post(self):
""" Avoids to validate a refund with less quantity of product than
quantity in the linked RMA.
"""
if self._check_rma_invoice_lines_qty():
raise ValidationError(
_(
"There is at least one invoice lines whose quantity is "

View File

@@ -925,16 +925,32 @@ class Rma(models.Model):
rma.action_refund
"""
self.ensure_one()
line_form.product_id = self.product_id
line_form.quantity = self.product_uom_qty
line_form.product_uom_id = self.product_uom
product = self._get_refund_line_product()
qty, uom = self._get_refund_line_quantity()
line_form.product_id = product
line_form.quantity = qty
line_form.product_uom_id = uom
line_form.price_unit = self._get_refund_line_price_unit()
def _get_refund_line_product(self):
"""To be overriden in a third module with the proper origin values
in case a kit is linked with the rma"""
return self.product_id
def _get_refund_line_quantity(self):
"""To be overriden in a third module with the proper origin values
in case a kit is linked with the rma """
return (self.product_uom_qty, self.product_uom)
def _get_refund_line_price_unit(self):
"""To be overriden in a third module with the proper origin values
in case a sale order is linked to the original move"""
return self.product_id.lst_price
def _get_extra_refund_line_vals(self):
"""Override to write aditional stuff into the refund line"""
return {}
# Returning business methods
def create_return(self, scheduled_date, qty=None, uom=None):
"""Intended to be invoked by the delivery wizard"""

View File

@@ -46,7 +46,7 @@
<tr class="active">
<th>RMA #</th>
<th class='d-none d-md-table-cell'>Date</th>
<th>Product</th>
<th name="th_product">Product</th>
<th class='text-right'>Quantity</th>
<th class='d-none d-md-table-cell'>Status</th>
</tr>
@@ -66,7 +66,7 @@
<span t-field="rma.date" />
</td>
<!-- Portal users don't have access to unpublished products -->
<td>
<td name="td_product">
<span t-esc="rma.sudo().product_id.display_name" />
</td>
<td class='text-right'>

View File

@@ -353,7 +353,7 @@
<field name="name">RMA</field>
<field name="res_model">rma</field>
<field name="view_mode">tree,form,pivot,calendar,activity</field>
<field name="context">{"search_default_user_id": uid}</field>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Click to add a new RMA.

View File

@@ -40,7 +40,7 @@ class CustomerPortal(CustomerPortal):
wizard = wizard_obj.with_context(active_id=order_id).create(
{"line_ids": line_vals, "location_id": location_id}
)
rma = wizard.sudo().create_rma()
rma = wizard.sudo().create_rma(from_portal=True)
for rec in rma:
rec.origin += _(" (Portal)")
# Add the user as follower of the created RMAs so they can

View File

@@ -25,6 +25,7 @@ class Rma(models.Model):
comodel_name="sale.order.line", compute="_compute_allowed_move_ids",
)
move_id = fields.Many2one(domain="[('id', 'in', allowed_move_ids)]")
sale_line_id = fields.Many2one(related="move_id.sale_line_id",)
allowed_product_ids = fields.Many2many(
comodel_name="product.product", compute="_compute_allowed_product_ids",
)
@@ -83,3 +84,24 @@ class Rma(models.Model):
if self.order_id:
invoice_form.invoice_user_id = self.order_id.user_id
return res
def _get_refund_line_price_unit(self):
"""Get the sale order price unit"""
if self.sale_line_id:
return self.sale_line_id.price_unit
return super()._get_refund_line_price_unit()
def _get_refund_line_product(self):
"""To be overriden in a third module with the proper origin values
in case a kit is linked with the rma """
if not self.sale_line_id:
return super()._get_refund_line_product()
return self.sale_line_id.product_id
def _prepare_refund_line(self, line_form):
"""Add line data"""
super()._prepare_refund_line(line_form)
line = self.sale_line_id
if line:
line_form.discount = line.discount
line_form.sequence = line.sequence

View File

@@ -1,7 +1,7 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
@@ -22,6 +22,16 @@ class SaleOrder(models.Model):
for record in self:
record.rma_count = mapped_data.get(record.id, 0)
def _prepare_rma_wizard_line_vals(self, data):
"""So we can extend the wizard easily"""
return {
"product_id": data["product"].id,
"quantity": data["quantity"],
"sale_line_id": data["sale_line_id"].id,
"uom_id": data["uom"].id,
"picking_id": data["picking"] and data["picking"].id,
}
def action_create_rma(self):
self.ensure_one()
if self.state not in ["sale", "done"]:
@@ -30,17 +40,7 @@ class SaleOrder(models.Model):
)
wizard_obj = self.env["sale.order.rma.wizard"]
line_vals = [
(
0,
0,
{
"product_id": data["product"].id,
"quantity": data["quantity"],
"sale_line_id": data["sale_line_id"].id,
"uom_id": data["uom"].id,
"picking_id": data["picking"] and data["picking"].id,
},
)
(0, 0, self._prepare_rma_wizard_line_vals(data))
for data in self.get_delivery_rma_data()
]
wizard = wizard_obj.with_context(active_id=self.id).create(
@@ -76,6 +76,19 @@ class SaleOrder(models.Model):
data += line.prepare_sale_rma_data()
return data
@api.depends("rma_ids.refund_id")
def _get_invoiced(self):
"""Search for possible RMA refunds and link them to the order. We
don't want to link their sale lines as that would unbalance the
qtys to invoice wich isn't correct for this case"""
super()._get_invoiced()
for order in self:
refunds = order.sudo().rma_ids.mapped("refund_id")
if not refunds:
continue
order.invoice_ids += refunds
order.invoice_count = len(order.invoice_ids)
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
@@ -98,7 +111,7 @@ class SaleOrderLine(models.Model):
def prepare_sale_rma_data(self):
self.ensure_one()
product = self.product_id
if self.product_id.type != "product":
if self.product_id.type not in ["product", "consu"]:
return {}
moves = self.get_delivery_move()
data = []

View File

@@ -131,12 +131,14 @@
</div>
</td>
<td class="text-left">
<t t-if="data['picking']">
<span t-esc="data['picking'].name"/>
<input type="hidden"
<span
t-esc="data['picking'] and data['picking'].name"
/>
<input
type="hidden"
t-attf-name="#{data_index}-picking_id"
t-att-value="data['picking'].id"/>
</t>
t-att-value="data['picking'] and data['picking'].id"
/>
</td>
<td class="text-left">
<select