[MIG] rma: Migration to 17.0

This commit is contained in:
Antoni Marroig Campomar
2024-05-08 17:05:54 +02:00
parent c22fa4e98a
commit 9cc5bca153
18 changed files with 229 additions and 358 deletions

View File

@@ -87,8 +87,8 @@ To use this module, you need to:
quantity to another RMA, preview the RMA in the website. All of these quantity to another RMA, preview the RMA in the website. All of these
operations can be done by clicking on the buttons in the status bar. operations can be done by clicking on the buttons in the status bar.
- If you click on 'Refund' button, a refund will be created, and it - If you click on 'To Refund' button, a refund will be created, and
will be accessible via the smart button labeled Refund. The RMA it will be accessible via the smart button labeled Refund. The RMA
will be set automatically to 'Refunded' state when the refund is will be set automatically to 'Refunded' state when the refund is
validated. validated.
- If you click on 'Replace' or 'Return to customer' button instead, - If you click on 'Replace' or 'Return to customer' button instead,
@@ -171,6 +171,9 @@ Contributors
- Chafique Delli <chafique.delli@akretion.com> - Chafique Delli <chafique.delli@akretion.com>
- Giovanni Serra - Ooops <giovanni@ooops404.com> - Giovanni Serra - Ooops <giovanni@ooops404.com>
- `APSL-Nagarro <https://www.apsl.tech>`__:
- Antoni Marroig <amarroig@apsl.net>
Maintainers Maintainers
----------- -----------

View File

@@ -5,7 +5,7 @@
{ {
"name": "Return Merchandise Authorization Management", "name": "Return Merchandise Authorization Management",
"summary": "Return Merchandise Authorization (RMA)", "summary": "Return Merchandise Authorization (RMA)",
"version": "16.0.1.2.0", "version": "17.0.1.0.0",
"development_status": "Production/Stable", "development_status": "Production/Stable",
"category": "RMA", "category": "RMA",
"website": "https://github.com/OCA/rma", "website": "https://github.com/OCA/rma",

View File

@@ -41,8 +41,7 @@
<field <field
name="subject" name="subject"
>{{object.company_id.name}} RMA (Ref {{object.name or 'n/a' }})</field> >{{object.company_id.name}} RMA (Ref {{object.name or 'n/a' }})</field>
<field name="report_template" ref="report_rma_action" /> <field name="report_template_ids" eval="[(4, ref('rma.report_rma_action'))]" />
<field name="report_name">{{(object.name or '')}}</field>
<field name="lang">{{object.partner_id.lang}}</field> <field name="lang">{{object.partner_id.lang}}</field>
<field name="auto_delete" eval="True" /> <field name="auto_delete" eval="True" />
<field name="body_html" type="html"> <field name="body_html" type="html">
@@ -78,8 +77,7 @@
<field <field
name="subject" name="subject"
>{{object.company_id.name}} RMA (Ref {{object.name or 'n/a' }}) products received</field> >{{object.company_id.name}} RMA (Ref {{object.name or 'n/a' }}) products received</field>
<field name="report_template" ref="report_rma_action" /> <field name="report_template_ids" eval="[(4, ref('rma.report_rma_action'))]" />
<field name="report_name">{{(object.name or '')}}</field>
<field name="lang">{{object.partner_id.lang}}</field> <field name="lang">{{object.partner_id.lang}}</field>
<field name="auto_delete" eval="True" /> <field name="auto_delete" eval="True" />
<field name="body_html" type="html"> <field name="body_html" type="html">
@@ -114,8 +112,7 @@
<field <field
name="subject" name="subject"
>{{object.company_id.name}} Your RMA has been succesfully created (Ref {{object.name or 'n/a' }})</field> >{{object.company_id.name}} Your RMA has been succesfully created (Ref {{object.name or 'n/a' }})</field>
<field name="report_template" ref="report_rma_action" /> <field name="report_template_ids" eval="[(4, ref('rma.report_rma_action'))]" />
<field name="report_name">{{(object.name or '')}}</field>
<field name="lang">{{object.partner_id.lang}}</field> <field name="lang">{{object.partner_id.lang}}</field>
<field name="auto_delete" eval="True" /> <field name="auto_delete" eval="True" />
<field name="body_html" type="html"> <field name="body_html" type="html">

View File

@@ -1,12 +1,8 @@
# Copyright 2020 Tecnativa - Ernesto Tejeda # Copyright 2020 Tecnativa - Ernesto Tejeda
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import SUPERUSER_ID, api
def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
def post_init_hook(env):
def _get_next_picking_type_color(): def _get_next_picking_type_color():
"""Choose the next available color for the operation types.""" """Choose the next available color for the operation types."""
stock_picking_type = env["stock.picking.type"] stock_picking_type = env["stock.picking.type"]

View File

@@ -35,60 +35,37 @@ class Rma(models.Model):
sent = fields.Boolean() sent = fields.Boolean()
name = fields.Char( name = fields.Char(
index=True, index=True,
readonly=True,
states={"draft": [("readonly", False)]},
copy=False, copy=False,
default=lambda self: _("New"), default=lambda self: _("New"),
) )
origin = fields.Char( origin = fields.Char(
string="Source Document", string="Source Document",
states={
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
help="Reference of the document that generated this RMA.", help="Reference of the document that generated this RMA.",
) )
date = fields.Datetime( date = fields.Datetime(
default=fields.Datetime.now, default=fields.Datetime.now,
index=True, index=True,
required=True, required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
deadline = fields.Date(
states={
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
) )
deadline = fields.Date()
user_id = fields.Many2one( user_id = fields.Many2one(
comodel_name="res.users", comodel_name="res.users",
string="Responsible", string="Responsible",
index=True, index=True,
tracking=True, tracking=True,
states={
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
) )
team_id = fields.Many2one( team_id = fields.Many2one(
comodel_name="rma.team", comodel_name="rma.team",
string="RMA team", string="RMA team",
index=True, index=True,
states={
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
compute="_compute_team_id", compute="_compute_team_id",
store=True, store=True,
readonly=False,
) )
tag_ids = fields.Many2many(comodel_name="rma.tag", string="Tags") tag_ids = fields.Many2many(comodel_name="rma.tag", string="Tags")
finalization_id = fields.Many2one( finalization_id = fields.Many2one(
string="Finalization Reason", string="Finalization Reason",
comodel_name="rma.finalization", comodel_name="rma.finalization",
copy=False, copy=False,
readonly=True,
domain=( domain=(
"['|', ('company_id', '=', False), ('company_id', '='," " company_id)]" "['|', ('company_id', '=', False), ('company_id', '='," " company_id)]"
), ),
@@ -97,16 +74,10 @@ class Rma(models.Model):
company_id = fields.Many2one( company_id = fields.Many2one(
comodel_name="res.company", comodel_name="res.company",
default=lambda self: self.env.company, default=lambda self: self.env.company,
states={
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
) )
partner_id = fields.Many2one( partner_id = fields.Many2one(
string="Customer", string="Customer",
comodel_name="res.partner", comodel_name="res.partner",
readonly=True,
states={"draft": [("readonly", False)]},
index=True, index=True,
tracking=True, tracking=True,
) )
@@ -143,8 +114,6 @@ class Rma(models.Model):
" ('partner_id', 'child_of', commercial_partner_id)," " ('partner_id', 'child_of', commercial_partner_id),"
"]" "]"
), ),
readonly=True,
states={"draft": [("readonly", False)]},
) )
move_id = fields.Many2one( move_id = fields.Many2one(
comodel_name="stock.move", comodel_name="stock.move",
@@ -187,18 +156,10 @@ class Rma(models.Model):
procurement_group_id = fields.Many2one( procurement_group_id = fields.Many2one(
comodel_name="procurement.group", comodel_name="procurement.group",
string="Procurement group", string="Procurement group",
readonly=True,
states={
"draft": [("readonly", False)],
"confirmed": [("readonly", False)],
"received": [("readonly", False)],
},
) )
priority = fields.Selection( priority = fields.Selection(
selection=PROCUREMENT_PRIORITIES, selection=PROCUREMENT_PRIORITIES,
default="1", default="1",
readonly=True,
states={"draft": [("readonly", False)]},
) )
operation_id = fields.Many2one( operation_id = fields.Many2one(
comodel_name="rma.operation", comodel_name="rma.operation",
@@ -222,12 +183,7 @@ class Rma(models.Model):
copy=False, copy=False,
tracking=True, tracking=True,
) )
description = fields.Html( description = fields.Html()
states={
"locked": [("readonly", True)],
"cancelled": [("readonly", True)],
},
)
# Reception fields # Reception fields
location_id = fields.Many2one( location_id = fields.Many2one(
comodel_name="stock.location", comodel_name="stock.location",
@@ -249,12 +205,10 @@ class Rma(models.Model):
# Refund fields # Refund fields
refund_id = fields.Many2one( refund_id = fields.Many2one(
comodel_name="account.move", comodel_name="account.move",
readonly=True,
copy=False, copy=False,
) )
refund_line_id = fields.Many2one( refund_line_id = fields.Many2one(
comodel_name="account.move.line", comodel_name="account.move.line",
readonly=True,
copy=False, copy=False,
) )
can_be_refunded = fields.Boolean(compute="_compute_can_be_refunded") can_be_refunded = fields.Boolean(compute="_compute_can_be_refunded")
@@ -263,7 +217,6 @@ class Rma(models.Model):
comodel_name="stock.move", comodel_name="stock.move",
inverse_name="rma_id", inverse_name="rma_id",
string="Delivery reservation", string="Delivery reservation",
readonly=True,
copy=False, copy=False,
) )
delivery_picking_count = fields.Integer( delivery_picking_count = fields.Integer(
@@ -275,11 +228,6 @@ class Rma(models.Model):
compute="_compute_delivered_qty", compute="_compute_delivered_qty",
store=True, store=True,
) )
delivered_qty_done = fields.Float(
digits="Product Unit of Measure",
compute="_compute_delivered_qty",
compute_sudo=True,
)
can_be_returned = fields.Boolean( can_be_returned = fields.Boolean(
compute="_compute_can_be_returned", compute="_compute_can_be_returned",
) )
@@ -297,11 +245,6 @@ class Rma(models.Model):
digits="Product Unit of Measure", digits="Product Unit of Measure",
compute="_compute_remaining_qty", compute="_compute_remaining_qty",
) )
remaining_qty_to_done = fields.Float(
string="Remaining delivered qty to done",
digits="Product Unit of Measure",
compute="_compute_remaining_qty",
)
uom_category_id = fields.Many2one( uom_category_id = fields.Many2one(
related="product_id.uom_id.category_id", string="Category UoM" related="product_id.uom_id.category_id", string="Category UoM"
) )
@@ -312,7 +255,6 @@ class Rma(models.Model):
origin_split_rma_id = fields.Many2one( origin_split_rma_id = fields.Many2one(
comodel_name="rma", comodel_name="rma",
string="Extracted from", string="Extracted from",
readonly=True,
copy=False, copy=False,
) )
@@ -335,8 +277,7 @@ class Rma(models.Model):
"delivery_move_ids.state", "delivery_move_ids.state",
"delivery_move_ids.scrapped", "delivery_move_ids.scrapped",
"delivery_move_ids.product_uom_qty", "delivery_move_ids.product_uom_qty",
"delivery_move_ids.reserved_availability", "delivery_move_ids.quantity",
"delivery_move_ids.quantity_done",
"delivery_move_ids.product_uom", "delivery_move_ids.product_uom",
"product_uom", "product_uom",
) )
@@ -355,29 +296,21 @@ class Rma(models.Model):
""" """
for record in self: for record in self:
delivered_qty = 0.0 delivered_qty = 0.0
delivered_qty_done = 0.0
for move in record.delivery_move_ids.filtered( for move in record.delivery_move_ids.filtered(
lambda r: r.state != "cancel" and not r.scrapped lambda r: r.state != "cancel" and not r.scrapped
): ):
if move.quantity_done: if move.quantity:
quantity_done = move.product_uom._compute_quantity( quantity = move.product_uom._compute_quantity(
move.quantity_done, record.product_uom move.quantity, record.product_uom
)
if move.state == "done":
delivered_qty_done += quantity_done
delivered_qty += quantity_done
elif move.reserved_availability:
delivered_qty += move.product_uom._compute_quantity(
move.reserved_availability, record.product_uom
) )
delivered_qty += quantity
elif move.product_uom_qty: elif move.product_uom_qty:
delivered_qty += move.product_uom._compute_quantity( delivered_qty += move.product_uom._compute_quantity(
move.product_uom_qty, record.product_uom move.product_uom_qty, record.product_uom
) )
record.delivered_qty = delivered_qty record.delivered_qty = delivered_qty
record.delivered_qty_done = delivered_qty_done
@api.depends("product_uom_qty", "delivered_qty", "delivered_qty_done") @api.depends("product_uom_qty", "delivered_qty")
def _compute_remaining_qty(self): def _compute_remaining_qty(self):
"""Compute 'remaining_qty' and 'remaining_qty_to_done' fields. """Compute 'remaining_qty' and 'remaining_qty_to_done' fields.
@@ -392,7 +325,6 @@ class Rma(models.Model):
""" """
for r in self: for r in self:
r.remaining_qty = r.product_uom_qty - r.delivered_qty r.remaining_qty = r.product_uom_qty - r.delivered_qty
r.remaining_qty_to_done = r.product_uom_qty - r.delivered_qty_done
@api.depends( @api.depends(
"state", "state",
@@ -443,7 +375,7 @@ class Rma(models.Model):
and rma.remaining_qty > 0 and rma.remaining_qty > 0
) )
@api.depends("product_uom_qty", "state", "remaining_qty", "remaining_qty_to_done") @api.depends("product_uom_qty", "state", "remaining_qty")
def _compute_can_be_split(self): def _compute_can_be_split(self):
"""Compute 'can_be_split'. This field controls the """Compute 'can_be_split'. This field controls the
visibility of 'Split' button in the rma form view and visibility of 'Split' button in the rma form view and
@@ -460,10 +392,10 @@ class Rma(models.Model):
else: else:
r.can_be_split = False r.can_be_split = False
@api.depends("remaining_qty_to_done", "state") @api.depends("state")
def _compute_can_be_locked(self): def _compute_can_be_locked(self):
for r in self: for r in self:
r.can_be_locked = r.remaining_qty_to_done > 0 and r.state in [ r.can_be_locked = r.remaining_qty > 0 and r.state in [
"received", "received",
"waiting_return", "waiting_return",
"waiting_replacement", "waiting_replacement",
@@ -612,34 +544,41 @@ class Rma(models.Model):
def _send_draft_email(self): def _send_draft_email(self):
"""Send customer notifications they place the RMA from the portal""" """Send customer notifications they place the RMA from the portal"""
for rma in self.filtered("company_id.send_rma_draft_confirmation"): for rma in self.filtered("company_id.send_rma_draft_confirmation"):
rma_template_id = rma.company_id.rma_mail_draft_confirmation_template_id.id
rma.with_context( rma.with_context(
force_send=True, force_send=True,
mark_rma_as_sent=True, mark_rma_as_sent=True,
default_subtype_id=self.env.ref("rma.mt_rma_notification").id, ).message_post_with_source(
).message_post_with_template(rma_template_id) rma.company_id.rma_mail_draft_confirmation_template_id.get_external_id()[
rma.company_id.rma_mail_draft_confirmation_template_id.id
],
subtype_xmlid="rma.mt_rma_notification",
)
def _send_confirmation_email(self): def _send_confirmation_email(self):
"""Auto send notifications""" """Auto send notifications"""
for rma in self.filtered(lambda p: p.company_id.send_rma_confirmation): for rma in self.filtered(lambda p: p.company_id.send_rma_confirmation):
rma_template_id = rma.company_id.rma_mail_confirmation_template_id.id
rma.with_context( rma.with_context(
force_send=True, force_send=True,
mark_rma_as_sent=True, mark_rma_as_sent=True,
default_subtype_id=self.env.ref("rma.mt_rma_notification").id, ).message_post_with_source(
).message_post_with_template(rma_template_id) rma.company_id.rma_mail_confirmation_template_id.get_external_id()[
rma.company_id.rma_mail_confirmation_template_id.id
],
subtype_xmlid="rma.mt_rma_notification",
)
def _send_receipt_confirmation_email(self): def _send_receipt_confirmation_email(self):
"""Send customer notifications when the products are received""" """Send customer notifications when the products are received"""
for rma in self.filtered("company_id.send_rma_receipt_confirmation"): for rma in self.filtered("company_id.send_rma_receipt_confirmation"):
rma_template_id = (
rma.company_id.rma_mail_receipt_confirmation_template_id.id
)
rma.with_context( rma.with_context(
force_send=True, force_send=True,
mark_rma_as_sent=True, mark_rma_as_sent=True,
default_subtype_id=self.env.ref("rma.mt_rma_notification").id, ).message_post_with_source(
).message_post_with_template(rma_template_id) rma.company_id.rma_mail_receipt_confirmation_template_id.get_external_id()[
rma.company_id.rma_mail_receipt_confirmation_template_id.id
],
subtype_xmlid="rma.mt_rma_notification",
)
# Action methods # Action methods
def action_rma_send(self): def action_rma_send(self):
@@ -682,6 +621,7 @@ class Rma(models.Model):
reception_move = self._create_receptions_from_picking() reception_move = self._create_receptions_from_picking()
else: else:
reception_move = self._create_receptions_from_product() reception_move = self._create_receptions_from_product()
reception_move.picked = True
self.write({"reception_move_id": reception_move.id, "state": "confirmed"}) self.write({"reception_move_id": reception_move.id, "state": "confirmed"})
self._add_message_subscribe_partner() self._add_message_subscribe_partner()
self._send_confirmation_email() self._send_confirmation_email()
@@ -703,10 +643,10 @@ class Rma(models.Model):
(0, 0, rma._prepare_refund_line_vals()) (0, 0, rma._prepare_refund_line_vals())
) )
refund = self.env["account.move"].sudo().create(refund_vals) refund = self.env["account.move"].sudo().create(refund_vals)
refund.with_user(self.env.uid).message_post_with_view( refund.with_user(self.env.uid).message_post_with_source(
"mail.message_origin_link", "mail.message_origin_link",
values={"self": refund, "origin": rmas}, render_values={"self": refund, "origin": rmas},
subtype_id=self.env.ref("mail.mt_note").id, subtype_id=self.env["ir.model.data"]._xmlid_to_res_id("mail.mt_note"),
) )
for line in refund.invoice_line_ids: for line in refund.invoice_line_ids:
line.rma_id.write( line.rma_id.write(
@@ -1027,10 +967,10 @@ class Rma(models.Model):
picking = self.env["stock.picking"].create(self._prepare_picking_vals()) picking = self.env["stock.picking"].create(self._prepare_picking_vals())
picking.action_confirm() picking.action_confirm()
picking.action_assign() picking.action_assign()
picking.message_post_with_view( picking.message_post_with_source(
"mail.message_origin_link", "mail.message_origin_link",
values={"self": picking, "origin": self}, render_values={"self": picking, "origin": self},
subtype_id=self.env.ref("mail.mt_note").id, subtype_id=self.env["ir.model.data"]._xmlid_to_res_id("mail.mt_note"),
) )
return picking.move_ids return picking.move_ids
@@ -1068,7 +1008,7 @@ class Rma(models.Model):
self._ensure_can_be_split() self._ensure_can_be_split()
self._ensure_qty_to_extract(qty, uom) self._ensure_qty_to_extract(qty, uom)
self.product_uom_qty -= uom._compute_quantity(qty, self.product_uom) self.product_uom_qty -= uom._compute_quantity(qty, self.product_uom)
if self.remaining_qty_to_done <= 0: if self.remaining_qty <= 0:
if self.state == "waiting_return": if self.state == "waiting_return":
self.state = "returned" self.state = "returned"
elif self.state == "waiting_replacement": elif self.state == "waiting_replacement":
@@ -1083,10 +1023,10 @@ class Rma(models.Model):
"origin_split_rma_id": self.id, "origin_split_rma_id": self.id,
} }
) )
extracted_rma.message_post_with_view( extracted_rma.message_post_with_source(
"mail.message_origin_link", "mail.message_origin_link",
values={"self": extracted_rma, "origin": self}, render_values={"self": extracted_rma, "origin": self},
subtype_id=self.env.ref("mail.mt_note").id, subtype_id=self.env["ir.model.data"]._xmlid_to_res_id("mail.mt_note"),
) )
self.message_post( self.message_post(
body=_( body=_(
@@ -1175,10 +1115,10 @@ class Rma(models.Model):
) )
picking.action_confirm() picking.action_confirm()
picking.action_assign() picking.action_assign()
picking.message_post_with_view( picking.message_post_with_source(
"mail.message_origin_link", "mail.message_origin_link",
values={"self": picking, "origin": rmas}, render_values={"self": picking, "origin": rmas},
subtype_id=self.env.ref("mail.mt_note").id, subtype_id=self.env["ir.model.data"]._xmlid_to_res_id("mail.mt_note"),
) )
rmas_to_return.write({"state": "waiting_return"}) rmas_to_return.write({"state": "waiting_return"})
@@ -1234,7 +1174,7 @@ class Rma(models.Model):
% ( % (
{ {
"move_id": new_move.id, "move_id": new_move.id,
"move_name": new_move.name_get()[0][1], "move_name": new_move.display_name,
"picking_id": new_move.picking_id.id, "picking_id": new_move.picking_id.id,
"picking_name": new_move.picking_id.name, "picking_name": new_move.picking_id.name,
} }
@@ -1427,10 +1367,7 @@ class Rma(models.Model):
[stock.move]._action_cancel [stock.move]._action_cancel
""" """
rma = self.filtered( rma = self.filtered(
lambda r: ( lambda r: (r.state == "waiting_replacement" and 0 >= r.remaining_qty)
r.state == "waiting_replacement"
and 0 >= r.remaining_qty_to_done == r.remaining_qty
)
) )
if rma: if rma:
rma.write({"state": "replaced"}) rma.write({"state": "replaced"})
@@ -1438,7 +1375,7 @@ class Rma(models.Model):
def update_returned_state(self): def update_returned_state(self):
"""Invoked by [stock.move]._action_done""" """Invoked by [stock.move]._action_done"""
rma = self.filtered( rma = self.filtered(
lambda r: (r.state == "waiting_return" and r.remaining_qty_to_done <= 0) lambda r: (r.state == "waiting_return" and r.remaining_qty <= 0)
) )
if rma: if rma:
rma.write({"state": "returned"}) rma.write({"state": "returned"})

View File

@@ -59,7 +59,7 @@ class StockMove(models.Model):
""" """
for move in self.filtered(lambda r: r.state not in ("done", "cancel")): for move in self.filtered(lambda r: r.state not in ("done", "cancel")):
rma_receiver = move.sudo().rma_receiver_ids rma_receiver = move.sudo().rma_receiver_ids
if rma_receiver and move.quantity_done != rma_receiver.product_uom_qty: if rma_receiver and move.quantity != rma_receiver.product_uom_qty:
raise ValidationError( raise ValidationError(
_( _(
"The quantity done for the product '%(id)s' must " "The quantity done for the product '%(id)s' must "

View File

@@ -5,3 +5,5 @@
- Víctor Martínez - Víctor Martínez
- Chafique Delli \<<chafique.delli@akretion.com>\> - Chafique Delli \<<chafique.delli@akretion.com>\>
- Giovanni Serra - Ooops \<<giovanni@ooops404.com>\> - Giovanni Serra - Ooops \<<giovanni@ooops404.com>\>
- [APSL-Nagarro](https://www.apsl.tech):
- Antoni Marroig \<<amarroig@apsl.net>\>

View File

@@ -14,7 +14,7 @@ To use this module, you need to:
quantity to another RMA, preview the RMA in the website. All of quantity to another RMA, preview the RMA in the website. All of
these operations can be done by clicking on the buttons in the these operations can be done by clicking on the buttons in the
status bar. status bar.
- If you click on 'Refund' button, a refund will be created, and it - If you click on 'To Refund' button, a refund will be created, and it
will be accessible via the smart button labeled Refund. The RMA will be accessible via the smart button labeled Refund. The RMA
will be set automatically to 'Refunded' state when the refund is will be set automatically to 'Refunded' state when the refund is
validated. validated.

View File

@@ -434,8 +434,8 @@ return to the customer the same product or another product as a
replacement, split the RMA by extracting a part of the remaining replacement, split the RMA by extracting a part of the remaining
quantity to another RMA, preview the RMA in the website. All of these quantity to another RMA, preview the RMA in the website. All of these
operations can be done by clicking on the buttons in the status bar.<ul> operations can be done by clicking on the buttons in the status bar.<ul>
<li>If you click on Refund button, a refund will be created, and it <li>If you click on To Refund button, a refund will be created, and
will be accessible via the smart button labeled Refund. The RMA it will be accessible via the smart button labeled Refund. The RMA
will be set automatically to Refunded state when the refund is will be set automatically to Refunded state when the refund is
validated.</li> validated.</li>
<li>If you click on Replace or Return to customer button instead, <li>If you click on Replace or Return to customer button instead,
@@ -523,6 +523,10 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
</li> </li>
<li>Chafique Delli &lt;<a class="reference external" href="mailto:chafique.delli&#64;akretion.com">chafique.delli&#64;akretion.com</a>&gt;</li> <li>Chafique Delli &lt;<a class="reference external" href="mailto:chafique.delli&#64;akretion.com">chafique.delli&#64;akretion.com</a>&gt;</li>
<li>Giovanni Serra - Ooops &lt;<a class="reference external" href="mailto:giovanni&#64;ooops404.com">giovanni&#64;ooops404.com</a>&gt;</li> <li>Giovanni Serra - Ooops &lt;<a class="reference external" href="mailto:giovanni&#64;ooops404.com">giovanni&#64;ooops404.com</a>&gt;</li>
<li><a class="reference external" href="https://www.apsl.tech">APSL-Nagarro</a>:<ul>
<li>Antoni Marroig &lt;<a class="reference external" href="mailto:amarroig&#64;apsl.net">amarroig&#64;apsl.net</a>&gt;</li>
</ul>
</li>
</ul> </ul>
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">

View File

@@ -85,6 +85,8 @@ class TestRma(TransactionCase):
vals["product_uom_qty"] = qty vals["product_uom_qty"] = qty
if location: if location:
vals["location_id"] = location.id vals["location_id"] = location.id
vals["user_id"] = self.env.user.id
return self.env["rma"].create(vals) return self.env["rma"].create(vals)
def _create_confirm_receive( def _create_confirm_receive(
@@ -92,7 +94,7 @@ class TestRma(TransactionCase):
): ):
rma = self._create_rma(partner, product, qty, location) rma = self._create_rma(partner, product, qty, location)
rma.action_confirm() rma.action_confirm()
rma.reception_move_id.quantity_done = rma.product_uom_qty rma.reception_move_id.quantity = rma.product_uom_qty
rma.reception_move_id.picking_id._action_done() rma.reception_move_id.picking_id._action_done()
return rma return rma
@@ -107,7 +109,7 @@ class TestRma(TransactionCase):
limit=1, limit=1,
) )
picking_form = Form( picking_form = Form(
recordp=self.env["stock.picking"].with_context( record=self.env["stock.picking"].with_context(
default_picking_type_id=picking_type.id default_picking_type_id=picking_type.id
), ),
view="stock.view_picking_form", view="stock.view_picking_form",
@@ -124,7 +126,7 @@ class TestRma(TransactionCase):
picking = picking_form.save() picking = picking_form.save()
picking.action_confirm() picking.action_confirm()
for move in picking.move_ids: for move in picking.move_ids:
move.quantity_done = move.product_uom_qty move.quantity = move.product_uom_qty
picking.button_validate() picking.button_validate()
return picking return picking
@@ -157,7 +159,7 @@ class TestRmaCase(TestRma):
limit=1, limit=1,
) )
picking_form = Form( picking_form = Form(
recordp=self.env["stock.picking"].with_context( record=self.env["stock.picking"].with_context(
default_picking_type_id=outgoing_picking_type.id default_picking_type_id=outgoing_picking_type.id
), ),
view="stock.view_picking_form", view="stock.view_picking_form",
@@ -203,13 +205,13 @@ class TestRmaCase(TestRma):
self.assertEqual(rma.reception_move_id.product_uom_qty, 10) self.assertEqual(rma.reception_move_id.product_uom_qty, 10)
self.assertEqual(rma.reception_move_id.product_uom, rma.product_uom) self.assertEqual(rma.reception_move_id.product_uom, rma.product_uom)
self.assertEqual(rma.state, "confirmed") self.assertEqual(rma.state, "confirmed")
rma.reception_move_id.quantity_done = 9 rma.reception_move_id.quantity = 9
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
rma.reception_move_id.picking_id._action_done() rma.reception_move_id.picking_id._action_done()
rma.reception_move_id.quantity_done = 10 rma.reception_move_id.quantity = 10
rma.reception_move_id.picking_id._action_done() rma.reception_move_id.picking_id._action_done()
self.assertEqual(rma.reception_move_id.picking_id.state, "done") self.assertEqual(rma.reception_move_id.picking_id.state, "done")
self.assertEqual(rma.reception_move_id.quantity_done, 10) self.assertEqual(rma.reception_move_id.quantity, 10)
self.assertEqual(rma.state, "received") self.assertEqual(rma.state, "received")
def test_cancel(self): def test_cancel(self):
@@ -386,8 +388,6 @@ class TestRmaCase(TestRma):
self.assertTrue(rma.can_be_replaced) self.assertTrue(rma.can_be_replaced)
self.assertEqual(rma.delivered_qty, 2) self.assertEqual(rma.delivered_qty, 2)
self.assertEqual(rma.remaining_qty, 8) self.assertEqual(rma.remaining_qty, 8)
self.assertEqual(rma.delivered_qty_done, 0)
self.assertEqual(rma.remaining_qty_to_done, 10)
first_move = rma.delivery_move_ids first_move = rma.delivery_move_ids
picking = first_move.picking_id picking = first_move.picking_id
# Replace again with another product with the remaining quantity # Replace again with another product with the remaining quantity
@@ -413,18 +413,13 @@ class TestRmaCase(TestRma):
self.assertTrue(picking.state, "waiting") self.assertTrue(picking.state, "waiting")
self.assertEqual(rma.delivered_qty, 10) self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0) self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 0)
self.assertEqual(rma.remaining_qty_to_done, 10)
# remaining_qty is 0 but rma is not set to 'replaced' until # remaining_qty is 0 but rma is not set to 'replaced' until
# remaining_qty_to_done is less than or equal to 0 first_move.quantity = 2
first_move.quantity_done = 2 second_move.quantity = 8
second_move.quantity_done = 8
picking.button_validate() picking.button_validate()
self.assertEqual(picking.state, "done") self.assertEqual(picking.state, "done")
self.assertEqual(rma.delivered_qty, 10) self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0) self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 10)
self.assertEqual(rma.remaining_qty_to_done, 0)
# The RMA is now in 'replaced' state # The RMA is now in 'replaced' state
self.assertEqual(rma.state, "replaced") self.assertEqual(rma.state, "replaced")
self.assertFalse(rma.can_be_refunded) self.assertFalse(rma.can_be_refunded)
@@ -457,18 +452,14 @@ class TestRmaCase(TestRma):
self.assertTrue(rma.can_be_returned) self.assertTrue(rma.can_be_returned)
self.assertEqual(rma.delivered_qty, 2) self.assertEqual(rma.delivered_qty, 2)
self.assertEqual(rma.remaining_qty, 8) self.assertEqual(rma.remaining_qty, 8)
self.assertEqual(rma.delivered_qty_done, 0)
self.assertEqual(rma.remaining_qty_to_done, 10)
first_move = rma.delivery_move_ids first_move = rma.delivery_move_ids
picking = first_move.picking_id picking = first_move.picking_id
# Validate the picking # Validate the picking
first_move.quantity_done = 2 first_move.quantity = 2
picking.button_validate() picking.button_validate()
self.assertEqual(picking.state, "done") self.assertEqual(picking.state, "done")
self.assertEqual(rma.delivered_qty, 2) self.assertEqual(rma.delivered_qty, 2)
self.assertEqual(rma.remaining_qty, 8) self.assertEqual(rma.remaining_qty, 8)
self.assertEqual(rma.delivered_qty_done, 2)
self.assertEqual(rma.remaining_qty_to_done, 8)
# Return the remaining quantity to the customer # Return the remaining quantity to the customer
delivery_form = Form( delivery_form = Form(
self.env["rma.delivery.wizard"].with_context( self.env["rma.delivery.wizard"].with_context(
@@ -479,21 +470,16 @@ class TestRmaCase(TestRma):
delivery_wizard = delivery_form.save() delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver() delivery_wizard.action_deliver()
second_move = rma.delivery_move_ids - first_move second_move = rma.delivery_move_ids - first_move
second_move.quantity_done = 8 second_move.quantity = 8
self.assertEqual(rma.delivered_qty, 10) self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0) self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 2)
self.assertEqual(rma.remaining_qty_to_done, 8)
self.assertEqual(rma.state, "waiting_return") self.assertEqual(rma.state, "waiting_return")
# remaining_qty is 0 but rma is not set to 'returned' until # remaining_qty is 0 but rma is not set to 'returned' until
# remaining_qty_to_done is less than or equal to 0
picking_2 = second_move.picking_id picking_2 = second_move.picking_id
picking_2.button_validate() picking_2.button_validate()
self.assertEqual(picking_2.state, "done") self.assertEqual(picking_2.state, "done")
self.assertEqual(rma.delivered_qty, 10) self.assertEqual(rma.delivered_qty, 10)
self.assertEqual(rma.remaining_qty, 0) self.assertEqual(rma.remaining_qty, 0)
self.assertEqual(rma.delivered_qty_done, 10)
self.assertEqual(rma.remaining_qty_to_done, 0)
# The RMA is now in 'returned' state # The RMA is now in 'returned' state
self.assertEqual(rma.state, "returned") self.assertEqual(rma.state, "returned")
self.assertFalse(rma.can_be_refunded) self.assertFalse(rma.can_be_refunded)
@@ -579,7 +565,7 @@ class TestRmaCase(TestRma):
self.assertEqual(rma.product_id, rma.delivery_move_ids.product_id) self.assertEqual(rma.product_id, rma.delivery_move_ids.product_id)
self.assertEqual(rma.product_uom_qty, rma.delivery_move_ids.product_uom_qty) self.assertEqual(rma.product_uom_qty, rma.delivery_move_ids.product_uom_qty)
self.assertEqual(rma.product_uom, rma.delivery_move_ids.product_uom) self.assertEqual(rma.product_uom, rma.delivery_move_ids.product_uom)
rma.delivery_move_ids.quantity_done = rma.product_uom_qty rma.delivery_move_ids.quantity = rma.product_uom_qty
pick_1.button_validate() pick_1.button_validate()
pick_2.button_validate() pick_2.button_validate()
self.assertEqual(all_rmas.mapped("state"), ["returned"] * 4) self.assertEqual(all_rmas.mapped("state"), ["returned"] * 4)
@@ -643,8 +629,8 @@ class TestRmaCase(TestRma):
self.assertTrue(reception_moves[1].rma_receiver_ids) self.assertTrue(reception_moves[1].rma_receiver_ids)
self.assertEqual(reception_moves.mapped("rma_receiver_ids"), rmas) self.assertEqual(reception_moves.mapped("rma_receiver_ids"), rmas)
# Validate the reception picking to set rmas to 'received' state # Validate the reception picking to set rmas to 'received' state
reception_moves[0].quantity_done = reception_moves[0].product_uom_qty reception_moves[0].quantity = reception_moves[0].product_uom_qty
reception_moves[1].quantity_done = reception_moves[1].product_uom_qty reception_moves[1].quantity = reception_moves[1].product_uom_qty
reception.button_validate() reception.button_validate()
self.assertEqual(rmas.mapped("state"), ["received"] * 2) self.assertEqual(rmas.mapped("state"), ["received"] * 2)
@@ -658,7 +644,7 @@ class TestRmaCase(TestRma):
) )
rma = rma_form.save() rma = rma_form.save()
rma.action_confirm() rma.action_confirm()
rma.reception_move_id.quantity_done = 10 rma.reception_move_id.quantity = 10
rma.reception_move_id.picking_id._action_done() rma.reception_move_id.picking_id._action_done()
# Return quantity 4 of the same product to the customer # Return quantity 4 of the same product to the customer
delivery_form = Form( delivery_form = Form(
@@ -670,7 +656,7 @@ class TestRmaCase(TestRma):
delivery_form.product_uom_qty = 4 delivery_form.product_uom_qty = 4
delivery_wizard = delivery_form.save() delivery_wizard = delivery_form.save()
delivery_wizard.action_deliver() delivery_wizard.action_deliver()
rma.delivery_move_ids.quantity_done = 4 rma.delivery_move_ids.quantity = 4
rma.delivery_move_ids.picking_id.button_validate() rma.delivery_move_ids.picking_id.button_validate()
self.assertEqual(rma.state, "waiting_return") self.assertEqual(rma.state, "waiting_return")
# Extract the remaining quantity to another RMA # Extract the remaining quantity to another RMA
@@ -690,8 +676,6 @@ class TestRmaCase(TestRma):
self.assertEqual(new_rma.origin_split_rma_id, rma) self.assertEqual(new_rma.origin_split_rma_id, rma)
self.assertEqual(new_rma.delivered_qty, 0) self.assertEqual(new_rma.delivered_qty, 0)
self.assertEqual(new_rma.remaining_qty, 6) self.assertEqual(new_rma.remaining_qty, 6)
self.assertEqual(new_rma.delivered_qty_done, 0)
self.assertEqual(new_rma.remaining_qty_to_done, 6)
self.assertEqual(new_rma.state, "received") self.assertEqual(new_rma.state, "received")
self.assertTrue(new_rma.can_be_refunded) self.assertTrue(new_rma.can_be_refunded)
self.assertTrue(new_rma.can_be_returned) self.assertTrue(new_rma.can_be_returned)
@@ -699,8 +683,8 @@ class TestRmaCase(TestRma):
self.assertEqual(new_rma.move_id, rma.move_id) self.assertEqual(new_rma.move_id, rma.move_id)
self.assertEqual(new_rma.reception_move_id, rma.reception_move_id) self.assertEqual(new_rma.reception_move_id, rma.reception_move_id)
self.assertEqual(new_rma.product_uom_qty + rma.product_uom_qty, 10) self.assertEqual(new_rma.product_uom_qty + rma.product_uom_qty, 10)
self.assertEqual(new_rma.move_id.quantity_done, 10) self.assertEqual(new_rma.move_id.quantity, 10)
self.assertEqual(new_rma.reception_move_id.quantity_done, 10) self.assertEqual(new_rma.reception_move_id.quantity, 10)
def test_rma_to_receive_on_delete_invoice(self): def test_rma_to_receive_on_delete_invoice(self):
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc) rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
@@ -763,7 +747,7 @@ class TestRmaCase(TestRma):
) )
# Now we'll confirm the incoming goods picking and the automatic # Now we'll confirm the incoming goods picking and the automatic
# reception notification should be sent # reception notification should be sent
rma.reception_move_id.quantity_done = rma.product_uom_qty rma.reception_move_id.quantity = rma.product_uom_qty
rma.reception_move_id.picking_id.button_validate() rma.reception_move_id.picking_id.button_validate()
mail_receipt = ( mail_receipt = (
self.env["mail.message"].search([("partner_ids", "in", self.partner.ids)]) self.env["mail.message"].search([("partner_ids", "in", self.partner.ids)])

View File

@@ -5,154 +5,85 @@
<field name="inherit_id" ref="stock.res_config_settings_view_form" /> <field name="inherit_id" ref="stock.res_config_settings_view_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath <xpath
expr="//div[@data-key='stock']/div[hasclass('o_settings_container')]" expr="//block[@name='operations_setting_container']"
position="inside" position="inside"
> >
<div class="col-12 col-lg-6 o_setting_box" title="Finish RMAs manually"> <setting
<div class="o_setting_left_pane"> title="Finish RMAs manually"
help=" When the RMA is receive, allow to finsish it manually choosing a finalization reason."
>
<field name="group_rma_manual_finalization" /> <field name="group_rma_manual_finalization" />
</div> </setting>
<div class="o_setting_right_pane"> <setting
<label title="Values set here are company-specific."
for="group_rma_manual_finalization" help="Group RMA returns by customer and warehouse."
string="RMA Manual Finalization" >
/>
<div class="text-muted">
When the RMA is receive, allow to finsish it manually choosing
a finalization reason.
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="rma_return_grouping" /> <field name="rma_return_grouping" />
</div> </setting>
<div class="o_setting_right_pane"> <setting
<label for="rma_return_grouping" />
<span
class="fa fa-lg fa-building-o"
title="Values set here are company-specific."
groups="base.group_multi_company"
/>
<div class="text-muted">
Group RMA returns by customer and warehouse.
</div>
</div>
</div>
<div
class="col-12 col-lg-6 o_setting_box"
title="Send automatic RMA info to customer" title="Send automatic RMA info to customer"
help="When the RMA is confirmed, send an automatic information email."
> >
<div class="o_setting_left_pane">
<field name="send_rma_confirmation" /> <field name="send_rma_confirmation" />
</div> <div class="row mt16" invisible="not send_rma_confirmation">
<div class="o_setting_right_pane">
<label
for="send_rma_confirmation"
string="RMA Confirmation Email"
/>
<span
class="fa fa-lg fa-building-o"
title="Values set here are company-specific."
groups="base.group_multi_company"
/>
<div class="text-muted">
When the RMA is confirmed, send an automatic information email.
</div>
<div
class="row mt16"
attrs="{'invisible': [('send_rma_confirmation', '=', False)]}"
>
<label <label
for="rma_mail_confirmation_template_id" for="rma_mail_confirmation_template_id"
string="Email Template" string="Email Template"
class="col-lg-4 o_light_label" class="col-lg-4 o_light_label"
/> />
<field <field
name="rma_mail_confirmation_template_id" name="rma_mail_confirmation_template_id"
class="oe_inline" class="oe_inline"
attrs="{'required': [('send_rma_confirmation', '=', True)]}" required="send_rma_confirmation"
context="{'default_model': 'rma'}" context="{'default_model': 'rma'}"
/> />
</div> </div>
</div> </setting>
</div> <setting
<div
class="col-12 col-lg-6 o_setting_box"
title="Send automatic RMA products reception notification to customer" title="Send automatic RMA products reception notification to customer"
help="When the RMA products are received, send an automatic information email."
> >
<div class="o_setting_left_pane">
<field name="send_rma_receipt_confirmation" /> <field name="send_rma_receipt_confirmation" />
</div>
<div class="o_setting_right_pane">
<label
for="send_rma_receipt_confirmation"
string="RMA Receipt Confirmation Email"
/>
<span
class="fa fa-lg fa-building-o"
title="Values set here are company-specific."
groups="base.group_multi_company"
/>
<div class="text-muted">
When the RMA products are received, send an automatic information email.
</div>
<div <div
class="row mt16" class="row mt16"
attrs="{'invisible': [('send_rma_receipt_confirmation', '=', False)]}" invisible="not send_rma_receipt_confirmation"
> >
<label <label
for="rma_mail_receipt_confirmation_template_id" for="rma_mail_receipt_confirmation_template_id"
string="Email Template" string="Email Template"
class="col-lg-4 o_light_label" class="col-lg-4 o_light_label"
/> />
<field
name="rma_mail_receipt_confirmation_template_id" <field
class="oe_inline" name="rma_mail_receipt_confirmation_template_id"
attrs="{'required': [('send_rma_receipt_confirmation', '=', True)]}" class="oe_inline"
context="{'default_model': 'rma'}" required="send_rma_receipt_confirmation"
/> context="{'default_model': 'rma'}"
/>
</div> </div>
</div> </setting>
</div> <setting
<div
class="col-12 col-lg-6 o_setting_box"
title="Send automatic notification when the customer places an RMA" title="Send automatic notification when the customer places an RMA"
help="When customers themselves place an RMA from the portal, send an automatic notification acknowleging it."
> >
<div class="o_setting_left_pane">
<field name="send_rma_draft_confirmation" /> <field name="send_rma_draft_confirmation" />
</div>
<div class="o_setting_right_pane">
<label
for="send_rma_draft_confirmation"
string="RMA draft notification Email"
/>
<span
class="fa fa-lg fa-building-o"
title="Values set here are company-specific."
groups="base.group_multi_company"
/>
<div class="text-muted">
When customers themselves place an RMA from the portal, send an automatic notification acknowleging it.
</div>
<div <div
class="row mt16" class="row mt16"
attrs="{'invisible': [('send_rma_draft_confirmation', '=', False)]}" invisible="not send_rma_draft_confirmation"
> >
<label <label
for="rma_mail_draft_confirmation_template_id" for="rma_mail_draft_confirmation_template_id"
string="Email Template" string="Email Template"
class="col-lg-4 o_light_label" class="col-lg-4 o_light_label"
/> />
<field <field
name="rma_mail_draft_confirmation_template_id" name="rma_mail_draft_confirmation_template_id"
class="oe_inline" class="oe_inline"
attrs="{'required': [('send_rma_draft_confirmation', '=', True)]}" required="send_rma_draft_confirmation"
context="{'default_model': 'rma'}" context="{'default_model': 'rma'}"
/> />
</div> </div>
</div> </setting>
</div>
</xpath> </xpath>
</field> </field>
</record> </record>

View File

@@ -14,7 +14,7 @@
type="object" type="object"
class="oe_stat_button" class="oe_stat_button"
icon="fa-reply" icon="fa-reply"
attrs="{'invisible': [('rma_count', '=', 0)]}" invisible="rma_count == 0"
groups="rma.rma_group_user_own" groups="rma.rma_group_user_own"
> >
<field name="rma_count" widget="statinfo" string="RMA" /> <field name="rma_count" widget="statinfo" string="RMA" />

View File

@@ -28,7 +28,7 @@
name="web_ribbon" name="web_ribbon"
title="Archived" title="Archived"
bg_color="bg-danger" bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}" invisible="active"
/> />
<group> <group>
<field name="name" /> <field name="name" />

View File

@@ -10,7 +10,7 @@
<field name="name" /> <field name="name" />
<field name="user_id" /> <field name="user_id" />
<field name="company_id" groups="base.group_multi_company" /> <field name="company_id" groups="base.group_multi_company" />
<field name="company_id" invisible="1" /> <field name="company_id" column_invisible="1" />
</tree> </tree>
</field> </field>
</record> </record>
@@ -81,11 +81,7 @@
</kanban> </kanban>
</field> </field>
</page> </page>
<page <page name="emails" string="Email" invisible="not alias_domain">
name="emails"
string="Email"
attrs="{'invisible': [('alias_domain', '=', False)]}"
>
<group name="group_alias"> <group name="group_alias">
<label for="alias_name" string="Email Alias" /> <label for="alias_name" string="Email Alias" />
<div name="alias_def"> <div name="alias_def">

View File

@@ -120,73 +120,73 @@
type="object" type="object"
string="Send by Email" string="Send by Email"
name="action_rma_send" name="action_rma_send"
attrs="{'invisible':['|', ('sent','=',True), ('state', 'not in', ['draft', 'confirmed', 'received'])]}" invisible="sent or state not in ['draft', 'confirmed', 'received']"
class="btn-primary" class="btn-primary"
/> />
<button <button
type="object" type="object"
string="Send by Mail" string="Send by Mail"
name="action_rma_send" name="action_rma_send"
attrs="{'invisible':['|', ('sent','=',False), ('state', 'not in', ['draft', 'confirmed', 'received'])]}" invisible="not sent or state not in ['draft', 'confirmed', 'received']"
/> />
<button <button
type="object" type="object"
string="Confirm" string="Confirm"
name="action_confirm" name="action_confirm"
states="draft" invisible="state != 'draft'"
class="btn-primary" class="btn-primary"
/> />
<button <button
type="object" type="object"
string="To Refund" string="To Refund"
name="action_refund" name="action_refund"
attrs="{'invisible': [('can_be_refunded', '=', False)]}" invisible="not can_be_refunded"
class="btn-primary" class="btn-primary"
/> />
<button <button
type="object" type="object"
string="Replace" string="Replace"
name="action_replace" name="action_replace"
attrs="{'invisible': [('can_be_replaced', '=', False)]}" invisible="not can_be_replaced"
class="btn-primary" class="btn-primary"
/> />
<button <button
type="object" type="object"
string="Return to customer" string="Return to customer"
name="action_return" name="action_return"
attrs="{'invisible': [('can_be_returned', '=', False)]}" invisible="not can_be_returned"
class="btn-primary" class="btn-primary"
/> />
<button <button
type="object" type="object"
string="Split" string="Split"
name="action_split" name="action_split"
attrs="{'invisible': [('can_be_split', '=', False)]}" invisible="not can_be_split"
/> />
<button <button
type="object" type="object"
string="Cancel" string="Cancel"
name="action_cancel" name="action_cancel"
confirm="Are you sure you want to cancel this RMA" confirm="Are you sure you want to cancel this RMA"
states="draft,confirmed" invisible="state not in ['draft', 'confirmed']"
/> />
<button <button
type="object" type="object"
string="Set to draft" string="Set to draft"
name="action_draft" name="action_draft"
states="cancelled" invisible="state != 'cancelled'"
/> />
<button <button
type="object" type="object"
string="Lock" string="Lock"
name="action_lock" name="action_lock"
attrs="{'invisible': [('can_be_locked', '=', False)]}" invisible="not can_be_locked"
/> />
<button <button
type="object" type="object"
string="Unlock" string="Unlock"
name="action_unlock" name="action_unlock"
states="locked" invisible="state != 'locked'"
/> />
<button type="object" string="Preview" name="action_preview" /> <button type="object" string="Preview" name="action_preview" />
<field <field
@@ -203,7 +203,7 @@
string="Receipt" string="Receipt"
class="oe_stat_button" class="oe_stat_button"
icon="fa-truck" icon="fa-truck"
attrs="{'invisible': [('reception_move_id', '=', False)]}" invisible="not reception_move_id"
> >
</button> </button>
<button <button
@@ -211,7 +211,7 @@
name="action_view_delivery" name="action_view_delivery"
class="oe_stat_button" class="oe_stat_button"
icon="fa-truck" icon="fa-truck"
attrs="{'invisible': [('delivery_picking_count', '=', 0)]}" invisible="delivery_picking_count == 0"
> >
<field <field
name="delivery_picking_count" name="delivery_picking_count"
@@ -225,13 +225,13 @@
name="action_view_refund" name="action_view_refund"
class="oe_stat_button" class="oe_stat_button"
icon="fa-pencil-square-o" icon="fa-pencil-square-o"
attrs="{'invisible': [('refund_id', '=', False)]}" invisible="not refund_id"
> >
</button> </button>
</div> </div>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
<field name="name" readonly="1" /> <field name="name" readonly="state != 'draft'" />
</h1> </h1>
</div> </div>
<group> <group>
@@ -240,101 +240,133 @@
name="partner_id" name="partner_id"
widget="res_partner_many2one" widget="res_partner_many2one"
context="{'search_default_customer':1, 'show_address': 1, 'show_vat': True}" context="{'search_default_customer':1, 'show_address': 1, 'show_vat': True}"
attrs="{'readonly': [('state', '!=', 'draft')]}" readonly="state != 'draft'"
options="{'always_reload': True}" options="{'always_reload': True}"
/> />
<field <field
name="partner_shipping_id" name="partner_shipping_id"
attrs="{'readonly': [('state', '!=', 'draft')]}" readonly="state != 'draft'"
force_save="1" force_save="1"
/> />
<field <field
name="partner_invoice_id" name="partner_invoice_id"
attrs="{'readonly': [('state', 'not in', ['draft', 'confirmed', 'received'])]}" readonly="state not in ['draft', 'confirmed', 'received']"
force_save="1" force_save="1"
/> />
<field name="picking_id" options="{'no_create': True}" /> <field
name="picking_id"
options="{'no_create': True}"
readonly="state != 'draft'"
/>
<field <field
name="move_id" name="move_id"
attrs="{'required': [('picking_id', '!=', False)], 'readonly': ['|', ('picking_id', '=', False), ('state', '!=', 'draft')]}" required="picking_id"
readonly="not picking_id or state != 'draft'"
options="{'no_create': True}" options="{'no_create': True}"
force_save="1" force_save="1"
/> />
<field <field
name="product_id" name="product_id"
force_save="1" force_save="1"
attrs="{'readonly': ['|', ('picking_id', '!=', False), ('state', '!=', 'draft')]}" readonly="picking_id or state != 'draft'"
/> />
<field name="uom_category_id" invisible="1" /> <field name="uom_category_id" invisible="1" />
<label for="product_uom_qty" /> <label for="product_uom_qty" />
<div class="o_row"> <div class="o_row">
<field <field
name="product_uom_qty" name="product_uom_qty"
attrs="{'readonly': [('state', '!=', 'draft')]}" readonly="state != 'draft'"
force_save="1" force_save="1"
/> />
<field <field
name="product_uom" name="product_uom"
groups="uom.group_uom" groups="uom.group_uom"
domain="[('category_id', '=', uom_category_id)]" domain="[('category_id', '=', uom_category_id)]"
attrs="{'readonly': [('state', '!=', 'draft')]}" readonly="state != 'draft'"
force_save="1" force_save="1"
/> />
<field name="product_uom" invisible="1" /> <field name="product_uom" invisible="1" />
</div> </div>
<field <field
name="delivered_qty" name="delivered_qty"
attrs="{'invisible': [('delivered_qty', '=', 0.0)]}" invisible="delivered_qty == 0.0"
/> />
</group> </group>
<group> <group>
<field name="date" /> <field name="date" readonly="state != 'draft'" />
<field name="user_id" /> <field
<field name="team_id" /> name="user_id"
readonly="state in ['locked', 'cancelled']"
/>
<field
name="team_id"
readonly="state in ['locked', 'cancelled']"
/>
<field <field
name="tag_ids" name="tag_ids"
widget="many2many_tags" widget="many2many_tags"
options="{'color_field': 'color', 'no_create_edit': True}" options="{'color_field': 'color', 'no_create_edit': True}"
placeholder="Tags..." placeholder="Tags..."
/> />
<field name="origin" /> <field
name="origin"
readonly="state in ['locked', 'cancelled']"
/>
<field name="operation_id" /> <field name="operation_id" />
<field <field
name="finalization_id" name="finalization_id"
attrs="{'invisible': [('state', '!=', 'finished')]}" readonly="1"
invisible="state != 'finished'"
/> />
<field <field
name="company_id" name="company_id"
options="{'no_create': True}" options="{'no_create': True}"
groups="base.group_multi_company" groups="base.group_multi_company"
readonly="state in ['locked', 'cancelled']"
/>
<field
name="company_id"
invisible="1"
readonly="state in ['locked', 'cancelled']"
/> />
<field name="company_id" invisible="1" />
</group> </group>
</group> </group>
<notebook> <notebook>
<page name="page_other" string="Other Information"> <page name="page_other" string="Other Information">
<group> <group>
<group> <group>
<field name="procurement_group_id" /> <field
name="procurement_group_id"
readonly="state not in ['draft', 'confirmed', 'received']"
/>
<field <field
name="location_id" name="location_id"
options="{'no_create': True, 'no_open': True}" options="{'no_create': True, 'no_open': True}"
groups="stock.group_stock_multi_locations" groups="stock.group_stock_multi_locations"
attrs="{'readonly': [('state', '!=', 'draft')]}" readonly="state != 'draft'"
/> />
<field name="location_id" invisible="1" /> <field name="location_id" invisible="1" />
</group> </group>
<group> <group>
<field name="deadline" />
<field name="priority" widget="priority" />
<field <field
name="origin_split_rma_id" name="deadline"
attrs="{'invisible': [('origin_split_rma_id', '=', False)]}" readonly="state in ['locked', 'cancelled']"
/> />
<field
name="priority"
widget="priority"
readonly="state != 'draft'"
/>
<field name="origin_split_rma_id" invisible="1" />
</group> </group>
</group> </group>
<group> <group>
<field name="description" widget="html" colspan="4" /> <field
name="description"
widget="html"
colspan="4"
readonly="state in ['locked', 'cancelled']"
/>
</group> </group>
</page> </page>
</notebook> </notebook>
@@ -371,7 +403,7 @@
string="Finish" string="Finish"
name="action_finish" name="action_finish"
class="btn-primary" class="btn-primary"
attrs="{'invisible': [('can_be_finished', '=', False)]}" invisible="not can_be_finished"
groups="rma.group_rma_manual_finalization" groups="rma.group_rma_manual_finalization"
/> />
</xpath> </xpath>
@@ -392,7 +424,7 @@
<field name="name">rma.calendar</field> <field name="name">rma.calendar</field>
<field name="model">rma</field> <field name="model">rma</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<calendar date_start="date" mode="month" color="state" quick_add="False"> <calendar date_start="date" mode="month" color="state">
<field name="name" /> <field name="name" />
<field name="partner_id" /> <field name="partner_id" />
<field name="product_id" /> <field name="product_id" />

View File

@@ -13,7 +13,7 @@
type="object" type="object"
class="oe_stat_button" class="oe_stat_button"
icon="fa-reply" icon="fa-reply"
attrs="{'invisible': [('rma_count', '=', 0)]}" invisible="rma_count == 0"
groups="rma.rma_group_user_own" groups="rma.rma_group_user_own"
> >
<field name="rma_count" widget="statinfo" string="RMA" /> <field name="rma_count" widget="statinfo" string="RMA" />

View File

@@ -11,37 +11,26 @@
<group> <group>
<group> <group>
<field name="scheduled_date" /> <field name="scheduled_date" />
<field <field name="warehouse_id" invisible="type != 'replace'" />
name="warehouse_id"
attrs="{'invisible': [('type', '!=', 'replace')]}"
/>
<field <field
name="rma_return_grouping" name="rma_return_grouping"
attrs="{'invisible': ['|', ('type', '=', 'replace'), ('rma_count', '=', 1)]}" invisible="type == 'replace' or rma_count == 1"
/> />
</group> </group>
<group> <group>
<field name="uom_category_id" invisible="1" /> <field name="uom_category_id" invisible="1" />
<field <field
name="product_id" name="product_id"
attrs="{'invisible': ['|', ('type', '!=', 'replace'), ('rma_count', '>', 1)], 'required': [('type', '=', 'replace'), ('rma_count', '=', 1)]}" invisible="type != 'replace' or rma_count > 1"
required="type == 'replace' and rma_count == 1"
/> />
<label <label for="product_uom_qty" invisible="rma_count > 1" />
for="product_uom_qty" <div class="o_row" invisible="rma_count > 1">
attrs="{'invisible': [('rma_count', '>', 1)]}" <field name="product_uom_qty" required="rma_count == 1" />
/>
<div
class="o_row"
attrs="{'invisible': [('rma_count', '>', 1)]}"
>
<field
name="product_uom_qty"
attrs="{'required': [('rma_count', '=', 1)]}"
/>
<field <field
name="product_uom" name="product_uom"
groups="uom.group_uom" groups="uom.group_uom"
attrs="{'required': [('rma_count', '=', 1)]}" required="rma_count == 1"
domain="[('category_id', '=', uom_category_id)]" domain="[('category_id', '=', uom_category_id)]"
/> />
<field name="product_uom" invisible="1" /> <field name="product_uom" invisible="1" />

View File

@@ -12,7 +12,7 @@
<group name="group_rma"> <group name="group_rma">
<field <field
name="create_rma" name="create_rma"
attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}" invisible="picking_type_code != 'outgoing'"
/> />
<field name="rma_location_ids" invisible="1" /> <field name="rma_location_ids" invisible="1" />
<field name="picking_id" invisible="1" /> <field name="picking_id" invisible="1" />