BPM to Create New Record in ShipHead and ShipDtl

Good afternoon good people! I’ve created a Method Directive in the Project/Update BO that is triggered from a button on a dashboard. When the button is clicked, a UD field in the Project table is updated, triggering this new BPM. Several things happen, but most importantly is that I need to create a new record in the ShipHead and Detail tables.

The code below works to create a new row in the ShipHead and ShipDtl tables…

int packNum = 0;
string trackNum = “”;
bool shpHedExists = false;
bool shpDtlExists = false;

var Proj = ttProject.Where(r => r.Updated()).FirstOrDefault();

if (Proj == null)
return;

string projID = Proj.ProjectID;

// Connect to OrderHed table to get OrderNum
var ordHed = Db.OrderHed.Where(r => r.Company == Proj.Company && r.ProjectID_c == projID).FirstOrDefault();

if (ordHed == null)
return;

// Connect to OrderDtl table
var ordDtl = Db.OrderDtl.Where(r => r.Company == Proj.Company && r.OrderNum == ordHed.OrderNum && r.OrderLine == 1).FirstOrDefault();

if (ordDtl == null)
return;

// Connect to ShipHead and ShipDtl tables to check if a record exists
var shipHead = Db.ShipHead.Where(r => r.Company == ordHed.Company && r.OTSOrderNum == ordHed.OrderNum).FirstOrDefault();

if (shipHead != null)
shpHedExists = true;

var shipDtl = Db.ShipDtl.Where(r => r.Company == ordHed.Company && r.OrderNum == ordHed.OrderNum).FirstOrDefault();

if (shipDtl != null)
shpDtlExists = true;

if (shpHedExists && shpDtlExists)
{
this.err += “The Sales Order line for this project has already been shipped.”;
return;
}
else
this.err = “”;

// Create new record in ShipHead table
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (shpHedExists == false)
{
using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>())
{
CustShipTableset ts = new CustShipTableset();
svc.GetNewShipHead(ref ts);

  foreach (var x in ts.ShipHead.Where(r => r.Added()))
  {
  	x.OrderNum = ordHed.OrderNum;
  	x.TrackingNumber = "ACCT";
  	x.OTSOrderNum = ordHed.OrderNum;
  	x.RowMod = "A";
  }

  svc.Update(ref ts);
  packNum = ts.ShipHead[0].PackNum;
  trackNum = ts.ShipHead[0].TrackingNumber;

}
}

// Create new record in ShipDtl table
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (shpDtlExists == false)
{
using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>())
{
CustShipTableset ts = new CustShipTableset();
svc.GetNewOrdrShipDtl(ref ts, packNum, ordHed.OrderNum);

  foreach (var x in ts.ShipDtl.Where(r => r.Added()))
  {
  	x.OrderLine = 1;
  	x.OrderRelNum = 1;
  	x.PartNum = ordDtl.PartNum;
  	x.LineDesc = ordDtl.LineDesc;
  	x.IUM = "EA";
  	x.WarehouseCode = "PROD";
  	x.BinNum = "PROD";
  	x.WUM = "OZ";
  	x.SalesUM = "EA";
  	x.InventoryShipUOM = "EA";
  	x.JobShipUOM = "EA";
  	//x.ShipToCustNum = ordHed.ShipToCustNum;
  	//x.MFCustNum = Proj.ConCustNum;
  	x.RowMod = "A";
  }

  svc.Update(ref ts);

}
}

this.msg += "* Sales Order line has been shipped. Pack: " + packNum.ToString();

But then I add in the code below after the block of code that creates the ShipDtl record and I get an error…

// Set the ReadyToShip Flag and update everyting in ShipHead table
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>())
{
// Error related out parameters from Update
bool cError = false; bool compError = false; bool updateComplete = false; bool checkComplianceError = false; bool changeStatusError = false;
string msg = “”; string opPostUpdMessage = “”;

  CustShipTableset ts = new CustShipTableset();
  ts = svc.GetByID(packNum);

  var shipHeadRow = ts.ShipHead.NewRow();
  BufferCopy.Copy(ts.ShipHead[0], shipHeadRow);
  ts.ShipHead.Add(shipHeadRow);

  ts.ShipHead[1].ReadyToInvoice = true;
  ts.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;

  string msgOut; int lineNo = 0; bool belongToAnotherPC = false; 
  
  svc.POGetNew(0, packNum, out msgOut ); 
  svc.POGetDtlList(packNum, "", 0, "PACK", out msgOut); 
  svc.CheckPCBinOutLocation(ref ts, out lineNo, out belongToAnotherPC, out msgOut);

  // Do the update for the misc
  svc.UpdateMaster(ref ts, true, true, false, true, true, true, true, packNum, ts.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);

}

So I commented out the ShipDtl block of code and everything worked fine. My ShipHead record was created and the ReadyToInvoice field was set…

int packNum = 0;
string trackNum = “”;
bool shpHedExists = false;
bool shpDtlExists = false;

var Proj = ttProject.Where(r => r.Updated()).FirstOrDefault();

if (Proj == null)
return;

string projID = Proj.ProjectID;

// Connect to OrderHed table to get OrderNum
var ordHed = Db.OrderHed.Where(r => r.Company == Proj.Company && r.ProjectID_c == projID).FirstOrDefault();

if (ordHed == null)
return;

// Connect to OrderDtl table
var ordDtl = Db.OrderDtl.Where(r => r.Company == Proj.Company && r.OrderNum == ordHed.OrderNum && r.OrderLine == 1).FirstOrDefault();

if (ordDtl == null)
return;

// Connect to ShipHead and ShipDtl tables to check if a record exists
var shipHead = Db.ShipHead.Where(r => r.Company == ordHed.Company && r.OTSOrderNum == ordHed.OrderNum).FirstOrDefault();

if (shipHead != null)
shpHedExists = true;

var shipDtl = Db.ShipDtl.Where(r => r.Company == ordHed.Company && r.OrderNum == ordHed.OrderNum).FirstOrDefault();

if (shipDtl != null)
shpDtlExists = true;

if (shpHedExists && shpDtlExists)
{
this.err += “The Sales Order line for this project has already been shipped.”;
return;
}
else
this.err = “”;

// Create new record in ShipHead table
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (shpHedExists == false)
{
using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>())
{
CustShipTableset ts = new CustShipTableset();
svc.GetNewShipHead(ref ts);

  foreach (var x in ts.ShipHead.Where(r => r.Added()))
  {
  	x.OrderNum = ordHed.OrderNum;
  	x.TrackingNumber = "ACCT";
  	x.OTSOrderNum = ordHed.OrderNum;
  	x.RowMod = "A";
  }

  svc.Update(ref ts);
  packNum = ts.ShipHead[0].PackNum;
  trackNum = ts.ShipHead[0].TrackingNumber;

}
}

/*
// Create new record in ShipDtl table
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (shpDtlExists == false)
{
using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>())
{
CustShipTableset ts = new CustShipTableset();
svc.GetNewOrdrShipDtl(ref ts, packNum, ordHed.OrderNum);

  foreach (var x in ts.ShipDtl.Where(r => r.Added()))
  {
  	x.OrderLine = 1;
  	x.OrderRelNum = 1;
  	x.PartNum = ordDtl.PartNum;
  	x.LineDesc = ordDtl.LineDesc;
  	x.IUM = "EA";
  	x.WarehouseCode = "PROD";
  	x.BinNum = "PROD";
  	x.WUM = "OZ";
  	x.SalesUM = "EA";
  	x.InventoryShipUOM = "EA";
  	x.JobShipUOM = "EA";
  	//x.ShipToCustNum = ordHed.ShipToCustNum;
  	//x.MFCustNum = Proj.ConCustNum;
  	x.RowMod = "A";
  }

  svc.Update(ref ts);

}
}
*/

// Set the ReadyToShip Flag and update everyting in ShipHead table
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.CustShipSvcContract>())
{
// Error related out parameters from Update
bool cError = false; bool compError = false; bool updateComplete = false; bool checkComplianceError = false; bool changeStatusError = false;
string msg = “”; string opPostUpdMessage = “”;

CustShipTableset ts = new CustShipTableset();
ts = svc.GetByID(packNum);

var shipHeadRow = ts.ShipHead.NewRow();
BufferCopy.Copy(ts.ShipHead[0], shipHeadRow);
ts.ShipHead.Add(shipHeadRow);

ts.ShipHead[1].ReadyToInvoice = true;
ts.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;

string msgOut; int lineNo = 0; bool belongToAnotherPC = false;

svc.POGetNew(0, packNum, out msgOut);
svc.POGetDtlList(packNum, “”, 0, “PACK”, out msgOut);
svc.CheckPCBinOutLocation(ref ts, out lineNo, out belongToAnotherPC, out msgOut);

// Do the update for the misc
svc.UpdateMaster(ref ts, true, true, false, true, true, true, true, packNum, ts.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);
}

this.msg += "* Sales Order line has been shipped. Pack: " + packNum.ToString();

So, I can either create new records for ShipHead and ShipDtl and not set the ReadyToInvoice field, or I can create a new record in ShipHead only and set the ReadyToInvoice field. Does this make sense to anyone?

Thank you for your time and any help you can give before I pull my hair out. :grinning:

Since you are calling the service multiple times, I would add lines to dispose them after your updates.

svc.Dispose();

You should also probably wrap each major code block in context scopes. Should be able to find plenty examples of this throughout the site.

1 Like

using statement disposes of svc.

But, in general, multiple calls to the same instance of a service can be dangerous.
ERP/ICE services originally were implemented for the instance-per-call WCF model.
So, there is no guarantee that previous call does not leave some data initialized in the instance, and that data can affect subsequent calls.

1 Like

Hello @ShawnLeenerts sorry to necro but did you every get this sorted?

Many thanks!

1 Like