summaryrefslogtreecommitdiff
path: root/jb/models/currency.py
diff options
context:
space:
mode:
authorMax Nanis2026-02-19 02:43:23 -0500
committerMax Nanis2026-02-19 02:43:23 -0500
commitf0f96f83c2630e890a2cbcab53f77fd4c37e1684 (patch)
treec6d2cb092e76bf5d499e0ea9949508d6b22164fd /jb/models/currency.py
parent3eaa56f0306ead818f64c3d99fc6d230d9b970a4 (diff)
downloadamt-jb-f0f96f83c2630e890a2cbcab53f77fd4c37e1684.tar.gz
amt-jb-f0f96f83c2630e890a2cbcab53f77fd4c37e1684.zip
Models, Project files, some pytests, requirements.. etcHEADmaster
Diffstat (limited to 'jb/models/currency.py')
-rw-r--r--jb/models/currency.py70
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()))