Problem with getting ALL transactions out of episerver commerce when running under a schedule job

Joe
Joe
Vote:
 

I have created a schedule job to get commerce transactions from episerver commerce and process into our backend systems.

 

In development it appeared to be working fine – getting transactions from episerver commerce putting the information into a csv file

and then FTPing to a remote server (and this worked whether the job was run manually or via the schedule).  But it seemed only to have

worked because it was only getting the transactions which I had created on the development setup.

 

However, when I moved the schedule job to a test server where transactions have been done by other users, I noticed it was only picking-up

transactions which were created under my user and no others – and this was I presume because I am running the scheduler under the context of

an Administrator user (my user).

 

Obviously, this is a far from satisfactory situation – I need to get all transactions and not just those associated with a particular user – so my question is:

 

How do I get ALL transactions out of episerver commerce using a schedule job and not just the transactions created by the user which is being

used as the context to run the schedule job?  Note that if you run under the context of a no user, you get no transactions back.

 

Alternatively, how do I run a schedule job under the context of the user which runs the Commerce Manager tool as this can see ALL of the

transactions?  In other words, how do I run a schedule job under the context of a Commerce Manager user?

Relevant Code is:

Use this function to get PO's:

        public static List GetAllPurchaseOrdersCreatedBetweenDates(DateTime StateDate, DateTime EndDate)
        {
            List purchaseOrders = null;

            try
            {
                purchaseOrders = OrderRepository.Service.Load()
                                                   .Where(x => x.Created >= StateDate.Date && x.Created <= enddate.date) .orderbydescending(x=""> x.Created)
                                                   .ToList();

                if (purchaseOrders == null)
                {
                    Log.Error($"**** COMMERCE ERROR: EpiserverCommerceHelpers.GetAllPurchaseOrdersCreatedBetweenDates() is returning null");
                    throw new ApplicationException("EpiserverCommerceHelpers.GetAllPurchaseOrdersCreatedBetweenDates() is returning null");
                }

                if (purchaseOrders != null && purchaseOrders.Count == 0)
                {
                    Log.Error($"**** COMMERCE ERROR: EpiserverCommerceHelpers.GetAllPurchaseOrdersCreatedBetweenDates() is returning no purchase orders");
                    throw new ApplicationException("EpiserverCommerceHelpers.GetAllPurchaseOrdersCreatedBetweenDates() is returning no purchase orders");
                }
            }
            catch (Exception ex)
            {
                Log.Error($"**** COMMERCE ERROR: EpiserverCommerceHelpers.GetAllPurchaseOrdersCreatedBetweenDates() has thrown an exception: {ex.Message}");
            }

            return purchaseOrders;
        }

I use this function to set the user in the schedule code:

        public static string SetPrincipleUser(string Username = "")
        {
            try
            {
                // Manual triggering of a scheduled task will cause the task to run with the currently logged in user’s account and with access to that HttpContext
                // but triggering organically according to the schedule will cause the schedule to run under a limited permissions user and with no HttpContext.
                if (HttpContext.Current == null || PrincipalInfo.CurrentPrincipal.Identity.Name == string.Empty)
                {
                    // Running according to the schedule (not manual triggering)

                    string ScheduledJobPrincipleUser = (Username == string.Empty) ? ConfigurationManager.AppSettings["ScheduledJobPrincipleUser"] : Username;
                    if (!string.IsNullOrEmpty(ScheduledJobPrincipleUser))
                        // Run the scheduled task as a user specified from the web.config or from passed in Username without HttpContent (WORKS)
                        PrincipalInfo.CurrentPrincipal = UserImpersonation.Service.CreatePrincipal(ScheduledJobPrincipleUser);
                    else
                        // Run the scheduled task as an anonymous principal without HttpContext (Doesn't work but may do so if AnonymousScheduledJobPrincipleUser is created as a user)
                        PrincipalInfo.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("AnonymousScheduledJobPrincipleUser"), new[] { "Administrators" });
                }

                string CurrentUser = PrincipalInfo.CurrentPrincipal.Identity.Name;
                return (CurrentUser == string.Empty) ? string.Empty : $"{CurrentUser}";
            }
            catch
            {
                return string.Empty;
            }
        }
#185790
Dec 01, 2017 14:27
Vote:
 

Your problem lies inside the order repository extensions this call:

OrderRepository.Service.Load<IPurchaseOrder>()

Will always just load IPurchaseOrder for the current user and with the "Default" name.

It is called Load and not List for a reason. frown

The way we normally solve this is to write raw sql to list the Ids of those PurchaseOrders we want and then use the Load overload that takes an Id and retrieve them one by one.

Yes I know raw sql isn't encouraged in anyway, but if you find an alternative let me know. yell

#185796
Dec 01, 2017 14:57
Vote:
 

Although if you prefer you could try and navigate the old Mediachase library:

Mediachase.Commerce.Orders.OrderContext.Current.FundPurchaseOrders(...)

Was a long time since I tried using those thou and I can't vouch for their performance. :P

#185798
Dec 01, 2017 15:05
Vote:
 

First of all I'd suggest to use the term of "purchase order" here. I know "transactions" might have same meaning in some context, but for the consistency and to avoid confusion, we should use the term "purchase order".

If you want to find purchase orders which were created in a period, you would need to use OrderContext.FindPurchaseOrders.

https://world.episerver.com/documentation/Items/Developers-Guide/Episerver-Commerce/9/Orders/Searching-for-orders/

SqlMetaWhereClause can be like "META.Created BETWEEN {startTime} AND {endTime}"




                        
#185802
Dec 01, 2017 15:09
Joe
Vote:
 

Erik and Quan,

Thanks to both of your suggested solutions, I have now got the problem resolved.

Very much appreciated.

Joe

#185810
Dec 01, 2017 18:38
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.