2013/7/15 Cédric Krier <[email protected]>
> On 15/07/13 10:25 +0300, Giedrius Slavinskas wrote:
> > 2013/7/15 Guillem Barba Domingo <[email protected]>
> >
> > >
> > > El 15/07/2013 2:16, "Oscar Alvarez" <[email protected]>
> va
> > > escriure:
> > >
> > > >
> > > > El 14/07/13 17:20, Cédric Krier escribió:
> > > >
> > > >> Hi,
> > > >>
> > > >> I would like to submit this poll for this change:
> > > >>
> > > >> http://codereview.tryton.org/969002/#msg9
> > > >>
> > > >>
> > > >> kg.convert(1000, gr) == 1
> > >
> >
> > The above one is more logical and more object-oriented approach as you
> > provide the quantity (units and units of measurement) to the method
> convert.
> >
> > It would be even more logical if we would have quantity as object and we
> > could pass it as a single argument:
> >
> > class Quantity:
> > def __init__(self, units, uom):
> > self.units = units
> > self.uom = uom
> >
> > Unfortunatily, there is no such a infrastructure on tryton's orm, so the
> > best we can do is to pass the quantity by two arguments.
>
> So let's introduce it.
>
>
> class Measure(namedtuple('Measure', ['quantity', 'unit'])):
> __slots__ = ()
>
> def convert_to(self, uom, round=True):
> Uom = Pool().get('product.uom')
> return Measure(Uom.compute_qty(self.unit, self.quantity, uom,
> round=round), uom)
>
>
> Which will make:
>
> Measure(1000, gr).convert_to(kg) == Measure(1, kg)
I suggest more intuitive interface/naming. Here is just the idea,
nothing mean to work.
class Quantity(namedtuple('Quantity', ['units', 'uom'])):
__slots__ = ()
def convert(self, to_uom, round=False): # round=False is more common
usage
Uom = Pool().get('product.uom')
return Quantity(Uom.compute_qty(self.uom, self.units, to_uom,
round=round), to_uom)
def __add__(self, other): # same for __sub__, __mul__, etc
if isinstance(other, Quantity):
other = other.convert(self.uom, round=False).units
return Quantity(self.units + other, self.uom)
def __eq__(self, other): # same for __le__, __gt__, etc
if isinstance(other, Quantity):
other = other.convert(self.uom, round=False).units
return self.units == other
def round(self):
# round self.units by self.uom.digits
Then such class could be used as field on model:
class StockMove:
units = fields.Float("Quantity")
uom = fields.Many2One("product.uom", "Uom")
# changing the quantity it changes units and uom and vice versa.
# This field should not hold values, but only references.
quantity = fields.Function(Quantity('units', 'uom'))
internal_units = fields.Float('Internal Quantity', readonly=True,
required=True)
internal_quantity = fields.Function(Quantity('internal_units',
'product.default_uom'))
def do_something(self, moves):
"""Usage example"""
for move in moves:
self.quantity += move.quantity * 2
--
Giedrius