Need help with BPM Code: Adding when and error handling

,

I wrote some custom code that looks for a number and copies it to a UD field when the record is saved. I’m very new to code and can’t figure out 2 parts. How to only fire when UD10.Character02 is changed. I had a condition configured but it never fired and I couldn’t figure out why, the message box I added never showed up. Now it fires every time I hit save, which is fine but unnecessary. The second issue I have is if there isn’t a number to copy over. I’d like it to just stay 0 (with the best case a pop up that this lot doesn’t have an RML entered yet). I tried the code below but still get an error.

//Get Part Lot Table
Erp.Tables.PartLot LotTable;

//Get temp table for updated UD10 record
var NewRecord = ttUD10.FirstOrDefault();

//Get part and lot number of new record
var tranPart = NewRecord.Character01;
var tranLot = NewRecord.Character02;

//Link ttUD10 to PartLot using part and lot numbers
LotTable = (from PartLot_row in Db.PartLot
            where PartLot_row.Company == Session.CompanyID
            && PartLot_row.PartNum == tranPart
            && PartLot_row.LotNum == tranLot
            select PartLot_row).FirstOrDefault();
            
//Set UD10.Number03 to RML (partLot.FirmWare) for lot if RML is not null
if (LotTable.FirmWare != null)
  {NewRecord.Number03 = int.Parse(LotTable.FirmWare);}

here is how I would do this although you could likely do this all in widgets with no code.

You will need to add a reference to UD10

/* code to update Firmware */

using(var UD10Svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD10SvcContract>(Db, true))
{

bool errorOccurred;

decimal firmWareNum = 0;

UpdExtUD10Tableset ds = new UpdExtUD10Tableset();

foreach (var ttUD10 in (from ttUD_Row in ds.UD10
where ttUD_Row.Company == callContextClient.CurrentCompany && ttUD_Row.Updated()
select ttUD_Row))
{

var firmWare = (from PartLot_row in Db.PartLot
            where PartLot_row.Company == Session.CompanyID
            && PartLot_row.PartNum == ttUD10.Character01
            && PartLot_row.LotNum == ttUD10.Character02
            select PartLot_row.FirmWare).FirstOrDefault();



    var UD10 = new Ice.Tablesets.UD10Row
    {
      Key1 = ttUD10.Key1,
      Key2 = ttUD10.Key2,
      Key3 = ttUD10.Key3,
      Key4 = ttUD10.Key4,
      Key5 = ttUD10.Key5,
      Company = Session.CompanyID,
    };


      if(firmWare != null)
      {
        decimal.TryParse(firmWare, out firmWareNum);
        if(firmWareNum != 0)
        {
            //decimal firmWareNum 
            UD10.SetUDField<System.Decimal>("Number03",firmWareNum);
        }
      }
      else
      {
            UD10.SetUDField<System.Decimal>("Number03",0);
      }

     //add the record to our dataset
    ds.UD10.Add(UD10);
    
    BOUpdErrorTableset boUpdateErrors = UD10Svc.UpdateExt(ref ds, false,true, out errorOccurred);


}
}

Hi @gpayne this solution worked great. Until yesterday :frowning: I can’t figure out what the problem is. I made 2 changes. The first is entering date and time into one field instead of 2 separate fields, but I don’t see any of those referenced here so don’t know why it would be an issue. The second thing is I added UD fields to my UD10 table. I don’t use them in the BPM but might that have changed something in the background that I need to be aware of?
Thanks

Is there an error or message on the screen or in the event viewer?

If not then you will need to add Write Entry in the code to show the bpms progress and variable values.

I am not getting any error message, the data just isn’t showing up in the UD10 table.

I’ve never used the event viewer, where would that be?

Thanks
Melissa

Event View is the Windows Event Viewer on the App server. Epicor has there own node.

You can also see them in the appserver log which shows the whole run and not one at a time.

Ice.Diagnostics.Log.WriteEntry($"In calc Subs - Mtl Part is now {PartMtl.MtlPartNum}");

image

Thank you for all your help. I don’t see anything in the Event Viewer except the errors I got yesterday while trying to make another thing work :slight_smile:

I looked up how to write to the log and how to have a pop up show data so I added both but nothing shows up, either in the Event Viewer or a pop up box.

/* code to update Firmware */

using(var UD10Svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD10SvcContract>(Db, true))
{

bool errorOccurred;

decimal firmWareNum = 0;

UpdExtUD10Tableset ds = new UpdExtUD10Tableset();

foreach (var ttUD10 in (from ttUD_Row in ds.UD10
where ttUD_Row.Company == callContextClient.CurrentCompany && ttUD_Row.Added() | ttUD_Row.Updated()
select ttUD_Row))
{

var firmWare = (from PartLot_row in Db.PartLot
            where PartLot_row.Company == Session.CompanyID
            && PartLot_row.PartNum == ttUD10.Character01
            && PartLot_row.LotNum == ttUD10.Character02
            select PartLot_row.FirmWare).FirstOrDefault();

//Neither of these do anything
Ice.Diagnostics.Log.WriteEntry("Get data: " + firmWare);
InfoMessage.Publish(firmWare);

    var UD10 = new Ice.Tablesets.UD10Row
    {
      Key1 = ttUD10.Key1,
      Key2 = ttUD10.Key2,
      Key3 = ttUD10.Key3,
      Key4 = ttUD10.Key4,
      Key5 = ttUD10.Key5,
      Company = Session.CompanyID,
    };


      if(firmWare != null)
      {
        decimal.TryParse(firmWare, out firmWareNum);
        if(firmWareNum != 0)
        {
            //decimal firmWareNum 
            UD10.SetUDField<System.Decimal>("Number03",firmWareNum);
        }
      }
      else
      {
            UD10.SetUDField<System.Decimal>("Number03",0);
      }

      
     //add the record to our dataset
    ds.UD10.Add(UD10);
    
    BOUpdErrorTableset boUpdateErrors = UD10Svc.UpdateExt(ref ds, false,true, out errorOccurred);


}
}

So, I would add a write outside of the code at the top and the bottom with just Start XXX Routine and Exit XXX Routine to know that it even fired.

I added some entries at different points in the code. It writes to the log until the foreach statement then it doesn’t write any again until the last one. I did try starting from scratch with a brand new BPM and get the same result.

/* code to update Firmware */
//FIRES
Ice.Diagnostics.Log.WriteEntry("start code");
using(var UD10Svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD10SvcContract>(Db, true))
{

bool errorOccurred;

decimal firmWareNum = 0;
//FIRES
Ice.Diagnostics.Log.WriteEntry("after set firmware to 0");

UpdExtUD10Tableset ds = new UpdExtUD10Tableset();
//FIRES
Ice.Diagnostics.Log.WriteEntry("after UpdExtUD10Tableset");

foreach (var ttUD10 in (from ttUD_Row in ds.UD10
where ttUD_Row.Company == callContextClient.CurrentCompany && ttUD_Row.Updated()
select ttUD_Row))
{
  //DOESN'T FIRE
Ice.Diagnostics.Log.WriteEntry("after foreach");

var firmWare = (from PartLot_row in Db.PartLot
            where PartLot_row.Company == Session.CompanyID
            && PartLot_row.PartNum == ttUD10.Character01
            && PartLot_row.LotNum == ttUD10.Character02
            select PartLot_row.FirmWare).FirstOrDefault();
 //DOESN'T FIRE
Ice.Diagnostics.Log.WriteEntry("after select partlot first or default");

    var UD10 = new Ice.Tablesets.UD10Row
    {
      Key1 = ttUD10.Key1,
      Key2 = ttUD10.Key2,
      Key3 = ttUD10.Key3,
      Key4 = ttUD10.Key4,
      Key5 = ttUD10.Key5,
      Company = Session.CompanyID,
    };
 //DOESN'T FIRE
Ice.Diagnostics.Log.WriteEntry("after var UD10 Keys");

      if(firmWare != null)
      {
        decimal.TryParse(firmWare, out firmWareNum);
        if(firmWareNum != 0)
        {
            //decimal firmWareNum 
            UD10.SetUDField<System.Decimal>("Number03",firmWareNum);
             //DOESN'T FIRE
            Ice.Diagnostics.Log.WriteEntry("Number03" + firmWareNum);
        }
      }
      else
      {
            UD10.SetUDField<System.Decimal>("Number03",0);
             //DOESN'T FIRE
            Ice.Diagnostics.Log.WriteEntry("Number03 is 0");
      }

     //add the record to our dataset
    ds.UD10.Add(UD10);
    
    BOUpdErrorTableset boUpdateErrors = UD10Svc.UpdateExt(ref ds, false,true, out errorOccurred);


}
}
//FIRES
Ice.Diagnostics.Log.WriteEntry("End BPM");

Earlier the foreach was Added or Updated and it is now just Updated. You can print ttUD_Row.RowMod before the foreach

I added the or Added to the foreach. When I try to print the RowMod I get an error that ttUD_Row doesn’t exist. I tries ttUD10_Row also with the same result. I also get the same error if I put the print after the foreach statement.

//ttUD_Row doesn't exist error
Ice.Diagnostics.Log.WriteEntry(ttUD_Row.RowMod);

foreach (var ttUD10 in (from ttUD_Row in ds.UD10
where ttUD_Row.Company == callContextClient.CurrentCompany && ttUD_Row.Updated() | ttUD_Row.Added()
select ttUD_Row))
{

var firmWare = (from PartLot_row in Db.PartLot
            where PartLot_row.Company == Session.CompanyID
            && PartLot_row.PartNum == ttUD10.Character01
            && PartLot_row.LotNum == ttUD10.Character02
            select PartLot_row.FirmWare).FirstOrDefault();

Ice.Diagnostics.Log.WriteEntry("after select partlot first or default");

    var UD10 = new Ice.Tablesets.UD10Row
    {
      Key1 = ttUD10.Key1,
      Key2 = ttUD10.Key2,
      Key3 = ttUD10.Key3,
      Key4 = ttUD10.Key4,
      Key5 = ttUD10.Key5,
      Company = Session.CompanyID,
    };

Ice.Diagnostics.Log.WriteEntry("after var UD10 Keys");

      if(firmWare != null)
      {
        decimal.TryParse(firmWare, out firmWareNum);
        if(firmWareNum != 0)
        {
            //decimal firmWareNum 
            UD10.SetUDField<System.Decimal>("Number03",firmWareNum);
            Ice.Diagnostics.Log.WriteEntry("Number03" + firmWareNum);
        }
      }
      else
      {
            UD10.SetUDField<System.Decimal>("Number03",0);
            Ice.Diagnostics.Log.WriteEntry("Number03 is 0");
      }

     //add the record to our dataset
    ds.UD10.Add(UD10);
    
    BOUpdErrorTableset boUpdateErrors = UD10Svc.UpdateExt(ref ds, false,true, out errorOccurred);


}
}

Not sure if this will be any help, but I had some time this morning and figured it would be good exercise to see how I’d tackle this. Not tested. May be broken. Don’t see why it would, other than (maybe) the update part.

I typically use LINQ method syntax unless I’m doing joins (in which case query syntax is superior). Code usually ends up cleaner that way.

//this will return a selection of the original objects and not a copy of the rows.
var u10 = ds.UD10.Where(x => x.Company == Session.CompanyID && x.RowMod == "U");

using(var UD10Svc = Ice.Assemblies
                       .ServiceRenderer
                       .GetService<Ice.Contracts.UD10SvcContract>(Db))
{
    foreach(var u10row in u10)
    {
        var partlots = Db.PartLot.Where(x =>
                                        x.Company == u10row.Company &&
                                        x.PartNum == u10row.Character01 &&
                                        x.LotNum == u10row.Character02)
                                 .ToList(); //Copy the DB data to local object
//As a rule, we don't want to work with the DB directly any more than necessary.
//Personally, if I had more time, I'd structure this into a single query.
//It would execute right after the u10 does and before the for loop.
//I'd then do LINQ lookups on the copied list in each loop.
//one call to DB in total instead of 1 per loop.
//However, I don't know how your data is structured here.
                                 
        if(partlots.Any())
//Checks if any rows were returned from PartLot query.
        {
            var pl= partlots.FirstOrDefault();
            //Do whatever to edit the UD10 row.
            u10row.Number03 = decimal.Parse(pl.FirmWare);
            u10row.Date01 = DateTime.Now;
        }
    }
//we *should* have been modifiying the original object, so this should work.
//Haven't tested, so this may blow up in runtime.
//Regardless, since we have the whole UD10 dataset at hand, we shouldn't
//need to call UpdateExt instead of Update. So it's just a matter of copying ds.
    var u10ts = new Ice.Tablesets.UD10Tableset();
    u10ts = ds;
    UD10Svc.Update(ref u10ts); 
}