gateway/modules/datamodels/datamodelUtils.py
2026-02-09 23:44:52 +01:00

84 lines
3.5 KiB
Python

# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""Utility datamodels: Prompt, TextMultilingual."""
from typing import Dict, Optional
from pydantic import BaseModel, ConfigDict, Field, field_validator
from modules.shared.attributeUtils import registerModelLabels
import uuid
class Prompt(BaseModel):
model_config = ConfigDict(extra='allow') # Preserve system fields (_createdBy, _createdAt, etc.)
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Primary key", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
mandateId: str = Field(default="", description="ID of the mandate this prompt belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
isSystem: bool = Field(default=False, description="System prompt visible to all users (read-only for non-SysAdmin)", json_schema_extra={"frontend_type": "boolean", "frontend_readonly": True, "frontend_required": False})
content: str = Field(description="Content of the prompt", json_schema_extra={"frontend_type": "textarea", "frontend_readonly": False, "frontend_required": True})
name: str = Field(description="Name of the prompt", json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": True})
@field_validator('isSystem', mode='before')
@classmethod
def _coerceIsSystem(cls, v):
"""Existing records may have isSystem=None (field didn't exist). Treat None as False."""
if v is None:
return False
return v
registerModelLabels(
"Prompt",
{"en": "Prompt", "fr": "Invite"},
{
"id": {"en": "ID", "fr": "ID"},
"mandateId": {"en": "Mandate ID", "fr": "ID du mandat"},
"isSystem": {"en": "System", "fr": "Système"},
"content": {"en": "Content", "fr": "Contenu"},
"name": {"en": "Name", "fr": "Nom"},
},
)
class TextMultilingual(BaseModel):
"""
Multilingual text field supporting multiple languages.
Default languages: en (English), ge (German), fr (French), it (Italian)
English (en) is the default/required language.
"""
en: str = Field(description="English text (default language, required)")
ge: Optional[str] = Field(None, description="German text")
fr: Optional[str] = Field(None, description="French text")
it: Optional[str] = Field(None, description="Italian text")
@field_validator('en')
@classmethod
def validate_en_required(cls, v):
"""Ensure English text is not empty"""
if not v or not v.strip():
raise ValueError("English text (en) is required and cannot be empty")
return v
def model_dump(self, **kwargs) -> Dict[str, str]:
"""Return as dictionary, filtering out None values"""
result = {}
for lang in ['en', 'ge', 'fr', 'it']:
value = getattr(self, lang, None)
if value is not None:
result[lang] = value
return result
@classmethod
def from_dict(cls, data: Dict[str, str]) -> 'TextMultilingual':
"""Create TextMultilingual from dictionary"""
return cls(
en=data.get('en', ''),
ge=data.get('ge'),
fr=data.get('fr'),
it=data.get('it')
)
def get_text(self, lang: str = 'en') -> str:
"""Get text for a specific language, fallback to English if not available"""
value = getattr(self, lang, None)
if value:
return value
return self.en # Fallback to English