cadrumo.adapters.outbound.aeat.sede.declarations module¶
Read-only walker over AEAT’s Consultar declaraciones presentadas surface.
The expediente-tree walker (_walker.walk_expedientes_tree) walks
Mis Expedientes (/wlpl/TEWV-CORE/ResumenVlt) which is a
procedures surface — sanciones, recursos, gestión recaudación —
not the canonical filings register. To read the operator’s actual
filing history across supported periodic, annual, retention, and
informative declarations, we drive the
Consultar declaraciones presentadas form at
/wlpl/SCEJ-MANT/CONSUL/index.zul.
The form is built on the ZK framework. Input ids are generated by the
server and are not stable selectors; automation binds on label text
and visible row structure. The submit action is a real Buscar
button issuing a ZK AJAX RPC; URL parameters alone do not drive
results.
Parsed filings are grounded against the registry: each declaration is
resolved to its ModeloRevision and a RegistrySnapshot
(loaded through ValidatedRegistryAuthority), and reported casilla
values are surfaced as CasillaObservation rows carrying their
legal and source references.
- assert_declarations_read_landing(landing_url, *, policy=RemoteStateGuardPolicy(id='aeat-sede-declarations-read', evidence_tier=<EvidenceTier.OFFICIAL_SOURCE_GUIDANCE: 'official_source_guidance'>, classification='authenticated_read_surface', allowed_hosts=('www6.agenciatributaria.gob.es', ), allowed_host_suffixes=('agenciatributaria.gob.es', ), allowed_read_paths=(), allowed_read_post_paths=(), allowed_browser_action_patterns=('alert-modal-continuar', 'select-modelo', 'select-ejercicio', 'select-option-*', 'buscar-declaraciones-presentadas', 'open-cotejo-pdf', 'download-filed-data-file'), synthetic_data_allowed=False, requires_authentication=True, requires_aeat_authorization=True, forbidden_actions=(), allows_gov_idp_hosts=False))[source]¶
Refuse a landing that is not the declaraciones register.
The navigation INTO the register already refused a landing outside this prefix, which is why the rule is that same prefix rather than a wider one. What was missing is the other side of the search: Buscar is a real submit control, and its landing was LOGGED and never checked, so a search that left the register was recorded and then scraped. That failure is silent – the row parser finds no rows, and an empty listing is indistinguishable from a taxpayer who filed nothing that ejercicio.
- Parameters:
landing_url (
str) – The URL AEAT actually served, read off the page.policy (
RemoteStateGuardPolicy) – The read guard policy; defaults to the module’s own.
- Raises:
SedeNavigationError – When the landing is not the register.
- Return type:
Yield a long-lived Playwright instance for bulk register sweeps.
Standalone register reads spin up their own Playwright + BrowserSession. Bulk callers (e.g.
aeat sede capture-corpus) pay ~1s per iteration on Playwright startup; wrapping repeated reads in this helper amortises that cost across the entire run.Usage:
async with shared_playwright(session) as pw: for modelo in modelos: rows = await walk_declarations_register( session, modelo=modelo, ejercicio=ejercicio, playwright=pw, ) async with open_declarations_register( session, operation=operation, playwright=pw, ) as register: for declaration in rows: observation = await register.capture_observation(declaration)
- Parameters:
session (
AeatSession) – Authenticated AEAT session. Validated upfront so bulk reads fail fast rather than per-iteration.- Yields:
A live
Playwrightinstance. Cleaned up automatically on exit.- Return type:
AsyncGenerator[TypeAliasType]
- filed_register_modelo_options(html)[source]¶
Return the modelo codes the register’s modelo combobox offers.
The shape is the one the shipped selection path already matches against the live form: a modelo option reads
"<code> - <description>", which is why_drive_search()selects onf"{modelo} -". Requiring the dash is what keeps this disjoint from an ejercicio option, which is a bare year.Duplicates are collapsed in first-seen order, so the result is what AEAT offered rather than how many times it rendered it.
- Raises:
SedeParseError – When the snapshot carries no modelo-shaped option. An empty modelo list is not a taxpayer with no history — the register always offers modelos — so it means the form did not render or AEAT changed the option shape, and reporting it as “nothing offered” would turn a shape change into a silently empty history.
- Return type:
- Parameters:
html (str)
- filed_register_ejercicio_options(html)[source]¶
Return the ejercicios the register’s ejercicio combobox offers, newest first.
An ejercicio option is a bare four-digit year, which is what
_drive_search()selects on. Unlike the modelo list, an EMPTY result is a legitimate answer: the register genuinely offers no ejercicio for a modelo the authenticated taxpayer has nothing under, and that is one of the two readings this signal cannot distinguish between. So this returns()rather than refusing, and the caller must not read the emptiness as proof that nothing was filed.
- async discover_filed_declaration_availability(session, *, settings=None, playwright=None)[source]¶
Read what the declaraciones register OFFERS, without querying any pair.
Opens the register form once, enumerates the modelo combobox’s full option set, then selects each modelo in turn and enumerates the ejercicio combobox’s option set for it. Nothing is searched, downloaded or persisted: this is a read of the form’s own controls.
The result is tagged
AEAT_REGISTER_OPTIONSand MUST be consumed as AEAT’s offered option set. Whether those option lists are scoped to the authenticated NIF or are a static universal catalogue is unconfirmed, and settling it needs a live authenticated probe against an account with real filing history under explicit operator authorisation. So a caller may UNION this into a walk grid — widening coverage costs nothing — but may never measure completeness against it alone, and may never report a pair absent from it as a filing the taxpayer does not have.A modelo whose ejercicio enumeration fails is skipped with a logged diagnostic rather than failing the whole read, because this signal is additive by construction: losing one modelo’s options narrows a bonus, while refusing the read would deny the caller the widening entirely.
- Parameters:
session (
AeatSession) – Authenticated AEAT session whosestorage_state_pathcarries valid cookies.playwright (
TypeAliasType|None) – Optional pre-started Playwright instance, typically fromshared_playwright(). Caller owns its lifetime.
- Return type:
- Returns:
A
FiledDeclarationAvailabilityReportof the offered pairs.- Raises:
SedeNavigationError – When the register form does not load.
SedeParseError – When the modelo combobox renders no modelo-shaped option.
- class DeclaracionesRegisterSession(session, page, context, *, operation)[source]¶
Bases:
objectReusable read-only session for AEAT’s filed-declarations register.
- Parameters:
session (AeatSession)
page (Page)
context (BrowserContext)
operation (PinnedAuthorityOperation)
- async walk(*, modelo, ejercicio)[source]¶
Return
Declaracionrows for one(modelo, ejercicio)query.- Raises:
SedeParseError – When the grid declares more records than it rendered, per
_register_rows_from_snapshot().- Return type:
- Parameters:
- async capture_observation(declaration, *, registry_snapshot=None, artefact_sink=None)[source]¶
Capture a normalized
FiledDeclaracionObservationusing the active page.- Parameters:
declaration (
Declaracion) – TheDeclaracionrow to observe.registry_snapshot (
RegistrySnapshot|None) – Optional pre-builtRegistrySnapshot. When omitted, the snapshot is resolved from the declaration coordinates.artefact_sink (
TypeAliasType|None) – Optional callable storing each captured artefact.
- Return type:
- open_declarations_register(session, *, operation, settings=None, playwright=None)[source]¶
Open a
DeclaracionesRegisterSessionfor repeated filed-declaration register reads.- Return type:
- Parameters:
session (AeatSession)
operation (PinnedAuthorityOperation)
settings (Settings | None)
playwright (Playwright | None)
- async walk_declarations_register(session, *, modelo, ejercicio, settings=None, playwright=None)[source]¶
Drive the Consultar declaraciones presentadas form for one query.
- Parameters:
session (
AeatSession) – Authenticated AEAT session whosestorage_state_pathcarries valid cookies.modelo (
str) – Modelo code to query. The form’s modelo combobox is matched on the leading"<modelo> -"text.ejercicio (
int) – Tax year to query (2024).playwright (
TypeAliasType|None) – Optional pre-started Playwright instance (typically fromshared_playwright()). Reused across the call to amortise the ~1s startup cost in bulk sweeps. WhenNone, a fresh instance is started and torn down per call.
- Return type:
- Returns:
Tuple of
Declaracionrecords, one per filing row. Empty when AEAT returns “No se han encontrado resultados”.- Raises:
SedeParseError – When the grid declares more records than it rendered, per
_register_rows_from_snapshot().