aeat.application.user_profile._censo_sync module¶
Operator-facing Modelo 036 censo-sync service.
CensoSyncService exposes the four-verb surface the CLI mounts
under aeat config profile censo {refresh, show, compare, apply}.
Persisted profile facts are stamped onto a
UserProfileRecord on apply. AEAT
is the binding legal source of truth for censo data; this service is the
only application path that captures censo facts into the secure store
and stamps them onto the operator’s profile.
The service composes:
aeat.application.live._censo.CensoSnapshotServicefor bucket-scoped snapshot persistence,aeat.application.user_profile._repository.UserProfileLifecycleRepositoryfor reading/writing the profile,the existing bucket-event-history catalogue for
CENSO_REFRESHEDandCENSO_APPLIEDevent emission.
The sede G313 live fetch is injected as a fact_source callable so
the same service body backs both the production sede adapter and
real-behavior tests without conditional code paths. This service owns
profile-fact writes and CENSO_REFRESHED / CENSO_APPLIED event
emission. It does not mutate work units, calculation revisions, drafts,
or filing records directly; consumers that need downstream stale-state
handling react to the bucket events outside this module.
- CENSO_SOURCE_TAG: Final¶
UserProfileFact.sourcevalue stamped on every censo-derived fact.
- CENSO_DERIVED_SOURCE_TAG: Final¶
UserProfileFact.sourcefor facts derived from censo plus profile evidence.
- class CensoComparisonStatus(*values)[source]¶
Bases:
StrEnumPer-field comparison outcome between snapshot and profile.
- Variables:
MATCHES – Censo and profile values are identical.
DIVERGES – Both present, values differ.
PROFILE_ONLY – Operator has a value the censo does not publish.
CENSO_ONLY – AEAT publishes a value the operator’s profile does not yet record.
- MATCHES¶
- DIVERGES¶
- PROFILE_ONLY¶
- CENSO_ONLY¶
- class CensoFieldComparison(**data)[source]¶
Bases:
BaseModelOne field-by-field row of a
CensoProfileComparison.- Parameters:
path (str)
censo_value (str | None)
profile_value (str | None)
status (CensoComparisonStatus)
- path: str¶
- censo_value: str | None¶
- profile_value: str | None¶
- status: CensoComparisonStatus¶
- class CensoProfileComparison(**data)[source]¶
Bases:
BaseModelResult of
censo compare: full field-by-field diff payload.- Parameters:
snapshot_id (str)
profile_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=36, pattern=^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$, ascii_only=None)])
captured_at (datetime)
rows (tuple[CensoFieldComparison, ...])
- snapshot_id: str¶
- profile_id: ProfileId¶
- captured_at: datetime¶
- rows: tuple[CensoFieldComparison, ...]¶
- property diverging: tuple[CensoFieldComparison, ...]¶
- property censo_only: tuple[CensoFieldComparison, ...]¶
- property profile_only: tuple[CensoFieldComparison, ...]¶
- class CensoApplyResult(**data)[source]¶
Bases:
BaseModelResult of
censo apply: which facts landed on the profile.- Parameters:
- snapshot_id: str¶
- profile_id: ProfileId¶
- written_paths: tuple[str, ...]¶
- unchanged_paths: tuple[str, ...]¶
- derived_paths: tuple[str, ...]¶
- seeded_home_office_categories: tuple[str, ...]¶
- CensoFactSource¶
Callable returning the AEAT-side censo facts for one refresh.
In production this is wired to the sede G313 adapter; in tests it is a constant callable returning a fixture dictionary. The service stays sede-agnostic so the same body covers both call paths.
- class CensoSyncService(*, bucket_id, snapshots=None, profiles=None, events=None)[source]¶
Bases:
objectFour-verb operator-facing service over censo snapshots.
refreshcaptures a new snapshot from AEAT,showreturns the active or named snapshot,comparediffs the snapshot against the operator’s current profile, andapplywrites the snapshot facts onto the profile under theaeat_censo_readprovenance tag.- Parameters:
bucket_id (str)
snapshots (CensoSnapshotService | None)
profiles (UserProfileLifecycleRepository | None)
events (BucketEventHistoryRepositoryProtocol | None)
- refresh_censo(*, profile_id, source_url, fact_source)[source]¶
Fetch fresh censo facts, capture them as the new ACTIVE snapshot, and return the
CensoSnapshot.Raises
CensoNotAvailableErrorwhenfact_sourcereturns an empty mapping — AEAT publishes no censo for the operator’s NIF, so the caller should re-run after enrolment (or confirm the certificate is registered against the NIF).
- async refresh_censo_from_sede(*, profile_id)[source]¶
Drive the live G313 Playwright fetch and persist the snapshot.
Acquires (or refreshes) an authenticated
AeatSession, navigates to the documented G313 launcher, parses the response into aCensoFactSet, projects it into the dotted snapshot mapping, and captures viarefresh_censo().- Parameters:
profile_id (
str) – The profile id the captured censo snapshot is scoped to.- Return type:
- Returns:
The persisted
CensoSnapshotfor the profile.- Raises:
CensoNotAvailableError – when AEAT publishes no censo for the operator’s NIF (empty CensoFactSet).
- show_censo(*, profile_id, snapshot_id=None)[source]¶
Return one
CensoSnapshot— the latest ACTIVE by default.- Return type:
- Parameters:
- compare_censo_with_profile(*, profile_id, snapshot_id=None)[source]¶
Compare the active (or named) snapshot to the current profile.
Returns a
CensoProfileComparisonwith one row per censo-tracked path, classified into matches / diverges / profile_only / censo_only.- Return type:
- Parameters:
- apply_censo_to_profile(*, profile_id, snapshot_id=None)[source]¶
Stamp the snapshot facts onto the profile, replacing prior
aeat_censo_readfacts.Every raw censo fact lands as a
UserProfileFactwithsource = "aeat_censo_read". Facts defensibly derived from the censo/profile pair land withsource = "aeat_censo_derived". Pre-existing facts from either censo source are replaced; facts from other sources (manual_cli, wizard) are preserved untouched so operator-entered values stay addressable for the compare verb.Emits
CENSO_APPLIEDon the bucket-event-history catalogue itself so downstream maintenance can react without the CLI owning event-enrolment policy.Raises
CensoApplyConflictErrorwhen the profile is absent — there is nothing to stamp facts onto.- Returns:
The apply result details.
- Return type:
- Parameters:
- bound_raw_afectacion_ratio(*, profile_id)[source]¶
Return
office_m2 / total_m2from the active censo snapshot.Used by the ledger ratios CLI and the manual-transaction classify path to apply the legally-effective
aeat.application.ledger._ratios.censo_override_warning()andaeat.application.ledger._ratios.censo_business_pct_for()helpers without each consumer re-implementing the snapshot lookup. ReturnsNonewhen no ACTIVE snapshot exists OR when eithervivienda_office.total_m2/vivienda_office.office_m2is absent / non-decimal / zero.