[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 30677d35d5
commit 9614c93f88
9 changed files with 100 additions and 24 deletions

View File

@@ -9,15 +9,20 @@ from odoo.tools import float_compare
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
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")
return self.sudo().mapped("invoice_line_ids").filtered(
lambda r: (r.rma_id and float_compare(
r.quantity, r.rma_id.product_uom_qty, precision) < 0))
def action_invoice_open(self):
""" Avoids to validate a refund with less quantity of product than
quantity in the linked RMA.
"""
precision = self.env['decimal.precision'].precision_get(
'Product Unit of Measure')
if self.sudo().mapped('invoice_line_ids').filtered(
lambda r: (r.rma_id and float_compare(
r.quantity, r.rma_id.product_uom_qty, precision) < 0)):
if self._check_rma_invoice_lines_qty():
raise ValidationError(
_("There is at least one invoice lines whose quantity is "
"less than the quantity specified in its linked RMA."))

View File

@@ -611,12 +611,14 @@ class Rma(models.Model):
refund_vals = invoice_form._values_to_save(all_fields=True)
line_vals = refund_vals['invoice_line_ids'][-1][2]
line_vals.update(invoice_id=refund.id, rma_id=rma.id)
line_vals.update(rma._get_extra_refund_line_vals())
line = self.env['account.invoice.line'].create(line_vals)
rma.write({
'refund_line_id': line.id,
'refund_id': refund.id,
'state': 'refunded',
})
refund.compute_taxes()
refund.message_post_with_view(
'mail.message_origin_link',
values={'self': refund, 'origin': rmas},
@@ -952,16 +954,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.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.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

@@ -36,7 +36,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>
@@ -51,7 +51,7 @@
</td>
<td class="d-none d-md-table-cell"><span t-field="rma.date"/></td>
<!-- Portal users don't have access to unpublished products -->
<td><span t-esc="rma.sudo().product_id.display_name"/></td>
<td name="td_product"><span t-esc="rma.sudo().product_id.display_name"/></td>
<td class='text-right'><span t-field="rma.product_uom_qty"/></td>
<td class="d-none d-md-table-cell tx_status">
<span class="badge badge-pill badge-secondary"><span t-field="rma.state"/></span>

View File

@@ -283,7 +283,7 @@
<field name="res_model">rma</field>
<field name="view_type">form</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

@@ -36,7 +36,7 @@ class CustomerPortal(CustomerPortal):
'location_id': location_id,
'partner_shipping_id': partner_shipping_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

@@ -31,6 +31,9 @@ class Rma(models.Model):
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",
@@ -88,3 +91,34 @@ class Rma(models.Model):
if self.order_id:
invoice_form.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
def _get_extra_refund_line_vals(self):
"""Link sale line"""
self.ensure_one()
vals = super()._get_extra_refund_line_vals()
line = self.sale_line_id
if line:
vals.update({
"sequence": line.sequence,
})
return vals

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
@@ -28,19 +28,25 @@ 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']:
raise ValidationError(_("You may only create RMAs from a "
"confirmed or done sale order."))
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,
}) for data in self.get_delivery_rma_data()]
line_vals = [
(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({
'line_ids': line_vals,
'location_id': self.warehouse_id.rma_loc_id.id
@@ -78,6 +84,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"
@@ -96,7 +115,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

@@ -96,10 +96,10 @@
</div>
</td>
<td class="text-left">
<span t-esc="data['picking'].name"/>
<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-att-value="data['picking'] and data['picking'].id"/>
</td>
<td class="text-left">
<select t-attf-name="#{data_index}-operation_id"

View File

@@ -8,7 +8,7 @@
<field name="target">new</field>
</record>
<record id="=sale_order_rma_wizard_form_view" model="ir.ui.view">
<record id="sale_order_rma_wizard_form_view" model="ir.ui.view">
<field name="name">sale.order.rma.wizard.form</field>
<field name="model">sale.order.rma.wizard</field>
<field name="arch" type="xml">