BPM Method Directive custom code syntax

Upgrading from 10.1.400.18 to 10.2.500.23. Method directive custom code is wrong. Where can I find the syntax for custom code in a method directive for 10.2.500.x? I thought this was supposed to be converted to C#. I think I have ABL code.

FOR EACH JobProd.
FIND FIRST JOBASMBL WHERE JobProd_OrderNum = ttInvcDtl_OrderNum AND JobProd_OrderLine = ttInvcDtl_OrderLine AND JobProd_OrderRelNum = ttInvcDtl_OrderRelNum AND JOBASMBL_AssemblySeq = 0.
If available JobAsmbl then ttInvcDtl_Number19 = JobAsmbl_Number20.
END.

well, i am guessing at the context of your BPM. It SEEMS to be written to find when an INVOICE is modified, you want to get the number20 from the related jobAssembly record.
I am sure that someone else could write the two non-tt queries (jobprod/JobAssembly) in one JOINED linq query… but it just wasn’t coming easy for me today. so… something like this should work. Note that this is NOT tested.

foreach (var tIDtl = ttInvcDtl.Where(x => x.RowMod == "U")) {

    string jobNum = Db.JobProd.Where(x =>
        x.Company == CompanyID &&
        x.OrderNum == tIDtl.OrderNum &&
        x.OrderLine == tIDtl.OrderLine &&
        x.OrderRelNum == tIDtl.OrderRelNum &&
        x.AssemblySeq == 0).Select(x => x.JobNum).FirstOrDefault();

    if (jobNum != null) {
        decimal number20 = Db.JobAsmbl.Where(x =>
            x.Company == CompanyID &&
            x.JobNum == jobNum).Select(x => x.Number20).FirstOrDefault();

        if (numb != null) {
            ttIDtl.Number19 = number20;
        }
    }
}
2 Likes

Just for fun… :wink:

ttInvcDtl.Where(d => d.RowMod == "U")
         .ToList()
         .ForEach(d => Db.JobProd.Where(r => r.Company == d.Company
                                          && r.OrderNum == d.OrderNum
                                          && r.OrderLine == d.OrderLine
                                          && r.OrderRelNum == d.OrderRelNum)
                                 .Join(Db.JobAsmbl,
                                       jp => new { k1 = jp.Company, 
                                                   k2 = jp.JobNum,
                                                   k3 = 0 },
                                       ja => new { k1 = ja.Company, 
                                                   k2 = ja.JobNum 
                                                   k3 = ja.JobAsmbl },
                                       (jp, ja) => new { Number20 = ja.Number20 })
                                 .ToList()
                                 .ForEach(r => d.Number19 = r.Number20));
2 Likes

One problem with this is that you are joining a tt record to a non-tt record… this is a big nono… you should get the tt record into memory first, and then query the db records from there.
(unless that first .ForEach does that for you already…)

1 Like

Nope, I’m not, the join is between Db.JobProd and Db.JobAsmbl. The ttInvcDtl record is passed through the List’s ForEach method, which is client side. But you are right that cross context joins don’t work. But the compiler is going to tell you that anyway.

1 Like

As a sidenote, if Epicor used a more up to date compiler, we could use the null-coalescing, null-conditional and null-assignment operators to make that linq statement even better… When are you planning to upgrade to a more current version of the compiler ?? (operator pun intended)

I use the null-coalescing operator all the time… What version of Epicor are you on? Example, the following line populates a variable with the part description. If nothing found, then the description says “Part Not Found”:

string partDesc = Db.Part.Where(x=>x.Company == CompanyID && PartNum == "1032Knut").Select(x=>x.PartDescription) ?? "Part Not Found";

Ah well it must be recent, or I didn’t see the change come through and just assumed it still wasn’t working then… Last time I tried to use it the compiler was still < 6.0… So, the null conditional ?. also works (as in var a = ds.Table.FirstOrDefault()?.FieldA;)?