Pass in desired plant for async processing CustShip BO

Hello!

I’m wanting to take a beautiful synchronous process that creates customer shipments and turn it into an async process so the user does not have to wait for shipments to be made.

It all works great in sync, and in async I do synchronously grab the user id and plant before using the Customer Shipment BO async.

The required and very helpful method:
GetOrderRelInfo works synchronous but in async it keeps trying to use the plant the task agent service is in. I set the plant before calling this method. Is there a way to make this method aware of the desired (target) plant, or will I need to populate columns a different way? (yuck)

Action<int, int, int, int> createShipDtl = (myHeaderNum, myOrderNum, myOrderLine, myOrderRel) =>
  {
    //Check to ensure we will never add a duplicate line to the pack
    if (!Db.ShipDtl.Where(w => w.PackNum == myHeaderNum && w.OrderLine == myOrderLine && w.OrderRelNum == myOrderRel).Any())
    {      
      SentrySdk.AddBreadcrumb(
      message: "Order: " + myOrderNum + " Line: " + myOrderLine + " Release: " + myOrderRel,
      level: BreadcrumbLevel.Info);
      
      using (var customerShipSvc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>(Db)) //Create Customer Shipment BO
      {
        //We can only send in 1 dtl line per update or else the method is gunna have a bad time
        myCustShipDataSet.ShipDtl.Clear();
        //Create a new dtl row with defaults
        customerShipSvc.GetNewOrdrShipDtl(ref myCustShipDataSet, myHeaderNum, myOrderNum);
        //Select the current pack detail row
        var currPackLine = myCustShipDataSet.ShipDtl.Where(w => w.PackLine == 0).FirstOrDefault();   
        currPackLine.OrderNum = myOrderNum;
        currPackLine.OrderLine = myOrderLine;       
        currPackLine.Plant = syncPlant;
        //Check part on the line
        customerShipSvc.CheckPrePartInfo(ref prePartPartNum, currPackLine.OrderNum, currPackLine.OrderLine, out prePartvMsgText, out prePartVSubAvail, out prePartvMsgType, out prePartOrigPartNum);
        //Get order line details and populate shipdtl row
        customerShipSvc.GetOrderLineInfo(ref myCustShipDataSet, currPackLine.PackLine, currPackLine.OrderLine, prePartOrigPartNum);
        //Set row order release num
        currPackLine.OrderRelNum = myOrderRel; //for async
        customerShipSvc.GetOrderRelInfo(ref myCustShipDataSet,0, myOrderRel, true);
        //Set the partNum on the line. Need to do this as there is a bug here
        currPackLine.PartNum = prePartOrigPartNum;
        //Get part details of the order line and populate shipdtl row. Need to call because of bug
        customerShipSvc.GetPartInfo(ref myCustShipDataSet, currPackLine.PackLine, ref prePartOrigPartNum, Guid.Empty, string.Empty, out getPartInfo, out getPartInfo, out getPartInfoB, out getPartInfo);
        //Set Shipped Quantity to 0 as it defaults to release quantity
        customerShipSvc.GetQtyInfo(ref myCustShipDataSet, currPackLine.PackLine, 0, 0);
        //Finally update the record with our data
        customerShipSvc.UpdateMaster(ref myCustShipDataSet, false, false, false, false, false, false, false, myHeaderNum, 0, out opReleaseMessage, out opCompleteMessage, out opShippingMessage, out opLotMessage, out opInventoryMessage, out opLockQtyMessage, out opAllocationMessage, out opPartListNeedsAttr, out opLotListNeedsAttr, out shipCreditMsg, out cError, out compError, out msg, out opPostUpdMessage, out updateComplete, out checkComplianceError, out changeStatusError, out checkShipDtlAgain);
      };
    }  
  };

Async by nature would use a task agent thread to process the request vs. a user thread for sync, I would think. Passing another argument into your Action with the Plant would probably be what I would do.

Thanks Aaron, thats what I’m trying to do but the method GetOrderRelInfo keeps failing with order release from site is not XXX

I wonder if when you instantiate your customerShipSvc if it comes pre-packaged with the plant that it was instantiated by, regardless of the plant you’d like? Hard to say without testing.

Hmmm interesting thought, any idea if I can instantiate the BO as the current user/plant using impersonation or something?

Not that I know of, since it’s using the context of the bpm

Got it!
I needed to wrap my BO using in this:

using (CallContext.Current.TemporarySessionCreator.SetPlantID(myPlant).Create())
{
}     

Big thanks to this post!

Love this community @danbedwards thanks for providing this snippet! Exactly what I needed for this async task.

2 Likes

Nice work