"""
import locale
+from decimal import Decimal, InvalidOperation
import sqlalchemy as sa
+from formencode import validators, Invalid
from bluechips.lib.subclass import SmartSubclass
from weakref import WeakValueDictionary
return d
locale.localeconv = localeconv
+
+class CurrencyValidator(validators.FancyValidator):
+ "A validator to convert to Currency objects."
+ messages = {'amount': "Please enter a valid currency amount",
+ 'precision': "Only two digits after the decimal, please",
+ 'nonzero': "Please enter a non-zero amount"}
+
+ def _to_python(self, value, state):
+ try:
+ dec = Decimal(value)
+ except InvalidOperation:
+ raise Invalid(self.message('amount', state),
+ value, state)
+ else:
+ ret = dec.quantize(Decimal('1.00'))
+ if ret == 0:
+ raise Invalid(self.message('nonzero', state),
+ value, state)
+ elif ret != dec:
+ raise Invalid(self.message('precision', state),
+ value, state)
+ else:
+ return Currency(int(ret * 100))
+
+
class Currency(object):
"""
Store currency values as an integral number of cents
argument to an int
"""
return self.__mul__(other)
-
- def __str_no_dollar__(self):
+ def __div__(self, other):
"""
- Get to the formatted string without the dollar sign
+ If I don't define this, SmartSubclass will convert the other
+ argument to an int
+ """
+ return Currency(self.value / other)
+ def __truediv__(self, other):
+ """
+ If I don't define this, SmartSubclass will convert the other
+ argument to an int
"""
- return str(self).replace('$', '')
+ return Currency(self.value / other)
def __repr__(self):
return '%s("%s")' % (self.__class__.__name__, str(self))
def __str__(self):
return locale.currency(self.value / 100., grouping=True)
+
class DBCurrency(sa.types.TypeDecorator):
"""
A type which represents monetary amounts internally as integers.