Udashboard for UD tables

So I have a dashboard that is showing information from UD05 and UD04. UD05 is a comments table, and UD04 is for trucking information. I want to be able to let the users modify a comment (UD05) and be able to add tracking information (UD04). These are currently showing both values in one row in one grid. If I use the UD04/UD05 BO’s it only lets me change the fields in the respective table. Is there a way to call both BO’s? You can see a screen shot below of what I have so far.

On thought that I did have was to use context menu on the fields and create a update able dashboard for each situation so the user would right click, open with, modify x, depending on what they are clicking on. Does that sound like a valid option for making this work?

Sure, Just use the BPM Only Update Option and write the code yourself in the Updatable BAQ BPM Editor

Alright, I’ll see if I can figure this out. Why do you have to make everything so hard???

Just to give me a head start,

  1. does this go on pre, post or base?
  2. If I just get the base code from one of the update methods, can I just paste that into the BAQ BPM editor.

(you have to remember, I’m at the copy and paste stage of my coding career. :rofl:)

Never mind. I see in the user guides, it goes into the post, and you just set the fields from the dashboard with things that you publish from the dashboard.

I’m sure I’ll have more questions later…

Sorry @Banderson, if you are doing BPM Only Update you would do Base. Since you’d be writing the ALL of the code to update Epicor. It no longer uses the Built in BO logic but rather the logic you yourself write.
Start out something like this

foreach(var x in ttResults.Where(r=>r.RowMod=="U")
{
      //Call BO for UD04 and update appropriate Fields
      //Call BO for UD05 and update appropriate Fields there

} 

So here is the auto generated code for the UD05 update. I could get the same for the UD04 update with the same query by just changing the BO to UD05 and getting the code for that one. Can I put each of those into an Execute custom code block and then chain them together in my own custom base processing? Or do I have to merge the two into the same block?

// <auto-generated>
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// </auto-generated>

using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD05SvcContract>())
{
    var ttResultQuery = ttResults
        .Where(row => !string.IsNullOrEmpty(row.RowMod) && row.RowMod != "P");

    foreach (var ttResult in ttResultQuery)
    {
        var ds = new Ice.Tablesets.UpdExtUD05Tableset();
        bool errorOccurred;

        // Query to object mapping
        {
            var UD05 = new Ice.Tablesets.UD05Row
            {
                Company = ttResult.UD05_Company,
                Key1 = ttResult.UD05_Key1,
                Key2 = ttResult.UD05_Key2,
                Key3 = ttResult.UD05_Key3,
                Key4 = ttResult.UD05_Key4,
                Key5 = ttResult.UD05_Key5,
            };

            UD05.SetUDField<System.String>("Text_c", ttResult.UD05_Text_c);

            ds.UD05.Add(UD05);
        }

        BOUpdErrorTableset boUpdateErrors = svc.UpdateExt(ref ds, true, true, out errorOccurred);
        if (this.BpmDataFormIsPublished()) return;

        ttResult.RowMod = "P";

        // Object to query mapping
        {
            var UD05 = ds.UD05.FirstOrDefault(
                tableRow => tableRow.Company == ttResult.UD05_Company
                    && tableRow.Key1 == ttResult.UD05_Key1
                    && tableRow.Key2 == ttResult.UD05_Key2
                    && tableRow.Key3 == ttResult.UD05_Key3
                    && tableRow.Key4 == ttResult.UD05_Key4
                    && tableRow.Key5 == ttResult.UD05_Key5);
            if (UD05 == null)
            {
                UD05 = ds.UD05.LastOrDefault();
            }

            if (UD05 != null)
            {
                ttResult.UD05_Company = UD05.Company;
                ttResult.UD05_Key1 = UD05.Key1;
                ttResult.UD05_Key2 = UD05.Key2;
                ttResult.UD05_Key3 = UD05.Key3;
                ttResult.UD05_Key4 = UD05.Key4;
                ttResult.UD05_Key5 = UD05.Key5;
                ttResult.UD05_Text_c = UD05.UDField<System.String>("Text_c", throwIfNull:false);
            }
        }

        if (errorOccurred && boUpdateErrors?.BOUpdError != null)
        {
            ttErrors
                .AddRange(
                    boUpdateErrors.BOUpdError
                        .Select(
                            e => new ErrorsUbaqRow
                            {
                                TableName = e.TableName,
                                ErrorRowIdent = ttResult.RowIdent,
                                ErrorText = e.ErrorText,
                                ErrorType = e.ErrorType
                            }));
        }
    }
}

var ttResultsForDelete = ttResults
    .Where(row => row.RowMod != "P")
    .ToArray();

foreach (var ttResult in ttResultsForDelete)
{
    ttResults.Remove(ttResult);
}

foreach (var ttResult in ttResults)
{
    ttResult.RowMod = "";
}

Right so you can’t mess with the auto-generated code, you need to switch to BPM Only and write your own… their auto generated code is complicated anyways…
You can just do a simple GetByID, Update and then another GetByID for the UD04 and Update… etc.

I know that, but I can copy and paste it.

Not so simple for someone that’s never done it before… I’m trying, I just have no experience with coding, something simple for you is like a foreign language for me.

1 Like

ah sorry I misunderstood, so yes you can copy their code, and just do the same thing twice one for each UDXX inside the for each

So I copied each of the blocks, I got some errors when I clicked ok, so I went into add reference assemblies (or whatever they are called) I added the ones shown below, and the errors went away. Does that seem to make sense?

Yes you’ll need those in order to use the BO’s

so I’m in the BAQ, and it looks like it worked for the first block (UD05) but the second block (ud04) doesn’t save. I switch the blocks around, and the table that saved switched with it. So it’s only working for the first block. I suspect the first BO sets the field of the other on back to the original value before the the second block can get to it. I need all of the code in one block to make this work don’t I?

If you copied all the code you showed me, part of it clears the RowMods which is not going to help you. Make sure you only copy the part of the code which does the Update to UDXX and not the other stuff

So I need to delete this code from the end of the first block right? I need it on the second one don’t I?

foreach (var ttResult in ttResultsForDelete)
{
    ttResults.Remove(ttResult);
}

foreach (var ttResult in ttResults)
{
    ttResult.RowMod = "";
}

You don’t necessarily need it but yes you should remove it form the first block at least.

So I deleted the above code as well as these pieces. It looks like it’s working now, although I am only dealing with one row in testing. Is there any unintended consequences that you can think of that would cause problems with these deletions? Also

var ttResultsForDelete = ttResults
    .Where(row => row.RowMod != "P")
    .ToArray();

and

    ttResult.RowMod = "P";

Also for the UD04 table, there is information in the table that is not updateable, I should be able to delete the rows of the things that should be updated right? I should only need the keys and the field that I want to update? I’ve had problems with another dashboard where if the data from another column that isn’t supposed to be updateable writing what’s in the field to the database. This would happen if that data changed and you didn’t refresh before saving the update. I deleted the extra rows and it works in the UBAQ still with no errors, but I was just curious about what you thought about removing those lines.

    if (UD04 != null)
    {
        ttResult.UD04_Company = UD04.Company;
        ttResult.UD04_ContainerNum_c = UD04.UDField<System.String>("ContainerNum_c", throwIfNull:false);
        ttResult.UD04_ContainerWeight_c = UD04.UDField<System.String>("ContainerWeight_c", throwIfNull:false);
        ttResult.UD04_CreatedAt_c = UD04.UDField<System.DateTime?>("CreatedAt_c", throwIfNull:false);
        ttResult.UD04_JobNum_c = UD04.UDField<System.String>("JobNum_c", throwIfNull:false);
        ttResult.UD04_Key1 = UD04.Key1;
        ttResult.UD04_Key2 = UD04.Key2;
        ttResult.UD04_Key3 = UD04.Key3;
        ttResult.UD04_Key4 = UD04.Key4;
        ttResult.UD04_Key5 = UD04.Key5;
        ttResult.UD04_Num_c = UD04.UDField<System.Int32>("Num_c", throwIfNull:false);
        ttResult.UD04_SealNum_c = UD04.UDField<System.String>("SealNum_c", throwIfNull:false);
        ttResult.UD04_ShippedAt_c = UD04.UDField<System.DateTime?>("ShippedAt_c", throwIfNull:false);
        ttResult.UD04_ShippingCompany_c = UD04.UDField<System.String>("ShippingCompany_c", throwIfNull:false);
        ttResult.UD04_TrackingNum_c = UD04.UDField<System.String>("TrackingNum_c", throwIfNull:false);
        ttResult.UD04_UpdatedAt_c = UD04.UDField<System.DateTime?>("UpdatedAt_c", throwIfNull:false);
    }
}

So I’m sure you’ve seen my other post having problems with a new line sort of, so I’m going to bite the bullet and try to figure out these updates using adapters and code. Can you point my to a good (read simple) example that I can look at to start learning how to make some code for a simple row read writes? I’ll keep searching the site, but I don’t know exactly what I’m looking for.

BPM or Customization?

ummmm… for this example I think (and I could be totally wrong) that it will be a little simpler to write it in the Updatable Baq maintenance (so BPM), but I’m sure I’ll end up wanting to do both after a while.

How different is the implementation in a customization vs. a BPM?