aeat.core.setup_answers module¶
Canonical typed-answer model and projection slot for the setup flow.
SetupAnswers is the authoritative typed-answers model for the wizard
setup flow. Domain modules import it from here, not from the application
wizard layer, so the permitted dependency direction remains domain-to-core
rather than domain-to-application.
This module owns typed answer validation and the core registration slot for the
reverse projection from persisted canonical-token strings. It does not own
prompt rendering, profile persistence, secure storage, deadline scheduling, or
registry semantics. The application wizard registers its concrete projector at
startup with register_project_answers(); domain consumers call
project_answers() through this core slot and receive
ProjectAnswersNotRegisteredError if startup has not installed it.
The contract mirrors aeat.core.wizard_catalogue: the application layer
declares the SETUP_FLOW descriptor, while core exposes the stable answer
model and the projection hook. Downstream profile construction, including
taxpayer_profile_from_mapping, therefore stays aligned with wizard
canonical-token parsing without importing application modules directly.
Domain taxonomy types (EntityType, IVARegime, etc.) are imported lazily
inside validators rather than at module level to break the circular import
path: aeat.core.setup_answers -> aeat.domain.deadlines._models ->
aeat.domain.deadlines.__init__ -> aeat.domain.deadlines._profiles ->
aeat.core.setup_answers. This mirrors the deferral strategy used in
aeat.core.resources._repos.* and is the established project pattern.
- exception ProfileRegistrationError(message=None, *, context=None, suggestion=None, translated_message=None)[source]¶
Bases:
CoreErrorRaised when
register_project_answers()is called a second time with a different callable.A double-registration with the same callable is a safe no-op; a double-registration with a different callable is a programming error that must be surfaced as a typed, registry-bound exception so callers receive a structured error envelope rather than a bare
RuntimeError.- Parameters:
- Return type:
None
- code: ClassVar[ErrorCode]¶
- exception ProjectAnswersNotRegisteredError[source]¶
Bases:
CoreErrorRaised when domain code calls
project_answers()before registration.- Return type:
None
- code: ClassVar[ErrorCode]¶
- class ProjectAnswersFn(*args, **kwargs)[source]¶
Bases:
ProtocolStructural type for the project_answers callable.
Satisfied by
aeat.application.wizard._persistence.project_answers. Domain code depends only on this protocol.
- register_project_answers(fn)[source]¶
Register the concrete project_answers implementation from the application layer.
Call exactly once at application startup (e.g. in
aeat.application.wizard._persistencemodule body after the function is defined). A second call with an identical callable is a no-op; a second call with a different callable raisesProfileRegistrationError. Domain code should depend onproject_answers(), not on the application-layer implementation object registered here.- Return type:
- Parameters:
fn (ProjectAnswersFn)
- get_project_answers()[source]¶
Return the registered project_answers implementation.
- Return type:
- Returns:
The
ProjectAnswersFnregistered viaregister_project_answers().- Raises:
ProjectAnswersNotRegisteredError – When the application layer has not yet called
register_project_answers().
- project_answers(flow, values)[source]¶
Invoke the registered project_answers implementation.
Delegates to the application-layer function registered via
register_project_answers(). Domain callers import this function fromaeat.core.setup_answersso they never acquire a direct dependency onaeat.application.wizard._persistence.- Parameters:
flow (
Any) – The wizard flow descriptor identifying which flow to project answers for.values (
Mapping[str,str]) – Mapping of canonical token keys to raw string values collected from the wizard or read from profile storage. Blank strings preserve undeclared optional facts for the registered projector to interpret.
- Return type:
BaseModel- Returns:
A typed answers model instance produced by the registered implementation.
- class SetupAnswers(**data)[source]¶
Bases:
BaseModelTyped answers collected by the
setupflow.Canonical home is
aeat.core.setup_answers. The application wizard layer importsSetupAnswersfrom here; the domain deadline engine likewise imports it from here — no layer needs to cross the hexagonal boundary.The model stores canonical answer tokens and typed taxonomy values for the setup flow. It is not the persisted profile record and it is not the deadline-engine taxpayer profile; those are produced downstream by wizard persistence and deadline profile projection. Where validators allow the empty string, the value means undeclared/no answer rather than false, zero, or a default legal fact.
Field annotations use
Anyfor domain taxonomy union types because those types are loaded lazily inside validators to prevent a circular import. ThatAnyis not a loose schema: validators enforce the same invariants the original typed annotations carried, reject values outside the declared enum / blank-string set, and raiseProfileAnswerTypeError.- Parameters:
tax_id (str)
name (str)
surnames (str)
legal_name (str)
activity (str)
address_postcode (str)
activity_start_date (str)
taxation_type (Any)
output_language (OutputLanguage)
entity_type (Any)
legal_entity_form (Any)
incn_prior_12_months (str)
new_entity_first_two_profit_periods (Any)
ley_49_2002_option_declared (Any)
ley_49_2002_option_date (str)
ley_49_2002_renunciation_declared (Any)
ley_49_2002_renunciation_date (str)
irpf_income_categories (str)
taxpayer_sex (Any)
taxpayer_marital_status (Any)
taxpayer_marriage_date (str)
taxpayer_birth_date (str)
taxpayer_disability_grade (Any)
taxpayer_death_date (str)
spouse_tax_id (str)
spouse_name (str)
spouse_surnames (str)
spouse_birth_date (str)
spouse_sex (Any)
spouse_disability_grade (Any)
spouse_non_resident_irpf (bool)
spouse_eu_eea_resident (bool)
spouse_eu_eea_country (str)
family_descendants_eu_eea_deduction (bool)
family_minor_children_in_unit (bool)
situacion_familiar (Any)
unidad_familiar_descendientes_exclusivos (Any)
iva_regime (Any)
iva_roi_enrolled (bool)
iva_oss_enrolled (bool)
iva_group_member_enrolled (bool)
iva_group_dominant_entity_enrolled (bool)
iva_sii_enrolled (bool)
iva_redeme_enrolled (bool)
iva_intracommunity_operations_exceed_50000_eur (bool)
enrollment_large_company (bool)
enrollment_public_administration_budget_gt_6000000 (bool)
has_employees (bool)
pays_professionals_with_retencion (bool)
professional_income_withholding_ge_70pct (bool)
art109_activity_income_withholding_ge_70pct (bool)
pays_rent_with_retencion (bool)
pays_capital_income_with_retencion (bool)
modelo_111_no_retenciones_periods (str)
irpf_estimation_regime (Any)
objective_estimation_modulos_iae_epigraph (str)
objective_estimation_modulos_module_1_units (str)
objective_estimation_modulos_module_2_units (str)
objective_estimation_modulos_module_3_units (str)
objective_estimation_modulos_module_4_units (str)
objective_estimation_modulos_module_5_units (str)
objective_estimation_modulos_module_6_units (str)
objective_estimation_modulos_module_7_units (str)
irpf_special_regime (Any)
irpf_special_regime_start_date (str)
does_intracomunitario (bool)
third_party_transactions_above_347_threshold (bool)
bienes_extranjero_above_threshold (bool)
monedas_virtuales_extranjero_above_threshold (bool)
tax_residence_ccaa (Any)
fiscal_residency (Any)
country_of_fiscal_residence (str)
representante_fiscal_nif (str)
representante_fiscal_nombre (str)
cloud_evidence_upload (bool)
llm_vision (bool)
google_export (bool)
notes (str)
- tax_id: str¶
- name: str¶
- surnames: str¶
- legal_name: str¶
- activity: str¶
Free-text actividad económica / epígrafe IAE description.
- address_postcode: str¶
Optional Spanish postcode for the taxpayer’s activity/contact address.
- activity_start_date: str¶
Optional ISO-8601 censo alta date for the economic activity.
- taxation_type: Any¶
- output_language: OutputLanguage¶
- entity_type: Any¶
- legal_entity_form: Any¶
- incn_prior_12_months: str¶
Optional INCN as a canonical decimal string.
- new_entity_first_two_profit_periods: Any¶
Optional three-state bool for LIS Art. 29 new-entity rate.
- ley_49_2002_option_declared: Any¶
Optional three-state bool for the Ley 49/2002 Title II option.
- ley_49_2002_option_date: str¶
ISO-8601 date declared for the Ley 49/2002 Title II option.
- ley_49_2002_renunciation_declared: Any¶
Optional three-state bool for Ley 49/2002 Title II renunciation.
- ley_49_2002_renunciation_date: str¶
ISO-8601 date declared for the Ley 49/2002 Title II renunciation.
- irpf_income_categories: str¶
Comma-separated set of IrpfIncomeCategory tokens.
- taxpayer_sex: Any¶
- taxpayer_marital_status: Any¶
- taxpayer_marriage_date: str¶
ISO-8601 date when the current marriage began.
- taxpayer_birth_date: str¶
- taxpayer_disability_grade: Any¶
- taxpayer_death_date: str¶
- spouse_tax_id: str¶
- spouse_name: str¶
- spouse_surnames: str¶
- spouse_birth_date: str¶
- spouse_sex: Any¶
- spouse_disability_grade: Any¶
- spouse_non_resident_irpf: bool¶
- spouse_eu_eea_resident: bool¶
- spouse_eu_eea_country: str¶
- family_descendants_eu_eea_deduction: bool¶
- family_minor_children_in_unit: bool¶
- situacion_familiar: Any¶
Art. 82 LIRPF family situation governing conjunta eligibility.
- unidad_familiar_descendientes_exclusivos: Any¶
Custodia compartida progenitor claiming the monoparental unidad familiar.
- iva_regime: Any¶
- iva_roi_enrolled: bool¶
- iva_oss_enrolled: bool¶
- iva_group_member_enrolled: bool¶
- iva_group_dominant_entity_enrolled: bool¶
- iva_sii_enrolled: bool¶
- iva_redeme_enrolled: bool¶
- iva_intracommunity_operations_exceed_50000_eur: bool¶
- enrollment_large_company: bool¶
- enrollment_public_administration_budget_gt_6000000: bool¶
- has_employees: bool¶
- pays_professionals_with_retencion: bool¶
- professional_income_withholding_ge_70pct: bool¶
- art109_activity_income_withholding_ge_70pct: bool¶
- pays_rent_with_retencion: bool¶
- pays_capital_income_with_retencion: bool¶
- modelo_111_no_retenciones_periods: str¶
- irpf_estimation_regime: Any¶
- objective_estimation_modulos_iae_epigraph: str¶
- objective_estimation_modulos_module_1_units: str¶
- objective_estimation_modulos_module_2_units: str¶
- objective_estimation_modulos_module_3_units: str¶
- objective_estimation_modulos_module_4_units: str¶
- objective_estimation_modulos_module_5_units: str¶
- objective_estimation_modulos_module_6_units: str¶
- objective_estimation_modulos_module_7_units: str¶
- irpf_special_regime: Any¶
IRPF special-regime axis. Blank for the general regime.
- irpf_special_regime_start_date: str¶
ISO-8601 opt-in election date for the special regime.
- does_intracomunitario: bool¶
- third_party_transactions_above_347_threshold: bool¶
- bienes_extranjero_above_threshold: bool¶
- monedas_virtuales_extranjero_above_threshold: bool¶
- tax_residence_ccaa: Any¶
- fiscal_residency: Any¶
Fiscal residency category.
- country_of_fiscal_residence: str¶
ISO 3166-1 alpha-2 code of the country of fiscal residence.
- representante_fiscal_nif: str¶
NIF/NIE of the fiscal representative in Spain.
- representante_fiscal_nombre: str¶
Full name of the fiscal representative in Spain.
- cloud_evidence_upload: bool¶
- llm_vision: bool¶
- google_export: bool¶
- notes: str¶