from datetime import date, datetime from typing import List, Literal, Optional from pydantic import Field, BaseModel, ConfigDict from beanie import Indexed, PydanticObjectId from firm.core.models import CrudDocument, ForeignKey from firm.core.filter import Filter, FilterSchema class EntityType(BaseModel): @property def label(self) -> str: return self.title class Individual(EntityType): model_config = ConfigDict(title='Particulier') type: Literal['individual'] = 'individual' firstname: Indexed(str) = Field(title='Prénom') middlename: Indexed(str) = Field(default="", title='Autres prénoms') lastname: Indexed(str) = Field(title='Nom de famille') surnames: List[Indexed(str)] = Field( default=[], props={"items_per_row": "4", "numbered": True}, title="Surnoms" ) day_of_birth: Optional[date] = Field(default=None, title='Date de naissance') place_of_birth: Optional[str] = Field(default="", title='Lieu de naissance') @property def label(self) -> str: # if len(self.surnames) > 0: # return '{} "{}" {}'.format(self.firstname, self.surnames[0], self.lastname) return f"{self.firstname} {self.lastname}" class Employee(BaseModel): model_config = ConfigDict(title='Fiche Employé') position: Indexed(str) = Field(title='Poste') entity_id: PydanticObjectId = ForeignKey("entities", "Entity", title='Employé') class Corporation(EntityType): model_config = ConfigDict(title='Entreprise') type: Literal['corporation'] = 'corporation' title: Indexed(str) = Field(title='Dénomination sociale') activity: Indexed(str) = Field(title='Activité') employees: List[Employee] = Field(default=[], title='Employés') class Institution(Corporation): model_config = ConfigDict(title='Institution') type: Literal['institution'] = 'institution' class Entity(CrudDocument): """ Fiche d'un client """ model_config = ConfigDict(title='Client') entity_data: Individual | Corporation | Institution = Field(..., discriminator='type') address: str = Field(default="", title='Adresse') def compute_label(self) -> str: if not self.entity_data: return "" return self.entity_data.label class Settings(CrudDocument.Settings): fulltext_search = ['label'] bson_encoders = { date: lambda dt: dt if hasattr(dt, 'hour') else datetime(year=dt.year, month=dt.month, day=dt.day, hour=0, minute=0, second=0) } class EntityFilters(FilterSchema): class Constants(Filter.Constants): model = Entity search_model_fields = ["label"]