cadrumo.domain.renta.maritime_exemption module

Maritime worker IRPF exemption calculation engine.

Implements the legally distinct exemption pathways for trabajadores del mar and the associated profile completeness gate. Each calculation returns a CasillaObservation whose amount parameter and provenance come from the governed facts of the selected authority.

Active pathways:

Art. 7.p) LIRPF (Ley 35/2006, BOE-A-2006-20764)

Foreign-flagged vessel or international waters. The annual cap is the lirpf-art-7p-exemption-cap governed fact. Formula: min(annual_salary / 365 * qualifying_days, cap)

REBECA exemption (Ley 19/1994, Arts. 73.2 73.3 75.1 75.3, BOE-A-1994-15794)

Crew of REBECA-registered vessels or scheduled Canary Islands routes. The exempt fraction is the rebeca-maritime-exemption-fraction governed fact.

Inactive pathway:

DA 41 LIRPF (Ley 35/2006 DA 41, added by Ley 26/2014 BOE-A-2014-12327)

Tuna fleet crew. Requires EU state-aid clearance that has not been granted, so the engine refuses instead of silently applying it.

Profile completeness gate (not a calculation pathway):

RETM mandatory filing (Ley 35/2006 Art. 96, BOE-A-2006-20764)

RETMAR-registered workers must file IRPF regardless of income level.

The pathway selectors mirror the trabajador_del_mar exemption binding category in the registry.

exception MaritimeExemptionInactiveError(message=None, *, context=None, translated_message=None)[source]

Bases: RentaError

Raised when the DA 41 tuna-fleet selector resolves for a trabajador del mar.

DA 41 LIRPF requires prior EU state-aid clearance that has not been granted, so the engine refuses rather than producing exempt income.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ProfileCompletenessError(message=None, *, context=None, translated_message=None)[source]

Bases: RentaError

Raised when a RETMAR-registered worker’s profile is presented for filing.

This is a profile-completeness gate only. It does not alter output values or formula execution paths.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
class MaritimeWorkerFacts(worker_class=None, vessel_flag=None, waters_type=None, vessel_registry=None, tuna_fleet=False, pending_eu_clearance=False, retmar_registered=False)[source]

Bases: object

Resolved profile facts that gate maritime exemption pathway selection.

All fields default to the non-triggering value so callers can construct partial profiles. A profile whose worker_class is not "trabajador_del_mar" is unaffected by every selector here.

Parameters:
  • worker_class (str | None)

  • vessel_flag (str | None)

  • waters_type (str | None)

  • vessel_registry (str | None)

  • tuna_fleet (bool)

  • pending_eu_clearance (bool)

  • retmar_registered (bool)

worker_class: str | None
vessel_flag: str | None
waters_type: str | None
vessel_registry: str | None
tuna_fleet: bool
pending_eu_clearance: bool
retmar_registered: bool
art_7p_eligible(facts)[source]

Return whether Art. 7.p) LIRPF applies to the worker profile.

A trabajador del mar on a foreign-flagged vessel or in international waters (Ley 35/2006 Art. 7.p), BOE-A-2006-20764).

Return type:

bool

Parameters:

facts (MaritimeWorkerFacts)

rebeca_eligible(facts)[source]

Return whether the REBECA exemption applies to the worker profile.

A trabajador del mar on a REBECA vessel, a REBECA company vessel in another EU/EEA register, or a scheduled Canary Islands route (Ley 19/1994 Arts. 73.2 73.3 75.1 75.3, BOE-A-1994-15794).

Return type:

bool

Parameters:

facts (MaritimeWorkerFacts)

da41_eligible(facts)[source]

Return whether the inactive DA 41 tuna-fleet selector resolves.

Kept separate from guard_da41_inactive() so the selector is testable on its own (Ley 35/2006 DA 41 BOE-A-2006-20764).

Return type:

bool

Parameters:

facts (MaritimeWorkerFacts)

calculate_art_7p_exemption(*, annual_salary, qualifying_days, facts, authority=None, filing_period=None)[source]

Calculate the Art. 7.p) exempt amount.

Formula (Ley 35/2006 Art. 7.p) BOE-A-2006-20764):

exempt_amount = min(annual_salary / 365 * qualifying_days, cap)

Parameters:
  • annual_salary (Decimal) – Gross annual employment salary in EUR (Decimal).

  • qualifying_days (int) – Calendar days of work abroad in the tax year, within the ordinary calendar-day input range.

  • facts (MaritimeWorkerFacts) – Resolved profile facts; art_7p_eligible() must hold.

  • authority (GovernedFactSource | None) – Governed-fact authority. Defaults to the scoped authority, else the published one.

  • filing_period (date | None) – Filing-period coordinate for the cap; defaults to today.

Return type:

CasillaObservation

Returns:

CasillaObservation carrying the exempt amount and provenance.

Raises:

RentaValidationError – When eligibility predicate is not satisfied or when input values are out of range.

calculate_rebeca_exemption(*, gross_navigation_income, facts, authority=None, devengo_date=None)[source]

Calculate the REBECA exempt amount.

Formula (Ley 19/1994 Arts. 73-75 BOE-A-1994-15794):

exempt_amount = gross_navigation_income * fraction

Parameters:
  • gross_navigation_income (Decimal) – Total gross employment income from navigation in EUR (Decimal). Must be positive.

  • facts (MaritimeWorkerFacts) – Resolved profile facts; rebeca_eligible() must hold.

  • authority (GovernedFactSource | None) – Governed-fact authority. Defaults to the scoped authority, else the published one.

  • devengo_date (date | None) – Devengo-date coordinate for the fraction; defaults to today.

Return type:

CasillaObservation

Returns:

CasillaObservation carrying the exempt amount and provenance.

Raises:

RentaValidationError – When eligibility predicate is not satisfied or when input values are out of range.

guard_da41_inactive(facts)[source]

Refuse a DA 41 profile, whose exemption lacks EU state-aid clearance.

Call before any path that could produce DA 41 exempt income; applying it silently would be legally incorrect output.

Parameters:

facts (MaritimeWorkerFacts) – Resolved MaritimeWorkerFacts.

Raises:

MaritimeExemptionInactiveError – When da41_eligible() holds.

Return type:

None

check_retmar_mandatory_filing(facts)[source]

Raise ProfileCompletenessError for a RETMAR-registered worker.

RETMAR-registered workers must file IRPF regardless of income level (Ley 35/2006 Art. 96, BOE-A-2006-20764). This is a completeness gate only; it must not suppress further processing or alter output values.

Callers should catch ProfileCompletenessError, surface the message to the operator, and continue processing.

Parameters:

facts (MaritimeWorkerFacts) – Resolved MaritimeWorkerFacts.

Raises:

ProfileCompletenessError – When retmar_registered is True.

Return type:

None