from datetime import date from enum import Enum from typing import List, Literal, Optional from fastapi_filter import FilterDepends, with_prefix from pydantic import Field, BaseModel, ConfigDict from beanie import PydanticObjectId from firm.core.models import CrudDocument, ForeignKey, CrudDocumentConfig from firm.core.filter import Filter, FilterSchema class EntityType(BaseModel): @property def label(self) -> str: return self.title class EntityTypeEnum(str, Enum): individual = 'individual' corporation = 'corporation' institution = 'institution' class Individual(EntityType): model_config = ConfigDict(title='Particulier') type: Literal['individual'] = 'individual' firstname: str = Field(title='Prénom') middlename: str = Field(default="", title='Autres prénoms') lastname: str = Field(title='Nom de famille') surnames: List[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 f"{self.firstname} \"{self.surnames[0]}\" {self.lastname}" return f"{self.firstname} {self.lastname}" class Employee(BaseModel): model_config = ConfigDict(title='Fiche Employé') position: 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: str = Field(title='Dénomination sociale') activity: 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') document_config = CrudDocumentConfig( indexes=["entity_data.type"], ) 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 EntityDataFilter(Filter): type__in: Optional[list[str]] = None class Constants(Filter.Constants): model = EntityType class EntityFilters(FilterSchema): entity_data: Optional[EntityDataFilter] = FilterDepends(with_prefix("entity_data", EntityDataFilter)) class Constants(Filter.Constants): model = Entity search_model_fields = ["label"]