BPM call to UpdateMaster on Shipment not updating Order Release

,

I have a BPM that is updating a pack with some shipping information and then setting it ready to invoice. I had the same issue documented here before and needed to create the updated row

https://www.epiusers.help/t/wcf-to-set-order-shipment-as-ready-to-invoice/43560/18

https://www.epiusers.help/t/copy-a-ud-record-in-a-bpm/56503/2

I got it all to work…at least at the shipment level. It shows the items as shipped and ReadyToInvoice as set. In the UI it shows as shipped. However it is not updating the shipped quantities in the release, so the release/line/order is not closing.
I had to update the weight and tracking information in one update, then the ReadyToInvoice in a second. I do not know why it barked when I tried it all at once, but maybe that is a clue.

Any thoughts as to what I am doing wrong? Code below

var custShip = ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>(Db);

/////////////////////////////////////////////////////////////
// Update the shipping information in the Epicor ShipHead
Func<int, decimal, decimal, string, void> UpdateShippingInformation = delegate (int packID, decimal freightAmt, decimal shipWeight, string trackingNum)
{
bool error = true;
try
{
Erp.Tablesets.CustShipTableset custShipTs = new Erp.Tablesets.CustShipTableset();
custShipTs = custShip.GetByID(packID);
var shipHeadRow = custShipTs.ShipHead.NewRow();
BufferCopy.Copy(custShipTs.ShipHead[0], shipHeadRow);
custShipTs.ShipHead.Add(shipHeadRow);

  if( ( custShipTs.ShipHead[0].PayFlag!= "SHIP") && (freightAmt > 0.0M) ) //Epicor gives "Amount is required" error if amount is zero
  {
    //Freight amount added as a new ShipMisc line in the dataset
    custShip.GetNewShipMisc( ref custShipTs, packID, 0, 0);
    custShip.GetShipMiscDefaults(ref custShipTs, defaultFreightMiscChargeCode );
    var freightMisc = custShipTs.ShipMisc.Where(r => r.Added()).FirstOrDefault();
    freightMisc.DocMiscAmt = freightAmt;
    freightMisc.DspMiscAmt = freightAmt;
    freightMisc.MiscAmt = freightAmt;
    freightMisc.Description = "Freight";
  }      
  custShipTs.ShipHead[1].LabelComment = DateTime.Now.ToString();
  custShipTs.ShipHead[1].TrackingNumber = trackingNum;
  custShipTs.ShipHead[1].Weight = shipWeight;
  custShipTs.ShipHead[1].RowMod = "U";

  custShip.Update(ref custShipTs);
  error = false;

}
catch (Exception ex)
{
ReportError(ex.TargetSite +" — " + ex.Message);
error=true;
}
};

////////////////////////////////////////////////////////////
// Set the readyToShip Flag and update everyting. This marks it shipped in Epicor
Func<int, void> SetShipped = delegate (int packID)
{
bool error = true;

//error related out parameters from Update may want to use for reporting
bool cError = false; bool compError = false; bool updateComplete = false; bool checkComplianceError = false; bool changeStatusError = false;
string msg = “”; string opPostUpdMessage= “”;
try
{
Erp.Tablesets.CustShipTableset custShipTs = new Erp.Tablesets.CustShipTableset();
custShipTs = custShip.GetByID(packID);
var shipHeadRow = custShipTs.ShipHead.NewRow();
BufferCopy.Copy(custShipTs.ShipHead[0], shipHeadRow);
custShipTs.ShipHead.Add(shipHeadRow);

  custShipTs.ShipHead[1].ReadyToInvoice = true;
  custShipTs.ShipHead[1].RowMod = "U";

  //out parameters of Update
  string opReleaseMessage = string.Empty; string opCompleteMessage   = string.Empty; string opShippingMessage   = string.Empty; string opLotMessage       = string.Empty; string opInventoryMessage = string.Empty;
  string opLockQtyMessage = string.Empty; string opAllocationMessage = string.Empty; string opPartListNeedsAttr = string.Empty; string opLotListNeedsAttr = string.Empty; string shipCreditMsg      = string.Empty;
  bool checkShipDtlAgain = false;
  
  //do the update for the misc
  custShip.UpdateMaster(ref custShipTs, true, true, false, true, true, true, true,packID, custShipTs.ShipHead[0].CustNum, 
  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);
  error = false;

}
catch (Exception ex)
{
ReportError(ex.TargetSite +" — " + ex.Message);
}

};

When I dump OurInventoryShipQty and OurJobShipQty from the shipment the quantites are correct. However in the order release, the OurJobShippedQty and OurStockShippedQty the values are 0. I am not making the pack in the BPM, it is done by the user, and if I do the same pack (OK, one made the same way) from the UI, it all works fine.

Thanks

To answer my own question…I need to create the PackOut for the Shipment before I update. This will trickle through to the release, order, etc. So add the following code just before the call to Update, and all is well

///*********** string msgOut; int lineNo = 0; bool belongToAnotherPC = false; custShip.POGetNew(0, packID, out msgOut ); custShip.POGetDtlList(packID, "", 0, "PACK", out msgOut ); custShip.CheckPCBinOutLocation( ref custShipTs, out lineNo, out belongToAnotherPC, out msgOut );

I am trying to create the same function, but I get an error in the functions
GetNewShipMisc (ds, 1234.1,1);
GetShipMiscDefaults (ds, DefaultValueHandling)
apparently they receive a tableset and I’m sending them a dataset

 private  void ShipMethod(int packID, decimal freightAmt, decimal shipWeight, string trackingNum)
	{
		try
		{   System.String msg = "";System.String opPostUpdMessage = "";
		    System.String compError = ""; System.String updateComplete = "";
			System.String checkComplianceError =""; System.String changeStatusError= "";
			CustShipAdapter custShip = new CustShipAdapter(oTrans);
			Erp.Tablesets.CustShipTableset TS = new Erp.Tablesets.CustShipTableset();
		    custShip.BOConnect();
			custShip.GetByID(1234);			
			Erp.BO.CustShipDataSet ds = new  Erp.BO.CustShipDataSet (); 			     				
		    ds =custShip.CustShipData;			
			if (ds != null)
			{ //Create Before Image
				var currentRow =ds.ShipHead[0];               
				var origRow = ds.ShipHead.NewRow();				
    			Epicor.Data.BufferCopy.Copy(currentRow, origRow);
    			ds.ShipHead.Rows.Add(origRow); 
				//Update Record
			     if( ( ds.ShipHead[0].PayFlag!= "SHIP") && (freightAmt > 0.0M) ) //Epicor gives "Amount is required" error if amount is zero
				  {   //Freight amount added as a new ShipMisc line in the dataset
				    custShip.GetNewShipMisc(ds,1234,1,1);   //si existe GetNewShipMisc
				    custShip.GetShipMiscDefaults(ds, DefaultValueHandling);     // si existe GetShipMiscDefaults

				    var freightMisc = ds.ShipMisc.Where(r => r.Added()).FirstOrDefault(); 				    
					freightMisc.DocMiscAmt = freightAmt;
				    freightMisc.DspMiscAmt = freightAmt;
				    freightMisc.MiscAmt = freightAmt;
				    freightMisc.Description = "Freight";
		  		}      
				  ds.ShipHead[1].LabelComment = DateTime.Now.ToString();
				  ds.ShipHead[1].TrackingNumber = trackingNum;
				  ds.ShipHead[1].Weight = shipWeight;
				  ds.ShipHead[1].RowMod = "U";		
			  
			      custShip.Dispose();
			      oTrans.Update();
				}
		}
		catch (Exception ex)
	    {
			MessageBox.Show(ex.Message);
		}			
	}

I just wanted to say thank you @TimW for your post. I have been pulling my hair out at building a BPM that simply flags a shipment as shipped and your code, along with mine, got me where I needed to be. The CustShip BO is an absolute nightmare to work with.