diff options
| author | Max Nanis | 2026-02-19 02:43:23 -0500 |
|---|---|---|
| committer | Max Nanis | 2026-02-19 02:43:23 -0500 |
| commit | f0f96f83c2630e890a2cbcab53f77fd4c37e1684 (patch) | |
| tree | c6d2cb092e76bf5d499e0ea9949508d6b22164fd /jb/models/currency.py | |
| parent | 3eaa56f0306ead818f64c3d99fc6d230d9b970a4 (diff) | |
| download | amt-jb-master.tar.gz amt-jb-master.zip | |
Diffstat (limited to 'jb/models/currency.py')
| -rw-r--r-- | jb/models/currency.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/jb/models/currency.py b/jb/models/currency.py new file mode 100644 index 0000000..3094e2a --- /dev/null +++ b/jb/models/currency.py @@ -0,0 +1,70 @@ +import warnings +from decimal import Decimal +from typing import Any + +from pydantic import GetCoreSchemaHandler, NonNegativeInt +from pydantic_core import CoreSchema, core_schema + + +class USDCent(int): + def __new__(cls, value, *args, **kwargs): + + if isinstance(value, float): + warnings.warn( + "USDCent init with a float. Rounding behavior may " "be unexpected" + ) + + if isinstance(value, Decimal): + warnings.warn( + "USDCent init with a Decimal. Rounding behavior may " "be unexpected" + ) + + if value < 0: + raise ValueError("USDCent not be less than zero") + + return super(cls, cls).__new__(cls, value) + + def __add__(self, other): + assert isinstance(other, USDCent) + res = super(USDCent, self).__add__(other) + return self.__class__(res) + + def __sub__(self, other): + assert isinstance(other, USDCent) + res = super(USDCent, self).__sub__(other) + return self.__class__(res) + + def __mul__(self, other): + assert isinstance(other, USDCent) + res = super(USDCent, self).__mul__(other) + return self.__class__(res) + + def __abs__(self): + res = super(USDCent, self).__abs__() + return self.__class__(res) + + def __truediv__(self, other): + raise ValueError("Division not allowed for USDCent") + + def __str__(self): + return "%d" % int(self) + + def __repr__(self): + return "USDCent(%d)" % int(self) + + @classmethod + def __get_pydantic_core_schema__( + cls, source_type: Any, handler: GetCoreSchemaHandler + ) -> CoreSchema: + """ + https://docs.pydantic.dev/latest/concepts/types/#customizing-validation-with-__get_pydantic_core_schema__ + """ + return core_schema.no_info_after_validator_function( + cls, handler(NonNegativeInt) + ) + + def to_usd(self) -> Decimal: + return Decimal(int(self) / 100).quantize(Decimal(".01")) + + def to_usd_str(self) -> str: + return "${:,.2f}".format(float(self.to_usd())) |
