"""Category profile schema consumed by downstream classifiers.:class:`CategoryProfile` binds a :class:`SpendingCategory` to its display label,:class:`ProportionalityRule`, and optional :class:`IvaDeductibilityHint`."""from__future__importannotationsfromenumimportStrEnumfrompydanticimportBaseModel,model_validatorfrom...coreimportSTRICT_FROZEN_CONFIGfrom...core.i18nimportTranslatableastrfrom._errorsimportCategoryValidationErrorfrom._proportionalityimportProportionalityRulefrom._spending_categoryimportSpendingCategoryclass_CategoryProfileStrictFrozenModel(BaseModel):"""Shared strict immutable boundary model."""model_config=STRICT_FROZEN_CONFIG
[docs]classIvaDeductibilityHint(StrEnum):"""Local IVA hint kept decoupled from the IVA taxonomy branch."""GENERAL="general"EXEMPT_OR_NON_SUBJECT="exempt_or_non_subject"NON_DEDUCTIBLE_INPUT="non_deductible_input"
[docs]classCategoryProfile(_CategoryProfileStrictFrozenModel):"""Explainable category profile for one spending category."""category:SpendingCategorydisplay_label:trproportionality:ProportionalityRuleiva_hint:IvaDeductibilityHint|None=None@model_validator(mode="after")def_validate_profile(self)->CategoryProfile:ifnotstr(self.display_label).strip():raiseCategoryValidationError("category profile display_label must contain authoritative Spanish text")returnself