Source code for imednet_workflows.register_subjects

"""Workflow for registering subjects (patients) in iMednet via the Records API.

This workflow is self-contained and does not borrow from record_update.py.
It provides a simple, robust interface for registering one or more subjects.
"""

from typing import TYPE_CHECKING, cast

from imednet.spi.models import Job, RegisterSubjectRequest

# Use TYPE_CHECKING to avoid circular import at runtime
if TYPE_CHECKING:
    from imednet.spi.facade import ImednetFacade


[docs]class RegisterSubjectsWorkflow: """Manages the registration of subjects using the iMedNet SDK. Attributes: _sdk (ImednetSDK): An instance of the ImednetSDK. """
[docs] def __init__(self, sdk: "ImednetFacade"): # Use string literal for type hint """Initialize the RegisterSubjectsWorkflow. Args: sdk: An instance of the iMednet SDK facade. """ self._sdk = sdk
[docs] def register_subjects( self, study_key: str, subjects: list[RegisterSubjectRequest], email_notify: str | None = None, wait_for_completion: bool = False, timeout: int = 300, poll_interval: int = 5, ) -> Job: """Registers multiple subjects in the specified study. Sites and subject identifiers are validated before submission. Args: study_key: The key identifying the study. subjects: A list of RegisterSubjectRequest objects, each defining a subject to be registered. email_notify: Optional email address to notify upon completion. wait_for_completion: If True, wait for the job to complete. timeout: Timeout in seconds for waiting. poll_interval: Polling interval in seconds. Returns: A :class:`Job` object representing the background job created for the registration request. Raises: ApiError: If the API call fails. """ # Validate that each site exists before posting sites = {s.site_name for s in self._sdk.get_sites(study_key=study_key)} errors: list[str] = [] for idx, subj in enumerate(subjects): if not subj.site_name: errors.append(f"Index {idx}: siteName is required") elif subj.site_name not in sites: errors.append(f"Index {idx}: site '{subj.site_name}' not found") if errors: raise ValueError("; ".join(errors)) subjects_data = [s.model_dump(by_alias=True) for s in subjects] job = self._sdk.create_record( study_key=study_key, records_data=subjects_data, email_notify=email_notify ) if not wait_for_completion: return job if not job.batch_id: return job from imednet.spi.facade import ImednetFacade return cast( Job, (cast(ImednetFacade, self._sdk)).poll_job( # type: ignore[redundant-cast] study_key, job.batch_id, timeout=timeout, interval=poll_interval ), )