Skip to content

Api

Sibling-facing API for postal letter operations within the monolith.

__all__ module-attribute

__all__ = [
    "create_postal_request",
    "get_last_postal_request_for_user",
    "get_postal_request",
    "get_postal_request_status",
    "list_letters",
    "mark_postal_request_force_requested",
    "record_postal_letter_shipped",
    "retrieve_letter",
    "send_letter",
    "update_postal_request",
]

create_postal_request

create_postal_request(
    *,
    user_id,
    postal_flow,
    recipient_address=None,
    company_id=None,
    provider_letter_id=None,
    provider_name=None,
    forced_requested_at=None,
    requested_at=None,
    shipped_at=None,
    error_code=None,
    error_message=None,
    extra_metadata=None
)

Insert a PostalRequest row (caller owns commit()).

Source code in components/emailing/subcomponents/postal_letter/internal/actions/postal_request_actions.py
def create_postal_request(
    *,
    user_id: str,
    postal_flow: str,
    recipient_address: str | None = None,
    company_id: str | None = None,
    provider_letter_id: str | None = None,
    provider_name: str | None = None,
    forced_requested_at: date | None = None,
    requested_at: date | None = None,
    shipped_at: date | None = None,
    error_code: str | None = None,
    error_message: str | None = None,
    extra_metadata: dict[str, Any] | None = None,
) -> PostalRequest:
    """Insert a ``PostalRequest`` row (caller owns ``commit()``)."""
    row = PostalRequest(
        user_id=user_id,
        postal_flow=postal_flow,
        recipient_address=recipient_address,
        company_id=company_id,
        provider_letter_id=provider_letter_id,
        provider_name=provider_name,
        forced_requested_at=forced_requested_at,
        requested_at=requested_at,
        shipped_at=shipped_at,
        error_code=error_code,
        error_message=error_message,
        extra_metadata=extra_metadata,
    )
    current_session.add(row)
    current_session.flush()
    return row

get_last_postal_request_for_user

get_last_postal_request_for_user(*, user_id, postal_flow)

Return the latest postal request for user_id and postal_flow, if any.

Source code in components/emailing/subcomponents/postal_letter/internal/queries/postal_request_queries.py
def get_last_postal_request_for_user(
    *,
    user_id: str,
    postal_flow: str,
) -> PostalRequestStatus | None:
    """Return the latest postal request for ``user_id`` and ``postal_flow``, if any."""
    row = current_session.scalars(
        select(PostalRequest)
        .where(
            PostalRequest.user_id == user_id,
            PostalRequest.postal_flow == postal_flow,
        )
        .order_by(
            nullslast(desc(PostalRequest.requested_at)),
            desc(PostalRequest.id),
        )
        .limit(1)
    ).first()
    if row is None:
        return None
    return _to_postal_request_status(row)

get_postal_letter_ui_url

get_postal_letter_ui_url(*, postal_request_id)

Return the provider's UI URL for a postal request's letter, or None.

None when the request is unknown, letter id is not know or not supported by provider. This is the postal counterpart of an email's customerio_link.

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def get_postal_letter_ui_url(*, postal_request_id: UUID) -> str | None:
    """Return the provider's UI URL for a postal request's letter, or ``None``.

    ``None`` when the request is unknown, letter id is not know or not supported
    by provider. This is the postal counterpart of an email's ``customerio_link``.
    """
    return _postal_letter_ui_url(
        get_postal_request(postal_request_id=postal_request_id)
    )

get_postal_letter_ui_urls_by_request_id

get_postal_letter_ui_urls_by_request_id(
    *, postal_request_ids
)

Batch counterpart of get_postal_letter_ui_url.

Fetches every request in one query so callers avoid N+1.

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def get_postal_letter_ui_urls_by_request_id(
    *, postal_request_ids: list[UUID]
) -> dict[UUID, str | None]:
    """Batch counterpart of ``get_postal_letter_ui_url``.

    Fetches every request in one query so callers avoid N+1.
    """
    return {
        postal_request.id: _postal_letter_ui_url(postal_request)
        for postal_request in get_postal_requests(postal_request_ids=postal_request_ids)
    }

get_postal_request

get_postal_request(
    *, postal_request_id: UUID
) -> PostalRequest | None
get_postal_request(
    *, provider_name: str, provider_letter_id: str
) -> PostalRequest | None
get_postal_request(
    *,
    postal_request_id=None,
    provider_name=None,
    provider_letter_id=None
)

Return one postal request row, or None if missing.

Exactly one lookup mode, either by: - postal_request_id - OR provider_name + provider_letter_id

Source code in components/emailing/subcomponents/postal_letter/internal/queries/postal_request_queries.py
def get_postal_request(
    *,
    postal_request_id: UUID | None = None,
    provider_name: str | None = None,
    provider_letter_id: str | None = None,
) -> PostalRequest | None:
    """Return one postal request row, or ``None`` if missing.

    Exactly one lookup mode, either by:
    - ``postal_request_id``
    - OR ``provider_name`` + ``provider_letter_id``
    """
    by_id = postal_request_id is not None
    by_provider = provider_name is not None or provider_letter_id is not None

    if by_id and by_provider:
        raise ValueError(
            "Provide either postal_request_id or (provider_name, provider_letter_id), not both"
        )
    if not by_id and not by_provider:
        raise ValueError(
            "Provide either postal_request_id or (provider_name, provider_letter_id)"
        )
    if by_provider and (provider_name is None or provider_letter_id is None):
        raise ValueError("provider_name and provider_letter_id must both be set")

    if postal_request_id is not None:
        return current_session.scalars(
            select(PostalRequest).where(PostalRequest.id == postal_request_id)
        ).one_or_none()

    return current_session.scalars(
        select(PostalRequest).where(
            PostalRequest.provider_name == provider_name,
            PostalRequest.provider_letter_id == provider_letter_id,
        )
    ).one_or_none()

get_postal_request_status

get_postal_request_status(
    *, provider_name, provider_letter_id
)

Return status for one provider letter id, or None if missing.

Source code in components/emailing/subcomponents/postal_letter/internal/queries/postal_request_queries.py
def get_postal_request_status(
    *,
    provider_name: str,
    provider_letter_id: str,
) -> PostalRequestStatus | None:
    """Return status for one provider letter id, or ``None`` if missing."""
    postal_request = get_postal_request(
        provider_name=provider_name,
        provider_letter_id=provider_letter_id,
    )
    if postal_request is None:
        return None
    return _to_postal_request_status(postal_request)

list_letters

list_letters(*, query)

List letters filtered by provider metadata (e.g. user id).

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def list_letters(*, query: ListPostalLettersQuery) -> list[PostalLetterResult]:
    """List letters filtered by provider metadata (e.g. user id)."""
    return list_postal_letters(query)

mark_postal_request_force_requested

mark_postal_request_force_requested(
    *,
    postal_flow,
    provider_name,
    provider_letter_id,
    forced_requested_at=None
)

Set forced_requested_at on the matching emailing.postal_request row.

Returns False when no row exists or postal_flow does not match. Caller owns commit().

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def mark_postal_request_force_requested(
    *,
    postal_flow: str,
    provider_name: str,
    provider_letter_id: str,
    forced_requested_at: date | None = None,
) -> bool:
    """
    Set ``forced_requested_at`` on the matching ``emailing.postal_request`` row.

    Returns ``False`` when no row exists or ``postal_flow`` does not match.
    Caller owns ``commit()``.
    """
    postal_request = get_postal_request(
        provider_name=provider_name,
        provider_letter_id=provider_letter_id,
    )
    if postal_request is None or postal_request.postal_flow != postal_flow:
        return False

    update_postal_request(
        postal_request=postal_request,
        forced_requested_at=forced_requested_at
        if forced_requested_at is not None
        else utctoday(),
    )
    return True

record_postal_letter_shipped

record_postal_letter_shipped(
    *,
    postal_flow,
    provider_name,
    provider_letter_id,
    shipped_at=None
)

Set shipped_at on the emailing.postal_request row for a provider letter id.

Idempotent when shipped_at is already set.

Raises PostalRequestNotFoundForLetterError when no row exists for the provider letter id (caller may retry). Returns False when a row exists but postal_flow does not match (permanent mismatch — log and ack).

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def record_postal_letter_shipped(
    *,
    postal_flow: str,
    provider_name: str,
    provider_letter_id: str,
    shipped_at: date | None = None,
) -> bool:
    """
    Set ``shipped_at`` on the ``emailing.postal_request`` row for a provider letter id.

    Idempotent when ``shipped_at`` is already set.

    Raises ``PostalRequestNotFoundForLetterError`` when no row exists for the provider
    letter id (caller may retry). Returns ``False`` when a row exists but
    ``postal_flow`` does not match (permanent mismatch — log and ack).
    """
    postal_request = get_postal_request(
        provider_name=provider_name,
        provider_letter_id=provider_letter_id,
    )
    if postal_request is None:
        raise PostalRequestNotFoundForLetterError(
            use_case_key=postal_flow,
            letter_id=provider_letter_id,
            provider_name=provider_name,
        )
    if postal_request.postal_flow != postal_flow:
        return False
    if postal_request.shipped_at is not None:
        return True

    update_postal_request(
        postal_request=postal_request,
        shipped_at=shipped_at if shipped_at is not None else utctoday(),
    )
    return True

retrieve_letter

retrieve_letter(*, letter_id, context)

Fetch letter status / payload from the provider.

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def retrieve_letter(*, letter_id: str, context: PostalContext) -> PostalLetterResult:
    """Fetch letter status / payload from the provider."""
    return retrieve_postal_letter(letter_id=letter_id, context=context)

send_letter

send_letter(request)

Send one postal letter using the provider configured for request.context.

Caller owns DB transaction persistence (commit / rollback) for the postal_request row written by this function.

Source code in components/emailing/subcomponents/postal_letter/protected/api.py
def send_letter(request: SendPostalLetterRequest) -> PostalLetterResult:
    """Send one postal letter using the provider configured for ``request.context``.

    Caller owns DB transaction persistence (commit / rollback) for the
    ``postal_request`` row written by this function.
    """
    user_id = _user_id_from_metadata(request.metadata)
    if user_id is None:
        return send_postal_letter(request)

    extra_metadata: dict[str, object] = dict(request.metadata)
    if request.dry_run:
        extra_metadata["dry_run"] = True
    postal_request = create_postal_request(
        user_id=user_id,
        postal_flow=request.context.use_case_key,
        recipient_address=_format_recipient_address(request.postal_address),
        extra_metadata=extra_metadata,
    )
    result = send_postal_letter(request)

    update_postal_request(
        postal_request=postal_request,
        provider_letter_id=result.letter_id,
        provider_name=_provider_name_for_context(request.context),
        requested_at=utctoday(),
        forced_requested_at=utctoday()
        if _is_force_requested(request.metadata)
        else NOT_SET,
    )
    return replace(result, postal_request_id=postal_request.id)

update_postal_request

update_postal_request(
    *,
    postal_request,
    recipient_address=NOT_SET,
    company_id=NOT_SET,
    postal_flow=NOT_SET,
    provider_letter_id=NOT_SET,
    provider_name=NOT_SET,
    forced_requested_at=NOT_SET,
    requested_at=NOT_SET,
    shipped_at=NOT_SET,
    error_code=NOT_SET,
    error_message=NOT_SET,
    extra_metadata=NOT_SET
)

Patch mutable fields on an existing row (caller owns commit()).

Source code in components/emailing/subcomponents/postal_letter/internal/actions/postal_request_actions.py
def update_postal_request(
    *,
    postal_request: PostalRequest,
    recipient_address: NotSet[str | None] = NOT_SET,
    company_id: NotSet[str | None] = NOT_SET,
    postal_flow: NotSet[str] = NOT_SET,
    provider_letter_id: NotSet[str | None] = NOT_SET,
    provider_name: NotSet[str | None] = NOT_SET,
    forced_requested_at: NotSet[date | None] = NOT_SET,
    requested_at: NotSet[date | None] = NOT_SET,
    shipped_at: NotSet[date | None] = NOT_SET,
    error_code: NotSet[str | None] = NOT_SET,
    error_message: NotSet[str | None] = NOT_SET,
    extra_metadata: NotSet[dict[str, Any] | None] = NOT_SET,
) -> PostalRequest:
    """Patch mutable fields on an existing row (caller owns ``commit()``)."""
    field_values: list[tuple[str, Any]] = [
        ("recipient_address", recipient_address),
        ("company_id", company_id),
        ("postal_flow", postal_flow),
        ("provider_letter_id", provider_letter_id),
        ("provider_name", provider_name),
        ("forced_requested_at", forced_requested_at),
        ("requested_at", requested_at),
        ("shipped_at", shipped_at),
        ("error_code", error_code),
        ("error_message", error_message),
        ("extra_metadata", extra_metadata),
    ]
    for name, value in field_values:
        if is_set(value):
            setattr(postal_request, name, value)
    current_session.flush()
    return postal_request