Help with Select Serial Numbers - BAQ BPM

Hello,

I’ve been having a hard time trying to figure out how to duplicate the functionality of the Select Serial Numbers form.

I have been given a task to provide the users a button that will automatically generate the range of serials based on the lower level material’s serial numbers. The button will exist on Issue Material. All functionality resides in a uBAQ bpm.

I see the tables used by this process include SerialNo and SNTran. The prefix can be derived from partplant.

But I’m looking at the ERP Object Reference and confused by which service to use. I thought I should be using SerialNoAssign.KineticAddSerialNumbers but the more I dig into it, the more I don’t think that’s right.

I see SelectedSerialNumbers service as an AddSerialNum method, but none of these methods takes into account the prefix I need to use.

I hope that’s clear, and I appreciate your help!

I have not done what you are attempting, not to that level of complexity. But we do issue serial numbers via an Epicor Function (basically a BPM).

What I have is

  1. Invoke BO method:

image

  1. Fill Table By Query:

  1. And Invoke BO method (because I guess you are supposed to?)

image

Well… among many other steps (like quantity and from-warehouse/bin, etc.), but you were asking about serial numbers specifically.

1 Like

This is very helpful though, thank you! :slight_smile:

This is starting to ring a bell now - I remember thinking the same things.

Yeah, despite those “add” methods, none of them seem to work. You actually have to create the table yourself from scratch - that’s the fill table by query widget.

I only do one serial per transaction, so GetByID works for me. But I would assume :crossed_fingers: that GetRows could work too, if you are doing multiple?

Yeah I am now stepping through a trace when I assigned serials manually to a job to see all the BOs it invoked to see the process. Fun thing is my situation could be one or many depending on how the job was setup.

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