Source code for aeat.application.invoices._linking

"""Application service for explicit invoice-to-transaction linking.

:func:`link_invoice_transaction_repositories` loads both the
:class:`InvoiceCatalogue` via :class:`InvoiceCatalogueRepository` and
the :class:`TransactionCatalogue` via :class:`TransactionCatalogueRepository`,
applies the bidirectional link, and persists both updated catalogues.
"""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from ...adapters.persistence.profile.invoices import InvoiceCatalogueRepository
from ...adapters.persistence.profile.transactions import TransactionCatalogueRepository
from ...domain.invoices import (
    Invoice,
    InvoiceCatalogue,
    InvoiceCatalogueRepositoryProtocol,
    InvoiceLinkError,
    link_transaction,
)
from ...domain.transactions import TransactionCatalogue, TransactionCatalogueRepositoryProtocol, link_invoice


[docs] class InvoiceTransactionLinkResult(BaseModel): """Result of a persisted bidirectional invoice link command.""" model_config = ConfigDict(frozen=True, extra="forbid") invoice_id: str transaction_id: str invoice: Invoice invoices: InvoiceCatalogue transactions: TransactionCatalogue
def _canonical_transaction_id(catalogue: TransactionCatalogue, transaction_id: str) -> str: """Return the catalogue key accepted by transaction services.""" if transaction_id in catalogue: return transaction_id normalized = transaction_id.strip().lower() if normalized in catalogue: return normalized raise InvoiceLinkError( "transaction not found in catalogue", translated_message="application.invoices.linking.errors.transaction_not_found", context={"transaction_id": transaction_id}, )