cadrumo.domain.contribuyente.family_profile module¶
Family-level Modelo 100 aggregation and proration behaviors.
- class RentaFamilyProfile(**data)[source]¶
Bases:
BaseModelTyped repeated family-member facts consumed by Modelo 100 bindings.
- Parameters:
data (Any)
- schema_version: ProfileSchemaVersion¶
- descendants: tuple[RentaDescendantProfile, ...]¶
- ascendants: tuple[RentaAscendantProfile, ...]¶
- descendientes: tuple[DescendantInfo, ...]¶
- anualidades_alimentos_euros: Decimal | None¶
Judicial anualidades por alimentos the filer PAYS, or
Noneif undeclared.Filer-level rather than per-descendant, and that is the staged boundary rather than the intended end state. Art. 58 carves the dependency assimilation out where anualidades are satisfied, and the carve-out is per-child in the law; this profile cannot attribute a payment to one descendant, so a declared amount suppresses the assimilation for EVERY descendant until that attribution lands.
Suppressing them all is the under-granting direction, which is the safe one to default to, but it is a real narrowing: a filer paying anualidades for one child and supporting another outside any court order loses the second child’s assimilation too. The calculate path discloses that rather than leaving it silent.
A declared
0is an answer meaning none are paid and does NOT suppress; only a positive amount does.Nonemeans the question was never put.
- cotizaciones_ss_madre_2024: int¶
SS cotizaciones paid by the mother during 2024 (mirrors casilla 0013).
The statutory ceiling on the Art. 81.2 guardería incremento, applied to the household total after the per-child proration (
RentaFamilyProfile.incremento_guarderia_0613()computes each child’s ownmin(cap_anual / 12 × meses, su gasto)and sums them; this figure caps that sum). The annual cap is a registrymoneyparameter resolved by the caller, never a literal here (aeat-registry-authority-flow).Default
0(cap not declared; guardería incremento will be zero).
- property dependencia_assimilation_available: bool¶
Whether the dependency assimilation may apply to ANY descendant this year.
False as soon as the filer declares a positive anualidades figure. Art. 58 carves the assimilation out where anualidades are satisfied, and because this profile cannot yet attribute a payment to a particular descendant the carve-out is applied to all of them.
The narrowing is deliberate and one-directional: it withholds an allowance some filers are owed rather than granting one they are not. Reversing it needs per-child attribution, not a looser reading here.
- descendientes_menores_3_year_end(filing_year, *, context)[source]¶
Count of eligible descendientes whose age at year-end < 3 (Art. 58.2).
- Return type:
- Parameters:
filing_year (int)
context (FamilyFactResolutionContext)
- descendientes_guarderia_count(filing_year, *, context)[source]¶
Count of descendants who may carry an Art. 81.2 guardería increase.
Wider than the Art. 58.2 menor-de-tres count by exactly the turning-three period. Kept separate rather than widening that count, which has its own registry binding and its own statutory meaning for the supplement.
- Return type:
- Parameters:
filing_year (int)
context (FamilyFactResolutionContext)
- gastos_guarderia_reales(filing_year, *, context)[source]¶
Sum of the Art. 81.2 guardería spend every descendant contributes in filing_year.
Sums
DescendantInfo.guarderia_contributing_spend(), which applies the Art. 81.2 month rules per child: every declared month while the child is under three, and only the post-birthday months in the period the child turns three. The turning-three period is INCLUDED here and was not before, which is the campaign’s largest measured under-grant — a full birth cohort rather than a minority case, reducing cuota directly.Year-parameterised rather than pinned to 2024 because the calculate path derives
renta_family.gastos_guarderia_reales_{filing_year}for whatever year the registry declares a consumer for. A 2024-only accessor would have forced that path to keep its own parallel sum, which is how the monthly map could be declared and contribute nothing.- Return type:
- Parameters:
filing_year (int)
context (FamilyFactResolutionContext)
- incremento_guarderia_0613(filing_year, *, thresholds, cap_anual, context)[source]¶
Art. 81.2 guardería increment (casilla 0613), prorated and capped PER CHILD.
The manual states the increment “puede alcanzar hasta 1.000 euros anuales y se calculará proporcionalmente al número de meses en que se cumplan de forma simultánea los requisitos exigidos en el artículo 81.1 y 2”, and works it as
1.000 / 12 x meses. It then states the result as that child’s own limit — “Límite del incremento: 166,67 euros” — so the cap is per child rather than a household total.Each child contributes
min(cap_anual / 12 x meses, su gasto)and the contributions are SUMMED. The per-child bound is the load-bearing part: an aggregateminover the household lets one child’s unused cap absorb another child’s excess spend, and it is also what let the missing proration hide, because filtering one term of a household-wideminreads as completing the month rules.meses is the SIMULTANEITY intersection the manual describes, taken as the smaller of the two sides. The Art. 81.1 side is
DescendantInfo.guarderia_art_81_1_meses()rather than the deducción’s ownDescendantInfo.maternidad_contributing_meses(), and the distinction is load-bearing: the deducción stops at the child’s third birthday while the increment does not, so reusing it forced this total to zero for a child turning three in January and for a mother who began work after the birthday — two cases Capítulo 18 names explicitly as still qualifying.BOTH sides are real month sets, so meses is a true intersection rather than a bound. That is what the article asks for — “el número de meses en que se cumplan de forma simultánea los requisitos” is a question about WHICH months, and only months can answer it.
The manual’s caso a is the case that forced it: a mother entitled May to August against nursery paid January to June shares exactly two months, and AEAT prints
1.000 ÷ 12 × 2 = 166,67. Takingminover the two COUNTS yields four and 333,33 — an over-grant of the deducción, which under-declares tax. Counts cannot distinguish that case from a containment or a disjoint one, because the sizes are the same in all three; the geometry only survives if the months do.Preferred to a flat per-child cap, which over-grants every mid-year birth and every partial-year enrolment outright.
cap_anual is a registry
moneyparameter the caller resolves per filing year; this method performs no euro-figure lookup of its own (aeat-registry-authority-flow).Returns
Decimal("0")when no descendant qualifies, which is the legally correct zero rather than an under-declaration.- Return type:
- Parameters:
filing_year (int)
thresholds (MinimoDescendientesThresholds)
cap_anual (Decimal)
context (FamilyFactResolutionContext)
- meses_maternidad_por_descendiente(filing_year, *, thresholds, context)[source]¶
The Art. 81.1
(hijo_id, meses)pairs this profile contributes in filing_year.Pairs
DescendantInfo.maternidad_contributing_meses()with the descendant’s index, which is the identifier every other descendiente surface addresses a child by — thelistrenderer, theremoveverb, and the fact paths themselves. The deducción’s own per-hijo cap then applies over these pairs rather than over a collapsed total, so a second child can never absorb a first child’s unused months.Aggregates through the canonical record rather than summing the stored facts directly. The guardería path was broken for exactly one release by a second loop that read the raw fact under its own inline age test: the two diverged the moment the record learned a month rule, and a taxpayer could declare spend, see it stored, and receive nothing. One aggregation path per value is the lesson, and this is that path for Art. 81.1.
Reads
dependencia_assimilation_availableoff this profile rather than taking it as an argument, exactly asdescendientes_eligible_minimum()does, so the anualidades carve-out cannot be applied to the mínimo and skipped for the deducción that keys on it.Omits descendants contributing zero months, so an ineligible child and one whose mother declared no employment months are both simply absent rather than carrying a zero pair into the deducción.
- Return type:
- Parameters:
filing_year (int)
thresholds (MinimoDescendientesThresholds)
context (FamilyFactResolutionContext)
- descendientes_eligible_minimum(filing_year, *, thresholds, context)[source]¶
Count of descendientes eligible for the ordinary Art. 58.1 mínimo.
A descendant is eligible when cohabiting, under 25 at year-end or carrying any discapacidad, within the Art. 58.1 rentas ceiling, and not excluded by Art. 61 norma 2ª — see
DescendantInfo.is_eligible_ordinary().- Return type:
- Parameters:
filing_year (int)
thresholds (MinimoDescendientesThresholds)
context (FamilyFactResolutionContext)
- minimo_prorrata_factor(descendant, filing_year, *, thresholds, context, second_filer_indicated=False)[source]¶
Return the Art. 61 norma 1ª prorrata factor for one descendant.
Norma 1ª keys proration to ENTITLEMENT, not to custody: “Cuando dos o más contribuyentes tengan derecho a la aplicación del mínimo por descendientes … respecto de los mismos … descendientes, su importe se prorrateará entre ellos por partes iguales.” Shared custody is one way two contribuyentes come to be entitled, not the rule itself, so it remains a trigger rather than the test.
Precedence, highest first:
descendant.prorrata_minimo— an explicit operator answer always wins, in both directions.descendant.custodia_compartida— the judicially shared-custody case, preserved as a trigger.second_filer_indicated — the caller’s derivation from profile signals, used only when nothing above answered the question.
Returns the
lirpf-art-61-shared-custody-proration-factorgoverned fact (0.5today) when the descendant is mínimo-eligible and any of the above indicates a second entitled contribuyente, otherwiseDecimal("1"). A non-eligible descendant always returnsDecimal("1")because there is no mínimo to prorate.- Return type:
- Parameters:
descendant (DescendantInfo)
filing_year (int)
thresholds (MinimoDescendientesThresholds)
context (FamilyFactResolutionContext)
second_filer_indicated (bool)
- minimo_descendientes_estatal(filing_year, *, birth_order_amounts, menor_tres_supplement, fallecimiento_amount, thresholds, context, second_filer_indicated=False)[source]¶
Compute the Art. 58 mínimo por descendientes aggregate (casillas 0513/0514).
Ranks every Art. 58.1-eligible descendant (age < 25 at year-end, or any discapacidad grade, and cohabiting) by
birth_dateascending — the eldest eligible descendant is “el primero”, matching the AEAT Renta manual’s birth-order reading of Art. 58.1’s “primero/segundo/tercero/ cuarto y siguientes” tranches. Each eligible descendant contributes:the birth-order tranche amount from birth_order_amounts (index 0 for the 1st, index 1 for the 2nd, … the last entry repeats for the 4th and every subsequent descendant, per Art. 58.1’s “cuarto y siguientes” wording);
plus menor_tres_supplement when the descendant is also Art. 58.2-eligible (age < 3 at year-end);
the sum is then multiplied by the descendant’s Art. 61 norma 1ª prorrata factor (
minimo_prorrata_factor()), which is 0.5 whenever a second contribuyente is also entitled to this descendant’s mínimo — by explicit answer, by shared custody, or by the caller’s second_filer_indicated derivation.
No within-year temporal prorrateo is applied: Art. 58 (in force since 01/01/2015, BOE-A-2014-12327) declares only the two numbered subsections above and no birth/adoption-date cutoff for descendientes.
Art. 61 norma 4ª governs this aggregate rather than sitting outside it, and BOTH its limbs are applied here. The rule is easy to half-implement because its flat figure coincides with the first-child tranche, so a partial fix looks complete while leaving most of the over-grant standing.
LIMB ONE, the flat cuantía. A descendant who dies in the period takes a FLAT amount rather than their birth-order tranche — “en caso de fallecimiento de un descendiente que genere derecho al mínimo por este concepto, la cuantía aplicable es de 2.400 euros”. That figure equals the first-child tranche in every revision served today, so the substitution is worth nothing for a first child and 300 € to 2.100 € for a later one. It is supplied as fallecimiento_amount, its own registry parameter, and is deliberately not read off
birth_order_amounts[0]: the two are legally distinct figures that merely coincide.LIMB TWO, the ordering exclusion, is the one that is invisible on inspection. The deceased is dropped from the age ordering that ranks the survivors — “sin computar a estos efectos aquellos descendientes que … hubieran fallecido en el ejercicio con anterioridad a la fecha de devengo del impuesto”. Because the tranches ascend with rank, dropping the deceased moves every younger sibling to a CHEAPER rank, so omitting this limb over-grants the survivors as well as the deceased. A fix carrying only limb one would pass any test that checks the deceased’s own amount.
The two limbs read
death_datethrough different predicates and the difference is deliberate:died_in_period()for the cuantía,died_before_devengo()for the ordering. See thedeath_datefield documentation for why they are not one condition.The Art. 58.2 menor-3 supplement is added on top of the flat cuantía, not replaced by it: the AEAT manual states the increase “resulta aplicable en los casos en que el descendiente haya fallecido durante el período impositivo”. Replacing it would under-grant a bereaved filer.
A descendant who died in a PRIOR year contributes nothing at all — they fail
meets_non_income_conditions()and never reach the ranking.birth_order_amounts, menor_tres_supplement, fallecimiento_amount and thresholds are registry
moneyparameters the caller resolves per filing year; this domain method performs no euro-figure lookup of its own (aeat-registry-authority-flow).Returns
Decimal("0")when no descendant is Art. 58.1-eligible (including an emptydescendientestuple) — the legally correct zero for a childless filer, not an under-declaration. A descendant excluded by the rentas ceiling or the norma 2ª own-return rule contributes exactly zero, including its menor-3 supplement, because it never enters the birth-order ranking at all.- Return type:
- Parameters:
filing_year (int)
menor_tres_supplement (Decimal)
fallecimiento_amount (Decimal)
thresholds (MinimoDescendientesThresholds)
context (FamilyFactResolutionContext)
second_filer_indicated (bool)
- madrid_nacimiento_adopcion_eligible_count(filing_year, *, context)[source]¶
Count of descendants inside the Madrid nacimiento/adopción window who cohabit.
The raw (unweighted) eligible count;
madrid_nacimiento_adopcion_weighted_countapplies the per-descendant prorrateo the registry cuantía is multiplied by.- Return type:
- Parameters:
filing_year (int)
context (FamilyFactResolutionContext)
- unidad_familiar_otros_miembros_base()[source]¶
Base imponible of unidad-familiar members OTHER than the filer.
Framework primitive for the autonomic double income-limit gate (the unidad-familiar 61.860 € límite). For a monoparental/single filer the other members are the filer’s cohabiting children, whose own base imponible the profile does not hold and is treated as zero; the filer’s own base (casillas 0435 + 0460) is added by the registry formula. A conyugal unit’s spouse base is not persisted, so the derived-fact injector supplies this term only for the determinable single-filer case and the trigger stays advisory-only otherwise (fail-closed, no over-claim).
- Return type: