# Unit Conversion

I’m running into an issue with unit conversion on BOM pricing. There’s two issues, really.

I have a component product (CompA) which is priced per ton (Unit = Ton, Cost Price = 200).
I have a finished goods product (ProdA), and have created a BOM for it. This BOM contains 500 Pounds of CompA.
Additionally, I have two unit conversions set up: Tons = 2000 X Pounds, and Pounds = 0.0005 X Tons

When I calculate price, the code is taking my Price Per Ton (\$200 / 1 Ton) and multiplying it by the quantity of my component (500 Pound). This returns a value of \$100,000. Then, it applies the Ton to Pounds conversion, multiplying that value by a further 2,000, resulting in a final computed price of \$200,000,000, when it should be a mere \$50. This is easy enough to fix. Instead of doing:

``````BigDecimal costPrice = unitConversionService.convert(product.getUnit(), unit,
product.getCostPrice().multiply(consumptionQty));
``````

we should be doing this:

``````BigDecimal costPrice = product.getCostPrice().multiply(unitConversionService.convert(
unit, product.getUnit(), consumptionQty, appProductionService.getNbDecimalDigitForBomQty()));
``````

In effect, we should be converting the quantity first into the unit that the product defines its price in (alternatively, we should be dividing by the coefficient, not multiplying, but that’s nested down in the `unitConversionService`, which we don’t want to handle this). However, this leads to a second problem. The coefficient to convert Pounds to Tons (0.0005) is returned in a `BigDecimal` with a scale of `3`, so we are truncating the coefficient to be `0.000`. The model correctly defines the scale as being `12`, and the database stores the coefficient correctly with a scale of `12`. Further, the `Unit Conversions` page correctly displays the coefficient as `0.000500000000`. I’ve tried removing my Pound to Ton conversion (so the unit converter will invert the Ton to Pound conversion), but I run into the same issue.

The problem I need help with is determining where the coefficient is being truncated to a scale of only 3. The `UnitConversionRepo` already has the coefficient stored with a scale of 3 (which incorrectly truncates my coefficient), and the `UnitConversionService#getInverseCoefficientScale` is also not returning a large enough value.

Edit:

I filed two tickets to cover the incorrect scale calculation and the incorrect unit price conversion. The solution to my above issues can be found below in my reply, or in the respective tickets.

Update: I figured out the problem. It wasn’t actually a problem with the storage of the `UnitConversion`s. The problem lies in the inverse conversion functions within the `UnitConversionService`.

The `UnitConversionService` determines scale for an inverse coefficient like this:

``````(int) Math.log10(unitConversion.getCoef().intValue());
``````

Which for a value of `2000` will return a scale of `3`. However, the inverse of `2000` is `0.0005`, which is a scale of `4`. The problem is that `Math.log10(2000)` returns `3.30103` which, when cast to an int, is truncated to `3`. Instead, `UnitConversionService` should be doing this:

``````(int) Math.ceil(Math.log10(unitConversion.getCoef().intValue()));
``````

Note the addition of `Math.ceil(...)`, which will round `3.30103` up to `4`, giving us the correct scale. On the border cases (i.e., `Math.log10(100)`), we will pass a whole integer to `Math.ceil(...)`, which will return the original integer.

The reason this issue arose in my case is because the `getCoefficient(...)` method in `UnitConversionService` stops as soon as it reaches a `UnitConversion` where both units on the conversion match the parameter units. As such, it is finding my Ton -> Pound conversion before my Pound -> Ton conversion, and inverting it, which uncovers the bug regarding the incorrect scale calculation. I have not tried removing my Ton -> Pound conversion to see if the coefficient for my Pound -> Ton is being properly scaled or not. I leave this to another exercise.