diff --git a/rma/models/account_invoice.py b/rma/models/account_invoice.py index b3e86196..52a2f703 100644 --- a/rma/models/account_invoice.py +++ b/rma/models/account_invoice.py @@ -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.")) diff --git a/rma/models/rma.py b/rma/models/rma.py index 0b21d868..fbc061f2 100644 --- a/rma/models/rma.py +++ b/rma/models/rma.py @@ -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""" diff --git a/rma/views/rma_portal_templates.xml b/rma/views/rma_portal_templates.xml index 33b6e98e..c70e1c37 100644 --- a/rma/views/rma_portal_templates.xml +++ b/rma/views/rma_portal_templates.xml @@ -36,7 +36,7 @@
Click to add a new RMA. diff --git a/rma_sale/controllers/sale_portal.py b/rma_sale/controllers/sale_portal.py index d63fe6da..5c77c0c9 100644 --- a/rma_sale/controllers/sale_portal.py +++ b/rma_sale/controllers/sale_portal.py @@ -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 diff --git a/rma_sale/models/rma.py b/rma_sale/models/rma.py index c3a947fc..4fdda6eb 100644 --- a/rma_sale/models/rma.py +++ b/rma_sale/models/rma.py @@ -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 diff --git a/rma_sale/models/sale.py b/rma_sale/models/sale.py index 28ff0b14..795efe48 100644 --- a/rma_sale/models/sale.py +++ b/rma_sale/models/sale.py @@ -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 = [] diff --git a/rma_sale/views/sale_portal_template.xml b/rma_sale/views/sale_portal_template.xml index a1f0027e..9e7addc9 100644 --- a/rma_sale/views/sale_portal_template.xml +++ b/rma_sale/views/sale_portal_template.xml @@ -96,10 +96,10 @@