aeat.application.ledger._ratios module

Operator-facing extensions for the aeat app ledger ratios verb-group.

The existing usage-ratio CRUD verbs (list/set/unset) live in the application-layer ledger actions backed by the domain usage_ratios module. This module adds two read-only verbs that close the discoverability and pre-calculate readiness gaps:

eligible enumerate categories that may carry a user ratio,

annotated with their statutory default ratio

validate inspect the persisted profile against eligibility and

bound rules; report missing categories per modelo

class EligibleCategoryRow(**data)[source]

Bases: BaseModel

One row in the ratios eligible listing.

default_ratio is None for eligible categories whose proportionality rule does not ship a statutory default; the operator must supply an override before the modelo pre-calculate readiness check passes.

Parameters:
category: SpendingCategory
proportionality_kind: str
default_ratio: Decimal | None
override_present: bool
class RatiosValidationFinding(**data)[source]

Bases: BaseModel

One issue raised by ratios validate for an eligible category.

Parameters:
category: SpendingCategory
kind: str
detail: str
class RatiosValidationReport(**data)[source]

Bases: BaseModel

Result of ratios validate. Read-only, emits no bucket event.

Parameters:
bucket_id: BucketId
profile_present: bool
eligible_count: int
overrides_count: int
missing_overrides: tuple[SpendingCategory, ...]
findings: tuple[RatiosValidationFinding, ...]
eligible_ratio_categories(profile)[source]

Return all eligible categories with their default ratio + override flag.

The output is sorted by canonical category value so callers can diff snapshots without ordering noise. Each row is an EligibleCategoryRow.

Return type:

tuple[EligibleCategoryRow, ...]

Parameters:

profile (UsageRatioProfile)

validate_ratios_profile(*, bucket_id, profile, require_overrides_for=())[source]

Inspect a profile against eligibility and any required overrides.

require_overrides_for is the set of categories the caller needs explicitly populated (e.g. a modelo’s pre-calculate readiness check). Categories absent from ELIGIBLE_USAGE_RATIO_CATEGORIES raise a not_eligible finding rather than silently passing.

Returns a RatiosValidationReport.

Return type:

RatiosValidationReport

Parameters:
list_eligible_ratios_for_bucket(*, bucket_id)[source]

Convenience: load the bucket’s profile and project the eligibility report.

Each element is an EligibleCategoryRow describing one spending category’s eligibility and configured ratio.

Return type:

tuple[EligibleCategoryRow, ...]

Parameters:

bucket_id (str)

validate_ratios_for_bucket(*, bucket_id, require_overrides_for=())[source]

Load the bucket’s profile, run validation, and return a RatiosValidationReport.

Return type:

RatiosValidationReport

Parameters:
set_usage_ratio(*, bucket_id, category, ratio)[source]

Set or replace one per-category usage-ratio override on the bucket.

Loads the bucket’s UsageRatioProfile, applies the override through the domain with_ratio validator, and persists the result. Returns the prior override value for the category (None when there was none) so the caller can emit a before/after audit event. Application command boundary for the CLI ledger ratios set verb; the CLI no longer calls the domain load/save primitives directly.

The load-modify-save runs under the per-bucket aeat.domain.usage_ratios.usage_ratio_bucket_lock() so two concurrent writers cannot read the same snapshot and lose one another’s override.

Return type:

Decimal | None

Parameters:
unset_usage_ratio(*, bucket_id, category)[source]

Clear one per-category usage-ratio override on the bucket.

Returns the cleared value. Raises UsageRatioValidationError when the category carries no persisted override (so the caller can surface a precise “nothing to clear” message). Application command boundary for the CLI ledger ratios unset verb.

The load-modify-save runs under the per-bucket aeat.domain.usage_ratios.usage_ratio_bucket_lock() so a concurrent set on a sibling category cannot be lost by this clear.

Return type:

Decimal | None

Parameters:
class RatiosCensoOverrideWarning(**data)[source]

Bases: BaseModel

A non-fatal warning that the operator’s per-category override deviates from the censo-derived value.

The censo is the binding legal source of truth for censo-derived ratios. Operators may still override (e.g. to model a planned afectación change), but the engine emits a typed warning so downstream auditors can review the divergence.

Parameters:
category: SpendingCategory
override_ratio: Decimal
censo_derived_ratio: Decimal
raw_afectacion_ratio: Decimal
censo_business_pct_for(category, raw_afectacion_ratio, *, year=2025)[source]

Return the legally-effective business_pct for a category from censo.

The per-category projection of aeat.domain.usage_ratios.derive_home_office_ratios_from_censo(): given a single SpendingCategory and the operator’s bound censo office_m2 / total_m2, returns the raw_afectacion_ratio * statutory_multiplier value the classify and allocate paths should stamp onto Transaction.business_pct when no operator override is present. Returns None for categories outside the HOME_OFFICE families or when no censo has been applied yet, signalling to the caller that the operator’s explicit value (or the registry default) governs instead.

Return type:

Decimal | None

Parameters:
censo_override_warning(*, category, override_ratio, raw_afectacion_ratio, year=2025)[source]

Return a typed warning when an override deviates from the censo.

The check is silent for non-HOME_OFFICE categories: only the suministros and ownership home-office families are legally bound to the censo-derived afectación ratio (LIRPF Art. 30.2 rule 5, Ley 6/2017 BOE-A-2017-12544). For HOME_OFFICE categories the helper computes the legally-effective ratio (raw afectación times the rule’s statutory_multiplier) and compares it against override_ratio for exact equality. A non-equal pair returns a RatiosCensoOverrideWarning; equal values (and non-home-office categories) return None.

Parameters:
  • category (SpendingCategory) – The category being overridden via ratios set.

  • override_ratio (Decimal) – The operator-supplied override.

  • raw_afectacion_ratio (Decimal) – office_m2 / total_m2 from the bound censo snapshot.

  • year (int) – Registry year whose proportionality rule drives the derivation.

Return type:

RatiosCensoOverrideWarning | None

Returns:

A RatiosCensoOverrideWarning if a warning should be emitted, otherwise None.