Help with Select Serial Numbers - BAQ BPM

You reminded me to update the function I posted here since I had to fix it:

https://www.epiusers.help/t/epicor-function-to-issue-and-return-material/93575

Also this was what I started with:

1 Like

Interesting project you got there. For serial prefixes, you need to define the serial mask first to tell it how many chars the prefix has. Then, set those prefix chars in part maintenance. We don’t use those so that as far as I can go on this one.
For adding serials, I add them first in SelectedSerialNumbersSvc by calling GetSerialNumFormat and then AddSerialNum. Once I got all of them there, I copy that to the desired BO (IssueReturn or whatever you’re using there). You need to copy the fields one by one. Have a look at the reply here to see what I mean. Good luck!

1 Like

Thank you @Dragos!

I appreciate both of your responses! I’ve gotten pretty far, but when I run the following code:

  string oprCmpWarning = String.Empty;
  serialNoAssign.SetSerialNoAssign(ref serialNoAssignTS, false, out oprCmpWarning);

I get “ttSerialNoAssign record not found”

Here is the full JSON formatted version of serialNoAssignTS, and as you can see I have the SelectedSerialNumbers populated, no data seems to be missing so I’m lost as to why I am receiving this error. Thank you for the help!!

{"SelectedSerialNumbers":[{"ColumnNames":0,"Company":"401","SerialNumber":"203-180066","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080066","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180066","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180067","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080067","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180067","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180068","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080068","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180068","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180069","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080069","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180069","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180070","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080070","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180070","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180071","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080071","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180071","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180072","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080072","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180072","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180073","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080073","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180073","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180074","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080074","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180074","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180075","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080075","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180075","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180076","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080076","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180076","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180077","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080077","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180077","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180078","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080078","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180078","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180079","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080079","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180079","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}},{"ColumnNames":0,"Company":"401","SerialNumber":"203-180080","Scrapped":false,"ScrappedReasonCode":"","Voided":false,"Reference":"","ReasonCodeType":"","ReasonCodeDesc":"","PartNum":"N00983203-1","SNPrefix":"203-1","SNBaseNumber":"00000000000000080080","SourceRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","TransType":"","PassedInspection":false,"Deselected":false,"KitWhseList":"","RawSerialNum":"203-180080","KBLbrAction":0,"KBLbrActionDesc":"","PreventDeselect":false,"XRefPartNum":"","XRefPartType":"","PreDeselected":false,"poLinkValues":"","SNMask":"","NotSavedToDB":true,"SysRowID":"00000000-0000-0000-0000-000000000000","RowMod":"A","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"RowSelected":false,"SpecifiedProperties":"Ax8xEg=="}}],"SerialNoAssign":[{"ColumnNames":0,"Company":"401","JobNumber":"000012","AssemblySeq":0,"PartDescription":"Precision Part, Machined, 83mm","SerialNoQty":0.0,"PartNum":"N00983203-1","JobQty":15.00000000,"SysRowID":"9f655539-5fc7-452e-8056-38f96aaef0ce","RowMod":"","SpecifiedProperties":"7wA=","UserDefinedColumns":{}}],"SNFormat":[{"ColumnNames":0,"Company":"401","Plant":"MfgSys","PartNum":"N00983203-1","NumberOfDigits":5,"SNMask":"","SNBaseDataType":"INTEGER","SNFormat":"203-100009","LeadingZeroes":true,"SNPrefix":"203-1","SNMaskSuffix":"","SNMaskPrefix":"","SNLastUsedSeq":"","HasSerialNumbers":true,"SysRowID":"00000000-0000-0000-0000-000000000000","BitFlag":0,"PartPricePerCode":"E","PartTrackLots":true,"PartTrackSerialNum":true,"PartTrackDimension":false,"PartSalesUM":"EA","PartIUM":"EA","PartSellingFactor":1.00000000,"PartPartDescription":"Precision Part, Machined, 83mm","SerialMaskMaskType":0,"SerialMaskMask":"","SerialMaskExample":"","SerialMaskDescription":"","RowMod":"","SpecifiedProperties":"////Dw==","UserDefinedColumns":{"ColumnNames":0,"SpecifiedProperties":"/5f/Bw=="}}],"ExtensionTables":[]}

Hello @JasonMcD! Thanks for the help with your function library, I imported it and have been reviewing how you coded it and wanted to follow that same approach instead of all custom C# code.

So I did this:

And I get this error (which makes no sense to me since I selected the Tableset within SerialNoAssign):

There is at least one compilation error.
GetList.Post.CreateMatchTopSe.cs(34,31): error CS0433: The type 'SelectSerialNumbersParamsTableset' exists in both 'Erp.Contracts.BO.SelectedSerialNumbers, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992' and 'Erp.Contracts.BO.SerialNoAssign, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992'
GetList.Post.CreateMatchTopSe.cs(73,81): error CS0433: The type 'SelectSerialNumbersParamsTableset' exists in both 'Erp.Contracts.BO.SelectedSerialNumbers, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992' and 'Erp.Contracts.BO.SerialNoAssign, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992'
GetList.Post.CreateMatchTopSe.cs(325,78): error CS0433: The type 'SelectSerialNumbersParamsTableset' exists in both 'Erp.Contracts.BO.SelectedSerialNumbers, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992' and 'Erp.Contracts.BO.SerialNoAssign, Version=10.2.700.0, Culture=neutral, PublicKeyToken=5d3fa3c7105d7992'

makes no sense…

Memory lane again. Now I remember this even more.

Apparently it took 24 posts for me to understand this.

So, the serial “exists in both” thing is a common wall you’ll run into. You can’t have two “services” that both deal with whatever this thing is called, “type” I guess?

To me it’s just a lot of trial and error to get down to the bare minimum that will work, since Epicor Functions don’t allow overlapping services to coexist.

Yeah this is quite the challenge.

I ended up replacing all my custom code to perform the serial matching to using their call BO methods like you have in your function, where I have some custom code setting up workflow variables:

Once I run the uBAQ, I still get this error:
image

And I’m like… but I followed the trace, step by step. My only change was removing the GetSelectSerialNumbersParams call since it looks like that was never used. I’m so very lost…

In the JSON you posted, the “SerialNoAssign” section had a RowMod item, but no value was assigned. It needs to be assigned “A” or “U”. I assume the “SNFormat” section will have the same issue.

2 Likes

I’ll stick my neck out here, but I think this is one area where the trace just doesn’t help. I had to go rogue and build on the work of others. Especially if you do widgets, the “Fill table by query” step is not in the trace but it is necessary. Again, I think because the actual Epicor dev team seems to have objects they use that we cannot.

Thanks for this! Totally missed that.

I updated the loop I have so now I’m setting RowMod = “A”, SNFormat in my tracing doesn’t have any RowMod set. However still I am receiving the same error after running. Gonna retrace my steps and see…

Ah good point! And yes that was something I had to figure out too, but instead of using the Fill table by query, I wrote code in the custom block to fill that dataset object in a loop for the set serial number.

So I’ve “combed the desert” with this process over and over and over… and I can’t figure it out. RowMod is set correctly now, but the only thing I noticed between my trace and my code returns was my SNFormat and HasSerialNumbers wasn’t changing after GetNextSN. So, as a test I hard coded the values to see if it would make a difference, but nope. I still get the “ttSerialNoAssign record not found” when SetSerialNoAssign runs. I pasted my code below, and I attached a cleaned up trace (removed unnecessary tracePacket groups that are not related to the process.

Thanks to everyone for the help so far! I definitely got father in this thanks to your help :slight_smile:

uBAQ custom code:

// Support Functions
Func<string, object, bool> debugMsg = (title, dataObj) =>
{
    string jsonTxt = JsonConvert.SerializeObject(dataObj);
    string jsonMessage = string.Format("{0}: {1}{2}", title, Environment.NewLine, jsonTxt);
    this.PublishInfoMessage(jsonMessage, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"UBAQ", "Advanced");
    return true ;
};

// Common variables
var currPlant = callContextClient.CurrentPlant;
var currCompany = callContextClient.CurrentCompany;

// Get the params the BAQ was called with
var jobNum = ttExecutionParameter.Where(m => m.ParameterID == "sJobNum").Select(m => m.ParameterValue).FirstOrDefault();
List<string> partNums = ttExecutionParameter.Where(m => m.ParameterID == "sPartNum").Select(m => m.ParameterValue).ToList();
var assemblySeqStr = ttExecutionParameter.Where(m => m.ParameterID == "sAssemblySeq").Select(m => m.ParameterValue).FirstOrDefault();
var mtlSeqStr = ttExecutionParameter.Where(m => m.ParameterID == "sMtlSeq").Select(m => m.ParameterValue).FirstOrDefault();

// Setup our service calls
var serialNoAssign = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.SerialNoAssignSvcContract>(Db);
var selectedSerialNums = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.SelectedSerialNumbersSvcContract>(Db);

if (partNums.Any() && partNums.Count() > 1 && !string.IsNullOrEmpty(jobNum) && !string.IsNullOrEmpty(assemblySeqStr) && !string.IsNullOrEmpty(mtlSeqStr))
{
  /***************************************************************
   *                  Validations & Data Setup
   ***************************************************************/
   
  // Setup our two int type params
  int assemblySeq = 0;
  int mtlSeq = 0;
  int.TryParse(assemblySeqStr, out assemblySeq);
  int.TryParse(mtlSeqStr, out mtlSeq);
  
  // Ensure we have a JobAsmbl record (aka they saved the Issue Material form)
  var jobAsmblRec = Db.JobAsmbl.Where(m => m.Company == currCompany && m.Plant == currPlant && m.JobNum == jobNum && m.AssemblySeq == assemblySeq).ToList();
  if (!jobAsmblRec.Any())
  {
    string msgTxt = string.Format("Please ensure you saved the Issued Material before attempting to match serials");
    this.PublishInfoMessage(msgTxt, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"UBAQ", "Advanced");
    return;
  }
  var jobAsmbl = jobAsmblRec.FirstOrDefault();

  // Get the part details
  var partRecs = Db.Part.Where(m => m.Company == currCompany && partNums.Contains(m.PartNum)).ToList();
  var lowerLevel = partRecs.Where(m => m.LowLevelCode == 1).FirstOrDefault();
  var upperLevel = partRecs.Where(m => m.LowLevelCode == 0).FirstOrDefault();
  
  // Hard stop if we've already run a serial match process
  var hasTrans = Db.SNTran.Where(m => m.JobNum == jobNum && m.PartNum == upperLevel.PartNum).ToList();
  if (hasTrans.Any())
  {
    string msgTxt = string.Format("Serial transaction already exists for Job {0}, Part {1}", jobNum, upperLevel.PartNum);
    this.PublishInfoMessage(msgTxt, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"UBAQ", "Advanced");
    //return;
  }
  
  // We need to setup the range of serials, get the min and max from our lower level part
  var llSerials = Db.SerialNo
    .Where(m => m.Company == currCompany && m.MtlSeq == mtlSeq && m.PartNum == lowerLevel.PartNum && m.JobNum == jobNum && m.AssemblySeq == assemblySeq)
    .Select(m => m.SerialNumber).ToList();
  if (!llSerials.Any())
  {
    string msgTxt = string.Format("Serials could not be found for Job# {0}, Part {1}", jobNum, lowerLevel.PartNum);
    this.PublishInfoMessage(msgTxt, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual,"UBAQ", "Advanced");
    return;
  }
  var startSerial = llSerials.OrderBy(m => m).First();
  
  
  /***************************************************************
   *                Serialization Automation
   ***************************************************************/
   
  // Gets the default values for the Serial number assignment screen. Also populates the Selectedserialnumbers table for the job. 
  bool TrackSerialNo = false; 
  var serialNoAssignDS = serialNoAssign.GetSerialNoAssign(jobNum, assemblySeq, String.Empty, 0, out TrackSerialNo);
    
  // Get our Source Row ID from our serial number tableset
  var sourceRowID = serialNoAssignDS.SerialNoAssign.Select(m => m.SysRowID).FirstOrDefault().ToString();
  
  // Create a reference to the selected serial numbers for use
  var selectedSerialNumbersTS = new Erp.Tablesets.SelectedSerialNumbersTableset(); 
  
  // Gets the next serial number format based on the part number passed in.
  selectedSerialNums.GetSerialNumFormat(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, currPlant);
  
  // Gets the next serial number based on the format for the part number passed in
  string nextBaseSN = String.Empty;
  string snPrefix = String.Empty;
  string nextFullSN = String.Empty;
  bool snCounterMax = false;
  selectedSerialNums.GetNextSN(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, currPlant, out nextBaseSN, out snPrefix, out nextFullSN, out snCounterMax);
  
  // Temporary hard coding for testing purposes...
  selectedSerialNumbersTS.SNFormat[0].SNFormat = "99999";
  selectedSerialNumbersTS.SNFormat[0].HasSerialNumbers = false;
  
  // Create multiple serial number temporary records in the Selected Serial Numbers dataset
  selectedSerialNums.CreateSerialNumRange(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, jobAsmbl.RequiredQty, startSerial, sourceRowID, String.Empty, currPlant);
  
  // Gets the next serial number based on the format for the part number passed in
  nextBaseSN = String.Empty;
  snPrefix = String.Empty;
  nextFullSN = String.Empty;
  snCounterMax = false;
  selectedSerialNums.GetNextSN(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, currPlant, out nextBaseSN, out snPrefix, out nextFullSN, out snCounterMax);
    
  // Update the selected serial numbers object in our serial number assignment object
  foreach (var serialNum in selectedSerialNumbersTS.SelectedSerialNumbers)
  {
    var newRow = serialNoAssignDS.SelectedSerialNumbers.NewRow();
    newRow["Company"] = serialNum.Company;
    newRow["SerialNumber"] = serialNum.SerialNumber;
    newRow["Scrapped"] = serialNum.Scrapped;
    newRow["ScrappedReasonCode"] = serialNum.ScrappedReasonCode;
    newRow["Voided"] = serialNum.Voided;
    newRow["Reference"] = serialNum.Reference;
    newRow["ReasonCodeType"] = serialNum.ReasonCodeType;
    newRow["ReasonCodeDesc"] = serialNum.ReasonCodeDesc;
    newRow["PartNum"] = serialNum.PartNum;
    newRow["SNPrefix"] = serialNum.SNPrefix;
    newRow["SNBaseNumber"] = serialNum.SNBaseNumber;
    newRow["SourceRowID"] = serialNum.SourceRowID;
    newRow["TransType"] = serialNum.TransType;
    newRow["PassedInspection"] = serialNum.PassedInspection;
    newRow["Deselected"] = serialNum.Deselected;
    newRow["KitWhseList"] = serialNum.KitWhseList;
    newRow["RawSerialNum"] = serialNum.RawSerialNum;
    newRow["KBLbrAction"] = serialNum.KBLbrAction;
    newRow["KBLbrActionDesc"] = serialNum.KBLbrActionDesc;
    newRow["PreventDeselect"] = serialNum.PreventDeselect;
    newRow["XRefPartNum"] = serialNum.XRefPartNum;
    newRow["XRefPartType"] = serialNum.XRefPartType;
    newRow["PreDeselected"] = serialNum.PreDeselected;
    newRow["poLinkValues"] = serialNum.poLinkValues;
    newRow["SNMask"] = serialNum.SNMask;
    newRow["NotSavedToDB"] = serialNum.NotSavedToDB;
    newRow["SysRowID"] = serialNum.SysRowID;
    newRow["RowMod"] = serialNum.RowMod;
    serialNoAssignDS.SelectedSerialNumbers.Add(newRow);
  }
  
  // Now update the serial number format
  foreach (var serialNum in selectedSerialNumbersTS.SNFormat)
  {
    var newSNFormatRow = serialNoAssignDS.SNFormat.NewRow();
    newSNFormatRow["Company"] = serialNum.Company;
    newSNFormatRow["Plant"] = serialNum.Plant;
    newSNFormatRow["PartNum"] = serialNum.PartNum;
    newSNFormatRow["NumberOfDigits"] = serialNum.NumberOfDigits;
    newSNFormatRow["SNMask"] = serialNum.SNMask;
    newSNFormatRow["SNBaseDataType"] = serialNum.SNBaseDataType;
    newSNFormatRow["SNFormat"] = serialNum.SNFormat;
    newSNFormatRow["LeadingZeroes"] = serialNum.LeadingZeroes;
    newSNFormatRow["SNPrefix"] = serialNum.SNPrefix;
    newSNFormatRow["SNMaskSuffix"] = serialNum.SNMaskSuffix;
    newSNFormatRow["SNMaskPrefix"] = serialNum.SNMaskPrefix;
    newSNFormatRow["SNLastUsedSeq"] = serialNum.SNLastUsedSeq;
    newSNFormatRow["HasSerialNumbers"] = serialNum.HasSerialNumbers;
    newSNFormatRow["SysRowID"] = serialNum.SysRowID;
    newSNFormatRow["BitFlag"] = serialNum.BitFlag;
    newSNFormatRow["PartPricePerCode"] = serialNum.PartPricePerCode;
    newSNFormatRow["PartTrackLots"] = serialNum.PartTrackLots;
    newSNFormatRow["PartTrackSerialNum"] = serialNum.PartTrackSerialNum;
    newSNFormatRow["PartTrackDimension"] = serialNum.PartTrackDimension;
    newSNFormatRow["PartSalesUM"] = serialNum.PartSalesUM;
    newSNFormatRow["PartIUM"] = serialNum.PartIUM;
    newSNFormatRow["PartSellingFactor"] = serialNum.PartSellingFactor;
    newSNFormatRow["PartPartDescription"] = serialNum.PartPartDescription;
    newSNFormatRow["SerialMaskMaskType"] = serialNum.SerialMaskMaskType;
    newSNFormatRow["SerialMaskMask"] = serialNum.SerialMaskMask;
    newSNFormatRow["SerialMaskExample"] = serialNum.SerialMaskExample;
    newSNFormatRow["SerialMaskDescription"] = serialNum.SerialMaskDescription;
    newSNFormatRow["RowMod"] = String.Empty;
    serialNoAssignDS.SNFormat.Add(newSNFormatRow);
  }

  // Validates the job number, assembly sequence and part number. Also validates the part is serial tracked. 
  // Updates the SerialNo table and the Part table for the SN Format fields. Calls the SNTran create subroutine
  string oprCmpWarning = String.Empty;
  serialNoAssign.SetSerialNoAssign(ref serialNoAssignDS, false, out oprCmpWarning);
  
  //debugMsg("Serial No Assign TS", serialNoAssignDS);
}

Trace:
SerialNumAssignTrace.xml (232.6 KB)

It does. What happened here, is they(the devs) defined Tablesets with the same names in different assemblies.
These definitions may or may not have the same definitions etc,

The BPM code behind compiler doesn’t know which one to use.

Sometimes you can work around it in custom code. With the widgets, you may have to break it into chunks.

1 Like

Thank you for that explanation! I ended up going back to custom code instead of using the widgets, since I get the same error anyways no matter which approach I take.

Your trace shows this going to GetNextSN:

      <SelectedSerialNumbersDataSet xmlns="http://www.epicor.com/Ice/300/BO/SelectedSerialNumbers/SelectedSerialNumbers">
        <SNFormat>
          <SNFormat>203-100009</SNFormat>
          <HasSerialNumbers>true</HasSerialNumbers>
        </SNFormat>
      </SelectedSerialNumbersDataSet>

But your test data has this:

// Temporary hard coding for testing purposes...
  selectedSerialNumbersTS.SNFormat[0].SNFormat = "99999";
  selectedSerialNumbersTS.SNFormat[0].HasSerialNumbers = false;
  
1 Like

Yup I noticed that the return from GetNextSN modified those two elements so that’s the only reason I added those overrides in there.

Look here:

You run GetNextSN
don’t get the data you want ?
change some, run CreateSerialNumRange
then run GetNextSN again with probably the wrong data above

  // Gets the next serial number based on the format for the part number passed in
  string nextBaseSN = String.Empty;
  string snPrefix = String.Empty;
  string nextFullSN = String.Empty;
  bool snCounterMax = false;
  selectedSerialNums.GetNextSN(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, currPlant, out nextBaseSN, out snPrefix, out nextFullSN, out snCounterMax);
  
  // Temporary hard coding for testing purposes...
  selectedSerialNumbersTS.SNFormat[0].SNFormat = "99999";
  selectedSerialNumbersTS.SNFormat[0].HasSerialNumbers = false;
  
  // Create multiple serial number temporary records in the Selected Serial Numbers dataset
  selectedSerialNums.CreateSerialNumRange(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, jobAsmbl.RequiredQty, startSerial, sourceRowID, String.Empty, currPlant);
  
  // Gets the next serial number based on the format for the part number passed in
  nextBaseSN = String.Empty;
  snPrefix = String.Empty;
  nextFullSN = String.Empty;
  snCounterMax = false;
  selectedSerialNums.GetNextSN(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, currPlant, out nextBaseSN, out snPrefix, out nextFullSN, out snCounterMax);
    

what happens if you change it to this ?:


  // Gets the next serial number based on the format for the part number passed in
  string nextBaseSN = String.Empty;
  string snPrefix = String.Empty;
  string nextFullSN = String.Empty;
  bool snCounterMax = false;
  selectedSerialNums.GetNextSN(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, currPlant, out nextBaseSN, out snPrefix, out nextFullSN, out snCounterMax);
  
  // Create multiple serial number temporary records in the Selected Serial Numbers dataset
  selectedSerialNums.CreateSerialNumRange(ref selectedSerialNumbersTS, upperLevel.PartNum, String.Empty, String.Empty, 0, jobAsmbl.RequiredQty, startSerial, sourceRowID, String.Empty, currPlant);
  

1 Like

The data going in to GetSNFormat should have been:

<SNFormat>203-100009</SNFormat>
<HasSerialNumbers>true</HasSerialNumbers>

That’s what the trace says

what did your data look like just before your call ?

1 Like

specifically the return from “GetSerialNumFormat”

1 Like

Hello!

So the data going into GetSerialNumFormat is an empty Tableset, but includes input params, here is the snippet from the trace:

  <parameters>
    <parameter name="ds" type="Erp.BO.SelectedSerialNumbersDataSet">
      <SelectedSerialNumbersDataSet xmlns="http://www.epicor.com/Ice/300/BO/SelectedSerialNumbers/SelectedSerialNumbers" />
  </parameter>
    <parameter name="partNum" type="System.String"><![CDATA[N00983203-1]]></parameter>
    <parameter name="xrefPartNum" type="System.String"><![CDATA[]]></parameter>
    <parameter name="xrefPartType" type="System.String"><![CDATA[]]></parameter>
    <parameter name="xrefCustNum" type="System.Int32"><![CDATA[0]]></parameter>
    <parameter name="plantID" type="System.String"><![CDATA[MfgSys]]></parameter>
  </parameters>

The return from GetSerialNumFormat, via the trace was:

<returnParameter name="ds" type="Erp.Tablesets.SelectedSerialNumbersTableset">
      <SelectedSerialNumbersDataSet xmlns="http://www.epicor.com/Ice/300/BO/SelectedSerialNumbers/SelectedSerialNumbers">
        <SNFormat>
          <Company>401</Company>
          <Plant>MfgSys</Plant>
          <PartNum>N00983203-1</PartNum>
          <NumberOfDigits>5</NumberOfDigits>
          <SNMask></SNMask>
          <SNBaseDataType>INTEGER</SNBaseDataType>
          <SNFormat>203-100009</SNFormat>
          <LeadingZeroes>true</LeadingZeroes>
          <SNPrefix>203-1</SNPrefix>
          <SNMaskSuffix></SNMaskSuffix>
          <SNMaskPrefix></SNMaskPrefix>
          <SNLastUsedSeq></SNLastUsedSeq>
          <HasSerialNumbers>true</HasSerialNumbers>
          <SysRowID>00000000-0000-0000-0000-000000000000</SysRowID>
          <BitFlag>0</BitFlag>
          <PartPricePerCode>E</PartPricePerCode>
          <PartTrackLots>true</PartTrackLots>
          <PartTrackSerialNum>true</PartTrackSerialNum>
          <PartTrackDimension>false</PartTrackDimension>
          <PartSalesUM>EA</PartSalesUM>
          <PartIUM>EA</PartIUM>
          <PartSellingFactor>1.00000000</PartSellingFactor>
          <PartPartDescription>Precision Part, Machined, 83mm</PartPartDescription>
          <SerialMaskMaskType>0</SerialMaskMaskType>
          <SerialMaskMask></SerialMaskMask>
          <SerialMaskExample></SerialMaskExample>
          <SerialMaskDescription></SerialMaskDescription>
          <RowMod></RowMod>
        </SNFormat>
      </SelectedSerialNumbersDataSet>
    </returnParameter>

The return from my custom code is (JSON format):

"GetSerialNumFormat return":{
   "SelectedSerialNumbers":[
      
   ],
   "SNFormat":[
      {
         "ColumnNames":0,
         "Company":"401",
         "Plant":"MfgSys",
         "PartNum":"N00983203-1",
         "NumberOfDigits":5,
         "SNMask":"",
         "SNBaseDataType":"INTEGER",
         "SNFormat":"203-100009",
         "LeadingZeroes":true,
         "SNPrefix":"203-1",
         "SNMaskSuffix":"",
         "SNMaskPrefix":"",
         "SNLastUsedSeq":"",
         "HasSerialNumbers":true,
         "SysRowID":"00000000-0000-0000-0000-000000000000",
         "BitFlag":0,
         "PartPricePerCode":"E",
         "PartTrackLots":true,
         "PartTrackSerialNum":true,
         "PartTrackDimension":false,
         "PartSalesUM":"EA",
         "PartIUM":"EA",
         "PartSellingFactor":1.00000000,
         "PartPartDescription":"Precision Part, Machined, 83mm",
         "SerialMaskMaskType":0,
         "SerialMaskMask":"",
         "SerialMaskExample":"",
         "SerialMaskDescription":"",
         "RowMod":"",
         "SpecifiedProperties":"/5f/Bw==",
         "UserDefinedColumns":{
            
         }
      }
   ],
   "ExtensionTables":[
      
   ]
}

Also I removed those two override lines (where I was manually setting the SNFormat and HasSerialNumbers.

Thank you for the help!