Im trying to get a true is laborqty, including what the user is trying to report, is greater than production qty and false if not. However, this reports everything as false.
Erp.Tables.LaborDtl LaborDtl;
Erp.Tables.LaborDtl LaborDtl1;
Erp.Tables.JobAsmbl JobOpDtl;
string Company = "";
decimal LaborQty = 0.0m;
decimal LaborQty1 = 0.0m;
decimal LaborQty2 = 0.0m;
int OperationSeq = 0;
int LaborSeqDtl = 0;
decimal ProductionQty = 0.0m;
foreach (var ttLaborDtl_iterator in (from ttLaborDtl_Row in ttLaborDtl
where string.Equals(ttLaborDtl_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) || string.Equals(ttLaborDtl_Row.RowMod, IceRow.ROWSTATE_UPDATED, StringComparison.OrdinalIgnoreCase)
select ttLaborDtl_Row))
{
var ttLaborDtlRow = ttLaborDtl_iterator;
if (ttLaborDtlRow.LaborType == "P")
{
Company = ttLaborDtlRow.Company;
LaborSeqDtl = ttLaborDtlRow.LaborDtlSeq;
LaborQty = ttLaborDtlRow.LaborQty;
JobOpDtl = (from JobOpDtl_Row in Db.JobAsmbl
where string.Compare(JobOpDtl_Row.Company,ttLaborDtlRow.Company, true) == 0 &&
JobOpDtl_Row.JobNum == ttLaborDtlRow.JobNum && JobOpDtl_Row.AssemblySeq == ttLaborDtlRow.AssemblySeq
select JobOpDtl_Row).FirstOrDefault();
if (JobOpDtl != null)
{
ProductionQty = JobOpDtl.RequiredQty;
}
foreach (var LaborDtl1_iterator in (from LaborDtl1_Row in Db.LaborDtl
where LaborDtl1_Row.Company == Company && LaborDtl1_Row.JobNum == ttLaborDtlRow.JobNum && LaborDtl1_Row.AssemblySeq == ttLaborDtlRow.AssemblySeq && LaborDtl1_Row.OprSeq == ttLaborDtlRow.OprSeq && LaborSeqDtl != LaborDtl1_Row.LaborDtlSeq
select LaborDtl1_Row))
{
LaborDtl1 = LaborDtl1_iterator;
LaborQty2 = LaborQty2 + LaborDtl1.LaborQty;
}
LaborQty2 = LaborQty2 + LaborQty;
bool Overs;
if (LaborQty2 > ProductionQty)
{
Overs = true;
}
else
{
Overs = false;
}
}
}
I would actually just use string.Equals, unless you have reason to believe that you’ll need to ignore case:
string.Equals(LaborDtl1_Row.Company, Company)
You’ve also got some major scope issues that will bite you if your main foreach iterates more than once.
All of your variable declarations at the top really belong inside the main foreach, and your declaration of your Overs variable should either be outside of the foreach, or you need to use it while it exists (as it is, you assign a value to it, then it is blown away with the next iteration of you foreach or the end of the loop)
Thank you for the input. Can you point me where I can find examples of the best practices? I’m trying to learn as I go with getting these bpms working.
I made some changes, (phoned a friend for a bit of help…he’s not an Epicor perosn), and have one error message I can’t seem to get fixed. Error is “Member declartation is not allowed inside the code block”.
public class Company
{
public string Name { get; set; }
// Add any additional properties related to a company
}
decimal LaborQty2 = 0.0m; // Initialize LaborQty2 outside of the loop
foreach (var ttLaborDtl_iterator in (from ttLaborDtl_Row in ttLaborDtl
where string.Equals(ttLaborDtl_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) || string.Equals(ttLaborDtl_Row.RowMod, IceRow.ROWSTATE_UPDATED, StringComparison.OrdinalIgnoreCase)
select ttLaborDtl_Row))
{
var ttLaborDtlRow = ttLaborDtl_iterator;
if (ttLaborDtlRow.LaborType == "P")
{
Company company = new Company { Name = ttLaborDtlRow.Company };
LaborSeqDtl = ttLaborDtlRow.LaborDtlSeq;
LaborQty = ttLaborDtlRow.LaborQty;
LaborQty2 = 0.0m; // Reset LaborQty2 to zero before accumulating
JobOpDtl = (from JobOpDtl_Row in Db.JobAsmbl
where string.Compare(JobOpDtl_Row.Company, company.Name, true) == 0 &&
JobOpDtl_Row.JobNum == ttLaborDtlRow.JobNum && JobOpDtl_Row.AssemblySeq == ttLaborDtlRow.AssemblySeq
select JobOpDtl_Row).FirstOrDefault();
if (JobOpDtl != null)
{
ProductionQty = JobOpDtl.RequiredQty;
}
foreach (var LaborDtl1_iterator in (from LaborDtl1_Row in Db.LaborDtl
where LaborDtl1_Row.Company == company.Name && LaborDtl1_Row.JobNum == ttLaborDtlRow.JobNum && LaborDtl1_Row.AssemblySeq == ttLaborDtlRow.AssemblySeq && LaborDtl1_Row.OprSeq == ttLaborDtlRow.OprSeq && LaborSeqDtl != LaborDtl1_Row.LaborDtlSeq
select LaborDtl1_Row))
{
LaborDtl1 = LaborDtl1_iterator;
LaborQty2 = LaborQty2 + LaborDtl1.LaborQty;
}
LaborQty2 = LaborQty2 + LaborQty;
bool Overs;
if (LaborQty2 > ProductionQty)
{
Overs = true;
}
else
{
Overs = false;
}
}
}
You can’t declare a class within these code blocks - it adds no value in this case, anyway just leave the Company value as a string, instead of embedding it into another object
Looking at @gpayne’s code, you apparently don’t have to mess with string compare?? So we can clean that up…
I also kept getting confused with similarly named variables, so I put “this” on the front of local variables - just to keep them straight
I sometimes run into variables that the system won’t use in in expressions, so I dump any that I’ll be using into a local variable (especially if I’ll use it more than once)
foreach (var ttLaborDtlRow in (from ttLaborDtl_Row in ttLaborDtl
where ttLaborDtl_Row.RowMod == IceRow.ROWSTATE_ADDED ||
ttLaborDtl_Row.RowMod == IceRow.ROWSTATE_UPDATED
select ttLaborDtl_Row))
{
if (ttLaborDtlRow.LaborType == "P")
{
string thisCompany = ttLaborDtlRow.Company;
string thisJobNum = ttLaborDtlRow.JobNum;
int thisAssemblySeq = ttLaborDtlRow.AssemblySeq;
int thisLaborDtlSeq = ttLaborDtlRow.LaborDtlSeq;
int thisOprSeq = ttLaborDtlRow.OprSeq;
decimal thisLaborQty = ttLaborDtlRow.LaborQty;
var JobOpDtl =
(from JobOpDtl_Row in Db.JobAsmbl
where JobOpDtl_Row.Company == ttLaborDtlRow.Company &&
JobOpDtl_Row.JobNum == thisJobNum &&
JobOpDtl_Row.AssemblySeq == thisAssemblySeq
select JobOpDtl_Row).FirstOrDefault();
if (JobOpDtl == null)
{
// raise exception or return:
// everything after here is broken if there is no JobOpDtl found
}
decimal thisProductionQty = JobOpDtl.RequiredQty;
// Use LINQ capability to sum the selected values
// (no need for a foreach and accumulator)
decimal LaborQty2 =
(from LaborDtl1_Row in Db.LaborDtl
where LaborDtl1_Row.Company == thisCompany &&
LaborDtl1_Row.JobNum == thisJobNum &&
LaborDtl1_Row.AssemblySeq == thisAssemblySeq &&
LaborDtl1_Row.OprSeq == thisOprSeq &&
LaborDtl1_Row.LaborDtlSeq != thisLaborDtlSeq
select LaborDtl1_Row)
.Sum(laborDtl => laborDtl.LaborQty) // If no LaborDtl found, results in 0
+ thisLaborQty;
// I still don't understand what you need to happen here
// Is there an output variable? Display a message like gpayne?
// This right here is a local variable whose life ends at the end of each foreach iteration
bool Overs;
if (LaborQty2 > ProductionQty)
{
Overs = true;
}
else
{
Overs = false;
}
}
}
The only error was on ProductionQty. It needed to be thisProductionQty. However, still seems I am back at square one as it only shows false for everything.
Above bool Overs; you state that you don’t understand what I am needing here. Basically I am needing for all the labor records (found in Job Tracker–>Operations–>Labor Transactions) and sum all those qty’s. Then I need to add in the current amount they are wanting to add to it. That total then is compared to the production qty, or required qty. So if the production qty is more than the required qty, give me a true, if not, false.
In the bpm, after the custom code, I will put a condition that says Overs = True. Then I’ll add an exception box under the true for the condition.