Source code for cadrumo.application.modelo.work_create_policy
"""Application policies for creating modelo work units.The work-create command runs these guards before provisioning a work unit. Theycover three distinct policy surfaces: modelo codes that are still stub-only inthe local work-unit flow, modelos that do not apply to the active profile'staxpayer model, and active profiles whose CCAA points at a foral tax regime.Stub-only checks are locale-key lookups over :class:`Modelo` members and a fewregistry-known numeric forms. Applicability checks derive a profile projectionfrom the active workflow state, then ask the registry-owned applicability ruleswhether the requested modelo is excluded. The foral check delegates to thecanonical tax-region parser so the CLI renders the same refusal text as profilesetup. Once these CLI policy guards pass,:func:`cadrumo.application.modelo.work_lifecycle.create_work_unit` performs the applicationreadiness and registry revision checks before inserting the:class:`~WorkUnit`.See Also: :mod:`cadrumo.entrypoints.cli._modelo_work_lifecycle_cli`: Calls these guards from ``app modelo work create``. :func:`cadrumo.domain.calculations.registry.applicability.derive_modelo_applicability`: Registry-owned modelo applicability classifier used by this guard. :func:`cadrumo.domain.contribuyente.tax_residence.parse_tax_region`: Canonical CCAA parser that raises foral-regime refusals."""from__future__importannotationsfromdataclassesimportdataclassfromtypingimportTYPE_CHECKINGfrompydanticimportValidationErrorifTYPE_CHECKING:from...domain.user_profile.valuesimportUserProfileRecord#: Ceded autonomic-tax modelos that are administered by the Comunidades#: Autónomas rather than the AEAT, and are therefore absent from the#: calculation registry entirely: ITP-AJD (``600``, ``620``) and ISD (``650``,#: ``660``) are tributos cedidos. A registry discovery lookup for one of these#: codes must redirect the operator to the competent regional Hacienda / CCAA#: instead of surfacing a generic not-present-in-registry error. The values#: reuse the work-create refusal copy, which already names the ceded tax, its#: enabling law, and the regional filing route in every locale.CEDED_AUTONOMIC_MODELO_LOCALE_KEYS:dict[str,str]={"600":"cli.app.modelo.work.create_stub_modelo_600_refused","620":"cli.app.modelo.work.create_stub_modelo_620_refused","650":"cli.app.modelo.work.create_stub_modelo_650_refused","660":"cli.app.modelo.work.create_stub_modelo_660_refused",}
[docs]defceded_autonomic_modelo_locale_key(modelo:str)->str|None:"""Return the instructive autonomic-redirect locale key for a ceded modelo. ITP-AJD (``600`` / ``620``) and ISD (``650`` / ``660``) are ceded autonomic taxes administered by the Comunidades Autónomas, not AEAT modelos present in the calculation registry. Discovery surfaces (``describe`` / ``casillas`` / ``formulas``) must redirect an operator who references one of these codes to the competent regional Hacienda / CCAA rather than surface a generic not-present error. Whitespace is normalised; ``None`` is returned for any other modelo, including registry-backed and genuinely unknown codes. See Also: :func:`modelo_work_create_refusal_locale_key`: The sibling work-create refusal this discovery redirect mirrors. """returnCEDED_AUTONOMIC_MODELO_LOCALE_KEYS.get(modelo.strip())
[docs]@dataclass(frozen=True,slots=True)classModeloWorkCreateApplicabilityRefusal:"""Application refusal for a modelo the active profile should not file. ``modelo`` is the stripped requested modelo code. ``reason`` is the registry-derived applicability reason surfaced by the CLI together with its ``--allow-not-applicable`` escape hatch. """modelo:strreason:str
[docs]defmodelo_work_create_refusal_locale_key(modelo:str)->str|None:"""Return the jurisdiction redirect for a ceded autonomic tax, if any. AEAT modelo capability is deliberately absent from this policy. Registry snapshot, readiness, calculation, and filing boundaries each validate the capability they actually require; a hand-maintained "stub" classification cannot represent those distinct surfaces and inevitably lags them. See Also: :func:`ceded_autonomic_modelo_locale_key`: The domain-owned jurisdiction classifier delegated to here. :mod:`cadrumo.entrypoints.cli._modelo_work_lifecycle_cli`: Converts the locale key into a typed CLI refusal. """returnceded_autonomic_modelo_locale_key(modelo)
[docs]defmodelo_work_create_applicability_refusal(modelo:str,*,allow_not_applicable:bool,record:UserProfileRecord|None,)->ModeloWorkCreateApplicabilityRefusal|None:"""Return an applicability refusal for the active profile, if one applies. When ``allow_not_applicable`` is true, the guard deliberately returns ``None`` so the CLI can provision the work unit and record that the operator bypassed the applicability guard. Otherwise the caller's loaded profile record is projected into :class:`cadrumo.domain.deadlines.models.TaxpayerProfile` facts and checked against the registry-owned applicability rules. Only ``NOT_APPLICABLE`` and ``ATTRIBUTION_PASS_THROUGH`` verdicts block creation. Returns: A :class:`ModeloWorkCreateApplicabilityRefusal` for a blocking verdict, or ``None`` when the modelo is applicable, unsupported by an explicit rule, or deliberately bypassed. See Also: :func:`cadrumo.domain.calculations.registry.applicability.derive_modelo_applicability`: Registry-owned applicability classifier used by this guard. :func:`cadrumo.application.user_profile.projections.projection_for_taxpayer`: Builds the taxpayer profile consumed by the classifier. Core types: :class:`~cadrumo.domain.user_profile.values.UserProfileRecord`. """ifallow_not_applicable:returnNonefrom...application.user_profile.projectionsimportprojection_for_taxpayerfrom...domain.calculations.registry.applicabilityimportderive_modelo_applicabilityfrom...domain.calculations.registry.authorityimportbundled_indexed_authorityfrom.profile_readiness_gateimportBLOCKING_APPLICABILITY_VERDICTSwithbundled_indexed_authority().operation()asoperation:try:profile=projection_for_taxpayer(recordor{},schema=operation.profile_schema())exceptValidationError:returnNoneapplicability=derive_modelo_applicability(profile,modelo.strip())ifapplicability.verdictnotinBLOCKING_APPLICABILITY_VERDICTS:returnNonereturnModeloWorkCreateApplicabilityRefusal(modelo=modelo.strip(),reason=applicability.reason)
[docs]defguard_active_profile_foral_ccaa(record:UserProfileRecord|None)->None:"""Raise the canonical foral-regime refusal for the active profile, if present. The guard reads ``tax_residence.ccaa`` from the active profile record the caller already loaded and delegates to :func:`cadrumo.domain.contribuyente.tax_residence.parse_tax_region`. Common-regime CCAA values pass through; foral values raise the domain refusal before work-unit creation reaches the generic unsupported-modelo checks. Core types: :class:`~cadrumo.domain.user_profile.values.UserProfileRecord`. """from...application.user_profile.projectionsimportfact_valuefrom...domain.contribuyente.tax_residenceimportparse_tax_regionraw_ccaa=fact_value(record,"tax_residence.ccaa")ifraw_ccaa:parse_tax_region(raw_ccaa)