55import functools
66import hashlib
77import logging
8+ import json
9+ import yaml
810import uuid
911import sys
1012from datetime import datetime , timedelta
1113
1214import odoo
15+ from odoo .tools .safe_eval import safe_eval
1316
1417from .exception import (NoSuchJobError ,
1518 FailedJobError ,
@@ -55,14 +58,15 @@ class DelayableRecordset(object):
5558
5659 def __init__ (self , recordset , priority = None , eta = None ,
5760 max_retries = None , description = None , channel = None ,
58- identity_key = None ):
61+ identity_key = None , keep_context = False ):
5962 self .recordset = recordset
6063 self .priority = priority
6164 self .eta = eta
6265 self .max_retries = max_retries
6366 self .description = description
6467 self .channel = channel
6568 self .identity_key = identity_key
69+ self .keep_context = keep_context
6670
6771 def __getattr__ (self , name ):
6872 if name in self .recordset :
@@ -87,7 +91,9 @@ def delay(*args, **kwargs):
8791 eta = self .eta ,
8892 description = self .description ,
8993 channel = self .channel ,
90- identity_key = self .identity_key )
94+ identity_key = self .identity_key ,
95+ keep_context = self .keep_context
96+ )
9197 return delay
9298
9399 def __str__ (self ):
@@ -297,6 +303,7 @@ def _load_from_db_record(cls, job_db_record):
297303 if stored .company_id :
298304 job_ .company_id = stored .company_id .id
299305 job_ .identity_key = stored .identity_key
306+ job_ .keep_context = stored .context or {}
300307 return job_
301308
302309 def job_record_with_same_identity_key (self ):
@@ -311,7 +318,7 @@ def job_record_with_same_identity_key(self):
311318 @classmethod
312319 def enqueue (cls , func , args = None , kwargs = None ,
313320 priority = None , eta = None , max_retries = None , description = None ,
314- channel = None , identity_key = None ):
321+ channel = None , identity_key = None , keep_context = None ):
315322 """Create a Job and enqueue it in the queue. Return the job uuid.
316323
317324 This expects the arguments specific to the job to be already extracted
@@ -324,7 +331,8 @@ def enqueue(cls, func, args=None, kwargs=None,
324331 new_job = cls (func = func , args = args ,
325332 kwargs = kwargs , priority = priority , eta = eta ,
326333 max_retries = max_retries , description = description ,
327- channel = channel , identity_key = identity_key )
334+ channel = channel , identity_key = identity_key ,
335+ keep_context = keep_context )
328336 if new_job .identity_key :
329337 existing = new_job .job_record_with_same_identity_key ()
330338 if existing :
@@ -355,7 +363,8 @@ def db_record_from_uuid(env, job_uuid):
355363 def __init__ (self , func ,
356364 args = None , kwargs = None , priority = None ,
357365 eta = None , job_uuid = None , max_retries = None ,
358- description = None , channel = None , identity_key = None ):
366+ description = None , channel = None ,
367+ identity_key = None , keep_context = False ):
359368 """ Create a Job
360369
361370 :param func: function to execute
@@ -381,6 +390,8 @@ def __init__(self, func,
381390 as argument)
382391 :param env: Odoo Environment
383392 :type env: :class:`odoo.api.Environment`
393+ :param keep_context: Determine if the current context should be restored
394+ :type keep_context: :bool or list
384395 """
385396 if args is None :
386397 args = ()
@@ -397,6 +408,7 @@ def __init__(self, func,
397408
398409 recordset = func .__self__
399410 env = recordset .env
411+ self .keep_context = keep_context
400412 self .model_name = recordset ._name
401413 self .method_name = func .__name__
402414 self .recordset = recordset
@@ -500,6 +512,10 @@ def store(self):
500512 }
501513
502514 dt_to_string = odoo .fields .Datetime .to_string
515+ context = {}
516+ if self .keep_context :
517+ context = self .env .context .copy ()
518+ vals .update ({"context" : json .dumps (context )})
503519 if self .date_enqueued :
504520 vals ['date_enqueued' ] = dt_to_string (self .date_enqueued )
505521 if self .date_started :
@@ -516,6 +532,9 @@ def store(self):
516532 db_record .write (vals )
517533 else :
518534 date_created = dt_to_string (self .date_created )
535+ # We store the original context used at import on create
536+ ctx = self .env .context .copy () or '{}'
537+ vals .update ({'original_context' : json .dumps (ctx ) or '' })
519538 # The following values must never be modified after the
520539 # creation of the job
521540 vals .update ({'uuid' : self .uuid ,
@@ -532,14 +551,40 @@ def store(self):
532551 if self .channel :
533552 vals .update ({'channel' : self .channel })
534553
535- self .env [self .job_model_name ].sudo ().create (vals )
554+ job = self .env [self .job_model_name ].sudo ().create (vals )
536555
537556 def db_record (self ):
538557 return self .db_record_from_uuid (self .env , self .uuid )
539558
559+ def _get_abs_context (self , original_ctx , ctx ):
560+ try :
561+ import_ctx = json .loads (original_ctx )
562+ current_ctx = json .loads (ctx )
563+ except Exception as e :
564+ _logger .error ("\n \n ERROR CONTEXT JSON CONVERSION: %s\n \n " % e )
565+ return self .env .context .copy ()
566+ else :
567+ if isinstance (import_ctx , dict ) and isinstance (current_ctx , dict ):
568+ import_ctx .update (current_ctx )
569+ return import_ctx
570+ return self .env .context .copy ()
571+
572+ def _get_record_context (self ):
573+ """
574+ Get the context to execute the job
575+ """
576+ ctx = self ._get_abs_context (self .db_record ().original_context ,
577+ self .db_record ().context )
578+ if self .company_id :
579+ ctx .update ({'allowed_company_ids' : [self .company_id ]})
580+ if self .uuid :
581+ ctx .update ({"job_uuid" : self .uuid })
582+ return ctx
583+
540584 @property
541585 def func (self ):
542- recordset = self .recordset .with_context (job_uuid = self .uuid )
586+ context = self ._get_record_context ()
587+ recordset = self .recordset .with_context (** context )
543588 recordset = recordset .sudo (self .user_id )
544589 return getattr (recordset , self .method_name )
545590
0 commit comments