"""Narrow Protocol surfaces and value types for the submission engine.The submission engine is composed of read-only sub-systems that thetest suite exercises with concrete, hand-rolled Protocol-conformingclasses (no mocks, no patches). Each Protocol declares only thesurface the engine actually consumes, decoupling submission from thericher surfaces of its sibling subpackages.- :class:`AuthProviderProbe` — narrow auth-provider surface for the preflight gate.- :class:`DeadlineWindowChecker` — narrow surface over :mod:`aeat.domain.deadlines` used by preflight.- :class:`ModeloFinding` / :class:`ModeloDraftLike` / :class:`ModeloDraftLoader` — narrow filing draft surfaces; :class:`aeat.application.filing.ModeloDraft` structurally conforms to :class:`ModeloDraftLike`.Every record is either a strict+frozen pydantic v2 model or a``runtime_checkable`` ``Protocol``; no dataclasses; no bare dicts."""from__future__importannotationsfromcollections.abcimportIterable,Iterator,MappingfromdatetimeimportdatefromenumimportStrEnumfrompathlibimportPathfromtypingimportTYPE_CHECKING,Protocol,runtime_checkablefrompydanticimportBaseModelfrom...coreimportSTRICT_FROZEN_CONFIGas_STRICT_FROZENfrom...core.errorsimportBaseSeverityfrom._modelsimportModeloPresentadoifTYPE_CHECKING:# pragma: no cover — type-only importfrom...coreimportPeriodfrom...core.identityimportSubjectTaxId
[docs]@runtime_checkableclassAuthProviderDescriptionLike(Protocol):"""Submission-facing shape returned by an auth provider. Attributes: kind: Provider identifier (kept as ``object`` so the protocol does not couple submission to the auth subpackage's enum). label: Human-readable provider name. configured: Whether the provider's required settings are present. available: Whether a session can currently be established. subject: Subject DN (or equivalent identity string), if known. expires_on: Expiry date for the underlying credential, if known. """@propertydefkind(self)->object:"""Provider kind identifier."""...@propertydeflabel(self)->str:"""Human-readable provider name."""...@propertydefconfigured(self)->bool:"""Whether the provider's required settings are present."""...@propertydefavailable(self)->bool:"""Whether a session can currently be established."""...@propertydefsubject(self)->str|None:"""Subject DN or identity string when known, else ``None``."""...@propertydefexpires_on(self)->date|None:"""Expiry date for the underlying credential, when known."""...
[docs]@runtime_checkableclassAuthProviderProbe(Protocol):"""Narrow submission-facing auth-provider surface."""@propertydefkind(self)->object:"""Provider kind identifier consumed by the preflight gate."""...
[docs]defdescribe(self)->AuthProviderDescriptionLike:"""Return an :class:`AuthProviderDescriptionLike` describing the active auth provider."""...
[docs]@runtime_checkableclassDeadlineWindowChecker(Protocol):"""Narrow surface over :mod:`aeat.domain.deadlines` for the preflight gate."""
[docs]defis_window_open(self,modelo:str,period:Period,today:date)->bool:"""Return ``True`` iff the AEAT filing window for ``modelo`` / ``period`` is open on ``today``."""...
[docs]classModeloFinding(BaseModel):"""Minimal finding record consumed by the preflight gate. Distinct from :class:`aeat.application.filing.ModeloValidationFinding`, which carries the validator's full provenance graph; the submission engine reads only ``severity`` to decide whether the draft is blocked. Attributes: severity: The finding severity; ``ERROR`` blocks submission. message: Multilingual finding message. """model_config=_STRICT_FROZENseverity:BaseSeveritymessage:str
[docs]classModeloDraftStatus(StrEnum):"""Lifecycle status of a modelo draft, spanning preparation and submission. The state machine carries a draft from creation through validation, operator approval, submission, and the AEAT-side terminal states. The preflight engine consumes only :attr:`APROBADO` and :attr:`APROBACION_CADUCADA` on its happy path; the broader filing / submission stack consumes the full lifecycle. Member names and values mirror the AEAT Sede labels per ADR A7.2. Attributes: BORRADOR: New draft, not yet validated. VALIDADO: Validation rules executed without errors. LISTO_PARA_PRESENTAR: Draft fully prepared for an attempt. APROBADO: Operator-approved for submission. APROBACION_CADUCADA: Approval timestamp aged out. PRESENTADA: A submission attempt is recorded. ACEPTADA: AEAT acknowledged the filing. RECHAZADA: AEAT rejected the filing. ENMENDADO: Superseded by an amendment record. ANULADO: Operator cancelled before submission. """BORRADOR="BORRADOR"VALIDADO="VALIDADO"LISTO_PARA_PRESENTAR="LISTO_PARA_PRESENTAR"APROBADO="APROBADO"APROBACION_CADUCADA="APROBACION_CADUCADA"PRESENTADA="PRESENTADA"ACEPTADA="ACEPTADA"RECHAZADA="RECHAZADA"ENMENDADO="ENMENDADO"ANULADO="ANULADO"
[docs]@runtime_checkableclassModeloDraftLike(Protocol):"""Narrow surface over a filing draft. :class:`aeat.application.filing.ModeloDraft` structurally conforms to this Protocol so the engine can accept either the real draft or any Protocol-conforming hand-rolled class in tests. Attributes are declared as read-only properties so pyright treats them covariantly and frozen pydantic models satisfy the protocol without invariance errors. """@propertydefdraft_id(self)->str:...@propertydefmodelo(self)->str:...@propertydefperiod(self)->Period:...@propertydefprofile_tax_id(self)->SubjectTaxId:...@propertydefstatus(self)->object:...@propertydefvalues(self)->Mapping[str,str]|Iterable[object]:...@propertydeffindings(self)->tuple[object,...]:...
[docs]@runtime_checkableclassModeloDraftLoader(Protocol):"""Loads a :class:`ModeloDraftLike` from a draft path on disk."""
[docs]defload(self,_draft_path:Path,/)->ModeloDraftLike:"""Load and return the :class:`ModeloDraftLike` at ``draft_path``."""...
[docs]@runtime_checkableclassSubmissionRepositoryProtocol(Protocol):"""Narrow domain-facing repository contract for the submission engine. The concrete :class:`~aeat.adapters.persistence.profile.submission.SubmissionRepository` lives in the persistence adapter and inherits from the adapter-layer :class:`~aeat.adapters.persistence.storage.SecureBoundRepository`. This Protocol captures only the surface the engine consumes so the domain depends inward on this port, and the application layer constructs the concrete repository and injects it into :class:`SubmissionEngine`. """
[docs]defload(self,record_id:str,/)->ModeloPresentado|None:"""Load a persisted :class:`ModeloPresentado` by id, or return None if absent."""...
[docs]defiter_submissions(self)->Iterator[ModeloPresentado]:"""Yield every persisted submission in lexicographic id order. Returns: Iterator over :class:`ModeloPresentado` records. """...
[docs]deflist_submission_ids(self)->tuple[str,...]:"""Return every submission id persisted in this repository."""...