"""Canonical AEAT modelo identifier enumeration.
This module exposes the closed set of AEAT modelo *identifiers* the codebase
references. Almost every member has a directory under
``src/aeat/_data/registry/aeat/modelos/`` and is therefore registry-loadable;
the enum value is the bare three-digit code string (``"036"``, ``"100"``, …) so
it is directly substitutable for the existing bare-string usage throughout the
codebase.
A small set of members are known modelos that the code references as
identifiers but which have **no registry definition by design** — currently the
retired :data:`Modelo.M037` (censo simplificada, suppressed by
Orden HAC/1526/2024). These are enumerated in :data:`NON_REGISTRY_MODELOS`.
They are real codes with implementation support (lifecycle routing, portal
entries), but
:meth:`~domain.calculations.registry.ValidatedRegistryAuthority.validate_modelo`
raises for them and no registry TOML exists or may be created for them.
Filing-grade authority — deadline windows, period restrictions, and casilla
definitions — remains the :class:`~domain.calculations.registry.ValidatedRegistryAuthority`
and the typed :class:`~domain.calculations.registry.RegistrySnapshot` it
produces. This enum is the closed-set *identifier* type: it tells you which
modelos exist; the registry tells you what (if anything) they contain.
Modelo-specific support such as filing, export, extraction, and verification is
declared on registry data such as
:attr:`~domain.calculations.registry.ModeloDefinition.capabilities`, not by
branching on this enum.
A gate test in ``src/aeat/core/tests/test_modelo.py`` binds the registry-backed
members to :func:`application.modelo.registry_modelo_codes` (enum minus
:data:`NON_REGISTRY_MODELOS`) so the two cannot drift silently, and pins every
non-registry member to its deliberately-absent registry definition.
"""
from __future__ import annotations
from collections.abc import Mapping
from enum import StrEnum
__all__ = ["NON_REGISTRY_MODELOS", "OUT_OF_SCOPE_OBLIGATIONS", "UNMODELED_OBLIGATIONS", "Modelo"]
[docs]
class Modelo(StrEnum):
"""Closed enumeration of AEAT modelo identifier codes.
Each member's *name* is the prefixed form (``M036``, ``M100``, …) and
its *value* is the bare three-digit code string (``"036"``, ``"100"``, …).
Because :class:`Modelo` inherits from :class:`str` via :class:`~enum.StrEnum`,
every member compares equal to its raw string value::
Modelo.M303 == "303" # True
Modelo.M303 == Modelo.M303 # True
The registry-backed members are bound to the registry directory listing by
:func:`application.modelo.registry_modelo_codes`; adding a new modelo
to the registry without updating this enum will fail the core parity test.
Members in :data:`NON_REGISTRY_MODELOS` (the retired :data:`M037` and the
recognized-but-not-yet-modeled obligations in :data:`UNMODELED_OBLIGATIONS`)
are known identifiers with no registry definition by design.
Use this enum at code boundaries that carry a modelo identifier. Operator
input and registry TOML still enter as strings; callers may coerce with
``Modelo(value)`` when they need the closed enum contract, while registry
consumers validate loadable support through the registry authority.
"""
M030 = "030"
M035 = "035"
M036 = "036"
M037 = "037"
M038 = "038"
M043 = "043"
M100 = "100"
M111 = "111"
M115 = "115"
M117 = "117"
M121 = "121"
M122 = "122"
M123 = "123"
M126 = "126"
M128 = "128"
M130 = "130"
M131 = "131"
M136 = "136"
M140 = "140"
M143 = "143"
M145 = "145"
M149 = "149"
M150 = "150"
M151 = "151"
M156 = "156"
M159 = "159"
M165 = "165"
M170 = "170"
M171 = "171"
M172 = "172"
M173 = "173"
M179 = "179"
M180 = "180"
M181 = "181"
M182 = "182"
M184 = "184"
M185 = "185"
M186 = "186"
M187 = "187"
M188 = "188"
M189 = "189"
M190 = "190"
M192 = "192"
M193 = "193"
M194 = "194"
M196 = "196"
M198 = "198"
M200 = "200"
M202 = "202"
M210 = "210"
M216 = "216"
M218 = "218"
M221 = "221"
M235 = "235"
M236 = "236"
M240 = "240"
M241 = "241"
M242 = "242"
M220 = "220"
M222 = "222"
M231 = "231"
M232 = "232"
M233 = "233"
M234 = "234"
M238 = "238"
M270 = "270"
M280 = "280"
M289 = "289"
M290 = "290"
M291 = "291"
M294 = "294"
M295 = "295"
M296 = "296"
M303 = "303"
M308 = "308"
M309 = "309"
M322 = "322"
M341 = "341"
M345 = "345"
M347 = "347"
M349 = "349"
M353 = "353"
M360 = "360"
M361 = "361"
M362 = "362"
M363 = "363"
M368 = "368"
M369 = "369"
M379 = "379"
M380 = "380"
M390 = "390"
M430 = "430"
M480 = "480"
M490 = "490"
M510 = "510"
M511 = "511"
M517 = "517"
M518 = "518"
M519 = "519"
M520 = "520"
M521 = "521"
M522 = "522"
M524 = "524"
M548 = "548"
M553 = "553"
M554 = "554"
M555 = "555"
M556 = "556"
M557 = "557"
M558 = "558"
M559 = "559"
M560 = "560"
M561 = "561"
M562 = "562"
M563 = "563"
M566 = "566"
M568 = "568"
M570 = "570"
M573 = "573"
M576 = "576"
M580 = "580"
M581 = "581"
M582 = "582"
M583 = "583"
M584 = "584"
M585 = "585"
M586 = "586"
M587 = "587"
M588 = "588"
M589 = "589"
M590 = "590"
M591 = "591"
M592 = "592"
M593 = "593"
M595 = "595"
M596 = "596"
M604 = "604"
M714 = "714"
M718 = "718"
M720 = "720"
M721 = "721"
M795 = "795"
M796 = "796"
M797 = "797"
M798 = "798"
M763 = "763"
M840 = "840"
M848 = "848"
M993 = "993"
#: Recognized AEAT obligation modelos the registry does **not** yet model, each
#: mapped to a short description of the obligation. These are real, currently
#: fileable AEAT forms outside the registry directory listing; the
#: obligation-coverage reconciliation
#: (:func:`application.overview.build_obligation_coverage`) treats them as
#: part of the AEAT obligation universe and surfaces each as an *advised*
#: (registry-unmodeled → investigate) row rather than leaving it invisible.
#: Promoting one to a full registry definition (deadline windows + applicability
#: rule) removes it from this delta and folds it into
#: :func:`application.modelo.registry_modelo_codes`. The mapping is the
#: extensible edge of AEAT-wide enrollment: it ratchets up as obligations are
#: recognized and shrinks as they are modeled. The current set covers the common
#: retención autoliquidaciones and declaraciones informativas an autónomo, a PYME,
#: or an entity may owe, grounded against AEAT's published catalogue of
#: declaraciones informativas and retención forms; it is not yet AEAT's full
#: ~200-form set.
UNMODELED_OBLIGATIONS: Mapping[Modelo, str] = {}
#: Registry modelos (with a TOML definition) deliberately out of scope of the
#: overview obligation calendar, each with the recorded reason it is not scheduled.
_REGISTRY_OUT_OF_SCOPE_OBLIGATIONS: Mapping[Modelo, str] = {
Modelo.M036: "registration form, not a periodic self-assessment the calendar schedules",
Modelo.M145: "local IRPF payer communication, not an AEAT filing/calendar obligation",
Modelo.M151: "IRPF impatriado special regime, outside the autonomo/PYME core",
Modelo.M714: "Impuesto sobre el Patrimonio, outside the IRPF/IVA/IS core",
Modelo.M840: "Impuesto sobre Actividades Economicas, most taxpayers exempt (INCN < 1M)",
}
#: Recognized AEAT obligations OUTSIDE the registry that a general autónomo / PYME /
#: entity never files — filed by financial institutions, registrars, or under a
#: regional special regime — each with its recorded reason. They are declared out of
#: scope rather than advised so they do not become investigate-noise for the target
#: profiles, while still being explicitly accounted for by the completeness invariant.
_UNMODELED_OUT_OF_SCOPE_OBLIGATIONS: Mapping[Modelo, str] = {
Modelo.M510: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M511: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M517: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M518: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M519: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M520: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M521: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M522: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M524: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M548: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M553: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M554: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M555: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M556: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M557: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M558: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M559: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M561: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M562: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M563: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M566: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M570: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M573: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M580: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M581: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M582: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M590: "impuesto especial de fabricacion; lo declaran fabricantes, depositos u operadores del sector",
Modelo.M560: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M595: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M596: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M583: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M584: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M585: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M588: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M589: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M591: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M586: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M587: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M593: "impuesto medioambiental/sectorial; lo declaran productores o instalaciones del sector",
Modelo.M430: "impuesto sobre primas de seguros; lo declaran las entidades aseguradoras",
Modelo.M480: "impuesto sobre primas de seguros, resumen anual; lo declaran las aseguradoras",
Modelo.M568: "IEDMT solicitud de devolucion; tramite puntual del sector de matriculacion",
Modelo.M149: "regimen especial de impatriados (vinculado al Modelo 151); fuera del nucleo autonomo/PYME",
Modelo.M150: "regimen especial de impatriados, declaracion residual; fuera del nucleo autonomo/PYME",
Modelo.M218: "pago fraccionado IS residual, sustituido en la practica por el Modelo 202",
Modelo.M221: "prestacion patrimonial por conversion de activos por impuesto diferido; supuesto especializado",
Modelo.M235: "actualizacion de mecanismos transfronterizos DAC6; complementa el Modelo 234, filers especializados",
Modelo.M236: "utilizacion de mecanismos transfronterizos DAC6; complementa el Modelo 234, filers especializados",
Modelo.M240: "Impuesto Complementario (Pilar 2), comunicacion; solo grandes grupos multinacionales",
Modelo.M241: "Impuesto Complementario (Pilar 2), informativa GIR; solo grandes grupos multinacionales",
Modelo.M242: "Impuesto Complementario (Pilar 2), autoliquidacion; solo grandes grupos multinacionales",
Modelo.M718: "Impuesto Temporal de Solidaridad de las Grandes Fortunas; solo patrimonios netos elevados",
Modelo.M795: "gravamen temporal energetico; solo grandes operadores del sector",
Modelo.M796: "gravamen temporal energetico, pago anticipado; solo grandes operadores del sector",
Modelo.M797: "gravamen temporal de entidades de credito; solo grandes entidades del sector",
Modelo.M798: "gravamen temporal de entidades de credito, pago anticipado; solo grandes entidades",
Modelo.M159: "consumo de energia electrica (lo declaran las comercializadoras)",
Modelo.M170: "operaciones con tarjetas (lo declaran las entidades de gestion de cobros)",
Modelo.M171: "imposiciones, disposiciones y cobros (lo declaran las entidades de credito)",
Modelo.M172: "saldos en monedas virtuales (lo declaran los proveedores de servicios)",
Modelo.M173: "operaciones con monedas virtuales (lo declaran los proveedores de servicios)",
Modelo.M192: "operaciones con Letras del Tesoro (lo declaran las entidades gestoras)",
Modelo.M196: "cuentas en instituciones financieras (lo declaran las entidades de credito)",
Modelo.M368: "MOSS del IVA sustituido por la ventanilla unica OSS/IOSS (Modelo 369); sin periodos vigentes",
Modelo.M030: "declaracion censal de personas fisicas (alta, domicilio, datos); no es autoliquidacion periodica",
Modelo.M035: "registro censal de la ventanilla unica OSS/IOSS del IVA; no es autoliquidacion periodica",
Modelo.M362: "reembolso de IVA diplomatico/consular/OOII; no aplica a contribuyentes generales",
Modelo.M363: "reconocimiento previo de exencion de IVA diplomatica/consular; no aplica a contribuyentes generales",
Modelo.M043: "tasa fiscal del juego (bingo); gestion cedida a las CCAA; no aplica a contribuyentes generales",
Modelo.M993: "procedimiento interno AEAT de control de deducciones autonomicas; sin orden de aprobacion",
Modelo.M198: "operaciones con activos financieros y otros valores mobiliarios (anual)",
Modelo.M290: "cuentas de personas estadounidenses (FATCA, instituciones financieras)",
Modelo.M291: "cuentas de no residentes sin establecimiento permanente (entidades)",
Modelo.M294: "clientes perceptores de beneficios de IIC (lo declaran las gestoras)",
Modelo.M295: "clientes con posicion inversora en IIC (lo declaran las gestoras)",
}
#: Registry modelos deliberately **out of scope** of the overview obligation
#: calendar, each mapped to the recorded reason it is not scheduled or advised.
#: The obligation-coverage reconciliation
#: (:func:`application.overview.build_obligation_coverage`) partitions every
#: obligation in the AEAT universe into exactly one of *surfaced*, *confidently
#: excluded*, *advised* (investigate), or *out of scope*; this mapping is the sole
#: home of the last bucket, so "invisible" is always a recorded product-scope
#: decision rather than a silent omission. A modelo absent from a deadline window
#: and from an applicability rule but NOT listed here is **advised**, not dropped —
#: membership here is the explicit opt-out. It spans both registry forms declared
#: out of scope and recognized non-registry forms a general taxpayer never files.
OUT_OF_SCOPE_OBLIGATIONS: Mapping[Modelo, str] = {
**_REGISTRY_OUT_OF_SCOPE_OBLIGATIONS,
**_UNMODELED_OUT_OF_SCOPE_OBLIGATIONS,
}
#: Known modelo identifiers that intentionally have **no registry definition**.
#: These are real, code-referenced modelos for which
#: :meth:`~domain.calculations.registry.ValidatedRegistryAuthority.validate_modelo`
#: raises and no registry TOML exists or may be created. Three reasons put a member
#: here: the retired :data:`Modelo.M037` (censo simplificada, suppressed by
#: Orden HAC/1526/2024; superseded by :data:`Modelo.M036`), every
#: recognized-but-not-yet-modeled obligation in :data:`UNMODELED_OBLIGATIONS`, and
#: every recognized non-registry obligation declared out of scope
#: (:data:`_UNMODELED_OUT_OF_SCOPE_OBLIGATIONS`). The parity gate compares the
#: remaining members to :func:`application.modelo.registry_modelo_codes`, so the
#: enum can carry retired codes, recognized-unmodeled obligations, and out-of-scope
#: non-registry forms without implying the registry can load them.
NON_REGISTRY_MODELOS: frozenset[Modelo] = (
frozenset({Modelo.M037}) | frozenset(UNMODELED_OBLIGATIONS) | frozenset(_UNMODELED_OUT_OF_SCOPE_OBLIGATIONS)
)