# (c) Nelen & Schuurmans from datetime import datetime from datetime import timezone from typing import Optional from typing import Type from typing import TypeVar from .exceptions import BadRequest from .value_object import ValueObject __all__ = ["RootEntity", "now"] def now(): # this function is there so that we can mock it in tests return datetime.now(timezone.utc) T = TypeVar("T", bound="RootEntity") class RootEntity(ValueObject): id: Optional[int] = None created_at: datetime updated_at: datetime @classmethod def create(cls: Type[T], **values) -> T: values.setdefault("created_at", now()) values.setdefault("updated_at", values["created_at"]) return super(RootEntity, cls).create(**values) def update(self: T, **values) -> T: if "id" in values and self.id is not None and values["id"] != self.id: raise BadRequest("Cannot change the id of an entity") values.setdefault("updated_at", now()) return super().update(**values) def __hash__(self): assert self.id is not None return hash(self.__class__) + hash(self.id)