[FIX+IMP] rma, rma_sale: fix bugs and add improvements

- Fix thrown error when trying to download a picking from the portal.
- Add the hook method to prepare RMA values ​​from the return pick wizard.
- Add the access rule for portal users.
- Show the portal 'Request RMAs' button on the sales page only to users
related to the sales order.

[UPD] Update rma.pot

rma 12.0.1.3.0

Update translation files

Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: rma-12.0/rma-12.0-rma
Translate-URL: https://translation.odoo-community.org/projects/rma-12-0/rma-12-0-rma/
This commit is contained in:
Ernesto Tejeda
2020-08-19 00:19:25 -04:00
parent 8fef57c081
commit 3b209dae5d
13 changed files with 92 additions and 66 deletions

View File

@@ -3,7 +3,7 @@
{ {
"name": "Return Merchandise Authorization Management", "name": "Return Merchandise Authorization Management",
"summary": "Return Merchandise Authorization (RMA)", "summary": "Return Merchandise Authorization (RMA)",
"version": "12.0.1.2.0", "version": "12.0.1.3.0",
"development_status": "Beta", "development_status": "Beta",
"category": "RMA", "category": "RMA",
"website": "https://github.com/OCA/rma", "website": "https://github.com/OCA/rma",

View File

@@ -102,13 +102,13 @@ class PortalRma(CustomerPortal):
values = self._rma_get_page_view_values(rma_sudo, access_token, **kw) values = self._rma_get_page_view_values(rma_sudo, access_token, **kw)
return request.render("rma.portal_rma_page", values) return request.render("rma.portal_rma_page", values)
@http.route(['/my/rma/picking/pdf/<int:picking_id>'], @http.route(['/my/rma/picking/pdf/<int:rma_id>/<int:picking_id>'],
type='http', auth="public", website=True) type='http', auth="public", website=True)
def portal_my_rma_picking_report(self, picking_id, access_token=None, def portal_my_rma_picking_report(self, rma_id, picking_id,
**kw): access_token=None, **kw):
try: try:
picking_sudo = self._stock_picking_check_access( picking_sudo = self._picking_check_access(
picking_id, access_token=access_token) rma_id, picking_id, access_token=access_token)
except exceptions.AccessError: except exceptions.AccessError:
return request.redirect('/my') return request.redirect('/my')
report_sudo = request.env.ref('stock.action_report_delivery').sudo() report_sudo = request.env.ref('stock.action_report_delivery').sudo()
@@ -119,14 +119,14 @@ class PortalRma(CustomerPortal):
] ]
return request.make_response(pdf, headers=pdfhttpheaders) return request.make_response(pdf, headers=pdfhttpheaders)
def _stock_picking_check_access(self, picking_id, access_token=None): def _picking_check_access(self, rma_id, picking_id, access_token=None):
rma = request.env['rma'].browse([rma_id])
picking = request.env['stock.picking'].browse([picking_id]) picking = request.env['stock.picking'].browse([picking_id])
picking_sudo = picking.sudo() picking_sudo = picking.sudo()
try: try:
picking.check_access_rights('read') picking.check_access_rights('read')
picking.check_access_rule('read') picking.check_access_rule('read')
except exceptions.AccessError: except exceptions.AccessError:
if not access_token or not consteq( if not access_token or not consteq(rma.access_token, access_token):
picking_sudo.sale_id.access_token, access_token):
raise raise
return picking_sudo return picking_sudo

View File

@@ -5,7 +5,7 @@
<field name="name">Draft RMA</field> <field name="name">Draft RMA</field>
<field name="res_model">rma</field> <field name="res_model">rma</field>
<field name="default" eval="False"/> <field name="default" eval="False"/>
<field name="description">New RMA in draft state</field> <field name="description">RMA in draft state</field>
</record> </record>
<!-- rma_team-related subtypes for messaging / Chatter --> <!-- rma_team-related subtypes for messaging / Chatter -->
<record id="mt_rma_team_rma_draft" model="mail.message.subtype"> <record id="mt_rma_team_rma_draft" model="mail.message.subtype">

View File

@@ -537,7 +537,7 @@ msgid "Draft RMA"
msgstr "RMA en estado Borrador" msgstr "RMA en estado Borrador"
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:1091 #: code:addons/rma/models/rma.py:1097
#, python-format #, python-format
msgid "" msgid ""
"E-mail subject: %s\n" "E-mail subject: %s\n"
@@ -640,7 +640,7 @@ msgstr ""
"sin eliminarlo." "sin eliminarlo."
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:1095 #: code:addons/rma/models/rma.py:1101
#, python-format #, python-format
msgid "Incoming e-mail" msgid "Incoming e-mail"
msgstr "Correo electrónico entrante" msgstr "Correo electrónico entrante"
@@ -747,16 +747,11 @@ msgstr "Nombre"
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:31 code:addons/rma/models/rma.py:495 #: code:addons/rma/models/rma.py:31 code:addons/rma/models/rma.py:495
#: code:addons/rma/models/rma.py:1094 #: code:addons/rma/models/rma.py:1100
#, python-format #, python-format
msgid "New" msgid "New"
msgstr "Nuevo" msgstr "Nuevo"
#. module: rma
#: model:mail.message.subtype,description:rma.mt_rma_draft
msgid "New RMA in draft state"
msgstr "Nuevo RMA en estado Borrador"
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline #: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline
msgid "Next Activity Deadline" msgid "Next Activity Deadline"
@@ -1073,6 +1068,11 @@ msgstr "Equipo de RMA del cual el usuario es miembro."
msgid "RMA count" msgid "RMA count"
msgstr "Cantidad de RMAs" msgstr "Cantidad de RMAs"
#. module: rma
#: model:mail.message.subtype,description:rma.mt_rma_draft
msgid "RMA in draft state"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_stock_move__rma_receiver_ids #: model:ir.model.fields,field_description:rma.field_stock_move__rma_receiver_ids
msgid "RMA receivers" msgid "RMA receivers"
@@ -1606,7 +1606,7 @@ msgid "You cannot delete RMAs that are not in draft state"
msgstr "No puede " msgstr "No puede "
#. module: rma #. module: rma
#: code:addons/rma/wizard/stock_picking_return.py:56 #: code:addons/rma/wizard/stock_picking_return.py:55
#, python-format #, python-format
msgid "" msgid ""
"You must specify the 'Customer' in the 'Stock Picking' from which RMAs will " "You must specify the 'Customer' in the 'Stock Picking' from which RMAs will "
@@ -1635,3 +1635,6 @@ msgid ""
msgstr "" msgstr ""
"El usuario tendrá acceso a la configuración de RMA y a los informes " "El usuario tendrá acceso a la configuración de RMA y a los informes "
"estadísticos." "estadísticos."
#~ msgid "New RMA in draft state"
#~ msgstr "Nuevo RMA en estado Borrador"

View File

@@ -535,7 +535,7 @@ msgid "Draft RMA"
msgstr "Rascunho do RMA" msgstr "Rascunho do RMA"
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:1091 #: code:addons/rma/models/rma.py:1097
#, python-format #, python-format
msgid "" msgid ""
"E-mail subject: %s\n" "E-mail subject: %s\n"
@@ -638,7 +638,7 @@ msgstr ""
"sem removê-lo." "sem removê-lo."
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:1095 #: code:addons/rma/models/rma.py:1101
#, python-format #, python-format
msgid "Incoming e-mail" msgid "Incoming e-mail"
msgstr "E-mail recebido" msgstr "E-mail recebido"
@@ -745,16 +745,11 @@ msgstr "Nome"
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:31 code:addons/rma/models/rma.py:495 #: code:addons/rma/models/rma.py:31 code:addons/rma/models/rma.py:495
#: code:addons/rma/models/rma.py:1094 #: code:addons/rma/models/rma.py:1100
#, python-format #, python-format
msgid "New" msgid "New"
msgstr "Novo(a)" msgstr "Novo(a)"
#. module: rma
#: model:mail.message.subtype,description:rma.mt_rma_draft
msgid "New RMA in draft state"
msgstr "Novo Rascunho de RMA"
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline #: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline
msgid "Next Activity Deadline" msgid "Next Activity Deadline"
@@ -1071,6 +1066,11 @@ msgstr "Equipe de RMA da qual o usuário é membro."
msgid "RMA count" msgid "RMA count"
msgstr "Contagem de RMA" msgstr "Contagem de RMA"
#. module: rma
#: model:mail.message.subtype,description:rma.mt_rma_draft
msgid "RMA in draft state"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_stock_move__rma_receiver_ids #: model:ir.model.fields,field_description:rma.field_stock_move__rma_receiver_ids
msgid "RMA receivers" msgid "RMA receivers"
@@ -1602,7 +1602,7 @@ msgid "You cannot delete RMAs that are not in draft state"
msgstr "Você não pode apagar RMAs que não estejam na situação \"Rascunho\"" msgstr "Você não pode apagar RMAs que não estejam na situação \"Rascunho\""
#. module: rma #. module: rma
#: code:addons/rma/wizard/stock_picking_return.py:56 #: code:addons/rma/wizard/stock_picking_return.py:55
#, python-format #, python-format
msgid "" msgid ""
"You must specify the 'Customer' in the 'Stock Picking' from which RMAs will " "You must specify the 'Customer' in the 'Stock Picking' from which RMAs will "
@@ -1630,3 +1630,6 @@ msgid ""
msgstr "" msgstr ""
"o usuário terá acesso à configuração RMA, bem como aos relatórios " "o usuário terá acesso à configuração RMA, bem como aos relatórios "
"estatísticos." "estatísticos."
#~ msgid "New RMA in draft state"
#~ msgstr "Novo Rascunho de RMA"

View File

@@ -486,7 +486,7 @@ msgid "Draft RMA"
msgstr "" msgstr ""
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:1091 #: code:addons/rma/models/rma.py:1097
#, python-format #, python-format
msgid "E-mail subject: %s\n" msgid "E-mail subject: %s\n"
"\n" "\n"
@@ -576,7 +576,7 @@ msgid "If the active field is set to false, it will allow you to hide the RMA Te
msgstr "" msgstr ""
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:1095 #: code:addons/rma/models/rma.py:1101
#, python-format #, python-format
msgid "Incoming e-mail" msgid "Incoming e-mail"
msgstr "" msgstr ""
@@ -684,16 +684,11 @@ msgstr ""
#. module: rma #. module: rma
#: code:addons/rma/models/rma.py:31 #: code:addons/rma/models/rma.py:31
#: code:addons/rma/models/rma.py:495 #: code:addons/rma/models/rma.py:495
#: code:addons/rma/models/rma.py:1094 #: code:addons/rma/models/rma.py:1100
#, python-format #, python-format
msgid "New" msgid "New"
msgstr "" msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_rma_draft
msgid "New RMA in draft state"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline #: model:ir.model.fields,field_description:rma.field_rma__activity_date_deadline
msgid "Next Activity Deadline" msgid "Next Activity Deadline"
@@ -989,6 +984,11 @@ msgstr ""
msgid "RMA count" msgid "RMA count"
msgstr "" msgstr ""
#. module: rma
#: model:mail.message.subtype,description:rma.mt_rma_draft
msgid "RMA in draft state"
msgstr ""
#. module: rma #. module: rma
#: model:ir.model.fields,field_description:rma.field_stock_move__rma_receiver_ids #: model:ir.model.fields,field_description:rma.field_stock_move__rma_receiver_ids
msgid "RMA receivers" msgid "RMA receivers"
@@ -1468,7 +1468,7 @@ msgid "You cannot delete RMAs that are not in draft state"
msgstr "" msgstr ""
#. module: rma #. module: rma
#: code:addons/rma/wizard/stock_picking_return.py:56 #: code:addons/rma/wizard/stock_picking_return.py:55
#, python-format #, python-format
msgid "You must specify the 'Customer' in the 'Stock Picking' from which RMAs will be created" msgid "You must specify the 'Customer' in the 'Stock Picking' from which RMAs will be created"
msgstr "" msgstr ""

View File

@@ -1080,6 +1080,12 @@ class Rma(models.Model):
} }
# Mail business methods # Mail business methods
def _track_subtype(self, init_values):
self.ensure_one()
if 'state' in init_values and self.state == 'draft':
return 'rma.mt_rma_draft'
return super()._track_subtype(init_values)
def message_new(self, msg_dict, custom_values=None): def message_new(self, msg_dict, custom_values=None):
"""Extract the needed values from an incoming rma emails data-set """Extract the needed values from an incoming rma emails data-set
to be used to create an RMA. to be used to create an RMA.

View File

@@ -88,6 +88,32 @@ class StockMove(models.Model):
res['rma_id'] = self.rma_id.id res['rma_id'] = self.rma_id.id
return res return res
def _prepare_return_rma_vals(self, original_picking):
""" hook method for preparing an RMA from the 'return picking wizard'.
"""
self.ensure_one()
partner = original_picking.partner_id
if hasattr(original_picking, 'sale_id') and original_picking.sale_id:
partner_invoice_id = original_picking.sale_id.partner_invoice_id.id
else:
partner_invoice_id = partner.address_get(
['invoice']).get('invoice', False),
return {
'user_id': self.env.user.id,
'partner_id': partner.id,
'partner_invoice_id': partner_invoice_id,
'origin': original_picking.name,
'picking_id': original_picking.id,
'move_id': self.origin_returned_move_id.id,
'product_id': self.origin_returned_move_id.product_id.id,
'product_uom_qty': self.product_uom_qty,
'product_uom': self.product_uom.id,
'reception_move_id': self.id,
'company_id': self.company_id.id,
'location_id': self.location_dest_id.id,
'state': 'confirmed',
}
class StockRule(models.Model): class StockRule(models.Model):
_inherit = 'stock.rule' _inherit = 'stock.rule'

View File

@@ -62,7 +62,7 @@ class StockWarehouse(models.Model):
sequence_data = warehouse._get_sequence_values() sequence_data = warehouse._get_sequence_values()
warehouse.rma_in_type_id.sequence_id.write( warehouse.rma_in_type_id.sequence_id.write(
sequence_data['rma_in_type_id']) sequence_data['rma_in_type_id'])
warehouse.rma_in_type_id.sequence_id.write( warehouse.rma_out_type_id.sequence_id.write(
sequence_data['rma_out_type_id']) sequence_data['rma_out_type_id'])
def _get_picking_type_create_values(self, max_sequence): def _get_picking_type_create_values(self, max_sequence):

View File

@@ -30,16 +30,23 @@
<!-- 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>
<field ref="model_rma" name="model_id"/> <field name="model_id" ref="model_rma"/>
<field name="domain_force">['|',('user_id','=',user.id),('user_id','=',False)]</field> <field name="domain_force">['|',('user_id','=',user.id),('user_id','=',False)]</field>
<field name="groups" eval="[(4, ref('rma_group_user_own'))]"/> <field name="groups" eval="[(4, ref('rma_group_user_own'))]"/>
</record> </record>
<record id="rma_rule_user_all" model="ir.rule"> <record id="rma_rule_user_all" model="ir.rule">
<field name="name">All RMAs</field> <field name="name">All RMAs</field>
<field ref="model_rma" name="model_id"/> <field name="model_id" ref="model_rma"/>
<field name="domain_force">[(1,'=',1)]</field> <field name="domain_force">[(1,'=',1)]</field>
<field name="groups" eval="[(4, ref('rma_group_user_all'))]"/> <field name="groups" eval="[(4, ref('rma_group_user_all'))]"/>
</record> </record>
<!-- RMA model rules for portal users -->
<record id="rma_rule_portal" model="ir.rule">
<field name="name">RMA portal users</field>
<field name="model_id" ref="rma.model_rma"/>
<field name="domain_force">[('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id])]</field>
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
</record>
<!-- Multi-Company Rules --> <!-- Multi-Company Rules -->
<record id="rma_rule_multi_company" model="ir.rule"> <record id="rma_rule_multi_company" model="ir.rule">
<field name="name">RMA multi-company</field> <field name="name">RMA multi-company</field>

View File

@@ -191,7 +191,7 @@
<section t-if="rma.reception_move_id" id="reception_section" style="page-break-inside: auto;" class="mt32"> <section t-if="rma.reception_move_id" id="reception_section" style="page-break-inside: auto;" class="mt32">
<strong class="d-block mb-1">Reception</strong> <strong class="d-block mb-1">Reception</strong>
<t t-set="picking" t-value="rma.reception_move_id.picking_id"/> <t t-set="picking" t-value="rma.reception_move_id.picking_id"/>
<t t-set="report_url" t-value="'/my/rma/picking/pdf/%s?%s' % (picking.id, keep_query())"/> <t t-set="report_url" t-value="'/my/rma/picking/pdf/%s/%s?%s' % (rma.id, picking.id, keep_query())"/>
<a class="list-group-item list-group-item-action d-flex flex-wrap align-items-center justify-content-between py-2 px-3" t-att-href="report_url"> <a class="list-group-item list-group-item-action d-flex flex-wrap align-items-center justify-content-between py-2 px-3" t-att-href="report_url">
<div> <div>
<i class="fa fa-truck mr-1" role="img" aria-label="Download" title="Download"/> <i class="fa fa-truck mr-1" role="img" aria-label="Download" title="Download"/>
@@ -230,7 +230,7 @@
<strong class="d-block mb-1">Delivery</strong> <strong class="d-block mb-1">Delivery</strong>
<ul class="list-group mb-4"> <ul class="list-group mb-4">
<t t-foreach="rma.delivery_move_ids.mapped('picking_id')" t-as="picking"> <t t-foreach="rma.delivery_move_ids.mapped('picking_id')" t-as="picking">
<t t-set="report_url" t-value="'/my/rma/picking/pdf/%s?%s' % (picking.id, keep_query())"/> <t t-set="report_url" t-value="'/my/rma/picking/pdf/%s/%s?%s' % (rma.id, picking.id, keep_query())"/>
<a class="list-group-item list-group-item-action d-flex flex-wrap align-items-center justify-content-between py-2 px-3" t-att-href="report_url"> <a class="list-group-item list-group-item-action d-flex flex-wrap align-items-center justify-content-between py-2 px-3" t-att-href="report_url">
<div> <div>
<i class="fa fa-truck mr-1" role="img" aria-label="Download" title="Download"/> <i class="fa fa-truck mr-1" role="img" aria-label="Download" title="Download"/>

View File

@@ -164,7 +164,7 @@
<field name="picking_id" <field name="picking_id"
options="{'no_create': True}"/> options="{'no_create': True}"/>
<field name="move_id" <field name="move_id"
attrs="{'required': [('picking_id', '!=', False)], 'readonly': [('picking_id', '=', False)]}" attrs="{'required': [('picking_id', '!=', False)], 'readonly': ['|', ('picking_id', '=', False), ('state', '!=', 'draft')]}"
options="{'no_create': True}" options="{'no_create': True}"
force_save="1"/> force_save="1"/>
<field name="product_id" <field name="product_id"

View File

@@ -51,33 +51,14 @@ class ReturnPicking(models.TransientModel):
# picking and change the default picking type to rma picking type # picking and change the default picking type to rma picking type
self_with_context = self.with_context(set_rma_picking_type=True) self_with_context = self.with_context(set_rma_picking_type=True)
res = super(ReturnPicking, self_with_context).create_returns() res = super(ReturnPicking, self_with_context).create_returns()
partner = self.picking_id.partner_id if not self.picking_id.partner_id:
if not partner:
raise ValidationError(_( raise ValidationError(_(
"You must specify the 'Customer' in the " "You must specify the 'Customer' in the "
"'Stock Picking' from which RMAs will be created")) "'Stock Picking' from which RMAs will be created"))
picking = self.picking_id
returned_picking = self.env['stock.picking'].browse(res['res_id']) returned_picking = self.env['stock.picking'].browse(res['res_id'])
if hasattr(picking, 'sale_id') and picking.sale_id: vals_list = [move._prepare_return_rma_vals(self.picking_id)
partner_invoice_id = picking.sale_id.partner_invoice_id.id for move in returned_picking.move_lines]
else: self.env['rma'].create(vals_list)
partner_invoice_id = partner.address_get(
['invoice']).get('invoice', False),
for move in returned_picking.move_lines:
self.env['rma'].create({
'partner_id': partner.id,
'partner_invoice_id': partner_invoice_id,
'origin': picking.name,
'picking_id': picking.id,
'move_id': move.origin_returned_move_id.id,
'product_id': move.origin_returned_move_id.product_id.id,
'product_uom_qty': move.product_uom_qty,
'product_uom': move.product_uom.id,
'reception_move_id': move.id,
'company_id': move.company_id.id,
'location_id': move.location_dest_id.id,
'state': 'confirmed',
})
return res return res
else: else:
return super().create_returns() return super().create_returns()