"""Application-level addressing for modelo work commands.
The address facade converts visible modelo/year/period filing targets and exact
work-unit ids into :class:`ModeloWorkAddress` values, resolves them through the
central selector contract, and returns the matching
:class:`~aeat.domain.modelos.WorkUnit` or :class:`CalculationRevision`.
This module is the application facade over the accepted addressing policy:
operators address the active bucket/profile plus modelo, filing year, and period;
raw ids remain advanced exact-addressing escape hatches. Ambiguous visible
targets, contradictory exact-id plus natural-key flags, and discarded default
matches are handled by :mod:`~aeat.application.modelo._selectors` rather than by
CLI-local string logic.
Creation flows validate the law-determined registry revision before delegating
to :func:`~aeat.application.modelo.create_work_unit`; an explicit
``--revision`` is an assertion of the selected legal revision, not a free
override. Revision flows apply
:class:`~aeat.application.modelo.ModeloCalculationRevisionSelector`
defaults so verify, file, and export commands consume only the lifecycle states
they are allowed to handle.
See Also:
:mod:`~aeat.application.modelo._selectors`:
The authoritative visible-target and revision-selector resolver.
:mod:`~aeat.entrypoints.cli._modelo`:
CLI commands that project operator flags into this facade.
"""
from __future__ import annotations
from dataclasses import dataclass
from ...core import Period
from ...core.resources import resources
from ...domain.calculations.registry import RegistrySnapshotError, select_revision
from ...domain.contribuyente import CCAA
from ...domain.modelos import (
CalculationRevision,
CalculationRevisionId,
CalculationRevisionState,
ModeloCode,
ModeloError,
WorkUnit,
WorkUnitId,
)
from ._calculation_actions import get_calculation_revision
from ._registry_discovery import declared_modelo_period_tokens
from ._selectors import (
ModeloCalculationRevisionDefault,
ModeloCalculationRevisionSelector,
ModeloCalculationRevisionSelectorAmbiguousError,
ModeloCalculationRevisionSelectorNotFoundError,
ModeloCalculationRevisionSelectorStateError,
ModeloWorkResolution,
ModeloWorkSelectorRequest,
ModeloWorkSelectorState,
resolve_modelo_calculation_revision_pick,
resolve_modelo_work_unit,
)
from ._work_lifecycle import create_work_unit, rename_work_unit
[docs]
class ModeloRevisionPickError(ModeloError, ValueError):
"""Raised when a calculation-revision selector is internally inconsistent."""
[docs]
@dataclass(frozen=True, slots=True)
class ModeloVisibleFilingTarget:
"""Operator-visible modelo filing target under one bucket/profile.
This is the normal user-facing address: bucket/profile plus modelo, filing
year, and period, with an optional registry-revision assertion for
disambiguation.
"""
modelo: str
filing_year: int
period: Period
registry_revision_id: str | None = None
bucket_id: str | None = None
[docs]
def to_work_address(self) -> ModeloWorkAddress:
"""Project the visible target into the shared :class:`ModeloWorkAddress` shape."""
return ModeloWorkAddress(
modelo=self.modelo,
filing_year=self.filing_year,
period=self.period,
registry_revision_id=self.registry_revision_id,
bucket_id=self.bucket_id,
)
[docs]
@dataclass(frozen=True, slots=True)
class ModeloExactWorkUnitTarget:
"""Advanced exact-addressing target for one content-addressed work unit.
Use this only when the caller already has an authoritative ``WorkUnitId``;
visible filing targets remain the default operator path.
"""
work_unit_id: WorkUnitId
bucket_id: str | None = None
[docs]
def to_work_address(self) -> ModeloWorkAddress:
"""Project the exact target into the shared :class:`ModeloWorkAddress` shape."""
return ModeloWorkAddress(work_unit_id=self.work_unit_id, bucket_id=self.bucket_id)
[docs]
@dataclass(frozen=True, slots=True)
class ModeloRevisionPick:
"""Command-specific calculation-revision pick under a resolved work target.
``default_for`` applies the command policy owned by
:mod:`~aeat.application.modelo._selectors`: verify selects a draft, file
selects a verified-complete revision, and export prefers the current filed
revision before falling back to an unambiguous verified revision.
"""
selector: ModeloCalculationRevisionSelector = ModeloCalculationRevisionSelector.CURRENT
calculation_revision_id: CalculationRevisionId | None = None
default_for: ModeloCalculationRevisionDefault | None = None
def __post_init__(self) -> None:
if self.selector is ModeloCalculationRevisionSelector.EXPLICIT:
if self.calculation_revision_id is None:
raise ModeloRevisionPickError(
"explicit revision picks require calculation_revision_id",
translated_message="application.modelo.errors.revision_pick_explicit_id_required",
)
return
if self.calculation_revision_id is not None:
raise ModeloRevisionPickError(
"calculation_revision_id is only valid with the explicit revision selector",
translated_message="application.modelo.errors.revision_pick_id_requires_explicit_selector",
)
[docs]
@classmethod
def explicit(cls, calculation_revision_id: CalculationRevisionId) -> ModeloRevisionPick:
"""Create an exact calculation-revision :class:`ModeloRevisionPick`."""
return cls(
selector=ModeloCalculationRevisionSelector.EXPLICIT,
calculation_revision_id=calculation_revision_id,
)
[docs]
@dataclass(frozen=True, slots=True)
class ModeloResolvedWorkProjection:
"""Support-safe projection of a resolved modelo work target.
The projection exposes the visible filing coordinates plus short ids for
support guidance without making raw ids the normal operator workflow.
"""
work_unit_id: WorkUnitId
short_work_unit_id: str
bucket_id: str
modelo: str
filing_year: int
period: Period
registry_revision_id: str
state: str
current_calculation_revision_id: CalculationRevisionId | None
filed_calculation_revision_id: CalculationRevisionId | None
current_filing_record_id: str | None
created_at: str
updated_at: str
[docs]
@classmethod
def from_work_unit(cls, work_unit: WorkUnit) -> ModeloResolvedWorkProjection:
"""Project an internal :class:`~aeat.domain.modelos.WorkUnit` into a :class:`ModeloResolvedWorkProjection`."""
return cls(
work_unit_id=work_unit.work_unit_id,
short_work_unit_id=work_unit.work_unit_id[-12:],
bucket_id=work_unit.bucket_id,
modelo=str(work_unit.modelo),
filing_year=work_unit.filing_year,
period=work_unit.period,
registry_revision_id=work_unit.revision_id,
state=work_unit.state.value,
current_calculation_revision_id=work_unit.current_calculation_revision_id,
filed_calculation_revision_id=work_unit.filed_calculation_revision_id,
current_filing_record_id=work_unit.current_filing_record_id,
created_at=work_unit.created_at.isoformat(),
updated_at=work_unit.updated_at.isoformat(),
)
[docs]
@dataclass(frozen=True, slots=True)
class ModeloResolvedRevisionProjection:
"""Support-safe projection of a resolved calculation revision.
Carries the selected revision, selector policy, lifecycle state, and short
ids used by CLI guidance after a work target has been resolved.
"""
calculation_revision_id: CalculationRevisionId
short_calculation_revision_id: str
work_unit_id: WorkUnitId
short_work_unit_id: str
selector: ModeloCalculationRevisionSelector
state: str
created_at: str
updated_at: str
verified_at: str | None = None
filed_at: str | None = None
[docs]
@classmethod
def from_revision(
cls,
revision: CalculationRevision,
*,
selector: ModeloCalculationRevisionSelector,
) -> ModeloResolvedRevisionProjection:
"""Project a :class:`CalculationRevision` into a :class:`ModeloResolvedRevisionProjection`."""
return cls(
calculation_revision_id=revision.calculation_revision_id,
short_calculation_revision_id=revision.calculation_revision_id[-12:],
work_unit_id=revision.work_unit_id,
short_work_unit_id=revision.work_unit_id[-12:],
selector=selector,
state=revision.state.value,
created_at=revision.created_at.isoformat(),
updated_at=revision.updated_at.isoformat(),
verified_at=revision.verified_at.isoformat() if revision.verified_at is not None else None,
filed_at=revision.filed_at.isoformat() if revision.filed_at is not None else None,
)
[docs]
@dataclass(frozen=True, slots=True)
class ModeloWorkAddress:
"""Operator-facing or exact modelo work address.
This is the shared transport shape consumed at the application facade
boundary. Prefer ``ModeloVisibleFilingTarget`` for model/year/period
addressing or ``ModeloExactWorkUnitTarget`` for the advanced exact-id
escape hatch, then project into this shape before selector resolution.
"""
work_unit_id: WorkUnitId | None = None
modelo: str | None = None
filing_year: int | None = None
period: Period | None = None
registry_revision_id: str | None = None
bucket_id: str | None = None
[docs]
@classmethod
def from_visible_target(cls, target: ModeloVisibleFilingTarget) -> ModeloWorkAddress:
"""Create a :class:`ModeloWorkAddress` from a natural modelo filing target."""
return target.to_work_address()
[docs]
@classmethod
def from_exact_target(cls, target: ModeloExactWorkUnitTarget) -> ModeloWorkAddress:
"""Create a :class:`ModeloWorkAddress` from an exact work-unit target."""
return target.to_work_address()
type ModeloWorkTarget = ModeloVisibleFilingTarget | ModeloExactWorkUnitTarget | ModeloWorkAddress
"""Supported work-target shapes for centralized modelo addressing."""
[docs]
class ModeloWorkAddressNotFoundError(ModeloError, LookupError):
"""Raised when a natural modelo work address resolves no active work unit."""
[docs]
class ModeloWorkRegistryYearMismatchError(ModeloError, ValueError):
"""Raised when an explicit revision diverges from the law-determined one."""
[docs]
class ModeloWorkPeriodTokenError(ModeloError, ValueError):
"""Raised when an operator-facing period token cannot be normalized."""
def __init__(
self,
*,
year: int,
token: str,
modelo: str | None,
declared_tokens: tuple[str, ...],
fallback: str | None = None,
) -> None:
context = {
"year": year,
"token": token,
"modelo": modelo or "",
"tokens": ", ".join(declared_tokens),
}
if declared_tokens:
super().__init__(
context=context,
translated_message="application.modelo.errors.work_period_token_invalid",
)
return
del fallback
super().__init__(
context=context,
translated_message="application.modelo.errors.work_period_token_unrecognised",
)
[docs]
@dataclass(frozen=True, slots=True)
class ModeloWorkEnsureResult:
"""Result of resolving or creating a visible-target work unit."""
work_unit: WorkUnit
reused: bool
name_applied: str | None = None
[docs]
def work_address_for_modelo_target(target: ModeloWorkTarget) -> ModeloWorkAddress:
"""Coerce a typed modelo work target into a :class:`ModeloWorkAddress` selector shape."""
if isinstance(target, ModeloWorkAddress):
return target
if isinstance(target, ModeloVisibleFilingTarget):
return target.to_work_address()
if isinstance(target, ModeloExactWorkUnitTarget):
return target.to_work_address()
raise TypeError(f"expected modelo work target, got {type(target).__name__}")
def _modelo_work_period_from_core(year: int, period: Period, *, modelo: str | None = None) -> Period:
"""Resolve a modelo work period through the core ``Period`` value object only."""
declared = declared_modelo_period_tokens(modelo)
if period.filing_year != year:
raise ModeloWorkPeriodTokenError(
year=year,
token=str(period),
modelo=modelo,
declared_tokens=declared,
)
return period
[docs]
def modelo_work_address_from_operator_target(
*,
work_unit_id: str | None,
modelo: str | None,
year: int | None,
period: Period | None,
registry_revision_id: str | None,
bucket_id: str | None = None,
) -> ModeloWorkAddress:
"""Build a :class:`ModeloWorkAddress` from exact or visible operator input.
A complete visible target is ``modelo`` + ``year`` + typed ``Period``. If no
visible target is supplied, an exact ``work_unit_id`` is required. Period year
mismatches fail here before the selector sees the request.
"""
if modelo is not None and year is not None and period is not None:
period = _modelo_work_period_from_core(year, period, modelo=modelo)
year = period.year
elif work_unit_id is None:
raise ModeloWorkAddressNotFoundError(
"pass an exact work-unit id, or address the filing with modelo, year, and period",
)
return ModeloWorkAddress(
work_unit_id=work_unit_id,
modelo=modelo,
filing_year=year,
period=period,
registry_revision_id=registry_revision_id,
bucket_id=bucket_id,
)
[docs]
def resolve_modelo_work_unit_for_operator_target(
*,
work_unit_id: str | None = None,
modelo: str | None = None,
year: int | None = None,
period: Period | None = None,
registry_revision_id: str | None = None,
bucket_id: str | None = None,
) -> WorkUnit:
"""Resolve exact or visible operator input to one active :class:`~aeat.domain.modelos.WorkUnit`.
The result comes from the shared selector boundary, so ambiguity and
exact-id/natural-key contradictions surface as typed selector errors.
"""
return resolve_modelo_work_address_unit(
modelo_work_address_from_operator_target(
work_unit_id=work_unit_id,
modelo=modelo,
year=year,
period=period,
registry_revision_id=registry_revision_id,
bucket_id=bucket_id,
),
)
[docs]
def resolve_modelo_revision_for_operator_target(
*,
calculation_revision_id: str | None,
work_unit_id: str | None,
modelo: str | None,
year: int | None,
period: Period | None,
registry_revision_id: str | None,
bucket_id: str | None = None,
selector: ModeloCalculationRevisionSelector = ModeloCalculationRevisionSelector.CURRENT,
default_for: ModeloCalculationRevisionDefault | None = None,
) -> CalculationRevision:
"""Resolve one :class:`CalculationRevision` from exact or visible operator input.
An explicit calculation-revision id can stand alone as the exact escape hatch.
Otherwise the work target is resolved first and the selector/default policy is
applied under that work unit.
"""
if (
calculation_revision_id is not None
and work_unit_id is None
and modelo is None
and year is None
and period is None
and registry_revision_id is None
and bucket_id is None
):
address = ModeloWorkAddress()
else:
address = modelo_work_address_from_operator_target(
work_unit_id=work_unit_id,
modelo=modelo,
year=year,
period=period,
registry_revision_id=registry_revision_id,
bucket_id=bucket_id,
)
if default_for == "verify":
return resolve_verifiable_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
)
if default_for == "file":
return resolve_fileable_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
)
if default_for == "export":
return resolve_exportable_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
)
return resolve_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
)
[docs]
def resolve_modelo_work_target(target: ModeloWorkTarget) -> ModeloWorkResolution:
"""Resolve any supported modelo target through the shared selector boundary.
Returns a :class:`ModeloWorkResolution` containing the resolved work unit or
typed absence/ambiguity metadata from :mod:`~aeat.application.modelo._selectors`.
"""
return resolve_modelo_work_address(work_address_for_modelo_target(target))
[docs]
def resolve_modelo_work_unit_id(target: ModeloWorkTarget) -> WorkUnitId:
"""Resolve a visible or exact modelo target to the authoritative work-unit id."""
resolution = resolve_modelo_work_target(target)
assert resolution.work_unit is not None
return resolution.work_unit.work_unit_id
[docs]
def project_modelo_work_unit(work_unit: WorkUnit) -> ModeloResolvedWorkProjection:
"""Project an internal work unit into the visible :class:`ModeloResolvedWorkProjection` addressing contract."""
return ModeloResolvedWorkProjection.from_work_unit(work_unit)
[docs]
def project_modelo_work_target(target: ModeloWorkTarget) -> ModeloResolvedWorkProjection:
"""Resolve a target and project it back to a :class:`ModeloResolvedWorkProjection`."""
resolution = resolve_modelo_work_target(target)
assert resolution.work_unit is not None
return project_modelo_work_unit(resolution.work_unit)
[docs]
def resolve_registry_revision_for_work_target(
*,
modelo: str,
filing_year: int,
period: Period,
registry_revision_id: str | None,
) -> str:
"""Resolve and validate the registry revision for a visible filing target.
When ``registry_revision_id`` is ``None`` the law-determined revision for
``(modelo, filing_year, period)`` is returned unconditionally.
When ``registry_revision_id`` is supplied it is treated as an
*assertion parameter* (per :func:`~aeat.domain.calculations.registry._temporal.select_revision`):
an explicit ``--revision`` is accepted only when it names exactly the revision
that ``select_revision`` would pick from ``(filing_year, period)`` alone. If
the supplied id diverges from the law-determined revision the call refuses with
an instructive error naming both the requested and the law-determined revision
and stating that the binding is fixed by law (per the CLI-boundary
instructive-refusal mandate in ``aeat-architecture-boundaries``).
``--revision`` is thereby demoted from a free override to an
idempotence/assertion handle, mirroring the operator-surface ADR's D8
shape for ``preflight --revision-id``.
Returns:
The revision id selected by
:func:`~aeat.domain.calculations.registry._temporal.select_revision`.
Raises:
ModeloWorkRegistryYearMismatchError: The supplied revision id is not the
law-determined revision for the visible filing period.
"""
definition = resources().modelos.authority.modelo(modelo.strip())
if registry_revision_id is None:
return select_revision(definition, filing_year=filing_year, period=period.registry_token).id
revision_id = registry_revision_id.strip()
try:
# Delegate the assertion to select_revision itself. Within a valid
# registry the non-overlap gate guarantees uniqueness, so narrowing by
# an id that genuinely covers (filing_year, period) returns the same
# revision the unconstrained call would; narrowing by any other id raises
# RegistrySnapshotError. This makes the structural property do the work
# instead of re-implementing a weaker year-only coverage check.
select_revision(definition, filing_year=filing_year, period=period.registry_token, revision_id=revision_id)
except RegistrySnapshotError:
# Determine the law-determined revision for a clear instructive message.
try:
law_revision = select_revision(definition, filing_year=filing_year, period=period.registry_token)
law_id = law_revision.id
except RegistrySnapshotError:
law_id = "<no revision found for this period>"
raise ModeloWorkRegistryYearMismatchError(
f"registry revision {revision_id!r} is not the law-determined revision for "
f"modelo {modelo.strip()!r} {filing_year} {period.registry_token!r}. "
f"The law-determined revision is {law_id!r}. "
f"The period-to-revision binding is fixed by law (AEAT orden ministerial); "
f"you cannot override it. Re-create the work unit without --revision to use "
f"the correct revision, or omit --revision to accept the law-determined default.",
) from None
return revision_id
[docs]
def ensure_modelo_work_unit_for_visible_target(
*,
bucket_id: str,
modelo: str,
filing_year: int,
period: Period,
registry_revision_id: str | None,
name: str | None = None,
actor: str = "operator",
causante_ccaa: CCAA | None = None,
enforce_applicability: bool = True,
) -> ModeloWorkEnsureResult:
"""Resume or create the active work unit for one visible filing target.
The visible target is resolved first. If one active unit exists, it is reused
after profile-readiness validation and optional rename. If none exists, the
law-determined registry revision is selected and a work unit is created.
Returns:
A :class:`ModeloWorkEnsureResult` marking whether the unit was reused or
newly created.
"""
requested_revision = registry_revision_id.strip() if registry_revision_id is not None else None
resolution = resolve_optional_modelo_work_address(
ModeloWorkAddress(
bucket_id=bucket_id,
modelo=modelo,
filing_year=filing_year,
period=period,
registry_revision_id=requested_revision,
),
)
if resolution.work_unit is not None:
unit = resolution.work_unit
from ._profile_readiness_gate import require_profile_ready_for_work_unit
require_profile_ready_for_work_unit(unit, enforce_applicability=enforce_applicability)
name_applied: str | None = None
if name is not None and name.strip() and name.strip() != unit.name:
unit = rename_work_unit(unit.work_unit_id, name, actor=actor)
name_applied = unit.name
return ModeloWorkEnsureResult(work_unit=unit, reused=True, name_applied=name_applied)
revision_id = resolve_registry_revision_for_work_target(
modelo=modelo,
filing_year=filing_year,
period=period,
registry_revision_id=requested_revision,
)
unit = create_work_unit(
bucket_id=bucket_id,
modelo=modelo,
filing_year=filing_year,
period=period,
revision_id=revision_id,
name=name,
actor=actor,
causante_ccaa=causante_ccaa,
enforce_applicability=enforce_applicability,
)
return ModeloWorkEnsureResult(work_unit=unit, reused=False)
[docs]
def resolve_modelo_work_address(address: ModeloWorkAddress) -> ModeloWorkResolution:
"""Resolve an operator-facing modelo work address to a required :class:`ModeloWorkResolution`."""
resolution = resolve_optional_modelo_work_address(address)
if resolution.state is ModeloWorkSelectorState.ABSENT or resolution.work_unit is None:
raise ModeloWorkAddressNotFoundError("no active modelo work unit matches the supplied address")
return resolution
[docs]
def resolve_optional_modelo_work_address(address: ModeloWorkAddress) -> ModeloWorkResolution:
"""Resolve an operator-facing modelo work address to a :class:`ModeloWorkResolution`."""
resolution = resolve_modelo_work_unit(
ModeloWorkSelectorRequest(
work_unit_id=address.work_unit_id,
modelo=ModeloCode(address.modelo) if address.modelo is not None else None,
filing_year=address.filing_year,
period=address.period,
revision_id=address.registry_revision_id,
bucket_id=address.bucket_id,
),
)
return resolution
[docs]
def resolve_modelo_work_address_unit(address: ModeloWorkAddress) -> WorkUnit:
"""Resolve an operator-facing modelo work address to one :class:`~aeat.domain.modelos.WorkUnit`."""
resolution = resolve_modelo_work_address(address)
assert resolution.work_unit is not None
return resolution.work_unit
[docs]
def resolve_modelo_calculation_revision_address(
*,
address: ModeloWorkAddress,
calculation_revision_id: str | None = None,
selector: ModeloCalculationRevisionSelector = ModeloCalculationRevisionSelector.CURRENT,
default_for: ModeloCalculationRevisionDefault | None = None,
) -> CalculationRevision:
"""Resolve a :class:`CalculationRevision` by exact id or under a modelo work address.
``default_for`` applies the command-specific selector default after the work
unit is resolved. A bare exact calculation-revision id bypasses work-address
resolution and loads the revision directly.
"""
if calculation_revision_id is not None and address == ModeloWorkAddress():
return get_calculation_revision(calculation_revision_id)
work_unit = resolve_modelo_work_address_unit(address)
return resolve_modelo_calculation_revision_pick(
work_unit,
selector=selector,
calculation_revision_id=calculation_revision_id,
default_for=default_for,
).revision
[docs]
def resolve_modelo_revision_pick(
*,
target: ModeloWorkTarget,
pick: ModeloRevisionPick | None = None,
) -> ModeloResolvedRevisionProjection:
"""Resolve and project a revision selection as :class:`ModeloResolvedRevisionProjection`."""
if pick is None:
pick = ModeloRevisionPick()
work_unit = resolve_modelo_work_address_unit(work_address_for_modelo_target(target))
selection = resolve_modelo_calculation_revision_pick(
work_unit,
selector=pick.selector,
calculation_revision_id=pick.calculation_revision_id,
default_for=pick.default_for,
)
return ModeloResolvedRevisionProjection.from_revision(selection.revision, selector=selection.selector)
def _require_revision_state(
revision: CalculationRevision,
*,
allowed: tuple[CalculationRevisionState, ...],
purpose: str,
) -> CalculationRevision:
if revision.state not in allowed:
allowed_values = ", ".join(state.value for state in allowed)
raise ModeloCalculationRevisionSelectorStateError(
f"selected revision {revision.calculation_revision_id!r} is in state "
f"{revision.state.value!r}; {purpose} requires {allowed_values}",
)
return revision
[docs]
def resolve_verifiable_modelo_calculation_revision_address(
*,
address: ModeloWorkAddress,
calculation_revision_id: str | None = None,
selector: ModeloCalculationRevisionSelector = ModeloCalculationRevisionSelector.CURRENT,
) -> CalculationRevision:
"""Resolve the draft :class:`CalculationRevision` that ``work verify`` may consume."""
revision = resolve_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
default_for="verify",
)
return _require_revision_state(
revision,
allowed=(CalculationRevisionState.BORRADOR,),
purpose="verification",
)
[docs]
def resolve_fileable_modelo_calculation_revision_address(
*,
address: ModeloWorkAddress,
calculation_revision_id: str | None = None,
selector: ModeloCalculationRevisionSelector = ModeloCalculationRevisionSelector.CURRENT,
) -> CalculationRevision:
"""Resolve the verified-complete :class:`CalculationRevision` that ``work file`` may consume."""
revision = resolve_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
default_for="file",
)
return _require_revision_state(
revision,
allowed=(CalculationRevisionState.VERIFICADO_COMPLETO,),
purpose="filing",
)
[docs]
def resolve_exportable_modelo_calculation_revision_address(
*,
address: ModeloWorkAddress,
calculation_revision_id: str | None = None,
selector: ModeloCalculationRevisionSelector = ModeloCalculationRevisionSelector.CURRENT,
) -> CalculationRevision:
"""Resolve the filed or verified-complete :class:`CalculationRevision` that ``modelo export`` may consume."""
revision = resolve_modelo_calculation_revision_address(
address=address,
calculation_revision_id=calculation_revision_id,
selector=selector,
default_for="export",
)
return _require_revision_state(
revision,
allowed=(
CalculationRevisionState.VERIFICADO_COMPLETO,
CalculationRevisionState.PRESENTADO,
),
purpose="export",
)
__all__ = [
"ModeloCalculationRevisionSelector",
"ModeloCalculationRevisionSelectorAmbiguousError",
"ModeloCalculationRevisionSelectorNotFoundError",
"ModeloCalculationRevisionSelectorStateError",
"ModeloExactWorkUnitTarget",
"ModeloResolvedRevisionProjection",
"ModeloResolvedWorkProjection",
"ModeloRevisionPick",
"ModeloRevisionPickError",
"ModeloVisibleFilingTarget",
"ModeloWorkAddress",
"ModeloWorkAddressNotFoundError",
"ModeloWorkEnsureResult",
"ModeloWorkPeriodTokenError",
"ModeloWorkRegistryYearMismatchError",
"ModeloWorkTarget",
"ensure_modelo_work_unit_for_visible_target",
"modelo_work_address_from_operator_target",
"project_modelo_work_target",
"project_modelo_work_unit",
"resolve_exportable_modelo_calculation_revision_address",
"resolve_fileable_modelo_calculation_revision_address",
"resolve_modelo_calculation_revision_address",
"resolve_modelo_revision_for_operator_target",
"resolve_modelo_revision_pick",
"resolve_modelo_work_address",
"resolve_modelo_work_address_unit",
"resolve_modelo_work_target",
"resolve_modelo_work_unit_for_operator_target",
"resolve_modelo_work_unit_id",
"resolve_optional_modelo_work_address",
"resolve_registry_revision_for_work_target",
"resolve_verifiable_modelo_calculation_revision_address",
"work_address_for_modelo_target",
]