# #region DictionaryCRUD [C:3] [TYPE Class] [SEMANTICS dictionary, crud, terminology] # @BRIEF CRUD operations for TerminologyDictionary records. # @RELATION DEPENDS_ON -> [TerminologyDictionary] # @RELATION DEPENDS_ON -> [TranslationJob] # @RELATION DEPENDS_ON -> [TranslationJobDictionary] from sqlalchemy import func from sqlalchemy.orm import Session from ...core.logger import belief_scope, logger from ...models.translate import ( DictionaryEntry, TerminologyDictionary, TranslationJob, TranslationJobDictionary, ) class DictionaryCRUD: """CRUD operations for terminology dictionaries.""" # region create_dictionary [TYPE Function] # @PURPOSE: Create a new terminology dictionary. @staticmethod def create_dictionary( db: Session, name: str, created_by: str | None = None, description: str | None = None, is_active: bool = True, ) -> TerminologyDictionary: with belief_scope("DictionaryCRUD.create_dictionary"): logger.reason("Creating dictionary", {"name": name}) dictionary = TerminologyDictionary( name=name, description=description, is_active=is_active, created_by=created_by, ) db.add(dictionary) db.commit() db.refresh(dictionary) logger.reflect("Dictionary created", {"id": dictionary.id}) return dictionary # endregion create_dictionary # region update_dictionary [TYPE Function] # @PURPOSE: Update an existing terminology dictionary. @staticmethod def update_dictionary( db: Session, dict_id: str, name: str | None = None, description: str | None = None, is_active: bool | None = None, ) -> TerminologyDictionary: with belief_scope("DictionaryCRUD.update_dictionary"): dictionary = db.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first() if not dictionary: raise ValueError(f"Dictionary not found: {dict_id}") logger.reason("Updating dictionary", {"id": dict_id}) if name is not None: dictionary.name = name if description is not None: dictionary.description = description if is_active is not None: dictionary.is_active = is_active db.commit() db.refresh(dictionary) logger.reflect("Dictionary updated", {"id": dictionary.id}) return dictionary # endregion update_dictionary # region delete_dictionary [TYPE Function] # @PURPOSE: Delete a dictionary, blocked if attached to active/scheduled jobs. @staticmethod def delete_dictionary(db: Session, dict_id: str) -> None: with belief_scope("DictionaryCRUD.delete_dictionary"): dictionary = db.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first() if not dictionary: raise ValueError(f"Dictionary not found: {dict_id}") blocked_statuses = ["ACTIVE", "READY", "RUNNING", "SCHEDULED"] attached_jobs = ( db.query(TranslationJobDictionary) .filter( TranslationJobDictionary.dictionary_id == dict_id, TranslationJobDictionary.job_id.in_( db.query(TranslationJob.id).filter(TranslationJob.status.in_(blocked_statuses)) ), ) .count() ) if attached_jobs > 0: logger.explore("Delete blocked: dictionary attached to active jobs", {"dict_id": dict_id, "jobs": attached_jobs}) raise ValueError( f"Cannot delete dictionary attached to {attached_jobs} active/scheduled job(s). " "Remove dictionary associations from jobs first." ) logger.reason("Deleting dictionary", {"id": dict_id}) db.query(DictionaryEntry).filter(DictionaryEntry.dictionary_id == dict_id).delete() db.query(TranslationJobDictionary).filter(TranslationJobDictionary.dictionary_id == dict_id).delete() db.delete(dictionary) db.commit() logger.reflect("Dictionary deleted", {"id": dict_id}) # endregion delete_dictionary # region get_dictionary [TYPE Function] # @PURPOSE: Get a single dictionary by ID. @staticmethod def get_dictionary(db: Session, dict_id: str) -> TerminologyDictionary: dictionary = db.query(TerminologyDictionary).filter(TerminologyDictionary.id == dict_id).first() if not dictionary: raise ValueError(f"Dictionary not found: {dict_id}") return dictionary # endregion get_dictionary # region list_dictionaries [TYPE Function] # @PURPOSE: List dictionaries with pagination. @staticmethod def list_dictionaries( db: Session, page: int = 1, page_size: int = 20, ) -> tuple[list[TerminologyDictionary], int]: total = db.query(func.count(TerminologyDictionary.id)).scalar() or 0 dictionaries = ( db.query(TerminologyDictionary) .order_by(TerminologyDictionary.created_at.desc()) .offset((page - 1) * page_size) .limit(page_size) .all() ) return dictionaries, total # endregion list_dictionaries # #endregion DictionaryCRUD