Cross UOM categories

Rational

Some uom are a combination of multiple uoms. Defining this combination would allow to calculate a variable depending of the uom categories implied in the combination.
Some examples: Speed = length /time (km/h), Density = weight/volume (Kg/m³) or even existing Tryton uom categories : Surface = length * length , Volume = Surface * length

Proposal

Defining a new model “cross_uom” that would define uom categories “linked” together. Considering uom_category_1 * uom_category_2 = uom_category_result * coefficient(1 by default).
Each uom_category will use by default the base uom.
Combination of the 3 uom_categories would be unique.

  • uom_category_1
  • uom_category_2
  • operation : * or / or …
  • uom_category_result
  • coefficient : default 1

Implementation

I think it will be good to define how the API to make conversion will look.

I think this can be achieved by storing in a column the ordered list of the three category ids.

I think we need to store which units are used to compute the base unit. For example, in density we use Kg/m3, which mixes Kg and m3.

So if we have a product of 100g, witha a volume of 0.1 liters it does not make sense to expres density as g/liter. We need to convert both units first to kg and m3 and then do the operation between them.

As there are combinations that use division and others multiplication I think we should also store the operation used to produce the combined unit.

It is not needed as we already the base unit defined as the unit with factor 1.

For “composed” uom, we will have to split to convert from base unit ?
I mean, i’ll create a new uom category “Density”, i’ll add an uom “gr/mm³” and define as base unit.(factor 1). To do calculations with cross uom, i’ll have to split “gr/mm³” in “gr” and "mm³) to apply factor on Weight and Volume following their base unit ?
Or by default, as Density is a cross unit, their will be a base uom which will be base uom from both uom composing cross uom… So Density is Weight/Volume . Default will be Kg/l ?

Split what?

No you do not need because the factor will be in the coefficient.

And what about rate and factor when defining uom ?
For Density, 1 Kg/l = 1gr/Cm³ … so in cross uom … coefficient will be 1 and i could have multiple uom as base unit in the same category ?
And if i prefer to have a default uom for Density in gr/mm³ , i define this uom with a factor/rate=1 to be the base unit and in cross-uom, coefficient will be 0,001 then.

So method to calculate would be:
def calculate (uom1, value1, uom2, value2):
((uom1.factor * value1) [operation (* or /) ] (uom2.factor * value2)) * coefficient = result in uom3.base
but this calculation should evolve following uom passed in arguments:
A/B = C is standard case, but we could have A,C to find B, so it will be A/C=B and third case with C and B as parameters : C * B = A (operation will be inversed)

Yes you can if they express the same quantity.

For me, the API should be:

def convert(value1, uom1, value2, uom2, to_uom):

So you will have the target uom from which you can apply the conversion factor against its base unit.

Can’t i use the Unique sql constraint on the three category ids instead of a column ?

Then it won’t check against different order.

Ok, so it would be:
unique_key = fields.Function(fields.Char(‘Unique Key’), ‘on_change_with_unique_key’)
unique_key_storage = fields.Char(“Unique Key”)

unique_key field would be a join of each uom category id… ex: id1, id2, id3
I add a unique constraint on unique_key_storage. And when saving i update unique_key_storage = unique_key
Is it the good way ? Or too complicated ?

I think you do not need to create a Function field unique_key but simply ensure that unique_key_storage is updated on each create and write calls.

1 Like