On 16/07/13 12:12 +0300, Giedrius Slavinskas wrote:
> 2013/7/15 Cédric Krier <cedric.kr...@b2ck.com>
> 
> > On 15/07/13 10:25 +0300, Giedrius Slavinskas wrote:
> > 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'])):

I don't understand why using "units" ? For me, it sounds wrong.
unit is what is called uom == Unit of Measure.

Quantity sounds like it is a scalar, when measure sounds better
especially because we already use "Unit of Measure".

>     __slots__ = ()
> 
>     def convert(self, to_uom, round=False): # round=False is more common
> usage

Aggre about the round because it should be done most of the time at the
end (see below).
But the name convert_to is more explicite.

>         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)

This makes the addition not commutative.

>     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

This must not be a function field but a property or a descriptor.
The descriptor could be set with a classmethod like:

    measure = Measure.descriptor('quantity', 'unit')

The setter should take care of rounding the quantity before storing it
on the instance.

-- 
Cédric Krier

B2CK SPRL
Rue de Rotterdam, 4
4000 Liège
Belgium
Tel: +32 472 54 46 59
Email/Jabber: cedric.kr...@b2ck.com
Website: http://www.b2ck.com/

Attachment: pgpmS2016I0HA.pgp
Description: PGP signature

Reply via email to