"""GraphQL enums, input models, and output models for the Abacus API.""" from enum import Enum from pydantic import BaseModel, ConfigDict, Field, field_serializer # --------------------------------------------------------------------------- # GraphQL enums (defined in the Abacus GraphQL schema) # --------------------------------------------------------------------------- class ContractType(str, Enum): DISTRIBUTION = 'distribution' LEGACY_DISTRIBUTION = 'legacy_distribution' NEIGHBOURING_RIGHTS = 'neighbouring_rights' class RenewalType(str, Enum): CONTINUOUSLY_ACTIVE = 'continuously_active' RENEW_AFTER_CERTAIN_DATE = 'renew_after_certain_date' RENEW_PERIODICALLY = 'renew_periodically' class PeriodType(str, Enum): DAY = 'day' MONTH = 'month' YEAR = 'year' def _snake_to_camel(name: str) -> str: parts = name.split('_') return parts[0] + ''.join(p.capitalize() for p in parts[1:]) # --------------------------------------------------------------------------- # Shared configs # --------------------------------------------------------------------------- _CAMEL_CONFIG = ConfigDict( frozen=True, alias_generator=_snake_to_camel, populate_by_name=True ) # --------------------------------------------------------------------------- # Response models (returned by queries and mutations) # # Use alias_generator so they can be constructed directly from camelCase # GraphQL responses without manual key conversion. # --------------------------------------------------------------------------- class RunController(BaseModel): """Run controller from abacusRunControllers query.""" model_config = _CAMEL_CONFIG run_controller_id: int = Field(...) run_controller_name: str | None = Field(default=None) contract_type: ContractType = Field(default=ContractType.DISTRIBUTION) class RunControllerContract(BaseModel): """Result of abacusUpdateRunControllerContracts mutation.""" model_config = _CAMEL_CONFIG contract_id: int = Field(...) run_controller_contract_id: int = Field(...) run_controller_id: int = Field(...) class ReferenceSigningEntity(BaseModel): """Signing entity from abacusReferenceSigningEntities query.""" model_config = _CAMEL_CONFIG reference_signing_entity_id: int = Field(...) legal_name: str = Field(..., min_length=1) company_code: str = Field(..., min_length=1) address: str | None = Field(default=None) company_registration_number: str | None = Field(default=None) vat_number: str | None = Field(default=None) class AbacusContract(BaseModel): """Contract returned by abacusCreateContractWithLifecycles.""" model_config = _CAMEL_CONFIG contract_id: int = Field(...) contract_name: str = Field(...) contract_type: str = Field(...) contract_status: str | None = Field(default=None) run_controller_id: int | None = Field(default=None) is_excluded_from_accounting_run: bool | None = Field(default=None) is_primary_contract: bool | None = Field(default=None) execution_date: str | None = Field(default=None) # --------------------------------------------------------------------------- # Input models (camelCase aliases for serialization) # --------------------------------------------------------------------------- class AbacusContractInput(BaseModel): """Contract fields for abacusCreateContractWithLifecycles.""" model_config = _CAMEL_CONFIG account_id: int = Field(...) contract_name: str = Field(...) contract_type: ContractType = Field(...) execution_date: str | None = Field(default=None) is_excluded_from_accounting_run: bool = Field(default=False) is_primary_contract: bool = Field(default=True) reference_signing_entity_id: int | None = Field(default=None) run_controller_id: int | None = Field(default=None) @field_serializer('contract_type') @classmethod def _serialize_contract_type(cls, v: ContractType) -> str: return v.value class AbacusContractLifecycleInput(BaseModel): """Lifecycle term start.""" model_config = _CAMEL_CONFIG lifecycle_term_start: str = Field(...) class AbacusContractLifecycleScheduleInput(BaseModel): """Lifecycle schedule details.""" model_config = _CAMEL_CONFIG renewal_type: RenewalType = Field(...) schedule_end: str | None = Field(default=None) termination_notice_detail_interval: int = Field(...) termination_notice_detail_type: PeriodType = Field(...) renewal_offset_detail_interval: int | None = Field(default=None) renewal_offset_detail_type: PeriodType | None = Field(default=None) collection_period_detail_interval: int | None = Field(default=None) collection_period_detail_type: PeriodType | None = Field(default=None) contract_lifecycle: AbacusContractLifecycleInput = Field(...) @field_serializer( 'renewal_type', 'termination_notice_detail_type', 'renewal_offset_detail_type', 'collection_period_detail_type', ) @classmethod def _serialize_enum_upper(cls, v: RenewalType | PeriodType | None) -> str | None: if v is None: return None return v.value.upper() class AbacusContractWithLifecyclesInput(BaseModel): """Top-level input for abacusCreateContractWithLifecycles.""" model_config = _CAMEL_CONFIG contract: AbacusContractInput = Field(...) lifecycle: AbacusContractLifecycleInput = Field(...) lifecycle_schedules: list[AbacusContractLifecycleScheduleInput] = Field(...)