Merge PR #256 into 14.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2022-02-01 22:17:27 +00:00
23 changed files with 809 additions and 255 deletions

View File

@@ -51,6 +51,11 @@ If you want RMAs to be created from incoming emails, you need to:
one. one.
#. Go to 'Email' tab and set an 'Email Alias'. #. Go to 'Email' tab and set an 'Email Alias'.
If you want to manually finish RMAs, you need to:
#. Go to *Settings > Inventory*.
#. Set *Finish RMAs manually* checkbox on.
Usage Usage
===== =====
@@ -79,6 +84,11 @@ To use this module, you need to:
The RMA will be set automatically to 'Replaced' or 'Returned' state when The RMA will be set automatically to 'Replaced' or 'Returned' state when
the RMA quantity is equal or lower than the quantity in done delivery the RMA quantity is equal or lower than the quantity in done delivery
orders linked to it. orders linked to it.
#. You can also finish the RMA without further ado. To do so click on the *Finish*
button. A wizard will ask you for the reason from a selection of preconfigured ones.
Be sure to configure them in advance on *RMA > Configuration > Finalization Reasons*.
Once the RMA is finished, it will be set to that state and the reason will be
registered.
An RMA can also be created from a return of a delivery order: An RMA can also be created from a return of a delivery order:

View File

@@ -10,7 +10,7 @@
"author": "Tecnativa, Odoo Community Association (OCA)", "author": "Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["ernestotejeda"], "maintainers": ["ernestotejeda"],
"license": "AGPL-3", "license": "AGPL-3",
"depends": ["account", "stock"], "depends": ["stock_account"],
"data": [ "data": [
"views/report_rma.xml", "views/report_rma.xml",
"report/report.xml", "report/report.xml",
@@ -21,9 +21,11 @@
"security/ir.model.access.csv", "security/ir.model.access.csv",
"wizard/stock_picking_return_views.xml", "wizard/stock_picking_return_views.xml",
"wizard/rma_delivery_views.xml", "wizard/rma_delivery_views.xml",
"wizard/rma_finalization_wizard_views.xml",
"wizard/rma_split_views.xml", "wizard/rma_split_views.xml",
"views/menus.xml", "views/menus.xml",
"views/res_partner_views.xml", "views/res_partner_views.xml",
"views/rma_finalization_views.xml",
"views/rma_portal_templates.xml", "views/rma_portal_templates.xml",
"views/rma_team_views.xml", "views/rma_team_views.xml",
"views/rma_views.xml", "views/rma_views.xml",

View File

@@ -56,15 +56,10 @@ def post_init_hook(cr, registry):
) )
data[picking_type] = stock_picking_type.create(values).id data[picking_type] = stock_picking_type.create(values).id
rma_out_type = stock_picking_type.browse(data["rma_out_type_id"]) if data:
rma_out_type.write( whs.write(data)
{"return_picking_type_id": data.get("rma_in_type_id", False)} whs.rma_in_type_id.return_picking_type_id = whs.rma_out_type_id.id
) whs.rma_out_type_id.return_picking_type_id = whs.rma_in_type_id.id
rma_in_type = stock_picking_type.browse(data["rma_in_type_id"])
rma_in_type.write(
{"return_picking_type_id": data.get("rma_out_type_id", False)}
)
whs.write(data)
# Create rma locations and picking types # Create rma locations and picking types
warehouses = env["stock.warehouse"].search([]) warehouses = env["stock.warehouse"].search([])

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-21 09:33+0000\n"
"PO-Revision-Date: 2022-01-21 09:33+0000\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -226,11 +228,6 @@ msgstr ""
msgid "<strong>Delivered quantity</strong>" msgid "<strong>Delivered quantity</strong>"
msgstr "" msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.report_rma_document
msgid "<strong>Invoicing address:</strong>"
msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.ui.view,arch_db:rma.report_rma_document #: model_terms:ir.ui.view,arch_db:rma.report_rma_document
msgid "<strong>Move:</strong>" msgid "<strong>Move:</strong>"
@@ -292,6 +289,16 @@ msgstr ""
msgid "<strong>Responsible:</strong>" msgid "<strong>Responsible:</strong>"
msgstr "" msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.report_rma_document
msgid "<strong>Shipping Address:</strong>"
msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.portal_rma_page
msgid "<strong>Shipping address:</strong>"
msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.ui.view,arch_db:rma.report_rma_document #: model_terms:ir.ui.view,arch_db:rma.report_rma_document
msgid "<strong>State:</strong>" msgid "<strong>State:</strong>"
@@ -321,9 +328,11 @@ msgid "Action Needed"
msgstr "" msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_finalization__active
#: model:ir.model.fields,field_description:rma.field_rma_operation__active #: model:ir.model.fields,field_description:rma.field_rma_operation__active
#: model:ir.model.fields,field_description:rma.field_rma_tag__active #: model:ir.model.fields,field_description:rma.field_rma_tag__active
#: model:ir.model.fields,field_description:rma.field_rma_team__active #: model:ir.model.fields,field_description:rma.field_rma_team__active
#: model_terms:ir.ui.view,arch_db:rma.rma_finalization_view_search
#: model_terms:ir.ui.view,arch_db:rma.rma_tag_view_search #: model_terms:ir.ui.view,arch_db:rma.rma_tag_view_search
msgid "Active" msgid "Active"
msgstr "" msgstr ""
@@ -374,7 +383,9 @@ msgid "Aliased Model"
msgstr "" msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.ui.view,arch_db:rma.rma_finalization_view_search
#: model_terms:ir.ui.view,arch_db:rma.rma_tag_view_search #: model_terms:ir.ui.view,arch_db:rma.rma_tag_view_search
#: model_terms:ir.ui.view,arch_db:rma.view_rma_finalization_form
msgid "Archived" msgid "Archived"
msgstr "" msgstr ""
@@ -394,6 +405,11 @@ msgstr ""
msgid "Avatar" msgid "Avatar"
msgstr "" msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__can_be_finished
msgid "Can Be Finished"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__can_be_locked #: model:ir.model.fields,field_description:rma.field_rma__can_be_locked
msgid "Can Be Locked" msgid "Can Be Locked"
@@ -420,6 +436,7 @@ msgid "Can Be Split"
msgstr "" msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.ui.view,arch_db:rma.rma_finalization_wizard_view_form
#: model_terms:ir.ui.view,arch_db:rma.rma_redelivery_wizard_view_form #: model_terms:ir.ui.view,arch_db:rma.rma_redelivery_wizard_view_form
#: model_terms:ir.ui.view,arch_db:rma.rma_split_wizard_view_form2 #: model_terms:ir.ui.view,arch_db:rma.rma_split_wizard_view_form2
#: model_terms:ir.ui.view,arch_db:rma.rma_view_form #: model_terms:ir.ui.view,arch_db:rma.rma_view_form
@@ -469,6 +486,7 @@ msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__company_id #: model:ir.model.fields,field_description:rma.field_rma__company_id
#: model:ir.model.fields,field_description:rma.field_rma_finalization__company_id
#: model:ir.model.fields,field_description:rma.field_rma_team__company_id #: model:ir.model.fields,field_description:rma.field_rma_team__company_id
msgid "Company" msgid "Company"
msgstr "" msgstr ""
@@ -513,6 +531,11 @@ msgstr ""
msgid "Create RMAs" msgid "Create RMAs"
msgstr "" msgstr ""
#. module: rma
#: model_terms:ir.actions.act_window,help:rma.action_rma_finalization
msgid "Create a new RMA finalization"
msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.actions.act_window,help:rma.action_rma_tag #: model_terms:ir.actions.act_window,help:rma.action_rma_tag
msgid "Create a new RMA tag" msgid "Create a new RMA tag"
@@ -521,6 +544,8 @@ msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__create_uid #: model:ir.model.fields,field_description:rma.field_rma__create_uid
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__create_uid #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__create_uid
#: model:ir.model.fields,field_description:rma.field_rma_finalization__create_uid
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__create_uid
#: model:ir.model.fields,field_description:rma.field_rma_operation__create_uid #: model:ir.model.fields,field_description:rma.field_rma_operation__create_uid
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard__create_uid #: model:ir.model.fields,field_description:rma.field_rma_split_wizard__create_uid
#: model:ir.model.fields,field_description:rma.field_rma_tag__create_uid #: model:ir.model.fields,field_description:rma.field_rma_tag__create_uid
@@ -531,6 +556,8 @@ msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__create_date #: model:ir.model.fields,field_description:rma.field_rma__create_date
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__create_date #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__create_date
#: model:ir.model.fields,field_description:rma.field_rma_finalization__create_date
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__create_date
#: model:ir.model.fields,field_description:rma.field_rma_operation__create_date #: model:ir.model.fields,field_description:rma.field_rma_operation__create_date
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard__create_date #: model:ir.model.fields,field_description:rma.field_rma_split_wizard__create_date
#: model:ir.model.fields,field_description:rma.field_rma_tag__create_date #: model:ir.model.fields,field_description:rma.field_rma_tag__create_date
@@ -625,6 +652,8 @@ msgstr ""
#: model:ir.model.fields,field_description:rma.field_res_users__display_name #: model:ir.model.fields,field_description:rma.field_res_users__display_name
#: model:ir.model.fields,field_description:rma.field_rma__display_name #: model:ir.model.fields,field_description:rma.field_rma__display_name
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__display_name #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__display_name
#: model:ir.model.fields,field_description:rma.field_rma_finalization__display_name
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__display_name
#: model:ir.model.fields,field_description:rma.field_rma_operation__display_name #: model:ir.model.fields,field_description:rma.field_rma_operation__display_name
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard__display_name #: model:ir.model.fields,field_description:rma.field_rma_split_wizard__display_name
#: model:ir.model.fields,field_description:rma.field_rma_tag__display_name #: model:ir.model.fields,field_description:rma.field_rma_tag__display_name
@@ -711,6 +740,36 @@ msgstr ""
msgid "Extracted from" msgid "Extracted from"
msgstr "" msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__finalization_id
msgid "Finalization Reason"
msgstr ""
#. module: rma
#: model:ir.model.constraint,message:rma.constraint_rma_finalization_name_company_uniq
msgid "Finalization name already exists !"
msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.rma_view_form
msgid "Finish"
msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.rma_finalization_wizard_view_form
msgid "Finish RMA"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.rma_finalization_wizard_action
msgid "Finish RMA Manualy"
msgstr ""
#. module: rma
#: model:ir.model.fields.selection,name:rma.selection__rma__state__finished
msgid "Finished"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__message_follower_ids #: model:ir.model.fields,field_description:rma.field_rma__message_follower_ids
#: model:ir.model.fields,field_description:rma.field_rma_team__message_follower_ids #: model:ir.model.fields,field_description:rma.field_rma_team__message_follower_ids
@@ -748,6 +807,8 @@ msgstr ""
#: model:ir.model.fields,field_description:rma.field_res_users__id #: model:ir.model.fields,field_description:rma.field_res_users__id
#: model:ir.model.fields,field_description:rma.field_rma__id #: model:ir.model.fields,field_description:rma.field_rma__id
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__id #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__id
#: model:ir.model.fields,field_description:rma.field_rma_finalization__id
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__id
#: model:ir.model.fields,field_description:rma.field_rma_operation__id #: model:ir.model.fields,field_description:rma.field_rma_operation__id
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard__id #: model:ir.model.fields,field_description:rma.field_rma_split_wizard__id
#: model:ir.model.fields,field_description:rma.field_rma_tag__id #: model:ir.model.fields,field_description:rma.field_rma_tag__id
@@ -818,6 +879,16 @@ msgstr ""
msgid "Invoice Address" msgid "Invoice Address"
msgstr "" msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.report_rma_document
msgid "Invoicing Address:"
msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.report_rma_document
msgid "Invoicing and Shipping Address:"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__message_is_follower #: model:ir.model.fields,field_description:rma.field_rma__message_is_follower
#: model:ir.model.fields,field_description:rma.field_rma_team__message_is_follower #: model:ir.model.fields,field_description:rma.field_rma_team__message_is_follower
@@ -843,6 +914,8 @@ msgstr ""
#: model:ir.model.fields,field_description:rma.field_res_users____last_update #: model:ir.model.fields,field_description:rma.field_res_users____last_update
#: model:ir.model.fields,field_description:rma.field_rma____last_update #: model:ir.model.fields,field_description:rma.field_rma____last_update
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard____last_update #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard____last_update
#: model:ir.model.fields,field_description:rma.field_rma_finalization____last_update
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard____last_update
#: model:ir.model.fields,field_description:rma.field_rma_operation____last_update #: model:ir.model.fields,field_description:rma.field_rma_operation____last_update
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard____last_update #: model:ir.model.fields,field_description:rma.field_rma_split_wizard____last_update
#: model:ir.model.fields,field_description:rma.field_rma_tag____last_update #: model:ir.model.fields,field_description:rma.field_rma_tag____last_update
@@ -858,6 +931,8 @@ msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__write_uid #: model:ir.model.fields,field_description:rma.field_rma__write_uid
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__write_uid #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__write_uid
#: model:ir.model.fields,field_description:rma.field_rma_finalization__write_uid
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__write_uid
#: model:ir.model.fields,field_description:rma.field_rma_operation__write_uid #: model:ir.model.fields,field_description:rma.field_rma_operation__write_uid
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard__write_uid #: model:ir.model.fields,field_description:rma.field_rma_split_wizard__write_uid
#: model:ir.model.fields,field_description:rma.field_rma_tag__write_uid #: model:ir.model.fields,field_description:rma.field_rma_tag__write_uid
@@ -868,6 +943,8 @@ msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__write_date #: model:ir.model.fields,field_description:rma.field_rma__write_date
#: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__write_date #: model:ir.model.fields,field_description:rma.field_rma_delivery_wizard__write_date
#: model:ir.model.fields,field_description:rma.field_rma_finalization__write_date
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__write_date
#: model:ir.model.fields,field_description:rma.field_rma_operation__write_date #: model:ir.model.fields,field_description:rma.field_rma_operation__write_date
#: model:ir.model.fields,field_description:rma.field_rma_split_wizard__write_date #: model:ir.model.fields,field_description:rma.field_rma_split_wizard__write_date
#: model:ir.model.fields,field_description:rma.field_rma_tag__write_date #: model:ir.model.fields,field_description:rma.field_rma_tag__write_date
@@ -901,6 +978,13 @@ msgstr ""
msgid "Main Attachment" msgid "Main Attachment"
msgstr "" msgstr ""
#. module: rma
#: model_terms:ir.actions.act_window,help:rma.action_rma_finalization
msgid ""
"Manage RMA finalization reasons to better classify them for tracking and "
"analysis purposes."
msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.actions.act_window,help:rma.action_rma_tag #: model_terms:ir.actions.act_window,help:rma.action_rma_tag
msgid "" msgid ""
@@ -1195,6 +1279,29 @@ msgstr ""
msgid "RMA Delivery Wizard" msgid "RMA Delivery Wizard"
msgstr "" msgstr ""
#. module: rma
#: model_terms:ir.ui.view,arch_db:rma.view_rma_finalization_form
msgid "RMA Finalization"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_rma_finalization
msgid "RMA Finalization Reason"
msgstr ""
#. module: rma
#: model:ir.actions.act_window,name:rma.action_rma_finalization
#: model:ir.ui.menu,name:rma.rma_configuration_rma_finalization_menu
#: model_terms:ir.ui.view,arch_db:rma.rma_finalization_view_search
#: model_terms:ir.ui.view,arch_db:rma.view_rma_finalization_list
msgid "RMA Finalization Reasons"
msgstr ""
#. module: rma
#: model:ir.model,name:rma.model_rma_finalization_wizard
msgid "RMA Finalization Wizard"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_stock_warehouse__rma_in_type_id #: model:ir.model.fields,field_description:rma.field_stock_warehouse__rma_in_type_id
msgid "RMA In Type" msgid "RMA In Type"
@@ -1341,6 +1448,16 @@ msgstr ""
msgid "RMAs yet to be fully processed" msgid "RMAs yet to be fully processed"
msgstr "" msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_finalization_wizard__finalization_id
msgid "Reason"
msgstr ""
#. module: rma
#: model:ir.model.fields,field_description:rma.field_rma_finalization__name
msgid "Reason Name"
msgstr ""
#. module: rma #. module: rma
#: model_terms:ir.ui.view,arch_db:rma.rma_view_form #: model_terms:ir.ui.view,arch_db:rma.rma_view_form
msgid "Receipt" msgid "Receipt"

View File

@@ -2,6 +2,7 @@
from . import account_move from . import account_move
from . import rma from . import rma
from . import rma_finalization
from . import rma_operation from . import rma_operation
from . import rma_tag from . import rma_tag
from . import rma_team from . import rma_team

View File

@@ -6,6 +6,11 @@ from odoo import fields, models
class ResConfigSettings(models.TransientModel): class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings" _inherit = "res.config.settings"
group_rma_manual_finalization = fields.Boolean(
string="Finish RMA manually choosing a reason",
help="Allow to finish an RMA without returning back a product or refunding",
implied_group="rma.group_rma_manual_finalization",
)
send_rma_confirmation = fields.Boolean( send_rma_confirmation = fields.Boolean(
related="company_id.send_rma_confirmation", related="company_id.send_rma_confirmation",
readonly=False, readonly=False,

View File

@@ -67,6 +67,14 @@ class Rma(models.Model):
states={"locked": [("readonly", True)], "cancelled": [("readonly", True)]}, states={"locked": [("readonly", True)], "cancelled": [("readonly", True)]},
) )
tag_ids = fields.Many2many(comodel_name="rma.tag", string="Tags") tag_ids = fields.Many2many(comodel_name="rma.tag", string="Tags")
finalization_id = fields.Many2one(
string="Finalization Reason",
comodel_name="rma.finalization",
copy=False,
readonly=True,
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]",
tracking=True,
)
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,
@@ -171,6 +179,7 @@ class Rma(models.Model):
("refunded", "Refunded"), ("refunded", "Refunded"),
("returned", "Returned"), ("returned", "Returned"),
("replaced", "Replaced"), ("replaced", "Replaced"),
("finished", "Finished"),
("locked", "Locked"), ("locked", "Locked"),
("cancelled", "Canceled"), ("cancelled", "Canceled"),
], ],
@@ -245,6 +254,9 @@ class Rma(models.Model):
can_be_locked = fields.Boolean( can_be_locked = fields.Boolean(
compute="_compute_can_be_locked", compute="_compute_can_be_locked",
) )
can_be_finished = fields.Boolean(
compute="_compute_can_be_finished",
)
remaining_qty = fields.Float( remaining_qty = fields.Float(
string="Remaining delivered qty", string="Remaining delivered qty",
digits="Product Unit of Measure", digits="Product Unit of Measure",
@@ -388,6 +400,14 @@ class Rma(models.Model):
"replaced", "replaced",
] ]
@api.depends("state", "remaining_qty")
def _compute_can_be_finished(self):
for rma in self:
rma.can_be_finished = (
rma.state in {"received", "waiting_replacement", "waiting_return"}
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", "remaining_qty_to_done")
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
@@ -718,6 +738,21 @@ class Rma(models.Model):
action["context"].update(active_id=self.id, active_ids=self.ids) action["context"].update(active_id=self.id, active_ids=self.ids)
return action return action
def action_finish(self):
"""Invoked when a user wants to manually finalize the RMA"""
self.ensure_one()
self._ensure_can_be_returned()
# Force active_id to avoid issues when coming from smart buttons
# in other models
action = (
self.env.ref("rma.rma_finalization_wizard_action")
.with_context(active_id=self.id)
.read()[0]
)
action["context"] = dict(self.env.context)
action["context"].update(active_id=self.id, active_ids=self.ids)
return action
def action_cancel(self): def action_cancel(self):
"""Invoked when 'Cancel' button in rma form view is clicked.""" """Invoked when 'Cancel' button in rma form view is clicked."""
self.mapped("reception_move_id")._action_cancel() self.mapped("reception_move_id")._action_cancel()
@@ -912,7 +947,14 @@ class Rma(models.Model):
lambda r: r.move_id != self.move_id lambda r: r.move_id != self.move_id
).unlink() ).unlink()
return_line = return_wizard.product_return_moves return_line = return_wizard.product_return_moves
return_line.quantity = self.product_uom_qty 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.
"to_refund": False,
}
)
# set_rma_picking_type is to override the copy() method of stock # set_rma_picking_type is to override the copy() method of stock
# picking and change the default picking type to rma picking type. # picking and change the default picking type to rma picking type.
picking_action = return_wizard.with_context( picking_action = return_wizard.with_context(

View File

@@ -0,0 +1,26 @@
# Copyright 2022 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class RmaFinalization(models.Model):
_description = "RMA Finalization Reason"
_name = "rma.finalization"
_order = "name"
active = fields.Boolean(default=True)
name = fields.Char(
string="Reason Name",
required=True,
translate=True,
copy=False,
)
company_id = fields.Many2one(comodel_name="res.company")
_sql_constraints = [
(
"name_company_uniq",
"unique (name, company_id)",
"Finalization name already exists !",
),
]

View File

@@ -6,3 +6,8 @@ If you want RMAs to be created from incoming emails, you need to:
#. Go to *RMA > Configuration > RMA Team* and select a team or create a new #. Go to *RMA > Configuration > RMA Team* and select a team or create a new
one. one.
#. Go to 'Email' tab and set an 'Email Alias'. #. Go to 'Email' tab and set an 'Email Alias'.
If you want to manually finish RMAs, you need to:
#. Go to *Settings > Inventory*.
#. Set *Finish RMAs manually* checkbox on.

View File

@@ -23,6 +23,11 @@ To use this module, you need to:
The RMA will be set automatically to 'Replaced' or 'Returned' state when The RMA will be set automatically to 'Replaced' or 'Returned' state when
the RMA quantity is equal or lower than the quantity in done delivery the RMA quantity is equal or lower than the quantity in done delivery
orders linked to it. orders linked to it.
#. You can also finish the RMA without further ado. To do so click on the *Finish*
button. A wizard will ask you for the reason from a selection of preconfigured ones.
Be sure to configure them in advance on *RMA > Configuration > Finalization Reasons*.
Once the RMA is finished, it will be set to that state and the reason will be
registered.
An RMA can also be created from a return of a delivery order: An RMA can also be created from a return of a delivery order:

View File

@@ -10,3 +10,7 @@ access_rma_tag_user_own,rma.tag.user.own,model_rma_tag,rma_group_user_own,1,0,0,
access_rma_tag_manager,rma.tag.manager,model_rma_tag,rma_group_manager,1,1,1,1 access_rma_tag_manager,rma.tag.manager,model_rma_tag,rma_group_manager,1,1,1,1
access_rma_delivery_wizard_user_all,rma.delivery.wizard.user.all,model_rma_delivery_wizard,rma_group_user_all,1,1,1,1 access_rma_delivery_wizard_user_all,rma.delivery.wizard.user.all,model_rma_delivery_wizard,rma_group_user_all,1,1,1,1
access_rma_split_wizard_user_all,rma.split.wizard.user.all,model_rma_split_wizard,rma_group_user_all,1,1,1,1 access_rma_split_wizard_user_all,rma.split.wizard.user.all,model_rma_split_wizard,rma_group_user_all,1,1,1,1
access_rma_finalization_portal,rma.finalization.portal,model_rma_finalization,base.group_portal,1,0,0,0
access_rma_finalization_user_own,rma.finalization.user.own,model_rma_finalization,rma_group_user_own,1,0,0,0
access_rma_finalization_manager,rma.finalization.manager,model_rma_finalization,rma_group_manager,1,1,1,1
access_rma_finalization_wizard_user_own,rma.finalization.wizard.user.own,model_rma_finalization_wizard,rma_group_user_own,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
10 access_rma_tag_manager rma.tag.manager model_rma_tag rma_group_manager 1 1 1 1
11 access_rma_delivery_wizard_user_all rma.delivery.wizard.user.all model_rma_delivery_wizard rma_group_user_all 1 1 1 1
12 access_rma_split_wizard_user_all rma.split.wizard.user.all model_rma_split_wizard rma_group_user_all 1 1 1 1
13 access_rma_finalization_portal rma.finalization.portal model_rma_finalization base.group_portal 1 0 0 0
14 access_rma_finalization_user_own rma.finalization.user.own model_rma_finalization rma_group_user_own 1 0 0 0
15 access_rma_finalization_manager rma.finalization.manager model_rma_finalization rma_group_manager 1 1 1 1
16 access_rma_finalization_wizard_user_own rma.finalization.wizard.user.own model_rma_finalization_wizard rma_group_user_own 1 0 0 0

View File

@@ -38,6 +38,10 @@
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
/> />
</record> </record>
<record id="group_rma_manual_finalization" model="res.groups">
<field name="name">Allow RMA manual finalization</field>
<field name="category_id" ref="base.module_category_hidden" />
</record>
<!-- Record Rules --> <!-- Record Rules -->
<record id="rma_rule_user_own" model="ir.rule"> <record id="rma_rule_user_own" model="ir.rule">
<field name="name">Personal RMAs</field> <field name="name">Personal RMAs</field>
@@ -79,6 +83,14 @@
name="domain_force" name="domain_force"
>['|',('company_id','=',False),('company_id','in',company_ids)]</field> >['|',('company_id','=',False),('company_id','in',company_ids)]</field>
</record> </record>
<record id="rma_finalization_comp_rule" model="ir.rule">
<field name="name">RMA Finalization Reason multi-company</field>
<field name="model_id" ref="model_rma_finalization" />
<field name="global" eval="True" />
<field
name="domain_force"
> ['|', ('company_id', 'in', company_ids), ('company_id', '=', False)]</field>
</record>
<!-- New users will belong to rma_group_user_own --> <!-- New users will belong to rma_group_user_own -->
<record id="base.default_user" model="res.users"> <record id="base.default_user" model="res.users">
<field name="groups_id" eval="[(4, ref('rma_group_user_own'))]" /> <field name="groups_id" eval="[(4, ref('rma_group_user_own'))]" />

View File

@@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <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> <title>Return Merchandise Authorization Management</title>
<style type="text/css"> <style type="text/css">
@@ -401,6 +401,11 @@ Besides, you have full integration of the RMA documents in the customer portal.<
one.</li> one.</li>
<li>Go to Email tab and set an Email Alias.</li> <li>Go to Email tab and set an Email Alias.</li>
</ol> </ol>
<p>If you want to manually finish RMAs, you need to:</p>
<ol class="arabic simple">
<li>Go to <em>Settings &gt; Inventory</em>.</li>
<li>Set <em>Finish RMAs manually</em> checkbox on.</li>
</ol>
</div> </div>
<div class="section" id="usage"> <div class="section" id="usage">
<h1><a class="toc-backref" href="#id2">Usage</a></h1> <h1><a class="toc-backref" href="#id2">Usage</a></h1>
@@ -430,6 +435,11 @@ the RMA quantity is equal or lower than the quantity in done delivery
orders linked to it.</li> orders linked to it.</li>
</ul> </ul>
</li> </li>
<li>You can also finish the RMA without further ado. To do so click on the <em>Finish</em>
button. A wizard will ask you for the reason from a selection of preconfigured ones.
Be sure to configure them in advance on <em>RMA &gt; Configuration &gt; Finalization Reasons</em>.
Once the RMA is finished, it will be set to that state and the reason will be
registered.</li>
</ol> </ol>
<p>An RMA can also be created from a return of a delivery order:</p> <p>An RMA can also be created from a return of a delivery order:</p>
<ol class="arabic simple"> <ol class="arabic simple">

View File

@@ -50,6 +50,13 @@ class TestRma(SavepointCase):
"type": "delivery", "type": "delivery",
} }
) )
cls.finalization_reason_1 = cls.env["rma.finalization"].create(
{"name": "[Test] It can't be repaired and customer doesn't want it"}
)
cls.finalization_reason_2 = cls.env["rma.finalization"].create(
{"name": "[Test] It's out of warranty. To be scrapped"}
)
cls.env.ref("rma.group_rma_manual_finalization").users |= cls.env.user
def _create_rma(self, partner=None, product=None, qty=None, location=None): def _create_rma(self, partner=None, product=None, qty=None, location=None):
rma_form = Form(self.env["rma"]) rma_form = Form(self.env["rma"])
@@ -123,6 +130,8 @@ class TestRma(SavepointCase):
picking.button_validate() picking.button_validate()
return picking return picking
class TestRmaCase(TestRma):
def test_onchange(self): def test_onchange(self):
rma_form = Form(self.env["rma"]) rma_form = Form(self.env["rma"])
# If partner changes, the invoice address is set # If partner changes, the invoice address is set
@@ -500,6 +509,22 @@ class TestRma(SavepointCase):
self.assertFalse(rma.can_be_replaced) self.assertFalse(rma.can_be_replaced)
self._test_readonly_fields(rma) self._test_readonly_fields(rma)
def test_finish_rma(self):
# Create, confirm and receive an RMA
rma = self._create_confirm_receive(self.partner, self.product, 10, self.rma_loc)
rma.action_finish()
finalization_form = Form(
self.env["rma.finalization.wizard"].with_context(
active_ids=rma.ids,
rma_finalization_type="replace",
)
)
finalization_form.finalization_id = self.finalization_reason_2
finalization_wizard = finalization_form.save()
finalization_wizard.action_finish()
self.assertEqual(rma.state, "finished")
self.assertEqual(rma.finalization_id, self.finalization_reason_2)
def test_mass_return_to_customer(self): def test_mass_return_to_customer(self):
# Create, confirm and receive rma_1 # Create, confirm and receive rma_1
rma_1 = self._create_confirm_receive( rma_1 = self._create_confirm_receive(

View File

@@ -15,14 +15,28 @@
</t> </t>
</t> </t>
<t <t
t-if="(doc.partner_id or doc.partner_invoice_id) and doc.partner_id != doc.partner_invoice_id" t-if="doc.partner_shipping_id == doc.partner_invoice_id
and doc.partner_invoice_id != doc.partner_id
or doc.partner_shipping_id != doc.partner_invoice_id"
> >
<t t-set="information_block"> <t t-set="information_block">
<strong>Invoicing address:</strong> <strong
<div t-if="doc.partner_shipping_id == doc.partner_invoice_id"
>Invoicing and Shipping Address:</strong>
<strong
t-if="doc.partner_shipping_id != doc.partner_invoice_id"
>Invoicing Address:</strong>
<div
t-field="doc.partner_invoice_id" t-field="doc.partner_invoice_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}' t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'
/> />
<t t-if="doc.partner_shipping_id != doc.partner_invoice_id">
<strong>Shipping Address:</strong>
<div
t-field="doc.partner_shipping_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'
/>
</t>
</t> </t>
</t> </t>
<div class="page"> <div class="page">

View File

@@ -8,6 +8,21 @@
expr="//div[@data-key='stock']/div[hasclass('o_settings_container')]" expr="//div[@data-key='stock']/div[hasclass('o_settings_container')]"
position="inside" position="inside"
> >
<div class="col-12 col-lg-6 o_setting_box" title="Finish RMAs manually">
<div class="o_setting_left_pane">
<field name="group_rma_manual_finalization" />
</div>
<div class="o_setting_right_pane">
<label
for="group_rma_manual_finalization"
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 <div
class="col-12 col-lg-6 o_setting_box" class="col-12 col-lg-6 o_setting_box"
title="Send automatic RMA info to customer" title="Send automatic RMA info to customer"

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="rma_finalization_view_search" model="ir.ui.view">
<field name="model">rma.finalization</field>
<field name="arch" type="xml">
<search string="RMA Finalization Reasons">
<field name="name" />
<filter
string="Archived"
name="inactive"
domain="[('active','=',False)]"
/>
<filter
string="Active"
name="active"
domain="[('active','!=',False)]"
/>
</search>
</field>
</record>
<record id="view_rma_finalization_form" model="ir.ui.view">
<field name="name">Rma Finalization Reasons</field>
<field name="model">rma.finalization</field>
<field name="arch" type="xml">
<form string="RMA Finalization">
<sheet>
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<group>
<field name="name" />
<field name="company_id" groups="base.group_multi_company" />
<field name="active" invisible="1" />
</group>
</sheet>
</form>
</field>
</record>
<record id="view_rma_finalization_list" model="ir.ui.view">
<field name="name">RMA Finalization Reasons</field>
<field name="model">rma.finalization</field>
<field eval="6" name="priority" />
<field name="arch" type="xml">
<tree string="RMA Finalization Reasons">
<field name="name" />
<field name="company_id" groups="base.group_multi_company" />
</tree>
</field>
</record>
<record id="action_rma_finalization" model="ir.actions.act_window">
<field name="name">RMA Finalization Reasons</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">rma.finalization</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new RMA finalization
</p><p>
Manage RMA finalization reasons to better classify them for tracking and analysis purposes.
</p>
</field>
</record>
<menuitem
id="rma_configuration_rma_finalization_menu"
name="RMA Finalization Reasons"
parent="rma_configuration_menu"
action="action_rma_finalization"
groups="rma.group_rma_manual_finalization"
/>
</odoo>

View File

@@ -159,6 +159,7 @@
<t t-set="card_body"> <t t-set="card_body">
<div id="general_information"> <div id="general_information">
<div class="row mt4"> <div class="row mt4">
<!-- Customer -->
<div <div
t-if="rma.partner_id" t-if="rma.partner_id"
class="col-12 col-md-6 mb-4 mb-md-0" class="col-12 col-md-6 mb-4 mb-md-0"
@@ -189,6 +190,38 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Shipping Address -->
<div
t-if="rma.partner_shipping_id"
class="col-12 col-md-6 mb-4 mb-md-0"
>
<h6>
<strong>Shipping address:</strong>
</h6>
<div class="row">
<div class="col flex-grow-0 pr-3">
<img
t-if="rma.partner_shipping_id.image_1024"
class="rounded-circle mt-1 o_portal_contact_img"
t-att-src="image_data_uri(rma.partner_shipping_id.image_1024)"
alt="Contact"
/>
<img
t-else=""
class="rounded-circle mt-1 o_portal_contact_img"
src="/web/static/src/img/user_menu_avatar.png"
alt="Contact"
/>
</div>
<div class="col pl-sm-0">
<address
t-field="rma.partner_shipping_id"
t-options='{"widget": "contact", "fields": ["name", "email", "phone", "address"]}'
/>
</div>
</div>
</div>
<!-- RMA Info -->
<div t-if="rma.user_id" class="col-12 col-md-6"> <div t-if="rma.user_id" class="col-12 col-md-6">
<h6> <h6>
<strong>Responsible:</strong> <strong>Responsible:</strong>

View File

@@ -98,6 +98,7 @@
<field name="product_uom" groups="uom.group_uom" /> <field name="product_uom" groups="uom.group_uom" />
<field name="date" /> <field name="date" />
<field name="deadline" /> <field name="deadline" />
<field name="finalization_id" optional="hide" />
<field name="state" /> <field name="state" />
</tree> </tree>
</field> </field>
@@ -281,6 +282,10 @@
/> />
<field name="origin" /> <field name="origin" />
<field name="operation_id" /> <field name="operation_id" />
<field
name="finalization_id"
attrs="{'invisible': [('state', '!=', 'finished')]}"
/>
<field <field
name="company_id" name="company_id"
options="{'no_create': True}" options="{'no_create': True}"
@@ -321,6 +326,7 @@
<field name="can_be_replaced" invisible="1" /> <field name="can_be_replaced" invisible="1" />
<field name="can_be_split" invisible="1" /> <field name="can_be_split" invisible="1" />
<field name="can_be_locked" invisible="1" /> <field name="can_be_locked" invisible="1" />
<field name="can_be_finished" invisible="1" />
<field name="commercial_partner_id" invisible="1" /> <field name="commercial_partner_id" invisible="1" />
<field name="remaining_qty" invisible="1" /> <field name="remaining_qty" invisible="1" />
</sheet> </sheet>
@@ -332,6 +338,28 @@
</form> </form>
</field> </field>
</record> </record>
<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']"
position="before"
>
<button
type="object"
string="Finish"
name="action_finish"
class="btn-primary"
attrs="{'invisible': [('can_be_finished', '=', False)]}"
/>
</xpath>
</field>
</record>
<record id="rma_view_pivot" model="ir.ui.view"> <record id="rma_view_pivot" model="ir.ui.view">
<field name="name">rma.pivot</field> <field name="name">rma.pivot</field>
<field name="model">rma</field> <field name="model">rma</field>

View File

@@ -1,5 +1,6 @@
# 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 . import rma_delivery from . import rma_delivery
from . import rma_finalization_wizard
from . import rma_split from . import rma_split
from . import stock_picking_return from . import stock_picking_return

View File

@@ -0,0 +1,18 @@
# Copyright 2022 Tecnativa - David Vidal
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class RmaFinalizationWizard(models.TransientModel):
_name = "rma.finalization.wizard"
_description = "RMA Finalization Wizard"
finalization_id = fields.Many2one(
comodel_name="rma.finalization", string="Reason", required=True
)
def action_finish(self):
self.ensure_one()
rma_ids = self.env.context.get("active_ids")
rma = self.env["rma"].browse(rma_ids)
rma.write({"finalization_id": self.finalization_id, "state": "finished"})

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2022 Tecnativa - David Vidal
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="rma_finalization_wizard_view_form" model="ir.ui.view">
<field name="model">rma.finalization.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<group>
<field name="finalization_id" />
</group>
</group>
<footer>
<button
name="action_finish"
string="Finish RMA"
type="object"
class="btn-primary"
/>
<button string="Cancel" class="btn-secondary" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="rma_finalization_wizard_action" model="ir.actions.act_window">
<field name="name">Finish RMA Manualy</field>
<field name="res_model">rma.finalization.wizard</field>
<field name="view_mode">form</field>
<field name="binding_model_id" ref="rma.model_rma" />
<field name="binding_view_types">list</field>
<field name="target">new</field>
</record>
</odoo>