Thread: [Fwd: Re: [Modeling-users] Money and Modeling]
Status: Abandoned
Brought to you by:
sbigaret
From: SoaF at H. <so...@la...> - 2003-07-08 21:21:51
Attachments:
Re: [Modeling-users] Money and Modeling
|
Seb please look at sf to fix this f**king 'reply to the list' :) I foward my reply |
From: Sebastien B. <sbi...@us...> - 2003-07-08 22:17:31
|
Yannick Gingras <yan...@sa...> wrote: > What are you guys doing with monetary values ? >=20 > mx.DateTime is a really nice class for dates management. Is there a class > out there for money ? >=20 > I'm not certain I fully understand how Modeling treats the SQL decimal > type. Decimal should be fixed points but retrieving and attribute > defined by : > <attribute displayLabel=3D'' > scale=3D'4' > name=3D'currencyRate' > isRequired=3D'1' > externalType=3D'numeric' > defaultValue=3D'None' > isClassProperty=3D'1'=20 > precision=3D'10'=20 > columnName=3D'currency_rate' > type=3D'string' > width=3D'0'/> > gives a float which is not quite fixed point... Is there anything wrong > with my model ? (It could have helped to know what you are getting, and what you were expecting --I simply assume that this was an approximation problem, if not, please be more explicit). As Soaf said: > Fixed point doesn't exist in the default python so . You always retrieve a > numeric but it's map to a float in python. And please be carefull about > this as, python do some strange round while using print() and stuff like > that . --> The problem here is python combined with the adaptor, this is not a problem with the framework in itself. Simply look at this (using the test package AuthorBooks): >>> import psycopg >>> cnx=3Dpsycopg.connect(dsn=3D"host=3Dlocalhost dbname=3DAUTHOR_BOOKS use= r=3Dpostgres") >>> cur=3Dcnx.cursor() >>> cur.execute("INSERT INTO BOOK(id,title,price) VALUES(5,'Test Title',7.9= 2)") >>> cnx.commit() >>> cur.execute('SELECT * FROM BOOK WHERE id=3D5') >>> cur.fetchone() (7.9199999999999999, 'Test Title', 5, None) Since your column is NUMERIC(10,4), any python adaptor (all, but sqlite for which all types are strings) will return a float, and there's nothing like fixed point float in python. So you'll get a value inherently dependent to the binary representation of the value, see: >>> 7.48 7.4800000000000004 >>> 7.85 7.8499999999999996 >>> 7.85=3D=3D7.8499999999999996 1 However, I noticed that your python type is _string_, I presume this is intended. What if you store the value in a VARCHAR? You'll stay away from these problems, then. BTW, have you looked at the python cookbook or searched for any monetary handling package? I'm quite confident such problems must have been already addressed somewhere, it's probably worth the search. Regards, -- S=E9bastien. |
From: Jerome K. <Jer...@fi...> - 2003-07-08 22:46:45
|
On Wed, Jul 09, 2003 at 12:16:56AM +0200, Sebastien Bigaret wrote: And once again >>> a= 7.85 >>> a 7.8499999999999996 >>> print a 7.85 >>> This drive me crazy the first time i write some code w/ money . |
From: Sebastien B. <sbi...@us...> - 2003-07-09 00:19:10
|
I wrote: > [...] BTW, have you looked at the python > cookbook or searched for any monetary handling package? I'm quite > confident such problems must have been already addressed somewhere, > it's probably worth the search. Instant Google search: http://fixedpoint.sourceforge.net/html/lib/module-FixedPoint.html |
From: Yannick G. <ygi...@yg...> - 2003-07-09 02:38:33
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 08 July 2003 20:18, Sebastien Bigaret wrote: > I wrote: > > [...] BTW, have you looked at the python > > cookbook or searched for any monetary handling package? I'm quite > > confident such problems must have been already addressed somewhere, > > it's probably worth the search. > > Instant Google search: > http://fixedpoint.sourceforge.net/html/lib/module-FixedPoint.html Nice ! Will Modeling return some fixed points of shoulf I do the trick with varchars ? - -- Yannick Gingras Coder for OBB : O'er Beamish Byssus http://OpenBeatBox.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE/Cwtmrhy5Fqn/MRARAr7eAJ9up6glOKvIaPkmG6CGQdbrKK8yLACcDNX5 wR6vPmtgvgwDzOR4IJKroc8= =hjls -----END PGP SIGNATURE----- |
From: Sebastien B. <sbi...@us...> - 2003-07-09 10:05:48
|
Yannick Gingras <ygi...@yg...> writes: > On Tuesday 08 July 2003 20:18, Sebastien Bigaret wrote: > > I wrote: > > > [...] BTW, have you looked at the python > > > cookbook or searched for any monetary handling package? I'm quite > > > confident such problems must have been already addressed somewhere, > > > it's probably worth the search. > > > > Instant Google search: > > http://fixedpoint.sourceforge.net/html/lib/module-FixedPoint.html >=20 > Nice ! >=20 > Will Modeling return some fixed points of shoulf I do the trick with > varchars ? Okay, I've thought a little about it and made some experimentations. This is a (yet undocumented) way of handling custom data types, i.e. data types that are not automatically handled by the core. I've made the following changes to test package AuthorBooks to adapt Book's attribute price to fixedPoint: - changed the model so that price is a string/VARCHAR (was: a float/NUMERIC(10,2)), - add _setPrice() and _getPrice() to AuthorBooks.Book (see the unified diff below) Now for the test: (remember to regenerate the DB schema!) >>> from fixedpoint import FixedPoint >>> from AuthorBooks.Book import Book >>> from Modeling.EditingContext import EditingContext >>> ec=3DEditingContext() >>> book=3DBook() >>> book.setTitle('Test FixedPoint') >>> book.setPrice(FixedPoint("3.341")) >>> book.getTitle(), book.getPrice() ('Test FixedPoint', FixedPoint('3.34', 2)) # PRECISION=3D=3D2 in Book.py >>> ec.insert(book) >>> ec.saveChanges() >>> book.getTitle(), book.getPrice() ('Test FixedPoint', FixedPoint('3.34', 2)) Here you can check in you db that it was stored as a varchar, as expected. Start a new python and test the fetch: >>> from fixedpoint import FixedPoint >>> from AuthorBooks.Book import Book >>> from Modeling.EditingContext import EditingContext >>> ec=3DEditingContext() >>> books=3Dec.fetch('Book') >>> books[0].getTitle(), books[0].getPrice() ('Test FixedPoint', FixedPoint('3.34', 2)) As you can see, FixedPoint is now correctly handled by the framework. Nice, isn't it?! Behind the scenes: here you can see the KeyValueCoding in action. The framework *always* accesses the attributes' values with the so-called "private" methods (storedValueForKey(), takeStoredValueForKey()). Look at their documentation, you'll see that they will try to use private setters/getters --such as _setPrice() and _getPrice()-- before the public ones --being getPrice() and setPrice()). So: 1. when the framework is about to save the data, it ends up calling _getprice(), which gently returns the corresponding string, =20=20=20=20 [same for validation before saving: type checking also calls _getPrice() and gets a string, so everything's ok] =20=20=20=20 2. when the framework fetches the data, price() is initialized with _setPrice() which turns the string back to FixedPoint. It's probably what you need here ;) However, attention please: I've never used this in real projects (never needed it), so I cannot guarantee that you won't get any errors at some point. If you choose that way and encounter errors or unexpected behaviour, please report, I'll try to my best to support this. And I'd be interested in success report too ;) -- S=E9bastien. ------------------------------------------------------------------------ Index: Book.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/Aut= horBooks/Book.py,v retrieving revision 1.4 diff -u -r1.4 Book.py --- Book.py 27 Mar 2003 11:47:57 -0000 1.4 +++ Book.py 9 Jul 2003 09:52:24 -0000 @@ -1,7 +1,9 @@ # Modeling from Modeling.CustomObject import CustomObject from Modeling.Validation import ValidationException +from fixedpoint import FixedPoint =20 +PRECISION=3D2 =20 class Book (CustomObject): """ @@ -61,7 +63,14 @@ "Change the Book / price attribute value" self.willChange() self._price =3D price + self._price.precision=3DPRECISION =20=20=20 + def _setPrice(self, value): + self._price =3D FixedPoint(value, PRECISION) +=20=20=20=20 + def _getPrice(self): + return str(self._price) +=20=20=20=20 def validatePrice(self, value): "Edit this to enforce custom business logic" if 0: # your custom bizlogic Index: model_AuthorBooks.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/Aut= horBooks/model_AuthorBooks.xml,v retrieving revision 1.6 diff -u -r1.6 model_AuthorBooks.xml --- model_AuthorBooks.xml 7 May 2003 11:27:10 -0000 1.6 +++ model_AuthorBooks.xml 9 Jul 2003 09:36:23 -0000 @@ -27,7 +27,7 @@ <attribute isClassProperty=3D'1' columnName=3D'title' name=3D'title' i= sRequired=3D'1' precision=3D'0' defaultValue=3D'None' externalType=3D'VARCH= AR' width=3D'40' scale=3D'0' type=3D'string' displayLabel=3D'Title'/> <attribute isClassProperty=3D'1' columnName=3D'id' name=3D'id' isRequi= red=3D'1' precision=3D'0' defaultValue=3D'0' externalType=3D'INT' width=3D'= 0' scale=3D'0' type=3D'int' displayLabel=3D''/> <attribute isClassProperty=3D'0' columnName=3D'FK_WRITER_ID' name=3D'= FK_Writer_Id' isRequired=3D'0' precision=3D'0' defaultValue=3D'None' extern= alType=3D'INTEGER' width=3D'0' scale=3D'0' type=3D'string' displayLabel=3D'= '/> - <attribute isClassProperty=3D'1' columnName=3D'PRICE' name=3D'price' = isRequired=3D'0' precision=3D'10' defaultValue=3D'None' externalType=3D'NUM= ERIC' width=3D'0' scale=3D'2' type=3D'float' displayLabel=3D''/> + <attribute isClassProperty=3D'1' columnName=3D'PRICE' name=3D'price' = isRequired=3D'0' precision=3D'0' defaultValue=3D'None' externalType=3D'VARC= HAR' width=3D'10' scale=3D'0' type=3D'string' displayLabel=3D''/> <relation deleteRule=3D'0' isClassProperty=3D'1' multiplicityUpperBoun= d=3D'1' multiplicityLowerBound=3D'0' destinationEntity=3D'Writer' name=3D'a= uthor' displayLabel=3D'' joinSemantic=3D'0'> <join sourceAttribute=3D'FK_Writer_Id' destinationAttribute=3D'id'/> </relation> ------------------------------------------------------------------------ |
From: Sebastien B. <sbi...@us...> - 2003-07-09 15:26:33
|
By the way, if any of you needs to make FixedPoint work w/ python 2.1 you'll probably be interested in the patch I submitted today: https://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D768353&group_= id=3D63070&atid=3D502758 Otherwise it will just not work (at least not as documented). -- S=E9bastien. |