ICPO with non-part-specific UOMS

After spending hours of my day yesterday step debugging an ICPO issue, I have determined that (seeming due to an oversight), ICPO does not properly handle non-part-specific UOMs.

Specifically it seems this is an oversight in the logic. class MTPOHeaderExp > function RunMTPOHeaderExp

   

//this insta-fails for non-part-specific uoms (and incoming PUM <> IUM)
//this query should also check to see if the record exists in UOMConv (non part specific) - if so, the incoming PUM can be converted as desired
//sidenote, if skip the first condition, the entire process works as expected
if (!this.ExistsPartUOM(this.Part.Company, this.Part.PartNum, this.IMOrderDtl.IUM))
{  //note that IMOrderDtl.IUM is actually the incoming PUM, blame my decompliler I guess
   this.verror = true;
   this.IMOrderDtl["InvalidData"] = true;
}
else
{
    this.IMOrderDtl.IUM = this.Part.IUM;
    decimal orderQty = this.IMOrderDtl.OrderQty;
    this.LibAppService.UOMConv(this.Part.PartNum, this.IMOrderDtl.SellingQuantity, 
    this.IMOrderDtl.SalesUM, this.Part.IUM, out orderQty, true);
    this.LibAppService.RoundToUOMDec(this.Part.IUM, ref orderQty);
    this.IMOrderDtl.OrderQty = orderQty;
}

In typical support fashion, they are trying to steer the discussion as if this is a setup or data issue. They told me that in fact PartUOM should return a record.

Can I get some thoughts here on this. My experience has been solidly that PartUOM is ONLY for part-specific UOMs (otherwise you get the record from UOMConv - which also has a flag that will indicate whether a specific uom is part-specific, and ultimately should live in the PartUOM table)

If this in fact true [I am willing to be shown that it is not] - does this not imply this is an oversight in the logic?

My proposal:

//create query to get\check if the UOM is in fact part specific (this doesnt currently exist)
bool partSpecificUOM = IsPartSpecificUOM(company, uom);
if (partSpecificUOM && !this.ExistsPartUOM(this.Part.Company, this.Part.PartNum, this.IMOrderDtl.IUM))

It is also my understanding the PartUOM is only for Part Specific conversions. Otherwise it would use the UOM Class to convert. I honestly don’t understand that first test, as the LibAppService.UOMConv seems to handle both the part and non part conversion scenarios.

It also only looks at that when the incoming order UM is not the stock UM, which sometimes isn’t the same as the selling UM.

I would think they would want to check to see if there was a valid conversion from IMOrderDtl.IUM and Part.IUM (or SalesUM?). Whether that be by part specific conversion or UOM class. If it there isn’t then throw the error otherwise move on with the process.

Agreed. And valid point about the Conversion call - I havent looked at it but I wonder if it returns true\false for successful conversion, if so you are spot and they could just call that and set an error if it fails (for any reason)

Also found the reason for my comment earlier about IMOrderDTL.IUM really seems to incoming PUM:
this.IMOrderDtl.IUM = this.ttIMPODetail.PUM;

@josecgomez says he does this and it works fine. I say prove it!

conditions:
global part
receiving comp IUM != sending comp SUM
sum = non part-specific uom