cadrumo.application.calculations.maritime_exemption_service module¶
Application-layer service for maritime worker IRPF exemption resolution.
Bridges the domain maritime exemption engine with the application observation
pipeline. The service accepts resolved
MaritimeWorkerFacts and income
inputs, evaluates the Art. 7.p) and REBECA selectors, delegates calculation to
calculate_art_7p_exemption() and
calculate_rebeca_exemption(), and
returns typed CasillaObservation
rows alongside a derived flat casilla_values mapping.
The flat mapping is for human readability; the typed observation tuple is the
canonical contract per aeat-calculation-grounding because it carries
legal_refs and source_refs from the registry binding entries.
Calling conventions:
result = resolve_maritime_exemption(
facts=MaritimeWorkerFacts(
worker_class="trabajador_del_mar",
vessel_flag="foreign",
waters_type="international",
),
annual_salary=Decimal("36500"),
qualifying_days=180,
)
# result.observations: tuple of CasillaObservation with legal_refs/source_refs
# result.casilla_values: {casilla_id: Decimal} derived view
Error handling:
MaritimeExemptionInactiveError - DA 41 selector resolved True (inactive)
ProfileCompletenessError - RETMAR mandatory filing gate triggered
RentaValidationError - input validation failed
Callers are responsible for catching
ProfileCompletenessError,
surfacing its message to the operator, and continuing processing. It is not a
blocking calculation error.
- class MaritimeExemptionResult(**data)[source]¶
Bases:
BaseModelTyped result for a maritime worker exemption resolution.
Carries the ordered tuple of
CasillaObservationrows with full legal/source provenance and a derived flat mapping for human readability. Theobservationsfield is the canonical contract; callers must not persist or transmit only the flatcasilla_valuesview.- Parameters:
data (Any)
- observations: tuple[CasillaObservation, ...]¶
- retmar_mandatory_filing: bool¶
- property casilla_values: Mapping[CasillaId, Decimal]¶
Derived flat view from canonical observations.
Returns a
Mapping[CasillaId, Decimal]for display and operator preview paths. The canonical storage isobservations; this view must not be used for persistence or wire payloads because it omitsCasillaObservationprovenance.
- resolve_maritime_exemption(*, facts, annual_salary=None, qualifying_days=None, gross_navigation_income=None, authority=None, filing_period=None, devengo_date=None)[source]¶
Resolve the applicable maritime exemption pathway and produce typed observations.
Evaluates
art_7p_eligible()andrebeca_eligible()in order. For each eligible pathway the corresponding domain calculation function is called and itsCasillaObservationis appended to the result.The DA 41 inactive guard runs before any calculation: if the DA 41 selector resolves true (currently when
tuna_fleetandpending_eu_clearanceare both set on a trabajador del mar profile),MaritimeExemptionInactiveErroris raised and no observations are produced.The RETMAR mandatory-filing gate is checked independently through
check_retmar_mandatory_filing(). Whenretmar_registeredis true,ProfileCompletenessErroris raised. Callers should catch it, surface the message to the operator, and continue processing. The gate does not suppress exemption calculations.- Parameters:
facts (
MaritimeWorkerFacts) – Resolved MaritimeWorkerFacts from the user profile.annual_salary (
Decimal|None) – Gross annual salary in EUR. Required when Art. 7.p) is potentially eligible.qualifying_days (
int|None) – Days of work outside Spain in the tax year. Required when Art. 7.p) is potentially eligible.gross_navigation_income (
Decimal|None) – Total gross navigation income in EUR. Required when REBECA is potentially eligible.authority (
GovernedFactSource|None) – Validated governed-fact authority for both calculations.filing_period (
date|None) – Filing-period coordinate for the Art. 7.p) cap.devengo_date (
date|None) – Devengo-date coordinate for the REBECA fraction.
- Return type:
- Returns:
MaritimeExemptionResultwith typed observations and flat view.- Raises:
RentaValidationError – Eligibility predicate mismatch or invalid input. The DA 41 inactive guard and RETMAR completeness gate raise their own typed exceptions from the called guards.
- retmar_mandatory_filing(facts)[source]¶
Whether RETMAR registration makes the filing mandatory for this worker.
Its own function because the answer is needed on a path where the full resolution cannot run. When the profile is incomplete the preview reruns
resolve_maritime_exemption()against facts with the RETMAR flag CLEARED – the only way to obtain observations at all from incomplete data – and the value on that rerun result is therefore always false, precisely when the real answer may be true.The CLI was quietly repairing that by reaching past the result to the untouched fact and folding the two with
or. It produced the right answer, so nothing failed; but the determination had moved into a renderer, and it would have stopped tracking this function the moment a second condition joined it here.- Return type:
- Parameters:
facts (MaritimeWorkerFacts)