[MERGE] *: remove read access to ir.actions.*

Remove all acccess rights on `ir.actions.*` models.
Interacting with the models is done using sudo or via the `/web/action/load` controller.

Part of task 8203

closes odoo/odoo#53335

Related: odoo/enterprise#11797
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
This commit is contained in:
Odoo's Mergebot
2020-08-17 12:25:17 +02:00
committed by GitHub
104 changed files with 271 additions and 207 deletions
@@ -459,7 +459,8 @@ class account_journal(models.Model):
if '.' not in action_name: if '.' not in action_name:
action_name = 'account.%s' % action_name action_name = 'account.%s' % action_name
action = self.env.ref(action_name).read()[0] action = self.env["ir.actions.act_window"]._for_xml_id(action_name)
context = self._context.copy() context = self._context.copy()
if 'context' in action and type(action['context']) == str: if 'context' in action and type(action['context']) == str:
context.update(ast.literal_eval(action['context'])) context.update(ast.literal_eval(action['context']))
@@ -533,7 +534,7 @@ class account_journal(models.Model):
def create_bank_statement(self): def create_bank_statement(self):
"""return action to create a bank statements. This button should be called only on journals with type =='bank'""" """return action to create a bank statements. This button should be called only on journals with type =='bank'"""
action = self.env.ref('account.action_bank_statement_tree').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_bank_statement_tree")
action.update({ action.update({
'views': [[False, 'form']], 'views': [[False, 'form']],
'context': "{'default_journal_id': " + str(self.id) + "}", 'context': "{'default_journal_id': " + str(self.id) + "}",
+2 -2
View File
@@ -2361,7 +2361,7 @@ class AccountMove(models.Model):
return self.move_type == 'out_invoice' and not self.payment_reference return self.move_type == 'out_invoice' and not self.payment_reference
def action_reverse(self): def action_reverse(self):
action = self.env.ref('account.action_view_account_move_reversal').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_view_account_move_reversal")
if self.is_invoice(): if self.is_invoice():
action['name'] = _('Credit Note') action['name'] = _('Credit Note')
@@ -2614,7 +2614,7 @@ class AccountMove(models.Model):
# offer the possibility to duplicate thanks to a button instead of a hidden menu, which is more visible # offer the possibility to duplicate thanks to a button instead of a hidden menu, which is more visible
def action_duplicate(self): def action_duplicate(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('account.action_move_journal_line').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_journal_line")
action['context'] = dict(self.env.context) action['context'] = dict(self.env.context)
action['context']['form_view_initial_mode'] = 'edit' action['context']['form_view_initial_mode'] = 'edit'
action['context']['view_no_maturity'] = False action['context']['view_no_maturity'] = False
@@ -226,7 +226,7 @@ class AccountReconcileModel(models.Model):
def action_reconcile_stat(self): def action_reconcile_stat(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('account.action_move_journal_line').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_journal_line")
self._cr.execute(''' self._cr.execute('''
SELECT ARRAY_AGG(DISTINCT move_id) SELECT ARRAY_AGG(DISTINCT move_id)
FROM account_move_line FROM account_move_line
+2 -2
View File
@@ -431,7 +431,7 @@ class ResCompany(models.Model):
@api.model @api.model
def action_open_account_onboarding_sale_tax(self): def action_open_account_onboarding_sale_tax(self):
""" Onboarding step for the invoice layout. """ """ Onboarding step for the invoice layout. """
action = self.env.ref('account.action_open_account_onboarding_sale_tax').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_open_account_onboarding_sale_tax")
action['res_id'] = self.env.company.id action['res_id'] = self.env.company.id
return action return action
@@ -485,7 +485,7 @@ class ResCompany(models.Model):
with the edi_invoice_template message loaded by default. """ with the edi_invoice_template message loaded by default. """
sample_invoice = self._get_sample_invoice() sample_invoice = self._get_sample_invoice()
template = self.env.ref('account.email_template_edi_invoice', False) template = self.env.ref('account.email_template_edi_invoice', False)
action = self.env.ref('account.action_open_account_onboarding_sample_invoice').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_open_account_onboarding_sample_invoice")
action['context'] = { action['context'] = {
'default_res_id': sample_invoice.id, 'default_res_id': sample_invoice.id,
'default_use_template': bool(template), 'default_use_template': bool(template),
+1 -1
View File
@@ -476,7 +476,7 @@ class ResPartner(models.Model):
def action_view_partner_invoices(self): def action_view_partner_invoices(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('account.action_move_out_invoice_type').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_out_invoice_type")
action['domain'] = [ action['domain'] = [
('move_type', 'in', ('out_invoice', 'out_refund')), ('move_type', 'in', ('out_invoice', 'out_refund')),
('partner_id', 'child_of', self.id), ('partner_id', 'child_of', self.id),
@@ -18,7 +18,7 @@ class ResConfigSettings(models.TransientModel):
config_parameter='base.template_portal_user_id') config_parameter='base.template_portal_user_id')
def open_template_user(self): def open_template_user(self):
action = self.env.ref('base.action_res_users').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("base.action_res_users")
action['res_id'] = literal_eval(self.env['ir.config_parameter'].sudo().get_param('base.template_portal_user_id', 'False')) action['res_id'] = literal_eval(self.env['ir.config_parameter'].sudo().get_param('base.template_portal_user_id', 'False'))
action['views'] = [[self.env.ref('base.view_users_form').id, 'form']] action['views'] = [[self.env.ref('base.view_users_form').id, 'form']]
return action return action
@@ -164,7 +164,7 @@ class BaseAutomation(models.Model):
if '__action_done' not in self._context: if '__action_done' not in self._context:
self = self.with_context(__action_done={}) self = self.with_context(__action_done={})
domain = [('model_name', '=', records._name), ('trigger', 'in', triggers)] domain = [('model_name', '=', records._name), ('trigger', 'in', triggers)]
actions = self.with_context(active_test=True).search(domain) actions = self.with_context(active_test=True).sudo().search(domain)
return actions.with_env(self.env) return actions.with_env(self.env)
def _get_eval_context(self): def _get_eval_context(self):
@@ -258,7 +258,7 @@ class BaseAutomation(models.Model):
'domain_post': domain_post, 'domain_post': domain_post,
} }
try: try:
self.action_server_id.with_context(**ctx).run() self.action_server_id.sudo().with_context(**ctx).run()
except Exception as e: except Exception as e:
self._add_postmortem_action(e) self._add_postmortem_action(e)
raise e raise e
@@ -1,3 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_base_automation,base.automation,model_base_automation,,1,0,0,0
access_base_automation_config,base.automation config,model_base_automation,base.group_system,1,1,1,1 access_base_automation_config,base.automation config,model_base_automation,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
access_base_automation base.automation model_base_automation 1 0 0 0
2 access_base_automation_config base.automation config model_base_automation base.group_system 1 1 1 1
@@ -60,7 +60,7 @@ class ResConfigSettings(models.TransientModel):
} }
def open_default_user(self): def open_default_user(self):
action = self.env.ref('base.action_res_users').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("base.action_res_users")
action['res_id'] = self.env.ref('base.default_user').id action['res_id'] = self.env.ref('base.default_user').id
action['views'] = [[self.env.ref('base.view_users_form').id, 'form']] action['views'] = [[self.env.ref('base.view_users_form').id, 'form']]
return action return action
+1 -1
View File
@@ -107,7 +107,7 @@ class Attendee(models.Model):
rendering_context.update({ rendering_context.update({
'colors': colors, 'colors': colors,
'ignore_recurrence': ignore_recurrence, 'ignore_recurrence': ignore_recurrence,
'action_id': self.env['ir.actions.act_window'].search([('view_id', '=', calendar_view.id)], limit=1).id, 'action_id': self.env['ir.actions.act_window'].sudo().search([('view_id', '=', calendar_view.id)], limit=1).id,
'dbname': self._cr.dbname, 'dbname': self._cr.dbname,
'base_url': self.env['ir.config_parameter'].sudo().get_param('web.base.url', default='http://localhost:8069'), 'base_url': self.env['ir.config_parameter'].sudo().get_param('web.base.url', default='http://localhost:8069'),
}) })
+1 -1
View File
@@ -17,7 +17,7 @@ class MailActivity(models.Model):
def action_create_calendar_event(self): def action_create_calendar_event(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('calendar.action_calendar_event').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("calendar.action_calendar_event")
action['context'] = { action['context'] = {
'default_activity_type_id': self.activity_type_id.id, 'default_activity_type_id': self.activity_type_id.id,
'default_res_id': self.env.context.get('default_res_id'), 'default_res_id': self.env.context.get('default_res_id'),
+1 -1
View File
@@ -800,7 +800,7 @@ class Lead(models.Model):
:return dict: dictionary value for created Meeting view :return dict: dictionary value for created Meeting view
""" """
self.ensure_one() self.ensure_one()
action = self.env.ref('calendar.action_calendar_event').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("calendar.action_calendar_event")
partner_ids = self.env.user.partner_id.ids partner_ids = self.env.user.partner_id.ids
if self.partner_id: if self.partner_id:
partner_ids.append(self.partner_id.id) partner_ids.append(self.partner_id.id)
+2 -2
View File
@@ -126,7 +126,7 @@ class Team(models.Model):
#TODO JEM : refactor this stuff with xml action, proper customization, #TODO JEM : refactor this stuff with xml action, proper customization,
@api.model @api.model
def action_your_pipeline(self): def action_your_pipeline(self):
action = self.env.ref('crm.crm_lead_action_pipeline').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("crm.crm_lead_action_pipeline")
user_team_id = self.env.user.sale_team_id.id user_team_id = self.env.user.sale_team_id.id
if user_team_id: if user_team_id:
# To ensure that the team is readable in multi company # To ensure that the team is readable in multi company
@@ -154,7 +154,7 @@ class Team(models.Model):
def action_primary_channel_button(self): def action_primary_channel_button(self):
if self.use_opportunities: if self.use_opportunities:
return self.env.ref('crm.crm_case_form_view_salesteams_opportunity').read()[0] return self.env["ir.actions.actions"]._for_xml_id("crm.crm_case_form_view_salesteams_opportunity")
return super(Team,self).action_primary_channel_button() return super(Team,self).action_primary_channel_button()
def _graph_get_model(self): def _graph_get_model(self):
+1 -1
View File
@@ -77,7 +77,7 @@ class Partner(models.Model):
def schedule_meeting(self): def schedule_meeting(self):
partner_ids = self.ids partner_ids = self.ids
partner_ids.append(self.env.user.partner_id.id) partner_ids.append(self.env.user.partner_id.id)
action = self.env.ref('calendar.action_calendar_event').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("calendar.action_calendar_event")
action['context'] = { action['context'] = {
'default_partner_ids': partner_ids, 'default_partner_ids': partner_ids,
} }
+1 -1
View File
@@ -23,7 +23,7 @@ class UtmCampaign(models.Model):
def action_redirect_to_leads_opportunities(self): def action_redirect_to_leads_opportunities(self):
view = 'crm.crm_lead_all_leads' if self.use_leads else 'crm.crm_lead_opportunities' view = 'crm.crm_lead_all_leads' if self.use_leads else 'crm.crm_lead_opportunities'
action = self.env.ref(view).read()[0] action = self.env.ref(view).sudo().read()[0]
action['view_mode'] = 'tree,kanban,graph,pivot,form,calendar' action['view_mode'] = 'tree,kanban,graph,pivot,form,calendar'
action['domain'] = [('campaign_id', 'in', self.ids)] action['domain'] = [('campaign_id', 'in', self.ids)]
action['context'] = {'active_test': False, 'create': False} action['context'] = {'active_test': False, 'create': False}
+1
View File
@@ -981,6 +981,7 @@ if record:
<field name="name">Crm: My Pipeline</field> <field name="name">Crm: My Pipeline</field>
<field name="model_id" ref="crm.model_crm_team"/> <field name="model_id" ref="crm.model_crm_team"/>
<field name="state">code</field> <field name="state">code</field>
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
<field name="code">action = model.action_your_pipeline()</field> <field name="code">action = model.action_your_pipeline()</field>
</record> </record>
@@ -243,7 +243,7 @@ class CRMLeadMiningRequest(models.Model):
def action_get_lead_action(self): def action_get_lead_action(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('crm.crm_lead_all_leads').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("crm.crm_lead_all_leads")
action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'lead')] action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'lead')]
action['help'] = _("""<p class="o_view_nocontent_empty_folder"> action['help'] = _("""<p class="o_view_nocontent_empty_folder">
No leads found No leads found
@@ -254,7 +254,7 @@ class CRMLeadMiningRequest(models.Model):
def action_get_opportunity_action(self): def action_get_opportunity_action(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('crm.crm_lead_opportunities').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("crm.crm_lead_opportunities")
action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'opportunity')] action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'opportunity')]
action['help'] = _("""<p class="o_view_nocontent_empty_folder"> action['help'] = _("""<p class="o_view_nocontent_empty_folder">
No opportunities found No opportunities found
@@ -111,13 +111,13 @@ class CRMRevealRule(models.Model):
rule.opportunity_count = mapping.get((rule.id, 'opportunity'), 0) rule.opportunity_count = mapping.get((rule.id, 'opportunity'), 0)
def action_get_lead_tree_view(self): def action_get_lead_tree_view(self):
action = self.env.ref('crm.crm_lead_all_leads').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("crm.crm_lead_all_leads")
action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'lead')] action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'lead')]
action['context'] = dict(self._context, create=False) action['context'] = dict(self._context, create=False)
return action return action
def action_get_opportunity_tree_view(self): def action_get_opportunity_tree_view(self):
action = self.env.ref('crm.crm_lead_opportunities').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("crm.crm_lead_opportunities")
action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'opportunity')] action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'opportunity')]
action['context'] = dict(self._context, create=False) action['context'] = dict(self._context, create=False)
return action return action
+1 -1
View File
@@ -219,7 +219,7 @@ class StockPicking(models.Model):
for tracker in carrier_trackers: for tracker in carrier_trackers:
msg += '<a href=' + tracker[1] + '>' + tracker[0] + '</a><br/>' msg += '<a href=' + tracker[1] + '>' + tracker[0] + '</a><br/>'
self.message_post(body=msg) self.message_post(body=msg)
return self.env.ref('delivery.act_delivery_trackers_url').read()[0] return self.env["ir.actions.actions"]._for_xml_id("delivery.act_delivery_trackers_url")
client_action = { client_action = {
'type': 'ir.actions.act_url', 'type': 'ir.actions.act_url',
+1 -1
View File
@@ -19,7 +19,7 @@ class ResPartner(models.Model):
partner.event_count = self.env['event.event'].search_count([('registration_ids.partner_id', 'child_of', partner.ids)]) partner.event_count = self.env['event.event'].search_count([('registration_ids.partner_id', 'child_of', partner.ids)])
def action_event_view(self): def action_event_view(self):
action = self.env.ref('event.action_event_view').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("event.action_event_view")
action['context'] = {} action['context'] = {}
action['domain'] = [('registration_ids.partner_id', 'child_of', self.ids)] action['domain'] = [('registration_ids.partner_id', 'child_of', self.ids)]
return action return action
+1 -1
View File
@@ -34,7 +34,7 @@ class Event(models.Model):
def action_view_linked_orders(self): def action_view_linked_orders(self):
""" Redirects to the orders linked to the current events """ """ Redirects to the orders linked to the current events """
sale_order_action = self.env.ref('sale.action_orders').read()[0] sale_order_action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
sale_order_action.update({ sale_order_action.update({
'domain': [('state', '!=', 'cancel'), ('order_line.event_id', 'in', self.ids)], 'domain': [('state', '!=', 'cancel'), ('order_line.event_id', 'in', self.ids)],
'context': {'create': 0}, 'context': {'create': 0},
@@ -58,7 +58,7 @@ class EventRegistration(models.Model):
registration.utm_medium_id = False registration.utm_medium_id = False
def action_view_sale_order(self): def action_view_sale_order(self):
action = self.env.ref('sale.action_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
action['views'] = [(False, 'form')] action['views'] = [(False, 'form')]
action['res_id'] = self.sale_order_id.id action['res_id'] = self.sale_order_id.id
return action return action
+2 -2
View File
@@ -26,11 +26,11 @@ class SaleOrder(models.Model):
if any(line.event_id for line in so.order_line): if any(line.event_id for line in so.order_line):
return self.env['ir.actions.act_window'] \ return self.env['ir.actions.act_window'] \
.with_context(default_sale_order_id=so.id) \ .with_context(default_sale_order_id=so.id) \
.for_xml_id('event_sale', 'action_sale_order_event_registration') ._for_xml_id('event_sale.action_sale_order_event_registration')
return res return res
def action_view_attendee_list(self): def action_view_attendee_list(self):
action = self.env.ref('event.event_registration_action_tree').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("event.event_registration_action_tree")
action['domain'] = [('sale_order_id', 'in', self.ids)] action['domain'] = [('sale_order_id', 'in', self.ids)]
return action return action
+3 -2
View File
@@ -281,7 +281,8 @@ class FleetVehicle(models.Model):
self.ensure_one() self.ensure_one()
xml_id = self.env.context.get('xml_id') xml_id = self.env.context.get('xml_id')
if xml_id: if xml_id:
res = self.env['ir.actions.act_window'].for_xml_id('fleet', xml_id)
res = self.env['ir.actions.act_window']._for_xml_id('fleet.%s' % xml_id)
res.update( res.update(
context=dict(self.env.context, default_vehicle_id=self.id, group_by=False), context=dict(self.env.context, default_vehicle_id=self.id, group_by=False),
domain=[('vehicle_id', '=', self.id)] domain=[('vehicle_id', '=', self.id)]
@@ -296,7 +297,7 @@ class FleetVehicle(models.Model):
self.ensure_one() self.ensure_one()
copy_context = dict(self.env.context) copy_context = dict(self.env.context)
copy_context.pop('group_by', None) copy_context.pop('group_by', None)
res = self.env['ir.actions.act_window'].for_xml_id('fleet', 'fleet_vehicle_costs_action') res = self.env['ir.actions.act_window']._for_xml_id('fleet.fleet_vehicle_costs_action')
res.update( res.update(
context=dict(copy_context, default_vehicle_id=self.id, search_default_parent_false=True), context=dict(copy_context, default_vehicle_id=self.id, search_default_parent_false=True),
domain=[('vehicle_id', '=', self.id)] domain=[('vehicle_id', '=', self.id)]
+1 -1
View File
@@ -188,7 +188,7 @@ class User(models.Model):
@api.model @api.model
def action_get(self): def action_get(self):
if self.env.user.employee_id: if self.env.user.employee_id:
return self.sudo().env.ref('hr.res_users_action_my').read()[0] return self.sudo().env.ref('hr.res_users_action_my').sudo().read()[0]
return super(User, self).action_get() return super(User, self).action_get()
@api.depends('employee_ids') @api.depends('employee_ids')
+1 -1
View File
@@ -124,7 +124,7 @@ class HrEmployeeBase(models.AbstractModel):
""" """
self.ensure_one() self.ensure_one()
employee = self.sudo() employee = self.sudo()
action_message = self.env.ref('hr_attendance.hr_attendance_action_greeting_message').read()[0] action_message = self.env["ir.actions.actions"]._for_xml_id("hr_attendance.hr_attendance_action_greeting_message")
action_message['previous_attendance_change_date'] = employee.last_attendance_id and (employee.last_attendance_id.check_out or employee.last_attendance_id.check_in) or False action_message['previous_attendance_change_date'] = employee.last_attendance_id and (employee.last_attendance_id.check_out or employee.last_attendance_id.check_in) or False
action_message['employee_name'] = employee.name action_message['employee_name'] = employee.name
action_message['barcode'] = employee.barcode action_message['barcode'] = employee.barcode
+2 -2
View File
@@ -325,7 +325,7 @@ class HrExpense(models.Model):
def action_get_attachment_view(self): def action_get_attachment_view(self):
self.ensure_one() self.ensure_one()
res = self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment') res = self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
res['domain'] = [('res_model', '=', 'hr.expense'), ('res_id', 'in', self.ids)] res['domain'] = [('res_model', '=', 'hr.expense'), ('res_id', 'in', self.ids)]
res['context'] = {'default_res_model': 'hr.expense', 'default_res_id': self.id} res['context'] = {'default_res_model': 'hr.expense', 'default_res_id': self.id}
return res return res
@@ -915,7 +915,7 @@ class HrExpenseSheet(models.Model):
return res return res
def action_get_attachment_view(self): def action_get_attachment_view(self):
res = self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment') res = self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
res['domain'] = [('res_model', '=', 'hr.expense'), ('res_id', 'in', self.expense_line_ids.ids)] res['domain'] = [('res_model', '=', 'hr.expense'), ('res_id', 'in', self.expense_line_ids.ids)]
res['context'] = { res['context'] = {
'default_res_model': 'hr.expense.sheet', 'default_res_model': 'hr.expense.sheet',
@@ -19,7 +19,7 @@ class FleetVehicleAssignationLog(models.Model):
def action_get_attachment_view(self): def action_get_attachment_view(self):
self.ensure_one() self.ensure_one()
res = self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment') res = self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
res['domain'] = [('res_model', '=', 'fleet.vehicle.assignation.log'), ('res_id', 'in', self.ids)] res['domain'] = [('res_model', '=', 'fleet.vehicle.assignation.log'), ('res_id', 'in', self.ids)]
res['context'] = {'default_res_model': 'fleet.vehicle.assignation.log', 'default_res_id': self.id} res['context'] = {'default_res_model': 'fleet.vehicle.assignation.log', 'default_res_id': self.id}
return res return res
+2 -2
View File
@@ -347,7 +347,7 @@ class HolidaysType(models.Model):
def action_see_days_allocated(self): def action_see_days_allocated(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('hr_holidays.hr_leave_allocation_action_all').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("hr_holidays.hr_leave_allocation_action_all")
domain = [ domain = [
('holiday_status_id', 'in', self.ids), ('holiday_status_id', 'in', self.ids),
('holiday_type', '!=', 'employee'), ('holiday_type', '!=', 'employee'),
@@ -366,7 +366,7 @@ class HolidaysType(models.Model):
def action_see_group_leaves(self): def action_see_group_leaves(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('hr_holidays.hr_leave_action_action_approve_department').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("hr_holidays.hr_leave_action_action_approve_department")
action['domain'] = [ action['domain'] = [
('holiday_status_id', '=', self.ids[0]), ('holiday_status_id', '=', self.ids[0]),
('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0))) ('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)))
+1 -1
View File
@@ -129,7 +129,7 @@ class Job(models.Model):
return self.env.ref('hr_recruitment.mt_job_new') return self.env.ref('hr_recruitment.mt_job_new')
def action_get_attachment_tree_view(self): def action_get_attachment_tree_view(self):
action = self.env.ref('base.action_attachment').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("base.action_attachment")
action['context'] = { action['context'] = {
'default_res_model': self._name, 'default_res_model': self._name,
'default_res_id': self.ids[0] 'default_res_id': self.ids[0]
@@ -339,7 +339,7 @@ class Applicant(models.Model):
partners = self.partner_id | self.user_id.partner_id | self.department_id.manager_id.user_id.partner_id partners = self.partner_id | self.user_id.partner_id | self.department_id.manager_id.user_id.partner_id
category = self.env.ref('hr_recruitment.categ_meet_interview') category = self.env.ref('hr_recruitment.categ_meet_interview')
res = self.env['ir.actions.act_window'].for_xml_id('calendar', 'action_calendar_event') res = self.env['ir.actions.act_window']._for_xml_id('calendar.action_calendar_event')
res['context'] = { res['context'] = {
'default_partner_ids': partners.ids, 'default_partner_ids': partners.ids,
'default_user_id': self.env.uid, 'default_user_id': self.env.uid,
@@ -98,7 +98,7 @@ class ImLivechatChannel(models.Model):
:returns : the ir.action 'action_view_rating' with the correct domain :returns : the ir.action 'action_view_rating' with the correct domain
""" """
self.ensure_one() self.ensure_one()
action = self.env['ir.actions.act_window'].for_xml_id('im_livechat', 'rating_rating_action_view_livechat_rating') action = self.env['ir.actions.act_window']._for_xml_id('im_livechat.rating_rating_action_view_livechat_rating')
action['domain'] = [('parent_res_id', '=', self.id), ('parent_res_model', '=', 'im_livechat.channel')] action['domain'] = [('parent_res_id', '=', self.id), ('parent_res_model', '=', 'im_livechat.channel')]
return action return action
+1 -1
View File
@@ -145,7 +145,7 @@ class LinkTracker(models.Model):
raise NotImplementedError('Moved on mail.render.mixin') raise NotImplementedError('Moved on mail.render.mixin')
def action_view_statistics(self): def action_view_statistics(self):
action = self.env['ir.actions.act_window'].for_xml_id('link_tracker', 'link_tracker_click_action_statistics') action = self.env['ir.actions.act_window']._for_xml_id('link_tracker.link_tracker_click_action_statistics')
action['domain'] = [('link_id', '=', self.id)] action['domain'] = [('link_id', '=', self.id)]
action['context'] = dict(self._context, create=False) action['context'] = dict(self._context, create=False)
return action return action
+2 -2
View File
@@ -300,7 +300,7 @@ class MassMailing(models.Model):
def action_schedule(self): def action_schedule(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('mass_mailing.mailing_mailing_schedule_date_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.mailing_mailing_schedule_date_action")
action['context'] = dict(self.env.context, default_mass_mailing_id=self.id) action['context'] = dict(self.env.context, default_mass_mailing_id=self.id)
return action return action
@@ -332,7 +332,7 @@ class MassMailing(models.Model):
return self._action_view_traces_filtered('sent') return self._action_view_traces_filtered('sent')
def _action_view_traces_filtered(self, view_filter): def _action_view_traces_filtered(self, view_filter):
action = self.env.ref('mass_mailing.mailing_trace_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.mailing_trace_action")
action['name'] = _('%s Traces') % (self.name) action['name'] = _('%s Traces') % (self.name)
action['context'] = {'search_default_mass_mailing_id': self.id,} action['context'] = {'search_default_mass_mailing_id': self.id,}
filter_key = 'search_default_filter_%s' % (view_filter) filter_key = 'search_default_filter_%s' % (view_filter)
+1 -1
View File
@@ -60,7 +60,7 @@ class MassMailingList(models.Model):
return [(list.id, "%s (%s)" % (list.name, list.contact_nbr)) for list in self] return [(list.id, "%s (%s)" % (list.name, list.contact_nbr)) for list in self]
def action_view_contacts(self): def action_view_contacts(self):
action = self.env.ref('mass_mailing.action_view_mass_mailing_contacts').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.action_view_mass_mailing_contacts")
action['domain'] = [('list_ids', 'in', self.ids)] action['domain'] = [('list_ids', 'in', self.ids)]
context = dict(self.env.context, search_default_filter_valid_email_recipient=1, default_list_ids=self.ids) context = dict(self.env.context, search_default_filter_valid_email_recipient=1, default_list_ids=self.ids)
action['context'] = context action['context'] = context
@@ -28,7 +28,7 @@ class MassMailing(models.Model):
def action_redirect_to_leads_and_opportunities(self): def action_redirect_to_leads_and_opportunities(self):
view = 'crm.crm_lead_all_leads' if self.use_leads else 'crm.crm_lead_opportunities' view = 'crm.crm_lead_all_leads' if self.use_leads else 'crm.crm_lead_opportunities'
action = self.env.ref(view).read()[0] action = self.env.ref(view).sudo().read()[0]
action['view_mode'] = 'tree,kanban,graph,pivot,form,calendar' action['view_mode'] = 'tree,kanban,graph,pivot,form,calendar'
action['domain'] = [('source_id', 'in', self.source_id.ids)] action['domain'] = [('source_id', 'in', self.source_id.ids)]
action['context'] = {'active_test': False, 'create': False} action['context'] = {'active_test': False, 'create': False}
@@ -29,13 +29,13 @@ class MassMailing(models.Model):
mass_mailing.sale_invoiced_amount = 0 mass_mailing.sale_invoiced_amount = 0
def action_redirect_to_quotations(self): def action_redirect_to_quotations(self):
action = self.env.ref('sale.action_quotations_with_onboarding').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_quotations_with_onboarding")
action['domain'] = self._get_sale_utm_domain() action['domain'] = self._get_sale_utm_domain()
action['context'] = {'create': False} action['context'] = {'create': False}
return action return action
def action_redirect_to_invoiced(self): def action_redirect_to_invoiced(self):
action = self.env.ref('account.action_move_out_invoice_type').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_out_invoice_type")
moves = self.env['account.move'].search(self._get_sale_utm_domain()) moves = self.env['account.move'].search(self._get_sale_utm_domain())
action['context'] = { action['context'] = {
'create': False, 'create': False,
@@ -28,7 +28,7 @@ group by list_id''', (tuple(self.ids), ))
def action_view_contacts(self): def action_view_contacts(self):
if self.env.context.get('mailing_sms'): if self.env.context.get('mailing_sms'):
action = self.env.ref('mass_mailing_sms.mailing_contact_action_sms').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing_sms.mailing_contact_action_sms")
action['domain'] = [('list_ids', 'in', self.ids)] action['domain'] = [('list_ids', 'in', self.ids)]
context = dict(self.env.context, search_default_filter_valid_sms_recipient=1, default_list_ids=self.ids) context = dict(self.env.context, search_default_filter_valid_sms_recipient=1, default_list_ids=self.ids)
action['context'] = context action['context'] = context
+2 -2
View File
@@ -19,7 +19,7 @@ class UtmCampaign(models.Model):
campaign.mailing_sms_count = len(campaign.mailing_sms_ids) campaign.mailing_sms_count = len(campaign.mailing_sms_ids)
def action_create_mass_sms(self): def action_create_mass_sms(self):
action = self.env.ref('mass_mailing.action_create_mass_mailings_from_campaign').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.action_create_mass_mailings_from_campaign")
action['context'] = { action['context'] = {
'default_campaign_id': self.id, 'default_campaign_id': self.id,
'default_mailing_type': 'sms', 'default_mailing_type': 'sms',
@@ -30,7 +30,7 @@ class UtmCampaign(models.Model):
return action return action
def action_redirect_to_mailing_sms(self): def action_redirect_to_mailing_sms(self):
action = self.env.ref('mass_mailing_sms.mailing_mailing_action_sms').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing_sms.mailing_mailing_action_sms")
action['context'] = { action['context'] = {
'default_campaign_id': self.id, 'default_campaign_id': self.id,
'default_mailing_type': 'sms', 'default_mailing_type': 'sms',
+4 -4
View File
@@ -394,7 +394,7 @@ class MrpProduction(models.Model):
view, if there is only one picking to show. view, if there is only one picking to show.
""" """
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_picking_tree_all').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_picking_tree_all")
pickings = self.mapped('picking_ids') pickings = self.mapped('picking_ids')
if len(pickings) > 1: if len(pickings) > 1:
action['domain'] = [('id', 'in', pickings.ids)] action['domain'] = [('id', 'in', pickings.ids)]
@@ -1247,7 +1247,7 @@ class MrpProduction(models.Model):
'product_expected_qty_uom': expected_qty 'product_expected_qty_uom': expected_qty
})) }))
ctx.update({'default_mrp_production_ids': self.ids, 'default_mrp_consumption_warning_line_ids': lines}) ctx.update({'default_mrp_production_ids': self.ids, 'default_mrp_consumption_warning_line_ids': lines})
action = self.env.ref('mrp.action_mrp_consumption_warning').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.action_mrp_consumption_warning")
action['context'] = ctx action['context'] = ctx
return action return action
@@ -1269,7 +1269,7 @@ class MrpProduction(models.Model):
'to_backorder': True 'to_backorder': True
})) }))
ctx.update({'default_mrp_production_ids': self.ids, 'default_mrp_production_backorder_line_ids': lines}) ctx.update({'default_mrp_production_ids': self.ids, 'default_mrp_production_backorder_line_ids': lines})
action = self.env.ref('mrp.action_mrp_production_backorder').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.action_mrp_production_backorder")
action['context'] = ctx action['context'] = ctx
return action return action
@@ -1559,7 +1559,7 @@ class MrpProduction(models.Model):
def action_see_move_scrap(self): def action_see_move_scrap(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_stock_scrap').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_stock_scrap")
action['domain'] = [('production_id', '=', self.id)] action['domain'] = [('production_id', '=', self.id)]
action['context'] = dict(self._context, default_origin=self.name) action['context'] = dict(self._context, default_origin=self.name)
return action return action
+1 -1
View File
@@ -192,7 +192,7 @@ class MrpWorkcenter(models.Model):
return super(MrpWorkcenter, self).write(vals) return super(MrpWorkcenter, self).write(vals)
def action_work_order(self): def action_work_order(self):
action = self.env.ref('mrp.action_work_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.action_work_orders")
return action return action
def _get_unavailability_intervals(self, start_datetime, end_datetime): def _get_unavailability_intervals(self, start_datetime, end_datetime):
+2 -2
View File
@@ -657,13 +657,13 @@ class MrpWorkorder(models.Model):
def action_see_move_scrap(self): def action_see_move_scrap(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_stock_scrap').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_stock_scrap")
action['domain'] = [('workorder_id', '=', self.id)] action['domain'] = [('workorder_id', '=', self.id)]
return action return action
def action_open_wizard(self): def action_open_wizard(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('mrp.mrp_workorder_mrp_production_form').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.mrp_workorder_mrp_production_form")
action['res_id'] = self.id action['res_id'] = self.id
return action return action
+4 -4
View File
@@ -39,7 +39,7 @@ class ProductTemplate(models.Model):
def action_used_in_bom(self): def action_used_in_bom(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('mrp.mrp_bom_form_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.mrp_bom_form_action")
action['domain'] = [('bom_line_ids.product_id', 'in', self.product_variant_ids.ids)] action['domain'] = [('bom_line_ids.product_id', 'in', self.product_variant_ids.ids)]
return action return action
@@ -48,7 +48,7 @@ class ProductTemplate(models.Model):
template.mrp_product_qty = float_round(sum(template.mapped('product_variant_ids').mapped('mrp_product_qty')), precision_rounding=template.uom_id.rounding) template.mrp_product_qty = float_round(sum(template.mapped('product_variant_ids').mapped('mrp_product_qty')), precision_rounding=template.uom_id.rounding)
def action_view_mos(self): def action_view_mos(self):
action = self.env.ref('mrp.mrp_production_report').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.mrp_production_report")
action['domain'] = [('state', '=', 'done'), ('product_tmpl_id', 'in', self.ids)] action['domain'] = [('state', '=', 'done'), ('product_tmpl_id', 'in', self.ids)]
action['context'] = { action['context'] = {
'graph_measure': 'product_uom_qty', 'graph_measure': 'product_uom_qty',
@@ -97,7 +97,7 @@ class ProductProduct(models.Model):
def action_used_in_bom(self): def action_used_in_bom(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('mrp.mrp_bom_form_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.mrp_bom_form_action")
action['domain'] = [('bom_line_ids.product_id', '=', self.id)] action['domain'] = [('bom_line_ids.product_id', '=', self.id)]
return action return action
@@ -163,7 +163,7 @@ class ProductProduct(models.Model):
product.free_qty = min(ratios_free_qty) // 1 product.free_qty = min(ratios_free_qty) // 1
def action_view_bom(self): def action_view_bom(self):
action = self.env.ref('mrp.product_open_bom').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("mrp.product_open_bom")
template_ids = self.mapped('product_tmpl_id').ids template_ids = self.mapped('product_tmpl_id').ids
# bom specific to this variant or global to template # bom specific to this variant or global to template
action['context'] = { action['context'] = {
+1 -1
View File
@@ -79,7 +79,7 @@ class MrpProduction(models.Model):
def action_view_stock_valuation_layers(self): def action_view_stock_valuation_layers(self):
self.ensure_one() self.ensure_one()
domain = [('id', 'in', (self.move_raw_ids + self.move_finished_ids + self.scrap_ids.move_id).stock_valuation_layer_ids.ids)] domain = [('id', 'in', (self.move_raw_ids + self.move_finished_ids + self.scrap_ids.move_id).stock_valuation_layer_ids.ids)]
action = self.env.ref('stock_account.stock_valuation_layer_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock_account.stock_valuation_layer_action")
context = literal_eval(action['context']) context = literal_eval(action['context'])
context.update(self.env.context) context.update(self.env.context)
context['no_at_date'] = True context['no_at_date'] = True
+1 -1
View File
@@ -22,7 +22,7 @@ class ResCompany(models.Model):
# Fail if there are no existing accounts # Fail if there are no existing accounts
self.env.company.get_chart_of_accounts_or_fail() self.env.company.get_chart_of_accounts_or_fail()
action = self.env.ref('payment.action_open_payment_onboarding_payment_acquirer_wizard').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("payment.action_open_payment_onboarding_payment_acquirer_wizard")
return action return action
def get_account_invoice_onboarding_steps_states_names(self): def get_account_invoice_onboarding_steps_states_names(self):
@@ -157,5 +157,5 @@ class PaymentWizard(models.TransientModel):
def action_onboarding_other_payment_acquirer(self): def action_onboarding_other_payment_acquirer(self):
self._set_payment_acquirer_onboarding_step_done() self._set_payment_acquirer_onboarding_step_done()
action = self.env.ref('payment.action_payment_acquirer').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("payment.action_payment_acquirer")
return action return action
+1 -1
View File
@@ -122,7 +122,7 @@ class PortalMixin(models.AbstractModel):
@api.model @api.model
def action_share(self): def action_share(self):
action = self.env.ref('portal.portal_share_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("portal.portal_share_action")
action['context'] = {'active_id': self.env.context['active_id'], action['context'] = {'active_id': self.env.context['active_id'],
'active_model': self.env.context['active_model']} 'active_model': self.env.context['active_model']}
return action return action
+6 -4
View File
@@ -429,20 +429,22 @@ class Project(models.Model):
favorite_projects.write({'favorite_user_ids': [(3, self.env.uid)]}) favorite_projects.write({'favorite_user_ids': [(3, self.env.uid)]})
def action_view_tasks(self): def action_view_tasks(self):
action = self.with_context(active_id=self.id, active_ids=self.ids).env.ref('project.act_project_project_2_project_task_all').read()[0] action = self.with_context(active_id=self.id, active_ids=self.ids) \
.env.ref('project.act_project_project_2_project_task_all') \
.sudo().read()[0]
action['display_name'] = self.name action['display_name'] = self.name
return action return action
def action_view_account_analytic_line(self): def action_view_account_analytic_line(self):
""" return the action to see all the analytic lines of the project's analytic account """ """ return the action to see all the analytic lines of the project's analytic account """
action = self.env.ref('analytic.account_analytic_line_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("analytic.account_analytic_line_action")
action['context'] = {'default_account_id': self.analytic_account_id.id} action['context'] = {'default_account_id': self.analytic_account_id.id}
action['domain'] = [('account_id', '=', self.analytic_account_id.id)] action['domain'] = [('account_id', '=', self.analytic_account_id.id)]
return action return action
def action_view_all_rating(self): def action_view_all_rating(self):
""" return the action to see all the rating of the project and activate default filters""" """ return the action to see all the rating of the project and activate default filters"""
action = self.env['ir.actions.act_window'].for_xml_id('project', 'rating_rating_action_view_project_rating') action = self.env['ir.actions.act_window']._for_xml_id('project.rating_rating_action_view_project_rating')
action['name'] = _('Ratings of %s') % (self.name,) action['name'] = _('Ratings of %s') % (self.name,)
action_context = ast.literal_eval(action['context']) if action['context'] else {} action_context = ast.literal_eval(action['context']) if action['context'] else {}
action_context.update(self._context) action_context.update(self._context)
@@ -1320,7 +1322,7 @@ class Task(models.Model):
} }
def action_subtask(self): def action_subtask(self):
action = self.env.ref('project.project_task_action_sub_task').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("project.project_task_action_sub_task")
# display all subtasks of current task # display all subtasks of current task
action['domain'] = [('id', 'child_of', self.id), ('id', '!=', self.id)] action['domain'] = [('id', 'child_of', self.id), ('id', '!=', self.id)]
@@ -25,4 +25,4 @@ class ProjectDelete(models.TransientModel):
def confirm_delete(self): def confirm_delete(self):
self.with_context(active_test=False).project_ids.unlink() self.with_context(active_test=False).project_ids.unlink()
return self.env.ref('project.open_view_project_all_config').read()[0] return self.env["ir.actions.actions"]._for_xml_id("project.open_view_project_all_config")
@@ -55,16 +55,16 @@ class ProjectTaskTypeDelete(models.TransientModel):
project_id = self.env.context.get('default_project_id') project_id = self.env.context.get('default_project_id')
if project_id: if project_id:
action = self.env.ref('project.action_view_task').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("project.action_view_task")
action['domain'] = [('project_id', '=', project_id)] action['domain'] = [('project_id', '=', project_id)]
action['context'] = str({ action['context'] = str({
'pivot_row_groupby': ['user_id'], 'pivot_row_groupby': ['user_id'],
'default_project_id': project_id, 'default_project_id': project_id,
}) })
elif self.env.context.get('stage_view'): elif self.env.context.get('stage_view'):
action = self.env.ref('project.open_task_type_form').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("project.open_task_type_form")
else: else:
action = self.env.ref('project.action_view_all_task').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("project.action_view_all_task")
context = dict(ast.literal_eval(action.get('context')), active_test=True) context = dict(ast.literal_eval(action.get('context')), active_test=True)
action['context'] = context action['context'] = context
+2 -2
View File
@@ -40,7 +40,7 @@ class ProductTemplate(models.Model):
return res return res
def action_view_po(self): def action_view_po(self):
action = self.env.ref('purchase.action_purchase_order_report_all').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("purchase.action_purchase_order_report_all")
action['domain'] = ['&', ('state', 'in', ['purchase', 'done']), ('product_tmpl_id', 'in', self.ids)] action['domain'] = ['&', ('state', 'in', ['purchase', 'done']), ('product_tmpl_id', 'in', self.ids)]
action['context'] = { action['context'] = {
'graph_measure': 'qty_ordered', 'graph_measure': 'qty_ordered',
@@ -71,7 +71,7 @@ class ProductProduct(models.Model):
product.purchased_product_qty = float_round(purchased_data.get(product.id, 0), precision_rounding=product.uom_id.rounding) product.purchased_product_qty = float_round(purchased_data.get(product.id, 0), precision_rounding=product.uom_id.rounding)
def action_view_po(self): def action_view_po(self):
action = self.env.ref('purchase.action_purchase_order_report_all').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("purchase.action_purchase_order_report_all")
action['domain'] = ['&', ('state', 'in', ['purchase', 'done']), ('product_id', 'in', self.ids)] action['domain'] = ['&', ('state', 'in', ['purchase', 'done']), ('product_id', 'in', self.ids)]
action['context'] = { action['context'] = {
'graph_measure': 'qty_ordered', 'graph_measure': 'qty_ordered',
+1 -1
View File
@@ -555,7 +555,7 @@ class PurchaseOrder(models.Model):
self.sudo()._read(['invoice_ids']) self.sudo()._read(['invoice_ids'])
invoices = self.invoice_ids invoices = self.invoice_ids
action = self.env.ref('account.action_move_in_invoice_type') action = self.env.ref('account.action_move_in_invoice_type').sudo()
result = action.read()[0] result = action.read()[0]
# choose the view_mode accordingly # choose the view_mode accordingly
if len(invoices) > 1: if len(invoices) > 1:
+1 -1
View File
@@ -272,7 +272,7 @@ class ProductionLot(models.Model):
def action_view_po(self): def action_view_po(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('purchase.purchase_form_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("purchase.purchase_form_action")
action['domain'] = [('id', 'in', self.mapped('purchase_order_ids.id'))] action['domain'] = [('id', 'in', self.mapped('purchase_order_ids.id'))]
action['context'] = dict(self._context, create=False) action['context'] = dict(self._context, create=False)
return action return action
+1 -1
View File
@@ -35,7 +35,7 @@ class ProductProduct(models.Model):
return r return r
def action_view_sales(self): def action_view_sales(self):
action = self.env.ref('sale.report_all_channels_sales_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.report_all_channels_sales_action")
action['domain'] = [('product_id', 'in', self.ids)] action['domain'] = [('product_id', 'in', self.ids)]
action['context'] = { action['context'] = {
'pivot_measures': ['product_uom_qty'], 'pivot_measures': ['product_uom_qty'],
+1 -1
View File
@@ -77,7 +77,7 @@ class ProductTemplate(models.Model):
'shared product.') % (target_company.name, ', '.join(used_products))) 'shared product.') % (target_company.name, ', '.join(used_products)))
def action_view_sales(self): def action_view_sales(self):
action = self.env.ref('sale.report_all_channels_sales_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.report_all_channels_sales_action")
action['domain'] = [('product_tmpl_id', 'in', self.ids)] action['domain'] = [('product_tmpl_id', 'in', self.ids)]
action['context'] = { action['context'] = {
'pivot_measures': ['product_uom_qty'], 'pivot_measures': ['product_uom_qty'],
+2 -2
View File
@@ -33,7 +33,7 @@ class ResCompany(models.Model):
def action_open_sale_onboarding_payment_acquirer(self): def action_open_sale_onboarding_payment_acquirer(self):
""" Called by onboarding panel above the quotation list.""" """ Called by onboarding panel above the quotation list."""
self.env.company.get_chart_of_accounts_or_fail() self.env.company.get_chart_of_accounts_or_fail()
action = self.env.ref('sale.action_open_sale_onboarding_payment_acquirer_wizard').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_open_sale_onboarding_payment_acquirer_wizard")
return action return action
def _get_sample_sales_order(self): def _get_sample_sales_order(self):
@@ -94,7 +94,7 @@ class ResCompany(models.Model):
self.action_close_sale_quotation_onboarding() self.action_close_sale_quotation_onboarding()
action = self.env.ref('sale.action_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
action.update({ action.update({
'views': [[self.env.ref('sale.view_order_form').id, 'form']], 'views': [[self.env.ref('sale.view_order_form').id, 'form']],
'view_mode': 'form', 'view_mode': 'form',
+1 -1
View File
@@ -570,7 +570,7 @@ class SaleOrder(models.Model):
def action_view_invoice(self): def action_view_invoice(self):
invoices = self.mapped('invoice_ids') invoices = self.mapped('invoice_ids')
action = self.env.ref('account.action_move_out_invoice_type').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_out_invoice_type")
if len(invoices) > 1: if len(invoices) > 1:
action['domain'] = [('id', 'in', invoices.ids)] action['domain'] = [('id', 'in', invoices.ids)]
elif len(invoices) == 1: elif len(invoices) == 1:
+1 -1
View File
@@ -130,7 +130,7 @@ class CrmTeam(models.Model):
def action_primary_channel_button(self): def action_primary_channel_button(self):
if self._context.get('in_sales_app'): if self._context.get('in_sales_app'):
return self.env.ref('sale.action_order_report_so_salesteam').read()[0] return self.env["ir.actions.actions"]._for_xml_id("sale.action_order_report_so_salesteam")
return super(CrmTeam, self).action_primary_channel_button() return super(CrmTeam, self).action_primary_channel_button()
def update_invoiced_target(self, value): def update_invoiced_target(self, value):
+2 -2
View File
@@ -46,13 +46,13 @@ class UtmCampaign(models.Model):
campaign.invoiced_amount = 0 campaign.invoiced_amount = 0
def action_redirect_to_quotations(self): def action_redirect_to_quotations(self):
action = self.env.ref('sale.action_quotations_with_onboarding').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_quotations_with_onboarding")
action['domain'] = [('campaign_id', '=', self.id)] action['domain'] = [('campaign_id', '=', self.id)]
action['context'] = {'default_campaign_id': self.id} action['context'] = {'default_campaign_id': self.id}
return action return action
def action_redirect_to_invoiced(self): def action_redirect_to_invoiced(self):
action = self.env.ref('account.action_move_journal_line').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("account.action_move_journal_line")
invoices = self.env['account.move'].search([('campaign_id', '=', self.id)]) invoices = self.env['account.move'].search([('campaign_id', '=', self.id)])
action['context'] = { action['context'] = {
'create': False, 'create': False,
+4 -4
View File
@@ -34,12 +34,12 @@ class CrmLead(models.Model):
def action_sale_quotations_new(self): def action_sale_quotations_new(self):
if not self.partner_id: if not self.partner_id:
return self.env.ref("sale_crm.crm_quotation_partner_action").read()[0] return self.env["ir.actions.actions"]._for_xml_id("sale_crm.crm_quotation_partner_action")
else: else:
return self.action_new_quotation() return self.action_new_quotation()
def action_new_quotation(self): def action_new_quotation(self):
action = self.env.ref("sale_crm.sale_action_quotations_new").read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale_crm.sale_action_quotations_new")
action['context'] = { action['context'] = {
'search_default_opportunity_id': self.id, 'search_default_opportunity_id': self.id,
'default_opportunity_id': self.id, 'default_opportunity_id': self.id,
@@ -56,7 +56,7 @@ class CrmLead(models.Model):
return action return action
def action_view_sale_quotation(self): def action_view_sale_quotation(self):
action = self.env.ref('sale.action_quotations_with_onboarding').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_quotations_with_onboarding")
action['context'] = { action['context'] = {
'search_default_draft': 1, 'search_default_draft': 1,
'search_default_partner_id': self.partner_id.id, 'search_default_partner_id': self.partner_id.id,
@@ -71,7 +71,7 @@ class CrmLead(models.Model):
return action return action
def action_view_sale_order(self): def action_view_sale_order(self):
action = self.env.ref('sale.action_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
action['context'] = { action['context'] = {
'search_default_partner_id': self.partner_id.id, 'search_default_partner_id': self.partner_id.id,
'default_partner_id': self.partner_id.id, 'default_partner_id': self.partner_id.id,
+1 -1
View File
@@ -15,7 +15,7 @@ class CrmTeam(models.Model):
def action_primary_channel_button(self): def action_primary_channel_button(self):
if self._context.get('in_sales_app') and self.use_opportunities: if self._context.get('in_sales_app') and self.use_opportunities:
return self.env.ref('sale.action_order_report_so_salesteam').read()[0] return self.env["ir.actions.actions"]._for_xml_id("sale.action_order_report_so_salesteam")
return super(CrmTeam,self).action_primary_channel_button() return super(CrmTeam,self).action_primary_channel_button()
def _graph_get_model(self): def _graph_get_model(self):
+1 -1
View File
@@ -134,7 +134,7 @@ class ProjectTask(models.Model):
so_to_confirm.action_confirm() so_to_confirm.action_confirm()
# redirect create invoice wizard (of the Sales Order) # redirect create invoice wizard (of the Sales Order)
action = self.env.ref('sale.action_view_sale_advance_payment_inv').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_view_sale_advance_payment_inv")
context = literal_eval(action.get('context', "{}")) context = literal_eval(action.get('context', "{}"))
context.update({ context.update({
'active_id': self.sale_order_id.id if len(self) == 1 else False, 'active_id': self.sale_order_id.id if len(self) == 1 else False,
+1 -1
View File
@@ -72,7 +72,7 @@ class SaleOrder(models.Model):
eval_context.update({'active_id': task_projects.id}) eval_context.update({'active_id': task_projects.id})
action['context'] = safe_eval(action['context'], eval_context) action['context'] = safe_eval(action['context'], eval_context)
else: else:
action = self.env.ref('project.action_view_task').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("project.action_view_task")
action['context'] = {} # erase default context to avoid default filter action['context'] = {} # erase default context to avoid default filter
if len(self.tasks_ids) > 1: # cross project kanban task if len(self.tasks_ids) > 1: # cross project kanban task
action['views'] = [[False, 'kanban'], [list_view_id, 'tree'], [form_view_id, 'form'], [False, 'graph'], [False, 'calendar'], [False, 'pivot']] action['views'] = [[False, 'kanban'], [list_view_id, 'tree'], [form_view_id, 'form'], [False, 'graph'], [False, 'calendar'], [False, 'pivot']]
+1 -1
View File
@@ -180,7 +180,7 @@ class SaleOrder(models.Model):
of given sales order ids. It can either be a in a list or in a form of given sales order ids. It can either be a in a list or in a form
view, if there is only one delivery order to show. view, if there is only one delivery order to show.
''' '''
action = self.env.ref('stock.action_picking_tree_all').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_picking_tree_all")
pickings = self.mapped('picking_ids') pickings = self.mapped('picking_ids')
if len(pickings) > 1: if len(pickings) > 1:
+1 -1
View File
@@ -135,7 +135,7 @@ class ProductionLot(models.Model):
def action_view_so(self): def action_view_so(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('sale.action_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
action['domain'] = [('id', 'in', self.mapped('sale_order_ids.id'))] action['domain'] = [('id', 'in', self.mapped('sale_order_ids.id'))]
action['context'] = dict(self._context, create=False) action['context'] = dict(self._context, create=False)
return action return action
+1 -1
View File
@@ -132,7 +132,7 @@ class Project(models.Model):
} }
def action_view_timesheet_plan(self): def action_view_timesheet_plan(self):
action = self.env.ref('sale_timesheet.project_timesheet_action_client_timesheet_plan').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale_timesheet.project_timesheet_action_client_timesheet_plan")
action['params'] = { action['params'] = {
'project_ids': self.ids, 'project_ids': self.ids,
} }
@@ -542,7 +542,7 @@ def _to_action_data(model=None, *, action=None, views=None, res_id=None, domain=
# pass in either action or (model, views) # pass in either action or (model, views)
if action: if action:
assert model is None and views is None assert model is None and views is None
act = clean_action(action.read()[0]) act = clean_action(action.read()[0], env=action.env)
model = act['res_model'] model = act['res_model']
views = act['views'] views = act['views']
# FIXME: search-view-id, possibly help? # FIXME: search-view-id, possibly help?
+1 -1
View File
@@ -52,7 +52,7 @@ class SaleOrder(models.Model):
def action_view_timesheet(self): def action_view_timesheet(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('sale_timesheet.timesheet_action_from_sales_order').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale_timesheet.timesheet_action_from_sales_order")
action['context'] = {} # erase default filters action['context'] = {} # erase default filters
if self.timesheet_count > 0: if self.timesheet_count > 0:
action['domain'] = [('so_line', 'in', self.order_line.ids)] action['domain'] = [('so_line', 'in', self.order_line.ids)]
@@ -51,7 +51,7 @@ class ProjectCreateInvoice(models.TransientModel):
def action_create_invoice(self): def action_create_invoice(self):
if not self.sale_order_id and self.sale_order_id.invoice_status != 'to invoice': if not self.sale_order_id and self.sale_order_id.invoice_status != 'to invoice':
raise UserError(_("The selected Sales Order should contain something to invoice.")) raise UserError(_("The selected Sales Order should contain something to invoice."))
action = self.env.ref('sale.action_view_sale_advance_payment_inv').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_view_sale_advance_payment_inv")
action['context'] = { action['context'] = {
'active_ids': self.sale_order_id.ids 'active_ids': self.sale_order_id.ids
} }
@@ -75,7 +75,7 @@ class ProjectCreateSalesOrder(models.TransientModel):
sale_order = self._create_sale_order() sale_order = self._create_sale_order()
view_form_id = self.env.ref('sale.view_order_form').id view_form_id = self.env.ref('sale.view_order_form').id
action = self.env.ref('sale.action_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
action.update({ action.update({
'views': [(view_form_id, 'form')], 'views': [(view_form_id, 'form')],
'view_mode': 'form', 'view_mode': 'form',
@@ -44,7 +44,7 @@ class ProjectTaskCreateSalesOrder(models.TransientModel):
sale_order = self._prepare_sale_order() sale_order = self._prepare_sale_order()
sale_order.action_confirm() sale_order.action_confirm()
view_form_id = self.env.ref('sale.view_order_form').id view_form_id = self.env.ref('sale.view_order_form').id
action = self.env.ref('sale.action_orders').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("sale.action_orders")
action.update({ action.update({
'views': [(view_form_id, 'form')], 'views': [(view_form_id, 'form')],
'view_mode': 'form', 'view_mode': 'form',
+9 -9
View File
@@ -431,7 +431,7 @@ class Product(models.Model):
return res return res
def action_view_orderpoints(self): def action_view_orderpoints(self):
action = self.env.ref('stock.action_orderpoint').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_orderpoint")
action['context'] = literal_eval(action.get('context')) action['context'] = literal_eval(action.get('context'))
action['context'].pop('search_default_trigger', False) action['context'].pop('search_default_trigger', False)
action['context'].update({ action['context'].update({
@@ -451,7 +451,7 @@ class Product(models.Model):
def action_view_stock_move_lines(self): def action_view_stock_move_lines(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.stock_move_line_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_move_line_action")
action['domain'] = [('product_id', '=', self.id)] action['domain'] = [('product_id', '=', self.id)]
return action return action
@@ -466,7 +466,7 @@ class Product(models.Model):
def action_open_product_lot(self): def action_open_product_lot(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_production_lot_form').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_production_lot_form")
action['domain'] = [('product_id', '=', self.id)] action['domain'] = [('product_id', '=', self.id)]
action['context'] = { action['context'] = {
'default_product_id': self.id, 'default_product_id': self.id,
@@ -513,7 +513,7 @@ class Product(models.Model):
def action_product_forecast_report(self): def action_product_forecast_report(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.stock_replenishment_product_product_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_replenishment_product_product_action")
return action return action
@api.model @api.model
@@ -758,7 +758,7 @@ class ProductTemplate(models.Model):
return self.action_open_quants() return self.action_open_quants()
else: else:
default_product_id = len(self.product_variant_ids) == 1 and self.product_variant_id.id default_product_id = len(self.product_variant_ids) == 1 and self.product_variant_id.id
action = self.env.ref('stock.action_change_product_quantity').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_change_product_quantity")
action['context'] = dict( action['context'] = dict(
self.env.context, self.env.context,
default_product_id=default_product_id, default_product_id=default_product_id,
@@ -780,13 +780,13 @@ class ProductTemplate(models.Model):
def action_view_stock_move_lines(self): def action_view_stock_move_lines(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.stock_move_line_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_move_line_action")
action['domain'] = [('product_id.product_tmpl_id', 'in', self.ids)] action['domain'] = [('product_id.product_tmpl_id', 'in', self.ids)]
return action return action
def action_open_product_lot(self): def action_open_product_lot(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_production_lot_form').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_production_lot_form")
action['domain'] = [('product_id.product_tmpl_id', '=', self.id)] action['domain'] = [('product_id.product_tmpl_id', '=', self.id)]
action['context'] = { action['context'] = {
'default_product_tmpl_id': self.id, 'default_product_tmpl_id': self.id,
@@ -811,13 +811,13 @@ class ProductTemplate(models.Model):
'product_id': products.id, 'product_id': products.id,
'warehouse_ids': warehouse.ids, 'warehouse_ids': warehouse.ids,
}, config=False) }, config=False)
action = self.env.ref('stock.action_stock_rules_report').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_stock_rules_report")
action['context'] = self.env.context action['context'] = self.env.context
return action return action
def action_product_tmpl_forecast_report(self): def action_product_tmpl_forecast_report(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.stock_replenishment_product_product_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id('stock.stock_replenishment_product_product_action')
return action return action
class ProductCategory(models.Model): class ProductCategory(models.Model):
+1 -1
View File
@@ -673,7 +673,7 @@ class StockMove(models.Model):
""" Opens a wizard to assign SN's name on each move lines. """ Opens a wizard to assign SN's name on each move lines.
""" """
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.act_assign_serial_numbers').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.act_assign_serial_numbers")
action['context'] = { action['context'] = {
'default_product_id': self.product_id.id, 'default_product_id': self.product_id.id,
'default_move_id': self.id, 'default_move_id': self.id,
+1 -1
View File
@@ -291,7 +291,7 @@ class StockWarehouseOrderpoint(models.Model):
return replenish report ir.actions.act_window return replenish report ir.actions.act_window
""" """
action = self.env.ref('stock.action_orderpoint_replenish').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_orderpoint_replenish")
action['context'] = self.env.context action['context'] = self.env.context
orderpoints = self.env['stock.warehouse.orderpoint'].search([]) orderpoints = self.env['stock.warehouse.orderpoint'].search([])
# Remove previous automatically created orderpoint that has been refilled. # Remove previous automatically created orderpoint that has been refilled.
+4 -4
View File
@@ -200,7 +200,7 @@ class PickingType(models.Model):
self.show_reserved = True self.show_reserved = True
def _get_action(self, action_xmlid): def _get_action(self, action_xmlid):
action = self.env.ref(action_xmlid).read()[0] action = self.env["ir.actions.actions"]._for_xml_id(action_xmlid)
if self: if self:
action['display_name'] = self.display_name action['display_name'] = self.display_name
@@ -1365,7 +1365,7 @@ class Picking(models.Model):
def action_see_move_scrap(self): def action_see_move_scrap(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_stock_scrap').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_stock_scrap")
scraps = self.env['stock.scrap'].search([('picking_id', '=', self.id)]) scraps = self.env['stock.scrap'].search([('picking_id', '=', self.id)])
action['domain'] = [('id', 'in', scraps.ids)] action['domain'] = [('id', 'in', scraps.ids)]
action['context'] = dict(self._context, create=False) action['context'] = dict(self._context, create=False)
@@ -1373,14 +1373,14 @@ class Picking(models.Model):
def action_see_packages(self): def action_see_packages(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.action_package_view').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_package_view")
packages = self.move_line_ids.mapped('result_package_id') packages = self.move_line_ids.mapped('result_package_id')
action['domain'] = [('id', 'in', packages.ids)] action['domain'] = [('id', 'in', packages.ids)]
action['context'] = {'picking_id': self.id} action['context'] = {'picking_id': self.id}
return action return action
def action_picking_move_tree(self): def action_picking_move_tree(self):
action = self.env.ref('stock.stock_move_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_move_action")
action['views'] = [ action['views'] = [
(self.env.ref('stock.view_picking_move_tree').id, 'tree'), (self.env.ref('stock.view_picking_move_tree').id, 'tree'),
] ]
+2 -2
View File
@@ -202,7 +202,7 @@ class StockQuant(models.Model):
def action_view_stock_moves(self): def action_view_stock_moves(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock.stock_move_line_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.stock_move_line_action")
action['domain'] = [ action['domain'] = [
('product_id', '=', self.product_id.id), ('product_id', '=', self.product_id.id),
'|', '|',
@@ -718,7 +718,7 @@ class QuantPackage(models.Model):
self.env['stock.quant']._unlink_zero_quants() self.env['stock.quant']._unlink_zero_quants()
def action_view_picking(self): def action_view_picking(self):
action = self.env.ref('stock.action_picking_tree_all').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock.action_picking_tree_all")
domain = ['|', ('result_package_id', 'in', self.ids), ('package_id', 'in', self.ids)] domain = ['|', ('result_package_id', 'in', self.ids), ('package_id', 'in', self.ids)]
pickings = self.env['stock.move.line'].search(domain).mapped('picking_id') pickings = self.env['stock.move.line'].search(domain).mapped('picking_id')
action['domain'] = [('id', 'in', pickings.ids)] action['domain'] = [('id', 'in', pickings.ids)]
+1 -1
View File
@@ -13,7 +13,7 @@ class StockPicking(models.Model):
self.ensure_one() self.ensure_one()
scraps = self.env['stock.scrap'].search([('picking_id', '=', self.id)]) scraps = self.env['stock.scrap'].search([('picking_id', '=', self.id)])
domain = [('id', 'in', (self.move_lines + scraps.move_id).stock_valuation_layer_ids.ids)] domain = [('id', 'in', (self.move_lines + scraps.move_id).stock_valuation_layer_ids.ids)]
action = self.env.ref('stock_account.stock_valuation_layer_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock_account.stock_valuation_layer_action")
context = literal_eval(action['context']) context = literal_eval(action['context'])
context.update(self.env.context) context.update(self.env.context)
context['no_at_date'] = True context['no_at_date'] = True
@@ -9,7 +9,7 @@ class StockQuantityHistory(models.TransientModel):
def open_at_date(self): def open_at_date(self):
active_model = self.env.context.get('active_model') active_model = self.env.context.get('active_model')
if active_model == 'stock.valuation.layer': if active_model == 'stock.valuation.layer':
action = self.env.ref('stock_account.stock_valuation_layer_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock_account.stock_valuation_layer_action")
action['domain'] = [('create_date', '<=', self.inventory_datetime)] action['domain'] = [('create_date', '<=', self.inventory_datetime)]
action['display_name'] = str(self.inventory_datetime) action['display_name'] = str(self.inventory_datetime)
return action return action
@@ -35,12 +35,12 @@ class AccountMove(models.Model):
'split_method': 'equal', 'split_method': 'equal',
}) for l in landed_costs_lines], }) for l in landed_costs_lines],
}) })
action = self.env.ref('stock_landed_costs.action_stock_landed_cost').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock_landed_costs.action_stock_landed_cost")
return dict(action, view_mode='form', res_id=landed_costs.id, views=[(False, 'form')]) return dict(action, view_mode='form', res_id=landed_costs.id, views=[(False, 'form')])
def action_view_landed_costs(self): def action_view_landed_costs(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('stock_landed_costs.action_stock_landed_cost').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock_landed_costs.action_stock_landed_cost")
domain = [('id', 'in', self.landed_costs_ids.ids)] domain = [('id', 'in', self.landed_costs_ids.ids)]
context = dict(self.env.context, default_vendor_bill_id=self.id) context = dict(self.env.context, default_vendor_bill_id=self.id)
views = [(self.env.ref('stock_landed_costs.view_stock_landed_cost_tree2').id, 'tree'), (False, 'form'), (False, 'kanban')] views = [(self.env.ref('stock_landed_costs.view_stock_landed_cost_tree2').id, 'tree'), (False, 'form'), (False, 'kanban')]
@@ -273,7 +273,7 @@ class StockLandedCost(models.Model):
def action_view_stock_valuation_layers(self): def action_view_stock_valuation_layers(self):
self.ensure_one() self.ensure_one()
domain = [('id', 'in', self.stock_valuation_layer_ids.ids)] domain = [('id', 'in', self.stock_valuation_layer_ids.ids)]
action = self.env.ref('stock_account.stock_valuation_layer_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("stock_account.stock_valuation_layer_action")
return dict(action, domain=domain) return dict(action, domain=domain)
def _get_targeted_move_ids(self): def _get_targeted_move_ids(self):
+1 -1
View File
@@ -25,7 +25,7 @@ class ResPartner(models.Model):
self.certifications_company_count = sum(child.certifications_count for child in self.child_ids) self.certifications_company_count = sum(child.certifications_count for child in self.child_ids)
def action_view_certifications(self): def action_view_certifications(self):
action = self.env.ref('survey.res_partner_action_certifications').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("survey.res_partner_action_certifications")
action['view_mode'] = 'tree' action['view_mode'] = 'tree'
action['domain'] = ['|', ('partner_id', 'in', self.ids), ('partner_id', 'in', self.child_ids.ids)] action['domain'] = ['|', ('partner_id', 'in', self.ids), ('partner_id', 'in', self.child_ids.ids)]
@@ -25,6 +25,7 @@ class TestServerAction(TestMailFullCommon, TestRecipients):
'model_id': cls.env['ir.model']._get('mail.test.sms').id, 'model_id': cls.env['ir.model']._get('mail.test.sms').id,
'state': 'sms', 'state': 'sms',
'sms_template_id': cls.sms_template.id, 'sms_template_id': cls.sms_template.id,
'groups_id': cls.env.ref('base.group_user'),
}) })
def test_action_sms(self): def test_action_sms(self):
+16 -9
View File
@@ -324,12 +324,18 @@ def set_cookie_and_redirect(redirect_url):
redirect.autocorrect_location_header = False redirect.autocorrect_location_header = False
return redirect return redirect
def clean_action(action): def clean_action(action, env):
action.setdefault('flags', {}) action.setdefault('flags', {})
action_type = action.setdefault('type', 'ir.actions.act_window_close') action_type = action.setdefault('type', 'ir.actions.act_window_close')
if action_type == 'ir.actions.act_window': if action_type == 'ir.actions.act_window':
return fix_view_modes(action) action = fix_view_modes(action)
return action
# When returning an action, only few information are really usefull
return {
field: value
for field, value in action.items()
if field in env[action['type']]._get_readable_fields()
}
# I think generate_views,fix_view_modes should go into js ActionManager # I think generate_views,fix_view_modes should go into js ActionManager
def generate_views(action): def generate_views(action):
@@ -1357,7 +1363,7 @@ class DataSet(http.Controller):
def call_button(self, model, method, args, kwargs): def call_button(self, model, method, args, kwargs):
action = self._call_kw(model, method, args, kwargs) action = self._call_kw(model, method, args, kwargs)
if isinstance(action, dict) and action.get('type') != '': if isinstance(action, dict) and action.get('type') != '':
return clean_action(action) return clean_action(action, env=request.env)
return False return False
@http.route('/web/dataset/resequence', type='json', auth="user") @http.route('/web/dataset/resequence', type='json', auth="user")
@@ -1687,7 +1693,7 @@ class Action(http.Controller):
except Exception: except Exception:
action_id = 0 # force failed read action_id = 0 # force failed read
base_action = Actions.browse([action_id]).read(['type']) base_action = Actions.browse([action_id]).sudo().read(['type'])
if base_action: if base_action:
ctx = dict(request.context) ctx = dict(request.context)
action_type = base_action[0]['type'] action_type = base_action[0]['type']
@@ -1696,15 +1702,16 @@ class Action(http.Controller):
if additional_context: if additional_context:
ctx.update(additional_context) ctx.update(additional_context)
request.context = ctx request.context = ctx
action = request.env[action_type].browse([action_id]).read() action = request.env[action_type].sudo().browse([action_id]).read()
if action: if action:
value = clean_action(action[0]) value = clean_action(action[0], env=request.env)
return value return value
@http.route('/web/action/run', type='json', auth="user") @http.route('/web/action/run', type='json', auth="user")
def run(self, action_id): def run(self, action_id):
result = request.env['ir.actions.server'].browse([action_id]).run() action = request.env['ir.actions.server'].browse([action_id])
return clean_action(result) if result else False result = action.run()
return clean_action(result, env=action.env) if result else False
class Export(http.Controller): class Export(http.Controller):
+2 -2
View File
@@ -10,7 +10,7 @@ class Company(models.Model):
@api.model @api.model
def action_open_website_theme_selector(self): def action_open_website_theme_selector(self):
action = self.env.ref('website.theme_install_kanban_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website.theme_install_kanban_action")
action['target'] = 'new' action['target'] = 'new'
return action return action
@@ -25,7 +25,7 @@ class Company(models.Model):
def _compute_website_theme_onboarding_done(self): def _compute_website_theme_onboarding_done(self):
""" The step is marked as done if one theme is installed. """ """ The step is marked as done if one theme is installed. """
# we need the same domain as the existing action # we need the same domain as the existing action
action = self.env.ref('website.theme_install_kanban_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website.theme_install_kanban_action")
domain = literal_eval(action['domain']) domain = literal_eval(action['domain'])
domain.append(('state', '=', 'installed')) domain.append(('state', '=', 'installed'))
installed_themes_count = self.env['ir.module.module'].sudo().search_count(domain) installed_themes_count = self.env['ir.module.module'].sudo().search_count(domain)
+2 -2
View File
@@ -144,7 +144,7 @@ class ResConfigSettings(models.TransientModel):
super(ResConfigSettings, self).set_values() super(ResConfigSettings, self).set_values()
def open_template_user(self): def open_template_user(self):
action = self.env.ref('base.action_res_users').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("base.action_res_users")
action['res_id'] = literal_eval(self.env['ir.config_parameter'].sudo().get_param('base.template_portal_user_id', 'False')) action['res_id'] = literal_eval(self.env['ir.config_parameter'].sudo().get_param('base.template_portal_user_id', 'False'))
action['views'] = [[self.env.ref('base.view_users_form').id, 'form']] action['views'] = [[self.env.ref('base.view_users_form').id, 'form']]
return action return action
@@ -189,6 +189,6 @@ class ResConfigSettings(models.TransientModel):
def install_theme_on_current_website(self): def install_theme_on_current_website(self):
self.website_id._force() self.website_id._force()
action = self.env.ref('website.theme_install_kanban_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website.theme_install_kanban_action")
action['target'] = 'main' action['target'] = 'main'
return action return action
+2 -2
View File
@@ -905,8 +905,8 @@ class Website(models.Model):
@api.model @api.model
def action_dashboard_redirect(self): def action_dashboard_redirect(self):
if self.env.user.has_group('base.group_system') or self.env.user.has_group('website.group_website_designer'): if self.env.user.has_group('base.group_system') or self.env.user.has_group('website.group_website_designer'):
return self.env.ref('website.backend_dashboard').read()[0] return self.env["ir.actions.actions"]._for_xml_id("website.backend_dashboard")
return self.env.ref('website.action_website').read()[0] return self.env["ir.actions.actions"]._for_xml_id("website.action_website")
def button_go_website(self): def button_go_website(self):
self._force() self._force()
+4 -2
View File
@@ -317,13 +317,15 @@
<field name="model_id" ref="website.model_website"/> <field name="model_id" ref="website.model_website"/>
<field name="state">code</field> <field name="state">code</field>
<field name="code">action = model.action_dashboard_redirect()</field> <field name="code">action = model.action_dashboard_redirect()</field>
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
</record> </record>
<record id="ir_actions_server_website_google_analytics" model="ir.actions.server"> <record id="ir_actions_server_website_google_analytics" model="ir.actions.server">
<field name="name">Website: Dashboard</field> <field name="name">Website: Analytics</field>
<field name="model_id" ref="website.model_website"/> <field name="model_id" ref="website.model_website"/>
<field name="state">code</field> <field name="state">code</field>
<field name="code">action = model.env.ref('website.backend_dashboard').read()[0]</field> <field name="code">action = model.env.ref('website.backend_dashboard').sudo().read()[0]</field>
<field name="groups_id" eval="[(4, ref('base.group_user'))]"/>
</record> </record>
<!-- Custom module kanban : install button (even if already installed) which --> <!-- Custom module kanban : install button (even if already installed) which -->
+1 -1
View File
@@ -28,7 +28,7 @@ class Lead(models.Model):
def action_redirect_to_page_views(self): def action_redirect_to_page_views(self):
visitors = self.visitor_ids visitors = self.visitor_ids
action = self.env.ref('website.website_visitor_page_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website.website_visitor_page_action")
action['domain'] = [('visitor_id', 'in', visitors.ids)] action['domain'] = [('visitor_id', 'in', visitors.ids)]
# avoid grouping if only few records # avoid grouping if only few records
if len(visitors.website_track_ids.ids) > 15 and len(visitors.page_ids.ids) > 1: if len(visitors.website_track_ids.ids) > 15 and len(visitors.page_ids.ids) > 1:
@@ -16,6 +16,6 @@ class Lead(models.Model):
def action_redirect_to_livechat_sessions(self): def action_redirect_to_livechat_sessions(self):
visitors = self.visitor_ids visitors = self.visitor_ids
action = self.env.ref('website_livechat.website_visitor_livechat_session_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_livechat.website_visitor_livechat_session_action")
action['domain'] = [('livechat_visitor_id', 'in', visitors.ids), ('channel_message_ids', '!=', False)] action['domain'] = [('livechat_visitor_id', 'in', visitors.ids), ('channel_message_ids', '!=', False)]
return action return action
@@ -46,7 +46,7 @@ class EventQuestion(models.Model):
(Along with secondary pivot and tree views) (Along with secondary pivot and tree views)
- A tree view showing textual answers values for text_box questions. """ - A tree view showing textual answers values for text_box questions. """
self.ensure_one() self.ensure_one()
action = self.env.ref('website_event_questions.action_event_registration_report').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_event_questions.action_event_registration_report")
action['domain'] = [('question_id', '=', self.id)] action['domain'] = [('question_id', '=', self.id)]
if self.question_type == 'simple_choice': if self.question_type == 'simple_choice':
action['views'] = [(False, 'graph'), (False, 'pivot'), (False, 'tree')] action['views'] = [(False, 'graph'), (False, 'pivot'), (False, 'tree')]
+1 -1
View File
@@ -13,5 +13,5 @@ class ResCompany(models.Model):
def action_open_website_sale_onboarding_payment_acquirer(self): def action_open_website_sale_onboarding_payment_acquirer(self):
""" Called by onboarding panel above the quotation list.""" """ Called by onboarding panel above the quotation list."""
self.env.company.get_chart_of_accounts_or_fail() self.env.company.get_chart_of_accounts_or_fail()
action = self.env.ref('website_sale.action_open_website_sale_onboarding_payment_acquirer_wizard').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_sale.action_open_website_sale_onboarding_payment_acquirer_wizard")
return action return action
+1 -1
View File
@@ -364,7 +364,7 @@ class Website(models.Model):
@api.model @api.model
def action_dashboard_redirect(self): def action_dashboard_redirect(self):
if self.env.user.has_group('sales_team.group_sale_salesman'): if self.env.user.has_group('sales_team.group_sale_salesman'):
return self.env.ref('website.backend_dashboard').read()[0] return self.env["ir.actions.actions"]._for_xml_id("website.backend_dashboard")
return super(Website, self).action_dashboard_redirect() return super(Website, self).action_dashboard_redirect()
def get_suggested_controllers(self): def get_suggested_controllers(self):
@@ -51,7 +51,7 @@ class Channel(models.Model):
self.filtered(lambda channel: not channel.is_published and channel.product_id.is_published).sudo().product_id.write({'is_published': False}) self.filtered(lambda channel: not channel.is_published and channel.product_id.is_published).sudo().product_id.write({'is_published': False})
def action_view_sales(self): def action_view_sales(self):
action = self.env.ref('website_sale_slides.sale_report_action_slides').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_sale_slides.sale_report_action_slides")
action['domain'] = [('product_id', 'in', self.product_id.ids)] action['domain'] = [('product_id', 'in', self.product_id.ids)]
return action return action
+1 -1
View File
@@ -34,7 +34,7 @@ class ResPartner(models.Model):
partner.slide_channel_company_count = 0 partner.slide_channel_company_count = 0
def action_view_courses(self): def action_view_courses(self):
action = self.env.ref('website_slides.slide_channel_action_overview').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_channel_action_overview")
action['name'] = _('Followed Courses') action['name'] = _('Followed Courses')
action['domain'] = ['|', ('partner_ids', 'in', self.ids), ('partner_ids', 'in', self.child_ids.ids)] action['domain'] = ['|', ('partner_ids', 'in', self.ids), ('partner_ids', 'in', self.child_ids.ids)]
return action return action
@@ -453,7 +453,7 @@ class Channel(models.Model):
# --------------------------------------------------------- # ---------------------------------------------------------
def action_redirect_to_members(self, state=None): def action_redirect_to_members(self, state=None):
action = self.env.ref('website_slides.slide_channel_partner_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_channel_partner_action")
action['domain'] = [('channel_id', 'in', self.ids)] action['domain'] = [('channel_id', 'in', self.ids)]
if len(self) == 1: if len(self) == 1:
action['display_name'] = _('Attendees of %s', self.name) action['display_name'] = _('Attendees of %s', self.name)
@@ -600,7 +600,7 @@ class Channel(models.Model):
self.env['slide.channel.partner'].sudo().search(removed_channel_partner_domain).unlink() self.env['slide.channel.partner'].sudo().search(removed_channel_partner_domain).unlink()
def action_view_slides(self): def action_view_slides(self):
action = self.env.ref('website_slides.slide_slide_action').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_slide_action")
action['context'] = { action['context'] = {
'search_default_published': 1, 'search_default_published': 1,
'default_channel_id': self.id 'default_channel_id': self.id
@@ -609,7 +609,7 @@ class Channel(models.Model):
return action return action
def action_view_ratings(self): def action_view_ratings(self):
action = self.env.ref('website_slides.rating_rating_action_slide_channel').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_slides.rating_rating_action_slide_channel")
action['name'] = _('Rating of %s') % (self.name) action['name'] = _('Rating of %s') % (self.name)
action['domain'] = [('res_id', 'in', self.ids)] action['domain'] = [('res_id', 'in', self.ids)]
return action return action
@@ -16,7 +16,7 @@ class Channel(models.Model):
def action_redirect_to_forum(self): def action_redirect_to_forum(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('website_forum.action_forum_post').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_forum.action_forum_post")
action['view_mode'] = 'tree' action['view_mode'] = 'tree'
action['context'] = { action['context'] = {
'create': False 'create': False
@@ -27,7 +27,7 @@ class Survey(models.Model):
# --------------------------------------------------------- # ---------------------------------------------------------
def action_survey_view_slide_channels(self): def action_survey_view_slide_channels(self):
action = self.env.ref('website_slides.slide_channel_action_overview').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_channel_action_overview")
action['display_name'] = _("Courses") action['display_name'] = _("Courses")
if self.slide_channel_count == 1: if self.slide_channel_count == 1:
action.update({'views': [(False, 'form')], action.update({'views': [(False, 'form')],
+70 -24
View File
@@ -117,7 +117,7 @@ class IrActions(models.Model):
user_groups = self.env.user.groups_id user_groups = self.env.user.groups_id
for action_id, action_model, binding_type in cr.fetchall(): for action_id, action_model, binding_type in cr.fetchall():
try: try:
action = self.env[action_model].browse(action_id) action = self.env[action_model].sudo().browse(action_id)
action_groups = getattr(action, 'groups_id', ()) action_groups = getattr(action, 'groups_id', ())
action_model = getattr(action, 'res_model', False) action_model = getattr(action, 'res_model', False)
if action_groups and not action_groups & user_groups: if action_groups and not action_groups & user_groups:
@@ -135,6 +135,38 @@ class IrActions(models.Model):
result['action'] = sorted(result['action'], key=lambda vals: vals.get('sequence', 0)) result['action'] = sorted(result['action'], key=lambda vals: vals.get('sequence', 0))
return result return result
@api.model
def _for_xml_id(self, full_xml_id):
""" Returns the action content for the provided xml_id
:param module: the module the act_window originates in
:param xml_id: the namespace-less id of the action (the @id
attribute from the XML file)
:return: A read() view of the ir.actions.action safe for web use
"""
record = self.env.ref(full_xml_id)
assert isinstance(self.env[record._name], type(self))
# TO CHECK MAT: check groups_id/res_model access?
action = record.sudo().read()[0]
return {
field: value
for field, value in action.items()
if field in record._get_readable_fields()
}
def _get_readable_fields(self):
""" return the list of fields that are safe to read
Fetched via /web/action/load or _for_xml_id method
Only fields used by the web client should included
Accessing content useful for the server-side must
be done manually with superuser
"""
return {
"binding_model_id", "binding_type", "binding_view_types",
"display_name", "help", "id", "name", "type", "xml_id",
}
class IrActionsActWindow(models.Model): class IrActionsActWindow(models.Model):
_name = 'ir.actions.act_window' _name = 'ir.actions.act_window'
@@ -232,18 +264,6 @@ class IrActionsActWindow(models.Model):
values['help'] = self.with_context(**ctx).env[model].get_empty_list_help(values.get('help', '')) values['help'] = self.with_context(**ctx).env[model].get_empty_list_help(values.get('help', ''))
return result return result
@api.model
def for_xml_id(self, module, xml_id):
""" Returns the act_window object created for the provided xml_id
:param module: the module the act_window originates in
:param xml_id: the namespace-less id of the action (the @id
attribute from the XML file)
:return: A read() view of the ir.actions.act_window
"""
record = self.env.ref("%s.%s" % (module, xml_id))
return record.read()[0]
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
self.clear_caches() self.clear_caches()
@@ -268,6 +288,14 @@ class IrActionsActWindow(models.Model):
return set(row[0] for row in self._cr.fetchall()) return set(row[0] for row in self._cr.fetchall())
def _get_readable_fields(self):
return super()._get_readable_fields() | {
"context", "domain", "filter", "groups_id", "limit", "res_id",
"res_model", "search_view", "search_view_id", "target", "view_id",
"view_mode", "views",
}
VIEW_TYPES = [ VIEW_TYPES = [
('tree', 'Tree'), ('tree', 'Tree'),
('form', 'Form'), ('form', 'Form'),
@@ -321,6 +349,11 @@ class IrActionsActUrl(models.Model):
target = fields.Selection([('new', 'New Window'), ('self', 'This Window')], target = fields.Selection([('new', 'New Window'), ('self', 'This Window')],
string='Action Target', default='new', required=True) string='Action Target', default='new', required=True)
def _get_readable_fields(self):
return super()._get_readable_fields() | {
"target", "url",
}
class IrActionsServer(models.Model): class IrActionsServer(models.Model):
""" Server actions model. Server action work on a base model and offer various """ Server actions model. Server action work on a base model and offer various
@@ -421,6 +454,11 @@ class IrActionsServer(models.Model):
if not self._check_m2m_recursion('child_ids'): if not self._check_m2m_recursion('child_ids'):
raise ValidationError(_('Recursion found in child server actions')) raise ValidationError(_('Recursion found in child server actions'))
def _get_readable_fields(self):
return super()._get_readable_fields() | {
"groups_id", "model_name",
}
def _get_runner(self): def _get_runner(self):
multi = True multi = True
t = type(self) t = type(self)
@@ -463,7 +501,7 @@ class IrActionsServer(models.Model):
return True return True
def _run_action_code_multi(self, eval_context): def _run_action_code_multi(self, eval_context):
safe_eval(self.sudo().code.strip(), eval_context, mode="exec", nocopy=True) # nocopy allows to return 'action' safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True) # nocopy allows to return 'action'
return eval_context.get('action') return eval_context.get('action')
def _run_action_multi(self, eval_context=None): def _run_action_multi(self, eval_context=None):
@@ -564,10 +602,19 @@ class IrActionsServer(models.Model):
return action return action
""" """
res = False res = False
for action in self: for action in self.sudo():
action_groups = action.groups_id action_groups = action.groups_id
if action_groups and not (action_groups & self.env.user.groups_id): if action_groups:
raise AccessError(_("You don't have enough access rights to run this action.")) if not (action_groups & self.env.user.groups_id):
raise AccessError(_("You don't have enough access rights to run this action."))
else:
try:
self.env[action.model_name].check_access_rights("write")
except AccessError:
_logger.warning("Forbidden server action %r executed while the user %s does not have access to %s.",
action.name, self.env.user.login, action.model_name,
)
raise
eval_context = self._get_eval_context(action) eval_context = self._get_eval_context(action)
@@ -597,13 +644,6 @@ class IrActionsServer(models.Model):
) )
return res or False return res or False
def _run_actions(self, ids):
"""
Run server actions with given ids.
Allow crons to run specific server actions
"""
return self.browse(ids).run()
class IrServerObjectLines(models.Model): class IrServerObjectLines(models.Model):
_name = 'ir.server.object.lines' _name = 'ir.server.object.lines'
@@ -797,3 +837,9 @@ class IrActionsActClient(models.Model):
params_store = doc.find(".//field[@name='params_store']") params_store = doc.find(".//field[@name='params_store']")
params_store.getparent().remove(params_store) params_store.getparent().remove(params_store)
return doc return doc
def _get_readable_fields(self):
return super()._get_readable_fields() | {
"context", "params", "res_model", "tag", "target",
}
+28 -16
View File
@@ -143,6 +143,11 @@ class IrActionsReport(models.Model):
else: else:
return FALSE_DOMAIN return FALSE_DOMAIN
def _get_readable_fields(self):
return super()._get_readable_fields() | {
"params", "report_name", "report_type", "target",
}
def associated_view(self): def associated_view(self):
"""Used in the ir.actions.report form view in order to search naively after the view(s) """Used in the ir.actions.report form view in order to search naively after the view(s)
used in the rendering. used in the rendering.
@@ -489,7 +494,7 @@ class IrActionsReport(models.Model):
report_obj = self.env['ir.actions.report'] report_obj = self.env['ir.actions.report']
conditions = [('report_name', '=', report_name)] conditions = [('report_name', '=', report_name)]
context = self.env['res.users'].context_get() context = self.env['res.users'].context_get()
return report_obj.with_context(context).search(conditions, limit=1) return report_obj.with_context(context).sudo().search(conditions, limit=1)
@api.model @api.model
def barcode(self, barcode_type, value, width=600, height=100, humanreadable=0, quiet=1, mask=None): def barcode(self, barcode_type, value, width=600, height=100, humanreadable=0, quiet=1, mask=None):
@@ -689,10 +694,13 @@ class IrActionsReport(models.Model):
data = {} data = {}
data.setdefault('report_type', 'pdf') data.setdefault('report_type', 'pdf')
# access the report details with sudo() but evaluation context as sudo(False)
self_sudo = self.sudo()
# In case of test environment without enough workers to perform calls to wkhtmltopdf, # In case of test environment without enough workers to perform calls to wkhtmltopdf,
# fallback to render_html. # fallback to render_html.
if (tools.config['test_enable'] or tools.config['test_file']) and not self.env.context.get('force_report_rendering'): if (tools.config['test_enable'] or tools.config['test_file']) and not self.env.context.get('force_report_rendering'):
return self._render_qweb_html(res_ids, data=data) return self_sudo._render_qweb_html(res_ids, data=data)
# As the assets are generated during the same transaction as the rendering of the # As the assets are generated during the same transaction as the rendering of the
# templates calling them, there is a scenario where the assets are unreachable: when # templates calling them, there is a scenario where the assets are unreachable: when
@@ -719,21 +727,21 @@ class IrActionsReport(models.Model):
# an asset bundle during the execution of test scenarios. In this case, return # an asset bundle during the execution of test scenarios. In this case, return
# the html version. # the html version.
if isinstance(self.env.cr, TestCursor): if isinstance(self.env.cr, TestCursor):
return self.with_context(context)._render_qweb_html(res_ids, data=data)[0] return self_sudo.with_context(context)._render_qweb_html(res_ids, data=data)[0]
save_in_attachment = OrderedDict() save_in_attachment = OrderedDict()
if res_ids: if res_ids:
# Dispatch the records by ones having an attachment and ones requesting a call to # Dispatch the records by ones having an attachment and ones requesting a call to
# wkhtmltopdf. # wkhtmltopdf.
Model = self.env[self.model] Model = self.env[self_sudo.model]
record_ids = Model.browse(res_ids) record_ids = Model.browse(res_ids)
wk_record_ids = Model wk_record_ids = Model
if self.attachment: if self_sudo.attachment:
for record_id in record_ids: for record_id in record_ids:
attachment = self.retrieve_attachment(record_id) attachment = self_sudo.retrieve_attachment(record_id)
if attachment: if attachment:
save_in_attachment[record_id.id] = self._retrieve_stream_from_attachment(attachment) save_in_attachment[record_id.id] = self_sudo._retrieve_stream_from_attachment(attachment)
if not self.attachment_use or not attachment: if not self_sudo.attachment_use or not attachment:
wk_record_ids += record_id wk_record_ids += record_id
else: else:
wk_record_ids = record_ids wk_record_ids = record_ids
@@ -744,7 +752,7 @@ class IrActionsReport(models.Model):
# - The report is not fully present in attachments. # - The report is not fully present in attachments.
if save_in_attachment and not res_ids: if save_in_attachment and not res_ids:
_logger.info('The PDF report has been generated from attachments.') _logger.info('The PDF report has been generated from attachments.')
return self._post_pdf(save_in_attachment), 'pdf' return self_sudo._post_pdf(save_in_attachment), 'pdf'
if self.get_wkhtmltopdf_state() == 'install': if self.get_wkhtmltopdf_state() == 'install':
# wkhtmltopdf is not installed # wkhtmltopdf is not installed
@@ -753,14 +761,14 @@ class IrActionsReport(models.Model):
# bypassed # bypassed
raise UserError(_("Unable to find Wkhtmltopdf on this system. The PDF can not be created.")) raise UserError(_("Unable to find Wkhtmltopdf on this system. The PDF can not be created."))
html = self.with_context(context)._render_qweb_html(res_ids, data=data)[0] html = self_sudo.with_context(context)._render_qweb_html(res_ids, data=data)[0]
# Ensure the current document is utf-8 encoded. # Ensure the current document is utf-8 encoded.
html = html.decode('utf-8') html = html.decode('utf-8')
bodies, html_ids, header, footer, specific_paperformat_args = self.with_context(context)._prepare_html(html) bodies, html_ids, header, footer, specific_paperformat_args = self_sudo.with_context(context)._prepare_html(html)
if self.attachment and set(res_ids) != set(html_ids): if self_sudo.attachment and set(res_ids) != set(html_ids):
raise UserError(_("The report's template '%s' is wrong, please contact your administrator. \n\n" raise UserError(_("The report's template '%s' is wrong, please contact your administrator. \n\n"
"Can not separate file to save as attachment because the report's template does not contains the attributes 'data-oe-model' and 'data-oe-id' on the div with 'article' classname.") % self.name) "Can not separate file to save as attachment because the report's template does not contains the attributes 'data-oe-model' and 'data-oe-id' on the div with 'article' classname.") % self.name)
@@ -773,8 +781,8 @@ class IrActionsReport(models.Model):
set_viewport_size=context.get('set_viewport_size'), set_viewport_size=context.get('set_viewport_size'),
) )
if res_ids: if res_ids:
_logger.info('The PDF report has been generated for model: %s, records %s.' % (self.model, str(res_ids))) _logger.info('The PDF report has been generated for model: %s, records %s.' % (self_sudo.model, str(res_ids)))
return self._post_pdf(save_in_attachment, pdf_content=pdf_content, res_ids=html_ids), 'pdf' return self_sudo._post_pdf(save_in_attachment, pdf_content=pdf_content, res_ids=html_ids), 'pdf'
return pdf_content, 'pdf' return pdf_content, 'pdf'
@api.model @api.model
@@ -808,10 +816,14 @@ class IrActionsReport(models.Model):
data = data and dict(data) or {} data = data and dict(data) or {}
if report_model is not None: if report_model is not None:
# _render_ may be executed in sudo but evaluation context as real user
report_model = report_model.sudo(False)
data.update(report_model._get_report_values(docids, data=data)) data.update(report_model._get_report_values(docids, data=data))
else: else:
docs = self.env[self.model].browse(docids) # _render_ may be executed in sudo but evaluation context as real user
docs = self.env[self.model].sudo(False).browse(docids)
data.update({ data.update({
'doc_ids': docids, 'doc_ids': docids,
'doc_model': self.model, 'doc_model': self.model,
@@ -854,7 +866,7 @@ class IrActionsReport(models.Model):
discard_logo_check = self.env.context.get('discard_logo_check') discard_logo_check = self.env.context.get('discard_logo_check')
if self.env.is_admin() and not self.env.company.external_report_layout_id and config and not discard_logo_check: if self.env.is_admin() and not self.env.company.external_report_layout_id and config and not discard_logo_check:
action = self.env.ref('base.action_base_document_layout_configurator').read()[0] action = self.env["ir.actions.actions"]._for_xml_id("base.action_base_document_layout_configurator")
ctx = action.get('context') ctx = action.get('context')
py_ctx = json.loads(ctx) if ctx else {} py_ctx = json.loads(ctx) if ctx else {}
report_action['close_on_report_download'] = True report_action['close_on_report_download'] = True
+1 -1
View File
@@ -570,7 +570,7 @@ class IrAttachment(models.Model):
@api.model @api.model
def action_get(self): def action_get(self):
return self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment') return self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
@api.model @api.model
def get_serve_attachment(self, url, extra_domain=None, extra_fields=None, order=None): def get_serve_attachment(self, url, extra_domain=None, extra_fields=None, order=None):

Some files were not shown because too many files have changed in this diff Show More