From b6bef1f775b42b3e4bf9a16df21a378c6e178905 Mon Sep 17 00:00:00 2001 From: ewandor Date: Wed, 12 Feb 2025 20:35:13 +0100 Subject: [PATCH] Adding a common moneratary amount field type --- api/app/account/models.py | 4 +--- api/app/account/schemas.py | 5 +++-- api/app/core/__init__.py | 0 api/app/core/types.py | 41 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 api/app/core/__init__.py create mode 100644 api/app/core/types.py diff --git a/api/app/account/models.py b/api/app/account/models.py index 6050c87..8034d63 100644 --- a/api/app/account/models.py +++ b/api/app/account/models.py @@ -1,8 +1,6 @@ -from typing import Optional, Any +from typing import Optional -from pydantic import computed_field from sqlmodel import Relationship -from sqlalchemy.sql import text from account.enums import CategoryFamily, Asset, Liability, AccountFamily from account.schemas import AccountBaseId diff --git a/api/app/account/schemas.py b/api/app/account/schemas.py index a272cfa..a31ca58 100644 --- a/api/app/account/schemas.py +++ b/api/app/account/schemas.py @@ -3,11 +3,12 @@ from decimal import Decimal from typing import Optional from uuid import UUID, uuid4 -from pydantic.json_schema import SkipJsonSchema from sqlmodel import Field, SQLModel from pydantic import Field as PydField +from pydantic.json_schema import SkipJsonSchema from account.enums import Asset, Liability, CategoryFamily +from core.types import MonetaryAmount class AccountBase(SQLModel): name: str = Field(index=True) @@ -39,7 +40,7 @@ class AccountWrite(BaseAccountWrite): } }) opening_date: date = Field() - opening_balance: Decimal = Field(decimal_places=2, default=0) + opening_balance: MonetaryAmount = Field() class AccountCreate(AccountWrite): pass diff --git a/api/app/core/__init__.py b/api/app/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/app/core/types.py b/api/app/core/types.py new file mode 100644 index 0000000..21a05a4 --- /dev/null +++ b/api/app/core/types.py @@ -0,0 +1,41 @@ +from dataclasses import dataclass +from decimal import Decimal +from typing import Any + +from pydantic import GetCoreSchemaHandler +from pydantic_core import core_schema + +@dataclass +class MonetaryAmount: + amount: Decimal# = Field(decimal_places=2, default=0) + + @classmethod + def __get_pydantic_core_schema__( + cls, source: type[Any], handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + assert source is MonetaryAmount + return core_schema.no_info_after_validator_function( + cls._validate, + core_schema.float_schema(multiple_of=0.01), + serialization=core_schema.plain_serializer_function_ser_schema( + cls._serialize, + info_arg=False, + return_schema=core_schema.float_schema(multiple_of=0.01), + ), + ) + + @staticmethod + def _validate(value: str) -> 'CompressedString': + inverse_dictionary: dict[str, int] = {} + text: list[int] = [] + for word in value.split(' '): + if word not in inverse_dictionary: + inverse_dictionary[word] = len(inverse_dictionary) + text.append(inverse_dictionary[word]) + return MonetaryAmount( + {v: k for k, v in inverse_dictionary.items()}, text + ) + + @staticmethod + def _serialize(value: 'CompressedString') -> str: + return value.amount