<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2654.45">
<TITLE>Tipo de dato Money</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>Introducción</FONT>
<BR><FONT SIZE=2>------------</FONT>
</P>

<P><FONT SIZE=2>La idea es hacer un tipo de datos Money, basicamente para usos financieros, donde se necesitan decimales pero el punto flotante es demasiado inexacto. El tipo Money deberá soportar las funciones y operaciones estándares a Python.</FONT></P>

<P><FONT SIZE=2>Como ejercicio de XP, escribiré los casos de prueba antes de la clase propiamente dicha, luego la dejaré en SourceForge junto con el resto de los datos.</FONT></P>

<P><FONT SIZE=2>Sería interesante (y útil) que esta clase pase a formar parte de la biblioteca estándar, falta verificar que condiciones debe cumplir para poder hacerlo.</FONT></P>

<P><FONT SIZE=2>Este código es de dominio público. En los módulos, asigné el copyright a PSF, falta verificar si hay que solicitar algo previamente.</FONT></P>

<P><FONT SIZE=2>Por favor, siéntanse libres de realizar cualquier sugerencia. Gracias.</FONT>
</P>
<BR>

<P><FONT SIZE=2>¿Por qué no usar FixedPoint de Tim Peters?</FONT>
<BR><FONT SIZE=2>------------------------------------------</FONT>
</P>

<P><FONT SIZE=2>Como veremos en Requerimientos, hay puntos que FixedPoint no cumple (porque no hace algo o lo hace distinto).</FONT>
</P>

<P><FONT SIZE=2>Se podría extender o modificar dicha clase para cumplir los Requerimientos, pero algunas necesidades son propias de la moneda, y algunas características de FixedPoint son demasiado para Money, lo que al sacarlas harán más simples a esta clase.</FONT></P>

<P><FONT SIZE=2>De cualquier manera, en algún momento quizás se pueda hacer que una sea subclase de la otra, o simplemente hacer una de ambas.</FONT></P>

<P><FONT SIZE=2>El código de la clase Money está basado en gran parte en el de FixedPoint de Tim Peters: gracias por tus (muy) valiosas ideas. </FONT></P>
<BR>

<P><FONT SIZE=2>Requerimientos</FONT>
<BR><FONT SIZE=2>--------------</FONT>
</P>

<P><FONT SIZE=2>La sintaxis debe ser Money(valor, [precision]).</FONT>
</P>

<P><FONT SIZE=2>El valor puede ser de tipo:</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- otro money (si no se incluye *precision*, la hereda)</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- int o long (*precision* default: 0)</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>Money(45): 45</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>Money(45, 2): 45.00</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>Money(5000000000,3): 5000000000.000</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- float (*precision* pasa a ser obligatoria)</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>Money(50.33, 3): 50.330</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- string (*precision* se extrae de la cadena).</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>Money('25.32'): 25.32</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>Money('25.32', 4): 25.3200</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- algo convertible por long() o float()</FONT>
</P>

<P><FONT SIZE=2>No se soportarán strings con notación ingenieril, ya que al hablar de dinero esto no se necesita. </FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR><FONT SIZE=2>La precisión debe ser un entero no negativo, y no podrá cambiarse luego de creado el objeto.</FONT>
</P>

<P><FONT SIZE=2>Se debe poder sobrecargar decimalSeparator y currencySymbol, para que se pueda cambiar facilmente haciendo una subclase. Ese mismo decimalSeparator es el que usa el constructor al recibir una string. Los default son: decimalSeparator = '.', currencySymbol = '$'. </FONT></P>

<P><FONT SIZE=2>Llamar a repr() no debe devolver str(self), ya que si la subclase indicar que decimalSeparator='', lleva a una confusión. Por lo tanto, repr() debe mostrar una tupla de tres valores: IntPart, FracPart, Precision.</FONT></P>

<P><FONT SIZE=2>Que cumpla el caso de prueba de Mark McEahern:</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>cost = Money('5.99')</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>percentDiscount = 10</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>months = 3</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>subTotal = cost * months</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>discount = subTotal * (percentDiscount * 1.0) / 100</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>total = subTotal - discount</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>assertEqual(total, Money('16.17'))</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR><FONT SIZE=2>Que soporte la aritmética básica (+, -, *, /, //, **, %, divmod) y las comparaciones (==, !=, &lt;, &gt;, &lt;=, &gt;=, cmp) en los siguientes casos:</FONT></P>

<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- Money op Money</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- Money op otherType</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- otherType op Money</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- Money op= otherType</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- Nota 1: OtherType puede ser int, float o long. Automáticamente se convertirá a Money, heredando la precision del otro componente de la operación (y por lo tanto, en el caso del float, posiblemente perdiendo precisión **antes** de la operación).</FONT></P>

<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- Nota 2: Cuando ambos son Money, el resultado tiene la mayor precisión de los dos.</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR><FONT SIZE=2>Que soporte los operadores unarios (-, +, abs).</FONT>
</P>

<P><FONT SIZE=2>Que soporte los métodos bult-in:</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- min, max</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- float, int, long (int y long son redondeados por Money).</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- str, repr</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- hash</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- copy, deepcopy</FONT>
</P>

<P><FONT SIZE=2>Que se pueda:</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- usar como clave en dict</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- usar como booleano</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- hacer un pickle</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR><FONT SIZE=2>Que tenga métodos que devuelvan sus componentes:</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- getPrecision: la precisión</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- getFracPart: la parte fraccional (como un long)</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- getIntPart: la parte entera (como un long)</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- debe cumplir que el valor de Money sea (parte entera) + (parte fraccional) / (10 ** precision)</FONT>
</P>

<P><FONT SIZE=2>Que el redondeo sea el financiero (ejemplo redondeando a dos deciamles):</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>a b , c d e f ...</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>--------- ----...</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>&nbsp;&nbsp;&nbsp; x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>se incrementará d si (y &gt; 50000...) o (y == 50000... y d es impar)</FONT>
</P>
<BR>

<P><FONT SIZE=2>Facundo Batista</FONT>
<BR><FONT SIZE=2>Gestión de Red</FONT>
<BR><FONT SIZE=2>fbatista@unifon.com.ar</FONT>
<BR><FONT SIZE=2>(54 11) 5130-4643</FONT>
<BR><FONT SIZE=2>Cel: 15 5132 0132</FONT>
</P>
<BR>
<BR>
<BR>
<BR>
<BR>
<BR>

<P><B><FONT SIZE=2>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .</FONT></B></P>

<P><B><U><FONT SIZE=2>ADVERTENCIA&nbsp;</FONT></U> </B>
</P>

<P><B><FONT SIZE=2>La información contenida en este mensaje y cualquier archivo anexo al mismo, son para uso exclusivo del destinatario y pueden contener información confidencial o propietaria, cuya divulgación es sancionada por la ley. </FONT></B></P>

<P><B><FONT SIZE=2>Si Ud. No es uno de los destinatarios consignados o la persona responsable de hacer llegar este mensaje a los destinatarios consignados, no está autorizado a divulgar, copiar, distribuir o retener información (o parte de ella) contenida en este mensaje. Por favor notifíquenos respondiendo al remitente, borre el mensaje original y borre las copias (impresas o grabadas en cualquier medio magnético) que pueda haber realizado del mismo. </FONT></B></P>

<P><B><FONT SIZE=2>Todas las opiniones contenidas en este mail son propias del autor del mensaje y no necesariamente coinciden con las de Telefónica Comunicaciones Personales S.A. o alguna empresa asociada. </FONT></B></P>

<P><B><FONT SIZE=2>Los mensajes electrónicos pueden ser alterados, motivo por el cual Telefónica Comunicaciones Personales S.A. no aceptará ninguna obligación cualquiera sea el resultante de este mensaje. </FONT></B></P>

<P><B><FONT SIZE=2>Muchas Gracias.</FONT></B>
</P>

</BODY>
</HTML>