[MIG] rma: Migration to 16.0

* Standard procedure.
* Transfer view groups to nodes.
* Adjusted upstream changed field names.
* Converted onchanges to computed writable fields.
* Replace `Form` by direct dictionary vals in record creation, as they
  don't handle now properly multiple existing fields in the view, and
  computed writable improve the compatibility on new values.
* Replace domain returned on onchange by static domain in field.
* Change maintainer.

TT44213
This commit is contained in:
Pedro M. Baeza
2023-08-24 10:04:56 +02:00
parent c093db19ec
commit ed3f242cb2
19 changed files with 349 additions and 456 deletions

View File

@@ -14,14 +14,14 @@ Return Merchandise Authorization Management
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github
:target: https://github.com/OCA/rma/tree/15.0/rma
:target: https://github.com/OCA/rma/tree/16.0/rma
:alt: OCA/rma
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/rma-15-0/rma-15-0-rma
:target: https://translation.odoo-community.org/projects/rma-16-0/rma-16-0-rma
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/145/15.0
:alt: Try me on Runbot
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/rma&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -138,7 +138,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rma/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/rma/issues/new?body=module:%20rma%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/rma/issues/new?body=module:%20rma%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
@@ -184,6 +184,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-ernestotejeda|
This module is part of the `OCA/rma <https://github.com/OCA/rma/tree/15.0/rma>`_ project on GitHub.
This module is part of the `OCA/rma <https://github.com/OCA/rma/tree/16.0/rma>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -1,14 +1,16 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# Copyright 2021-2023 Tecnativa - David Vidal
# Copyright 2021-2023 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Return Merchandise Authorization Management",
"summary": "Return Merchandise Authorization (RMA)",
"version": "15.0.1.1.3",
"version": "16.0.1.0.0",
"development_status": "Production/Stable",
"category": "RMA",
"website": "https://github.com/OCA/rma",
"author": "Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["ernestotejeda"],
"maintainers": ["pedrobaeza"],
"license": "AGPL-3",
"depends": ["stock_account"],
"data": [

View File

@@ -1,99 +0,0 @@
<?xml version='1.0' encoding='utf-8' ?>
<odoo>
<record id="mail_template_rma_notification" model="mail.template">
<field name="email_from">{{object.user_id.email_formatted}}</field>
<field name="partner_to">{{object.partner_id.id}}</field>
<field
name="subject"
>{{object.company_id.name}} RMA (Ref {{object.name or 'n/a' }})</field>
<field name="report_name">{{(object.name or '')}}</field>
<field name="lang">{{object.partner_id.lang}}</field>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-out="object.partner_id.name" />
<t t-if="object.partner_id.parent_id">
<t t-out="object.partner_id.parent_id.name" />
</t>
<br />
<br />
Here is the RMA
<strong>
<t t-out="object.name" />
</strong>
from
<t t-out="object.company_id.name" />
.
<br />
<br />
Do not hesitate to contact us if you have any question.
</p>
</div>
</field>
</record>
<record id="mail_template_rma_receipt_notification" model="mail.template">
<field name="email_from">{{object.user_id.email_formatted }}</field>
<field name="partner_to">{{object.partner_id.id}}</field>
<field
name="subject"
>{{object.company_id.name}} RMA (Ref {{object.name or 'n/a' }}) products received</field>
<field name="report_name">{{(object.name or '')}}</field>
<field name="lang">{{object.partner_id.lang}}</field>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-out="object.partner_id.name" />
<t t-if="object.partner_id.parent_id">
<t t-out="object.partner_id.parent_id.name" />
</t>
<br />
<br />
The products for your RMA
<strong>
<t t-out="object.name" />
</strong>
from
<t t-out="object.company_id.name" />
have been received in our warehouse.
<br />
<br />
Do not hesitate to contact us if you have any question.
</p>
</div>
</field>
</record>
<record id="mail_template_rma_draft_notification" model="mail.template">
<field name="email_from">{{object.user_id.email_formatted}}</field>
<field name="partner_to">{{object.partner_id.id}}</field>
<field
name="subject"
>{{object.company_id.name}} Your RMA has been succesfully created (Ref {{object.name or 'n/a' }})</field>
<field name="report_name">{{(object.name or '')}}</field>
<field name="lang">{{object.partner_id.lang}}</field>
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-out="object.partner_id.name" />
<t t-if="object.partner_id.parent_id">
<t t-out="object.partner_id.parent_id.name" />
</t>
<br />
<br />
You've succesfully placed your RMA
<strong>
<t t-out="object.name" />
</strong>
on
<t t-out="object.company_id.name" />
. Our team will check it and will validate it as soon as possible.
<br />
<br />
Do not hesitate to contact us if you have any question.
</p>
</div>
</field>
</record>
</odoo>

View File

@@ -1,18 +0,0 @@
# Copyright 2022 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
openupgrade.load_data(env.cr, "rma", "migrations/15.0.1.0.0/noupdate_changes.xml")
openupgrade.delete_record_translations(
env.cr,
"rma",
[
"mail_template_rma_notification",
"mail_template_rma_receipt_notification",
"mail_template_rma_draft_notification",
],
)

View File

@@ -1,10 +1,11 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# Copyright 2023 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
class Company(models.Model):
class ResCompany(models.Model):
_inherit = "res.company"
def _default_rma_mail_confirmation_template(self):
@@ -65,11 +66,12 @@ class Company(models.Model):
help="Email sent to the customer when they place " "an RMA from the portal",
)
@api.model
def create(self, vals):
company = super(Company, self).create(vals)
company.create_rma_index()
return company
@api.model_create_multi
def create(self, vals_list):
companies = super().create(vals_list)
for company in companies:
company.create_rma_index()
return companies
def create_rma_index(self):
return (

View File

@@ -1,4 +1,5 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda
# Copyright 2023 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from collections import Counter
@@ -78,6 +79,9 @@ class Rma(models.Model):
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
compute="_compute_team_id",
store=True,
readonly=False,
)
tag_ids = fields.Many2many(comodel_name="rma.tag", string="Tags")
finalization_id = fields.Many2one(
@@ -109,19 +113,21 @@ class Rma(models.Model):
partner_shipping_id = fields.Many2one(
string="Shipping Address",
comodel_name="res.partner",
readonly=True,
states={"draft": [("readonly", False)]},
help="Shipping address for current RMA.",
compute="_compute_partner_shipping_id",
store=True,
readonly=False,
)
partner_invoice_id = fields.Many2one(
string="Invoice Address",
comodel_name="res.partner",
readonly=True,
states={"draft": [("readonly", False)]},
domain=(
"['|', ('company_id', '=', False), ('company_id', '='," " company_id)]"
),
help="Refund address for current RMA.",
compute="_compute_partner_invoice_id",
store=True,
readonly=False,
)
commercial_partner_id = fields.Many2one(
comodel_name="res.partner",
@@ -149,28 +155,34 @@ class Rma(models.Model):
" ('picking_id', '!=', False)"
"]"
),
readonly=True,
states={"draft": [("readonly", False)]},
compute="_compute_move_id",
store=True,
readonly=False,
)
product_id = fields.Many2one(
comodel_name="product.product",
domain=[("type", "in", ["consu", "product"])],
compute="_compute_product_id",
store=True,
readonly=False,
)
product_uom_qty = fields.Float(
string="Quantity",
required=True,
default=1.0,
digits="Product Unit of Measure",
readonly=True,
states={"draft": [("readonly", False)]},
compute="_compute_product_uom_qty",
store=True,
readonly=False,
)
product_uom = fields.Many2one(
comodel_name="uom.uom",
string="UoM",
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
default=lambda self: self.env.ref("uom.product_uom_unit").id,
compute="_compute_product_uom",
store=True,
readonly=False,
)
procurement_group_id = fields.Many2one(
comodel_name="procurement.group",
@@ -220,8 +232,9 @@ class Rma(models.Model):
location_id = fields.Many2one(
comodel_name="stock.location",
domain=_domain_location_id,
readonly=True,
states={"draft": [("readonly", False)]},
compute="_compute_location_id",
store=True,
readonly=False,
)
warehouse_id = fields.Many2one(
comodel_name="stock.warehouse",
@@ -463,6 +476,83 @@ class Rma(models.Model):
[("rma_loc_id", "parent_of", record.location_id.id)], limit=1
)
@api.depends("user_id")
def _compute_team_id(self):
self.team_id = False
for record in self.filtered("user_id"):
record.team_id = (
self.env["rma.team"]
.sudo()
.search(
[
"|",
("user_id", "=", record.user_id.id),
("member_ids", "=", record.user_id.id),
"|",
("company_id", "=", False),
("company_id", "child_of", record.company_id.ids),
],
limit=1,
)
)
@api.depends("partner_id")
def _compute_partner_shipping_id(self):
self.partner_shipping_id = False
for record in self.filtered("partner_id"):
address = record.partner_id.address_get(["delivery"])
record.partner_shipping_id = address.get("delivery", False)
@api.depends("partner_id")
def _compute_partner_invoice_id(self):
self.partner_invoice_id = False
for record in self.filtered("partner_id"):
address = record.partner_id.address_get(["invoice"])
record.partner_invoice_id = address.get("invoice", False)
@api.depends("picking_id")
def _compute_move_id(self):
"""Empty move on picking change, but selecting the move in it if it's single."""
self.move_id = False
for record in self.filtered("picking_id"):
if len(record.picking_id.move_ids) == 1:
record.move_id = record.picking_id.move_ids.id
@api.depends("move_id")
def _compute_product_id(self):
self.product_id = False
for record in self.filtered("move_id"):
record.product_id = record.move_id.product_id.id
@api.depends("move_id")
def _compute_product_uom_qty(self):
self.product_uom_qty = False
for record in self.filtered("move_id"):
record.product_uom_qty = record.move_id.product_uom_qty
@api.depends("move_id", "product_id")
def _compute_product_uom(self):
for record in self:
if record.move_id:
record.product_uom = record.move_id.product_uom.id
elif record.product_id:
record.product_uom = record.product_id.uom_id
else:
record.product_uom = False
@api.depends("picking_id", "product_id", "company_id")
def _compute_location_id(self):
for record in self:
if record.picking_id:
warehouse = record.picking_id.picking_type_id.warehouse_id
record.location_id = warehouse.rma_loc_id.id
elif not record.location_id:
company = record.company_id or self.env.company
warehouse = self.env["stock.warehouse"].search(
[("company_id", "=", company.id)], limit=1
)
record.location_id = warehouse.rma_loc_id.id
def _compute_access_url(self):
for record in self:
record.access_url = "/my/rmas/{}".format(record.id)
@@ -483,76 +573,6 @@ class Rma(models.Model):
rma = self.filtered(lambda r: r.state not in ["draft", "cancelled"])
rma._ensure_required_fields()
# onchange methods (@api.onchange)
@api.onchange("user_id")
def _onchange_user_id(self):
if self.user_id:
self.team_id = (
self.env["rma.team"]
.sudo()
.search(
[
"|",
("user_id", "=", self.user_id.id),
("member_ids", "=", self.user_id.id),
"|",
("company_id", "=", False),
("company_id", "child_of", self.company_id.ids),
],
limit=1,
)
)
else:
self.team_id = False
@api.onchange("partner_id")
def _onchange_partner_id(self):
self.picking_id = False
partner_invoice_id = False
partner_shipping_id = False
if self.partner_id:
address = self.partner_id.address_get(["invoice", "delivery"])
partner_invoice_id = address.get("invoice", False)
partner_shipping_id = address.get("delivery", False)
self.partner_invoice_id = partner_invoice_id
self.partner_shipping_id = partner_shipping_id
@api.onchange("picking_id")
def _onchange_picking_id(self):
location = False
if self.picking_id:
warehouse = self.picking_id.picking_type_id.warehouse_id
location = warehouse.rma_loc_id.id
self.location_id = location
self.move_id = False
self.product_id = False
@api.onchange("move_id")
def _onchange_move_id(self):
if self.move_id:
self.product_id = self.move_id.product_id
self.product_uom_qty = self.move_id.product_uom_qty
self.product_uom = self.move_id.product_uom
@api.onchange("product_id")
def _onchange_product_id(self):
if self.product_id:
# Set UoM
if not self.product_uom or self.product_id.uom_id.id != self.product_uom.id:
self.product_uom = self.product_id.uom_id
# Set stock location (location_id)
user = self.env.user
if (
not user.has_group("stock.group_stock_multi_locations")
and not self.location_id
):
# If this condition is True, it is because a picking is not set
company = self.company_id or self.env.company
warehouse = self.env["stock.warehouse"].search(
[("company_id", "=", company.id)], limit=1
)
self.location_id = warehouse.rma_loc_id.id
# CRUD methods (ORM overrides)
@api.model_create_multi
def create(self, vals_list):
@@ -677,41 +697,25 @@ class Rma(models.Model):
group_dict[key] |= record
for rmas in group_dict.values():
origin = ", ".join(rmas.mapped("name"))
invoice_form = Form(
self.env["account.move"]
.sudo()
.with_context(
default_move_type="out_refund",
company_id=rmas[0].company_id.id,
),
"account.view_move_form",
)
rmas[0]._prepare_refund(invoice_form, origin)
refund = invoice_form.save()
refund_vals = rmas[0]._prepare_refund_vals(origin)
for rma in rmas:
# For each iteration the Form is edited, a new invoice line
# is added and then saved. This is to generate the other
# lines of the accounting entry and to specify the associated
# RMA to that new invoice line.
invoice_form = Form(refund)
with invoice_form.invoice_line_ids.new() as line_form:
rma._prepare_refund_line(line_form)
refund = invoice_form.save()
line = refund.invoice_line_ids.filtered(lambda r: not r.rma_id)
line.rma_id = rma.id
rma.write(
refund_vals["invoice_line_ids"].append(
(0, 0, rma._prepare_refund_line_vals())
)
refund = self.env["account.move"].sudo().create(refund_vals)
refund.with_user(self.env.uid).message_post_with_view(
"mail.message_origin_link",
values={"self": refund, "origin": rmas},
subtype_id=self.env.ref("mail.mt_note").id,
)
for line in refund.invoice_line_ids:
line.rma_id.write(
{
"refund_line_id": line.id,
"refund_id": refund.id,
"state": "refunded",
}
)
refund.invoice_origin = origin
refund.with_user(self.env.uid).message_post_with_view(
"mail.message_origin_link",
values={"self": refund, "origin": rmas},
subtype_id=self.env.ref("mail.mt_note").id,
)
def action_replace(self):
"""Invoked when 'Replace' button in rma form view is clicked."""
@@ -880,7 +884,6 @@ class Rma(models.Model):
rma._check_required_after_draft
rma.action_confirm
"""
ir_translation = self.env["ir.translation"]
required = [
"partner_id",
"partner_shipping_id",
@@ -891,7 +894,17 @@ class Rma(models.Model):
for record in self:
desc = ""
for field in filter(lambda item: not record[item], required):
desc += "\n%s" % ir_translation.get_field_string("rma")[field]
field_record = (
self.env["ir.model.fields"]
.sudo()
.search(
[
("model_id.model", "=", record._name),
("name", "=", field),
]
)
)
desc += f"\n{field_record.field_description}"
if desc:
raise ValidationError(_("Required field(s):%s") % desc)
@@ -982,9 +995,9 @@ class Rma(models.Model):
active_model="stock.picking",
)
)
if self.location_id:
stock_return_picking_form.location_id = self.location_id
return_wizard = stock_return_picking_form.save()
if self.location_id:
return_wizard.location_id = self.location_id
return_wizard.product_return_moves.filtered(
lambda r: r.move_id != self.move_id
).unlink()
@@ -992,8 +1005,8 @@ class Rma(models.Model):
return_line.update(
{
"quantity": self.product_uom_qty,
# The to_refund field is now True by default, which isn't right in the RMA
# creation context.
# The to_refund field is now True by default, which isn't right in the
# RMA creation context
"to_refund": False,
}
)
@@ -1005,20 +1018,13 @@ class Rma(models.Model):
picking_id = picking_action["res_id"]
picking = self.env["stock.picking"].browse(picking_id)
picking.origin = "{} ({})".format(self.name, picking.origin)
move = picking.move_lines
move = picking.move_ids
move.priority = self.priority
return move
def _create_receptions_from_product(self):
self.ensure_one()
picking_form = Form(
recordp=self.env["stock.picking"].with_context(
default_picking_type_id=self.warehouse_id.rma_in_type_id.id
),
view="stock.view_picking_form",
)
self._prepare_picking(picking_form)
picking = picking_form.save()
picking = self.env["stock.picking"].create(self._prepare_picking_vals())
picking.action_confirm()
picking.action_assign()
picking.message_post_with_view(
@@ -1026,17 +1032,33 @@ class Rma(models.Model):
values={"self": picking, "origin": self},
subtype_id=self.env.ref("mail.mt_note").id,
)
return picking.move_lines
return picking.move_ids
def _prepare_picking(self, picking_form):
picking_form.origin = self.name
picking_form.partner_id = self.partner_shipping_id
picking_form.location_id = self.partner_shipping_id.property_stock_customer
picking_form.location_dest_id = self.location_id
with picking_form.move_ids_without_package.new() as move_form:
move_form.product_id = self.product_id
move_form.product_uom_qty = self.product_uom_qty
move_form.product_uom = self.product_uom
def _prepare_picking_vals(self):
return {
"picking_type_id": self.warehouse_id.rma_in_type_id.id,
"origin": self.name,
"partner_id": self.partner_shipping_id.id,
"location_id": self.partner_shipping_id.property_stock_customer.id,
"location_dest_id": self.location_id.id,
"move_ids": [
(
0,
0,
{
"product_id": self.product_id.id,
# same text as origin move or product text in partner lang
"name": self.move_id.name
or self.product_id.with_context(
lang=self.partner_id.lang or "en_US"
).display_name,
"location_id": self.partner_shipping_id.property_stock_customer.id,
"location_dest_id": self.location_id.id,
"product_uom_qty": self.product_uom_qty,
},
)
],
}
# Extract business methods
def extract_quantity(self, qty, uom):
@@ -1074,7 +1096,7 @@ class Rma(models.Model):
return extracted_rma
# Refund business methods
def _prepare_refund(self, invoice_form, origin):
def _prepare_refund_vals(self, origin=False):
"""Hook method for preparing the refund Form.
This method could be override in order to add new custom field
@@ -1084,11 +1106,16 @@ class Rma(models.Model):
rma.action_refund
"""
self.ensure_one()
invoice_form.partner_id = self.partner_invoice_id
# Avoid set partner default value
invoice_form.invoice_payment_term_id = self.env["account.payment.term"]
return {
"move_type": "out_refund",
"company_id": self.company_id.id,
"partner_id": self.partner_invoice_id.id,
"invoice_payment_term_id": False,
"invoice_origin": origin,
"invoice_line_ids": [],
}
def _prepare_refund_line(self, line_form):
def _prepare_refund_line_vals(self):
"""Hook method for preparing a refund line Form.
This method could be override in order to add new custom field
@@ -1098,31 +1125,13 @@ class Rma(models.Model):
rma.action_refund
"""
self.ensure_one()
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 {}
return {
"product_id": self.product_id.id,
"quantity": self.product_uom_qty,
"product_uom_id": self.product_uom.id,
"price_unit": self.product_id.lst_price,
"rma_id": self.id,
}
# Returning business methods
def create_return(self, scheduled_date, qty=None, uom=None):
@@ -1148,32 +1157,13 @@ class Rma(models.Model):
grouped_rmas = rmas_to_return
for rmas in grouped_rmas:
origin = ", ".join(rmas.mapped("name"))
rma_out_type = rmas[0].warehouse_id.rma_out_type_id
picking_form = Form(
recordp=self.env["stock.picking"].with_context(
default_picking_type_id=rma_out_type.id
),
view="stock.view_picking_form",
)
rmas[0]._prepare_returning_picking(picking_form, origin)
picking = picking_form.save()
picking_vals = rmas[0]._prepare_returning_picking_vals(origin)
for rma in rmas:
with picking_form.move_ids_without_package.new() as move_form:
rma._prepare_returning_move(move_form, scheduled_date, qty, uom)
# rma_id is not present in the form view, so we need to get
# the 'values to save' to add the rma id and use the
# create method intead of save the form.
picking_vals = picking_form._values_to_save(all_fields=True)
move_vals = picking_vals["move_ids_without_package"][-1][2]
move_vals.update(
picking_id=picking.id,
rma_id=rma.id,
move_orig_ids=[(4, rma.reception_move_id.id)],
company_id=picking.company_id.id,
picking_vals["move_ids"].append(
(0, 0, rma._prepare_returning_move_vals(scheduled_date, qty, uom))
)
if "product_qty" in move_vals:
move_vals.pop("product_qty")
self.env["stock.move"].sudo().create(move_vals)
picking = self.env["stock.picking"].create(picking_vals)
for rma in rmas:
rma.message_post(
body=_(
'Return: <a href="#" data-oe-model="stock.picking" '
@@ -1190,18 +1180,34 @@ class Rma(models.Model):
)
rmas_to_return.write({"state": "waiting_return"})
def _prepare_returning_picking(self, picking_form, origin=None):
picking_form.picking_type_id = self.warehouse_id.rma_out_type_id
picking_form.origin = origin or self.name
picking_form.partner_id = self.partner_shipping_id
def _prepare_returning_picking_vals(self, origin=None):
self.ensure_one()
return {
"picking_type_id": self.warehouse_id.rma_out_type_id.id,
"location_id": self.location_id.id,
"location_dest_id": self.reception_move_id.location_id.id,
"origin": origin or self.name,
"partner_id": self.partner_shipping_id.id,
"company_id": self.company_id.id,
"move_ids": [],
}
def _prepare_returning_move(
self, move_form, scheduled_date, quantity=None, uom=None
):
move_form.product_id = self.product_id
move_form.product_uom_qty = quantity or self.product_uom_qty
move_form.product_uom = uom or self.product_uom
move_form.date = scheduled_date
def _prepare_returning_move_vals(self, scheduled_date, quantity=None, uom=None):
self.ensure_one()
return {
"product_id": self.product_id.id,
"name": self.product_id.with_context(
lang=self.partner_shipping_id.lang or "en_US"
).display_name,
"product_uom_qty": quantity or self.product_uom_qty,
"product_uom": uom and uom.id or self.product_uom.id,
"location_id": self.location_id.id,
"location_dest_id": self.reception_move_id.location_id.id,
"date": scheduled_date,
"rma_id": self.id,
"move_orig_ids": [(4, self.reception_move_id.id)],
"company_id": self.company_id.id,
}
# Replacing business methods
def create_replace(self, scheduled_date, warehouse, product, qty, uom):

View File

@@ -14,23 +14,24 @@ class StockPicking(models.Model):
def _compute_rma_count(self):
for rec in self:
rec.rma_count = len(rec.move_lines.mapped("rma_ids"))
rec.rma_count = len(rec.move_ids.mapped("rma_ids"))
def copy(self, default=None):
self.ensure_one()
if self.env.context.get("set_rma_picking_type"):
location_dest_id = default["location_dest_id"]
warehouse = self.env["stock.warehouse"].search(
[("rma_loc_id", "parent_of", location_dest_id)], limit=1
)
if warehouse:
default["picking_type_id"] = warehouse.rma_in_type_id.id
location_dest_id = default.get("location_dest_id")
if location_dest_id:
warehouse = self.env["stock.warehouse"].search(
[("rma_loc_id", "parent_of", location_dest_id)], limit=1
)
if warehouse:
default["picking_type_id"] = warehouse.rma_in_type_id.id
return super().copy(default)
def action_view_rma(self):
self.ensure_one()
action = self.sudo().env.ref("rma.rma_action").read()[0]
rma = self.move_lines.mapped("rma_ids")
rma = self.move_ids.mapped("rma_ids")
if len(rma) == 1:
action.update(
res_id=rma.id,

View File

@@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
<title>Return Merchandise Authorization Management</title>
<style type="text/css">
@@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/rma/tree/15.0/rma"><img alt="OCA/rma" src="https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/rma-15-0/rma-15-0-rma"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/145/15.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/rma/tree/16.0/rma"><img alt="OCA/rma" src="https://img.shields.io/badge/github-OCA%2Frma-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/rma-16-0/rma-16-0-rma"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runboat.odoo-community.org/webui/builds.html?repo=OCA/rma&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows you to manage <a class="reference external" href="https://en.wikipedia.org/wiki/Return_merchandise_authorization">Return Merchandise Authorization (RMA)</a>.
RMA documents can be created from scratch, from a delivery order or from
an incoming email. Product receptions and returning delivery operations
@@ -494,7 +494,7 @@ the product of that move is.</li>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/rma/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/rma/issues/new?body=module:%20rma%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/rma/issues/new?body=module:%20rma%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
@@ -528,7 +528,7 @@ mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/ernestotejeda"><img alt="ernestotejeda" src="https://github.com/ernestotejeda.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/rma/tree/15.0/rma">OCA/rma</a> project on GitHub.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/rma/tree/16.0/rma">OCA/rma</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>

View File

@@ -9,6 +9,16 @@ class TestRma(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(
context=dict(
cls.env.context,
mail_create_nolog=True,
mail_create_nosubscribe=True,
mail_notrack=True,
no_reset_password=True,
tracking_disable=True,
)
)
cls.user_rma = new_test_user(
cls.env,
login="user_rma",
@@ -24,18 +34,11 @@ class TestRma(TransactionCase):
cls.product = cls.product_product.create(
{"name": "Product test 1", "type": "product"}
)
account_type = cls.env["account.account.type"].create(
{
"name": "RCV type",
"type": "receivable",
"internal_group": "income",
}
)
cls.account_receiv = cls.env["account.account"].create(
{
"name": "Receivable",
"code": "RCV00",
"user_type_id": account_type.id,
"account_type": "asset_receivable",
"reconcile": True,
}
)
@@ -73,16 +76,16 @@ class TestRma(TransactionCase):
cls.env.company.rma_return_grouping = True
def _create_rma(self, partner=None, product=None, qty=None, location=None):
rma_form = Form(self.env["rma"])
vals = {}
if partner:
rma_form.partner_id = partner
vals["partner_id"] = partner.id
if product:
rma_form.product_id = product
vals["product_id"] = product.id
if qty:
rma_form.product_uom_qty = qty
vals["product_uom_qty"] = qty
if location:
rma_form.location_id = location
return rma_form.save()
vals["location_id"] = location.id
return self.env["rma"].create(vals)
def _create_confirm_receive(
self, partner=None, product=None, qty=None, location=None
@@ -93,25 +96,6 @@ class TestRma(TransactionCase):
rma.reception_move_id.picking_id._action_done()
return rma
def _test_readonly_fields(self, rma):
with Form(rma) as rma_form:
with self.assertRaises(AssertionError):
rma_form.partner_id = self.env["res.partner"]
with self.assertRaises(AssertionError):
rma_form.partner_invoice_id = self.env["res.partner"]
with self.assertRaises(AssertionError):
rma_form.picking_id = self.env["stock.picking"]
with self.assertRaises(AssertionError):
rma_form.move_id = self.env["stock.move"]
with self.assertRaises(AssertionError):
rma_form.product_id = self.env["product.product"]
with self.assertRaises(AssertionError):
rma_form.product_uom_qty = 0
with self.assertRaises(AssertionError):
rma_form.product_uom = self.env["uom.uom"]
with self.assertRaises(AssertionError):
rma_form.location_id = self.env["stock.location"]
def _create_delivery(self):
picking_type = self.env["stock.picking.type"].search(
[
@@ -139,18 +123,18 @@ class TestRma(TransactionCase):
move.product_uom_qty = 20
picking = picking_form.save()
picking.action_confirm()
for move in picking.move_lines:
for move in picking.move_ids:
move.quantity_done = move.product_uom_qty
picking.button_validate()
return picking
class TestRmaCase(TestRma):
def test_onchange(self):
rma_form = Form(self.env["rma"])
def test_computed(self):
# If partner changes, the invoice address is set
rma_form.partner_id = self.partner
self.assertEqual(rma_form.partner_invoice_id, self.partner_invoice)
rma = self.env["rma"].new()
rma.partner_id = self.partner
self.assertEqual(rma.partner_invoice_id, self.partner_invoice)
# If origin move changes, the product is set
uom_ten = self.env["uom.uom"].create(
{
@@ -182,21 +166,17 @@ class TestRmaCase(TestRma):
with picking_form.move_ids_without_package.new() as move:
move.product_id = product_2
move.product_uom_qty = 15
move.product_uom = uom_ten
picking = picking_form.save()
picking._action_done()
rma_form.picking_id = picking
rma_form.move_id = picking.move_lines
self.assertEqual(rma_form.product_id, product_2)
self.assertEqual(rma_form.product_uom_qty, 15)
self.assertEqual(rma_form.product_uom, uom_ten)
rma.picking_id = picking
rma.move_id = picking.move_ids
self.assertEqual(rma.product_id, product_2)
self.assertEqual(rma.product_uom_qty, 15)
self.assertEqual(rma.product_uom, uom_ten)
# If product changes, unit of measure changes
rma_form.picking_id = self.env["stock.picking"]
rma_form.product_id = self.product
self.assertEqual(rma_form.product_id, self.product)
self.assertEqual(rma_form.product_uom_qty, 15)
self.assertNotEqual(rma_form.product_uom, uom_ten)
self.assertEqual(rma_form.product_uom, self.product.uom_id)
rma.move_id = False
rma.product_id = self.product
self.assertEqual(rma.product_uom, self.product.uom_id)
def test_ensure_required_fields_on_confirm(self):
rma = self._create_rma()
@@ -204,17 +184,14 @@ class TestRmaCase(TestRma):
rma.action_confirm()
self.assertEqual(
e.exception.args[0],
"Required field(s):\nCustomer\nShipping Address\nInvoice Address\n"
"Product\nLocation",
"Required field(s):\nCustomer\nShipping Address\nInvoice Address\nProduct",
)
with Form(rma) as rma_form:
rma_form.partner_id = self.partner
rma.partner_id = self.partner.id
with self.assertRaises(ValidationError) as e:
rma.action_confirm()
self.assertEqual(e.exception.args[0], "Required field(s):\nProduct\nLocation")
with Form(rma) as rma_form:
rma_form.product_id = self.product
rma_form.location_id = self.rma_loc
self.assertEqual(e.exception.args[0], "Required field(s):\nProduct")
rma.product_id = self.product.id
rma.location_id = self.rma_loc.id
rma.action_confirm()
self.assertEqual(rma.state, "confirmed")
@@ -226,7 +203,6 @@ class TestRmaCase(TestRma):
self.assertEqual(rma.reception_move_id.product_uom_qty, 10)
self.assertEqual(rma.reception_move_id.product_uom, rma.product_uom)
self.assertEqual(rma.state, "confirmed")
self._test_readonly_fields(rma)
rma.reception_move_id.quantity_done = 9
with self.assertRaises(ValidationError):
rma.reception_move_id.picking_id._action_done()
@@ -235,14 +211,12 @@ class TestRmaCase(TestRma):
self.assertEqual(rma.reception_move_id.picking_id.state, "done")
self.assertEqual(rma.reception_move_id.quantity_done, 10)
self.assertEqual(rma.state, "received")
self._test_readonly_fields(rma)
def test_cancel(self):
# cancel a draft RMA
rma = self._create_rma(self.partner, self.product)
rma.action_cancel()
self.assertEqual(rma.state, "cancelled")
self._test_readonly_fields(rma)
# cancel a confirmed RMA
rma = self._create_rma(self.partner, self.product, 10, self.rma_loc)
rma.action_confirm()
@@ -304,7 +278,6 @@ class TestRmaCase(TestRma):
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
self._test_readonly_fields(rma)
def test_mass_refund(self):
# Create, confirm and receive rma_1
@@ -403,7 +376,7 @@ class TestRmaCase(TestRma):
delivery_form.product_uom_qty = 2
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
self.assertEqual(len(rma.delivery_move_ids.picking_id.move_lines), 1)
self.assertEqual(len(rma.delivery_move_ids.picking_id.move_ids), 1)
self.assertEqual(rma.delivery_move_ids.product_id, product_2)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 2)
self.assertTrue(rma.delivery_move_ids.picking_id.state, "waiting")
@@ -459,7 +432,6 @@ class TestRmaCase(TestRma):
# Despite being in 'replaced' state,
# RMAs can still perform replacements.
self.assertTrue(rma.can_be_replaced)
self._test_readonly_fields(rma)
def test_return_to_customer(self):
# Create, confirm and receive an RMA
@@ -475,7 +447,7 @@ class TestRmaCase(TestRma):
delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver()
picking = rma.delivery_move_ids.picking_id
self.assertEqual(len(picking.move_lines), 1)
self.assertEqual(len(picking.move_ids), 1)
self.assertEqual(rma.delivery_move_ids.product_id, self.product)
self.assertEqual(rma.delivery_move_ids.product_uom_qty, 2)
self.assertTrue(picking.state, "waiting")
@@ -527,7 +499,6 @@ class TestRmaCase(TestRma):
self.assertFalse(rma.can_be_refunded)
self.assertFalse(rma.can_be_returned)
self.assertFalse(rma.can_be_replaced)
self._test_readonly_fields(rma)
def test_finish_rma(self):
# Create, confirm and receive an RMA
@@ -590,19 +561,19 @@ class TestRmaCase(TestRma):
self.assertEqual(pick_2.partner_id, rma_4.partner_id)
# Each RMA of (rma_1, rma_2 and rma_3) is linked to a different
# line of picking_1
self.assertEqual(len(pick_1.move_lines), 3)
self.assertEqual(len(pick_1.move_ids), 3)
self.assertEqual(
pick_1.move_lines.mapped("rma_id"),
pick_1.move_ids.mapped("rma_id"),
(rma_1 | rma_2 | rma_3),
)
self.assertEqual(
(rma_1 | rma_2 | rma_3).mapped("delivery_move_ids"),
pick_1.move_lines,
pick_1.move_ids,
)
# rma_4 is linked with the unique move of pick_2
self.assertEqual(len(pick_2.move_lines), 1)
self.assertEqual(pick_2.move_lines.rma_id, rma_4)
self.assertEqual(rma_4.delivery_move_ids, pick_2.move_lines)
self.assertEqual(len(pick_2.move_ids), 1)
self.assertEqual(pick_2.move_ids.rma_id, rma_4)
self.assertEqual(rma_4.delivery_move_ids, pick_2.move_ids)
# Assert product and quantities are propagated correctly
for rma in all_rmas:
self.assertEqual(rma.product_id, rma.delivery_move_ids.product_id)
@@ -660,14 +631,14 @@ class TestRmaCase(TestRma):
return_wizard = stock_return_picking_form.save()
picking_action = return_wizard.create_returns()
# Each origin move is linked to a different RMA
origin_moves = origin_delivery.move_lines
origin_moves = origin_delivery.move_ids
self.assertTrue(origin_moves[0].rma_ids)
self.assertTrue(origin_moves[1].rma_ids)
rmas = origin_moves.mapped("rma_ids")
self.assertEqual(rmas.mapped("state"), ["confirmed"] * 2)
# Each reception move is linked one of the generated RMAs
reception = self.env["stock.picking"].browse(picking_action["res_id"])
reception_moves = reception.move_lines
reception_moves = reception.move_ids
self.assertTrue(reception_moves[0].rma_receiver_ids)
self.assertTrue(reception_moves[1].rma_receiver_ids)
self.assertEqual(reception_moves.mapped("rma_receiver_ids"), rmas)
@@ -682,7 +653,7 @@ class TestRmaCase(TestRma):
rma_form = Form(self.env["rma"])
rma_form.partner_id = self.partner
rma_form.picking_id = origin_delivery
rma_form.move_id = origin_delivery.move_lines.filtered(
rma_form.move_id = origin_delivery.move_ids.filtered(
lambda r: r.product_id == self.product
)
rma = rma_form.save()

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
Copyright 2023 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_partner_form" model="ir.ui.view">
<field name="name">res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="groups_id" eval="[(4, ref('rma.rma_group_user_own'))]" />
<field name="arch" type="xml">
<div name="button_box">
<button
@@ -15,6 +15,7 @@
class="oe_stat_button"
icon="fa-reply"
attrs="{'invisible': [('rma_count', '=', 0)]}"
groups="rma.rma_group_user_own"
>
<field name="rma_count" widget="statinfo" string="RMA" />
</button>

View File

@@ -33,6 +33,7 @@
<group>
<field name="name" />
<field name="company_id" groups="base.group_multi_company" />
<field name="company_id" invisible="1" />
<field name="active" invisible="1" />
</group>
</sheet>
@@ -47,6 +48,7 @@
<tree>
<field name="name" />
<field name="company_id" groups="base.group_multi_company" />
<field name="company_id" invisible="1" />
</tree>
</field>
</record>

View File

@@ -10,6 +10,7 @@
<field name="name" />
<field name="user_id" />
<field name="company_id" groups="base.group_multi_company" />
<field name="company_id" invisible="1" />
</tree>
</field>
</record>
@@ -33,6 +34,7 @@
options="{'no_create': True}"
groups="base.group_multi_company"
/>
<field name="company_id" invisible="1" />
</group>
</group>
<notebook>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
Copyright 2023 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="rma_view_search" model="ir.ui.view">
@@ -239,10 +240,19 @@
name="partner_id"
widget="res_partner_many2one"
context="{'search_default_customer':1, 'show_address': 1, 'show_vat': True}"
attrs="{'readonly': [('state', '!=', 'draft')]}"
options="{'always_reload': True}"
/>
<field name="partner_shipping_id" />
<field name="partner_invoice_id" />
<field
name="partner_shipping_id"
attrs="{'readonly': [('state', '!=', 'draft')]}"
force_save="1"
/>
<field
name="partner_invoice_id"
attrs="{'readonly': [('state', 'not in', ['draft', 'confirmed', 'received'])]}"
force_save="1"
/>
<field name="picking_id" options="{'no_create': True}" />
<field
name="move_id"
@@ -258,12 +268,19 @@
<field name="uom_category_id" invisible="1" />
<label for="product_uom_qty" />
<div class="o_row">
<field name="product_uom_qty" />
<field
name="product_uom_qty"
attrs="{'readonly': [('state', '!=', 'draft')]}"
force_save="1"
/>
<field
name="product_uom"
groups="uom.group_uom"
domain="[('category_id', '=', uom_category_id)]"
attrs="{'readonly': [('state', '!=', 'draft')]}"
force_save="1"
/>
<field name="product_uom" invisible="1" />
</div>
<field
name="delivered_qty"
@@ -291,6 +308,7 @@
options="{'no_create': True}"
groups="base.group_multi_company"
/>
<field name="company_id" invisible="1" />
</group>
</group>
<notebook>
@@ -302,7 +320,9 @@
name="location_id"
options="{'no_create': True, 'no_open': True}"
groups="stock.group_stock_multi_locations"
attrs="{'readonly': [('state', '!=', 'draft')]}"
/>
<field name="location_id" invisible="1" />
</group>
<group>
<field name="deadline" />
@@ -341,10 +361,6 @@
<record id="rma_finalization_form" model="ir.ui.view">
<field name="model">rma</field>
<field name="inherit_id" ref="rma.rma_view_form" />
<field
name="groups_id"
eval="[(4, ref('rma.group_rma_manual_finalization'))]"
/>
<field name="arch" type="xml">
<xpath
expr="//form//header//button[@name='action_cancel']"
@@ -356,6 +372,7 @@
name="action_finish"
class="btn-primary"
attrs="{'invisible': [('can_be_finished', '=', False)]}"
groups="rma.group_rma_manual_finalization"
/>
</xpath>
</field>

View File

@@ -6,7 +6,6 @@
<field name="name">stock.picking.form</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form" />
<field name="groups_id" eval="[(4, ref('rma.rma_group_user_own'))]" />
<field name="arch" type="xml">
<div name="button_box">
<button
@@ -15,6 +14,7 @@
class="oe_stat_button"
icon="fa-reply"
attrs="{'invisible': [('rma_count', '=', 0)]}"
groups="rma.rma_group_user_own"
>
<field name="rma_count" widget="statinfo" string="RMA" />
</button>

View File

@@ -4,14 +4,13 @@
<field name="name">Stock Warehouse Inherit MRP</field>
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="stock.view_warehouse" />
<field name="groups_id" eval="[(4, ref('rma.rma_group_user_own'))]" />
<field name="arch" type="xml">
<xpath expr="//field[@name='wh_output_stock_loc_id']/..">
<field name="rma_loc_id" />
<field name="rma_loc_id" groups="rma.rma_group_user_own" />
</xpath>
<xpath expr="//field[@name='out_type_id']/..">
<field name="rma_in_type_id" />
<field name="rma_out_type_id" />
<field name="rma_in_type_id" groups="rma.rma_group_user_own" />
<field name="rma_out_type_id" groups="rma.rma_group_user_own" />
</xpath>
</field>
</record>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
Copyright 2023 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="rma_redelivery_wizard_view_form" model="ir.ui.view">
@@ -43,6 +44,7 @@
attrs="{'required': [('rma_count', '=', 1)]}"
domain="[('category_id', '=', uom_category_id)]"
/>
<field name="product_uom" invisible="1" />
</div>
</group>
</group>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
Copyright 2023 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="rma_split_wizard_view_form2" model="ir.ui.view">
@@ -13,6 +14,7 @@
<div class="o_row">
<field name="product_uom_qty" />
<field name="product_uom" groups="uom.group_uom" />
<field name="product_uom" invisible="1" />
</div>
</group>
</group>

View File

@@ -10,39 +10,43 @@ class ReturnPicking(models.TransientModel):
create_rma = fields.Boolean(string="Create RMAs")
picking_type_code = fields.Selection(related="picking_id.picking_type_id.code")
rma_location_ids = fields.Many2many(
comodel_name="stock.location", compute="_compute_rma_location_id"
)
# Expand domain for RMAs
location_id = fields.Many2one(
domain="create_rma and [('id', 'child_of', rma_location_ids)]"
"or "
"['|', ('id', '=', original_location_id), '|', '&', "
"('return_location', '=', True), ('company_id', '=', False), '&', "
"('return_location', '=', True), ('company_id', '=', company_id)]"
)
@api.depends("picking_id")
def _compute_rma_location_id(self):
for record in self:
record.rma_location_ids = (
self.env["stock.warehouse"]
.search([("company_id", "=", record.picking_id.company_id.id)])
.rma_loc_id
)
@api.onchange("create_rma")
def _onchange_create_rma(self):
if self.create_rma:
warehouse = self.picking_id.picking_type_id.warehouse_id
self.location_id = warehouse.rma_loc_id.id
rma_loc = warehouse.search(
[("company_id", "=", self.picking_id.company_id.id)]
).mapped("rma_loc_id")
rma_loc_domain = [("id", "child_of", rma_loc.ids)]
# We want to avoid setting the return move `to_refund` as it will change
# the delivered quantities in the sale and set them to invoice.
self.product_return_moves.to_refund = False
else:
# If self.create_rma is not True, the value of the location and
# the location domain will be the same as assigned by default.
# If self.create_rma is not True, the value of the location will be the
# same as assigned by default
location_id = self.picking_id.location_id.id
return_picking_type = self.picking_id.picking_type_id.return_picking_type_id
if return_picking_type.default_location_dest_id.return_location:
location_id = return_picking_type.default_location_dest_id.id
self.location_id = location_id
rma_loc_domain = [
"|",
("id", "=", self.picking_id.location_id.id),
"|",
"&",
("return_location", "=", True),
("company_id", "=", False),
"&",
("return_location", "=", True),
("company_id", "=", self.picking_id.company_id.id),
]
return {"domain": {"location_id": rma_loc_domain}}
def create_returns(self):
"""Override create_returns method for creating one or more
@@ -67,7 +71,7 @@ class ReturnPicking(models.TransientModel):
returned_picking = self.env["stock.picking"].browse(res["res_id"])
vals_list = [
move._prepare_return_rma_vals(self.picking_id)
for move in returned_picking.move_lines
for move in returned_picking.move_ids
]
self.env["rma"].create(vals_list)
return res

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Tecnativa - Ernesto Tejeda
Copyright 2023 Tecnativa - Pedro M. Baeza
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_stock_return_picking_form" model="ir.ui.view">
@@ -7,19 +8,17 @@
<field name="model">stock.return.picking</field>
<field name="inherit_id" ref="stock.view_stock_return_picking_form" />
<field name="arch" type="xml">
<xpath
expr="//group[.//field[@name='product_return_moves']]"
position="before"
>
<field name="product_return_moves" position="after">
<group name="group_rma">
<field
name="create_rma"
attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}"
/>
<field name="rma_location_ids" invisible="1" />
<field name="picking_id" invisible="1" />
<field name="picking_type_code" invisible="1" />
</group>
</xpath>
</field>
</field>
</record>
</odoo>