aeat.application.calculations._iva_compensation_history module

Profile-scoped IVA compensation history built from filed Modelo 303s.

Records are stored at SensitivityClass AUDIT under the adapters.persistence.storage.IVA_COMPENSATION_HISTORY_NAMESPACE. The repository exposes typed IvaCompensationPeriodState objects; carry-forward projection is produced by build_iva_compensation_carry_forward_report(). Rows are written through SecureBoundRepository, so the namespace, schema version, and sensitivity declared by the storage registry remain the persistence authority.

This module uses IvaCompensationAnnualSummary and IvaCompensationAnnualCrossCheck for Modelo 303-to-Modelo 390 annual cross-checking.

See also

domain.iva_compensation._carry_forward

Pure FIFO lot projection and four-year review policy.

application.calculations._iva_wallet_balance

Offline balance query built from this repository.

application.calculations._iva_wallet_reconciliation

Wallet/local-history reconciliation consumer for Modelo 303 prior compensation.

class IvaCompensationAnnualSummary(**data)[source]

Bases: BaseModel

Filed Modelo 390 annual IVA compensation summary for cross-checking.

Compared against the IvaCompensationCarryForwardReport built from Modelo 303 period states by cross_check_iva_compensation_annual_summary().

Parameters:
  • taxpayer_nif (str)

  • filing_year (int)

  • expediente_id (str)

  • status (str)

  • presented_at (datetime)

  • last_period_compensation_amount (Decimal)

  • generated_not_in_last_period_amount (Decimal)

  • total_pending_amount (Decimal)

  • source_observation_key (str)

  • source_artefact_sha256 (str | None)

taxpayer_nif: str
filing_year: int
expediente_id: str
status: str
presented_at: datetime
last_period_compensation_amount: Decimal
generated_not_in_last_period_amount: Decimal
total_pending_amount: Decimal
source_observation_key: str
source_artefact_sha256: str | None
class IvaCompensationAnnualCrossCheck(**data)[source]

Bases: BaseModel

Comparison between Modelo 303 carry-forward lots and a filed Modelo 390 summary.

Carries the expected Modelo 390 annual carry fields derived by derive_iva_compensation_year_end_carry_partition() plus any mismatched CasillaId values.

Parameters:
  • filing_year (int)

  • carry_forward_remaining_amount (Decimal)

  • modelo_390_total_pending_amount (Decimal)

  • expected_last_period_compensation_amount (Decimal)

  • expected_generated_not_in_last_period_amount (Decimal)

  • difference_amount (Decimal)

  • last_period_difference_amount (Decimal)

  • generated_not_in_last_period_difference_amount (Decimal)

  • matches (bool)

  • mismatched_casilla_ids (tuple[CasillaId, ...])

  • expiry_review_states (tuple[str, ...])

  • summary_source_observation_key (str)

filing_year: int
carry_forward_remaining_amount: Decimal
modelo_390_total_pending_amount: Decimal
expected_last_period_compensation_amount: Decimal
expected_generated_not_in_last_period_amount: Decimal
difference_amount: Decimal
last_period_difference_amount: Decimal
generated_not_in_last_period_difference_amount: Decimal
matches: bool
mismatched_casilla_ids: tuple[CasillaId, ...]
expiry_review_states: tuple[str, ...]
summary_source_observation_key: str
iva_compensation_period_key(period)[source]

Return the latest-state key for one Modelo 303 period.

Return type:

str

Parameters:

period (Period)

class IvaCompensationHistoryRepository(*, bucket_id=None, objects=None, settings=None)[source]

Bases: SecureBoundRepository[IvaCompensationPeriodState]

Encrypted profile-local store of Modelo 303 IVA compensation history.

Persists IvaCompensationPeriodState rows in adapters.persistence.storage.IVA_COMPENSATION_HISTORY_NAMESPACE for later carry-forward, balance, and reconciliation reads. The SecureBoundRepository base writes those rows as encrypted AUDIT-class envelopes for active-bucket lookup.

Parameters:
namespace: ClassVar[str]
sensitivity: ClassVar[SensitivityClass]
schema_version: ClassVar[int]
payload_type

alias of IvaCompensationPeriodState

extract_identifier(payload)[source]

Return the natural id for payload (used as the SQL object key).

Subclasses MUST override. The base implementation raises NotImplementedError.

Return type:

str

Parameters:

payload (IvaCompensationPeriodState)

load_period(period)[source]

Return latest stored state for one period.

Returns an IvaCompensationPeriodState when a record exists, or None when none has been persisted for the given period.

Return type:

IvaCompensationPeriodState | None

Parameters:

period (Period)

save_period(state)[source]

Persist latest stored state for one period.

Return type:

None

Parameters:

state (IvaCompensationPeriodState)

list_periods()[source]

Return stored IvaCompensationPeriodState rows.

The returned tuple is sorted in chronological filing order using the same period sort key consumed by the domain carry-forward projection.

Return type:

tuple[IvaCompensationPeriodState, ...]

seed_iva_compensation_period(*, taxpayer_nif, period, amount, repository=None, seeded_at=None)[source]

Persist a manually declared carry-forward balance for one Modelo 303 period.

Returns an IvaCompensationPeriodState.

Intended for first-time users whose historical M303 carry-forward pre-dates the local compensation history. The seeded state is structurally identical to a filed-observation state but carries status='seeded' and synthetic provenance so downstream diagnostics can distinguish seed from filed records.

Raises IvaCompensationSeedConflictError if a state already exists for the specified period — seeding must not overwrite an existing record.

Return type:

IvaCompensationPeriodState

Parameters:
correct_iva_compensation_period(*, taxpayer_nif, period, amount, repository=None, corrected_at=None)[source]

Overwrite a manually-seeded carry-forward balance for one Modelo 303 period.

Returns the corrected IvaCompensationPeriodState.

The single-writer companion of seed_iva_compensation_period(): where seeding refuses if a record already exists, correction is the deliberate re-write path for a wrong opening compensation balance whose period pre-dates local history. It writes through the same IvaCompensationHistoryRepository (no parallel write path), so the corrected state replaces the stored record at the same period key.

The guard that a sealed (already-filed) Modelo 303 must not have its compensation basis silently changed lives one layer up, in the modelo application facade that resolves the bucket’s taxpayer and revisions; this primitive is the unguarded write the facade delegates to once that guard has passed. It refuses to fabricate a record from nothing: an absent period is a seed, not a correction, and raises IvaCompensationSeedConflictError with a correction-on-missing marker so the facade can surface the seed-first guidance.

Return type:

IvaCompensationPeriodState

Parameters:
iva_compensation_state_from_filed_observation(observation)[source]

Build an IvaCompensationPeriodState.

The source is a filed Modelo 303 FiledDeclaracionObservationProtocol captured from live or imported filed-declaration evidence.

Return type:

IvaCompensationPeriodState

Parameters:

observation (FiledDeclaracionObservationProtocol)

iva_compensation_state_from_registry_observation(observation, *, taxpayer_nif, expediente_id, status, presented_at, source_observation_key=None, source_artefact_sha256=None)[source]

Build an IvaCompensationPeriodState.

The source is a registry-grounded Modelo 303 RegistryModeloObservation, usually promoted from local calculation evidence or filed-observation conversion.

Return type:

IvaCompensationPeriodState

Parameters:
iva_compensation_annual_summary_from_filed_observation(observation)[source]

Build an IvaCompensationAnnualSummary.

The source is a filed Modelo 390 FiledDeclaracionObservationProtocol.

iva.anual.compensacion-ultimo-periodo-97 carries the final-period amount to compensate. iva.anual.compensacion-generada-ejercicio-no-97 carries generated pending compensation from the exercise that is not included in the final-period annual carry id. The summary is evidence for cross-checking the Modelo 303 carry-forward projection; it is not stored as a period state.

Return type:

IvaCompensationAnnualSummary

Parameters:

observation (FiledDeclaracionObservationProtocol)

cross_check_iva_compensation_annual_summary(report, summary, *, period_states=())[source]

Compare projections with filed evidence.

Returns an IvaCompensationAnnualCrossCheck.

The expected iva.anual.compensacion-ultimo-periodo-97 and iva.anual.compensacion-generada-ejercicio-no-97 figures are derived through the SAME FIFO carry partition that drives the Modelo 390 calculation (derive_iva_compensation_year_end_carry_partition()), so the cross-check and both annual carry bindings cannot diverge: all three read one partition of the year’s pending credit. period_states is the same tuple of filed Modelo 303 states the carry-forward report was built from; it supplies the last period’s disponible that discriminates the final-period carry from the generated-not-carried amount.

Return type:

IvaCompensationAnnualCrossCheck

Parameters: