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: BaseModel

Typed result for a maritime worker exemption resolution.

Carries the ordered tuple of CasillaObservation rows with full legal/source provenance and a derived flat mapping for human readability. The observations field is the canonical contract; callers must not persist or transmit only the flat casilla_values view.

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 is observations; this view must not be used for persistence or wire payloads because it omits CasillaObservation provenance.

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() and rebeca_eligible() in order. For each eligible pathway the corresponding domain calculation function is called and its CasillaObservation is appended to the result.

The DA 41 inactive guard runs before any calculation: if the DA 41 selector resolves true (currently when tuna_fleet and pending_eu_clearance are both set on a trabajador del mar profile), MaritimeExemptionInactiveError is raised and no observations are produced.

The RETMAR mandatory-filing gate is checked independently through check_retmar_mandatory_filing(). When retmar_registered is true, ProfileCompletenessError is 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:

MaritimeExemptionResult

Returns:

MaritimeExemptionResult with 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:

bool

Parameters:

facts (MaritimeWorkerFacts)