Skip to content

Api reference

components.health_programs.public.business_logic

actions

health_program_override

update_health_program_override_for_user
update_health_program_override_for_user(
    user,
    program_slug,
    overridden_segment_slug,
    custom_program_id,
    dedicated_time,
    commit=True,
)

Update or create the health program override for a user given some parameters.

Source code in components/health_programs/public/business_logic/actions/health_program_override.py
def update_health_program_override_for_user(
    user: FeatureUser,
    program_slug: str,
    overridden_segment_slug: Optional[str],
    custom_program_id: Optional[str],
    dedicated_time: Optional[str],
    commit: bool = True,
) -> None:
    """Update or create the health program override for a user given some parameters."""
    if overridden_segment_slug is not None and custom_program_id is not None:
        raise ValueError("You can't set both segment_slug and custom_program_id")

    program_override = (
        current_session.query(HealthProgramOverride)  # noqa: ALN085
        .filter(
            HealthProgramOverride.app_id == user.app_id,
            HealthProgramOverride.app_user_id == user.app_user_id,
            HealthProgramOverride.program_slug == program_slug,
        )
        .one_or_none()
    )

    if program_override is None:
        program_override = HealthProgramOverride(
            app_id=user.app_id,
            app_user_id=user.app_user_id,
            program_slug=program_slug,
        )
        current_session.add(program_override)

    update_health_program_override(
        program_override,
        overridden_segment_slug,
        custom_program_id,
        dedicated_time,
        commit,
    )

health_program_progress

mark_health_program_as_ready
mark_health_program_as_ready(
    user,
    program_slug,
    coach_name,
    coach_picture_url,
    has_booked_appointment,
    commit=True,
)
Source code in components/health_programs/public/business_logic/actions/health_program_progress.py
def mark_health_program_as_ready(  # noqa: D103
    user: FeatureUser,
    program_slug: str,
    coach_name: Optional[str],
    coach_picture_url: Optional[str],
    has_booked_appointment: bool,
    commit: bool = True,
) -> None:
    tracking_client.track(
        user.app_user_id,
        "health_program_ready",
        {
            "programSlug": program_slug,
            "coachName": coach_name,
            "coachPictureUrl": coach_picture_url,
            "hasBookedAppointment": has_booked_appointment,
        },
    )

    update_health_program_status(
        user=user,
        program_slug=program_slug,
        from_statuses=[
            HealthProgramStatus.program_in_preparation,
        ],
        to_status=HealthProgramStatus.program_ready,
        commit=commit,
    )

queries

health_program_override

get_all_health_program_overrides
get_all_health_program_overrides(user)
Source code in components/health_programs/public/business_logic/queries/health_program_override.py
def get_all_health_program_overrides(  # noqa: D103
    user: FeatureUser,
) -> list[HealthProgramOverrideData]:
    all_program_overrides = (
        current_session.query(HealthProgramOverride)  # noqa: ALN085
        .filter(
            HealthProgramOverride.app_id == user.app_id,
            HealthProgramOverride.app_user_id == user.app_user_id,
        )
        .all()
    )

    return [
        HealthProgramOverrideData.from_health_program_override_model(override)
        for override in all_program_overrides
    ]
get_health_program_override
get_health_program_override(user, program_slug)
Source code in components/health_programs/public/business_logic/queries/health_program_override.py
def get_health_program_override(  # noqa: D103
    user: FeatureUser, program_slug: str
) -> Optional[HealthProgramOverride]:
    return (
        current_session.query(HealthProgramOverride)  # noqa: ALN085
        .filter(
            HealthProgramOverride.app_id == user.app_id,
            HealthProgramOverride.app_user_id == user.app_user_id,
            HealthProgramOverride.program_slug == program_slug,
        )
        .one_or_none()
    )

health_program_progress

get_all_user_health_program_data
get_all_user_health_program_data(member_feature_user)

Get all health program progresses for a user.

Source code in components/health_programs/public/business_logic/queries/health_program_progress.py
def get_all_user_health_program_data(
    member_feature_user: FeatureUser,
) -> list[HealthProgramCompleteData]:
    """
    Get all health program progresses for a user.
    """
    # legacy code, we should use the queries that separates progress and override
    query = current_session.query(  # noqa: ALN085
        HealthProgramProgress, HealthProgramOverride
    ).outerjoin(
        HealthProgramOverride,
        (HealthProgramProgress.program_slug == HealthProgramOverride.program_slug)
        & (HealthProgramProgress.feature_user == HealthProgramOverride.feature_user),
    )

    results = query.filter(
        HealthProgramProgress.feature_user == member_feature_user,
    ).all()  # This will be a list of tuples (HealthProgramProgress, HealthProgramOverride or None)

    return [
        HealthProgramCompleteData.from_health_program_models(progress, override)
        for progress, override in results
    ]
get_all_user_health_program_progresses
get_all_user_health_program_progresses(member_feature_user)

Get all health program progresses for a user.

Source code in components/health_programs/public/business_logic/queries/health_program_progress.py
def get_all_user_health_program_progresses(
    member_feature_user: FeatureUser,
) -> list[HealthProgramProgressData]:
    """
    Get all health program progresses for a user.
    """
    all_program_progresses = (
        current_session.query(HealthProgramProgress)  # noqa: ALN085
        .filter(
            HealthProgramProgress.feature_user == member_feature_user,
        )
        .all()
    )
    return [
        HealthProgramProgressData.from_health_program_progress_model(program_progress)
        for program_progress in all_program_progresses
    ]
get_health_program_progress
get_health_program_progress(
    member_feature_user, program_slug
)

Get the health program progress for a user and a program.

Source code in components/health_programs/public/business_logic/queries/health_program_progress.py
def get_health_program_progress(
    member_feature_user: FeatureUser, program_slug: str
) -> HealthProgramProgressData | None:
    """
    Get the health program progress for a user and a program.
    """
    program_progress: HealthProgramProgress | None = (
        current_session.query(HealthProgramProgress)  # noqa: ALN085
        .filter(
            HealthProgramProgress.feature_user == member_feature_user,
            HealthProgramProgress.program_slug == program_slug,
        )
        .one_or_none()
    )

    if program_progress is None:
        return None

    return HealthProgramProgressData.from_health_program_progress_model(
        program_progress
    )

components.health_programs.public.controllers

health_program

HealthProgramController

Bases: BaseController

get_health_programs_override

get_health_programs_override(user)
Source code in components/health_programs/public/controllers/health_program.py
@HealthProgramController.action_route(
    "/override",
    methods=["GET"],
    auth_strategy=GlobalAuthorizationStrategies().authenticated(),
)
@inject_feature_user
@obs.api_call()
def get_health_programs_override(user: FeatureUser) -> Response:  # noqa: D103
    from components.health_programs.public.business_logic.queries.health_program_override import (
        get_all_health_program_overrides,
    )

    return make_json_response(get_all_health_program_overrides(user=user))

get_health_programs_progress_for_sync

get_health_programs_progress_for_sync(user)
Source code in components/health_programs/public/controllers/health_program.py
@HealthProgramController.action_route(
    "/sync",
    methods=["GET"],
    auth_strategy=GlobalAuthorizationStrategies().authenticated(),
)
@inject_feature_user
@obs.api_call()
def get_health_programs_progress_for_sync(user: FeatureUser) -> Response:  # noqa: D103
    from components.health_programs.public.business_logic.queries.health_program_progress import (
        get_all_user_health_program_progresses,
    )

    return make_json_response(
        get_all_user_health_program_progresses(member_feature_user=user)
    )

health_program_endpoint module-attribute

health_program_endpoint = Endpoint('health_programs')

post_health_program_progress

post_health_program_progress(user, params)
Source code in components/health_programs/public/controllers/health_program.py
@HealthProgramController.action_route(
    "/progress",
    methods=["POST"],
    auth_strategy=GlobalAuthorizationStrategies().authenticated(),
)
@inject_feature_user
@request_argument(
    "program_slug",
    type=str,
    help="Program's slug (ex: back-pain)",
    required=True,
)
@request_argument(
    "program_name",
    type=str,
    help="Program's name (ex: Dorsalgie) - is null if the program is not started yet",
    required=False,
)
@request_argument(
    "program_id",
    type=str,
    help="Program's id (deprecated)",  # No longer used since mobile v1.355.0
    required=False,
    owner_controller=NoOwner,
)
@request_argument(
    "program_status",
    type=str,
    help="Program's status",
    required=True,
)
@request_argument(
    "program_available_at",
    type=str,
    help="Program's available at date (deprecated)",  # No longer used since mobile v1.345.0
    required=False,
)
@request_argument(
    "preferred_notification_time_in_minutes",
    type=str,
    help="Time selected by the member to have reminder notifications (can be null if they selected none)",
    required=False,
)
@request_argument(
    "tasks",
    type=list,
    location="json",
    help="Program's tasks",
    required=True,
)
@request_argument(
    "current_day",
    type=int,
    help="The current day of the program (deprecated)",  # No longer used since mobile v1.365.0
    required=False,
)
@request_argument(
    "is_custom",
    type=bool,
    help="Whether or not the program has been tailor-made by a HP (deprecated)",  # No longer used since mobile v1.348.0
    required=False,
)
@request_argument(
    "survey_source_type",
    type=str,
    help="The source type of the survey the member filled before starting the program",
    required=True,
)
@request_argument(
    "last_updated_at",
    type=str,
    help="When the program was last updated, according to the client device's clock",
    required=True,
)
@request_argument(
    "assigned_coach_medical_admin_id",
    type=str,
    help="The assigned coach's medical admin id",
    required=False,
    owner_controller=NoOwner,
)
@obs.api_call()
def post_health_program_progress(user: FeatureUser, params: dict) -> Response:  # type: ignore[type-arg]  # noqa: D103
    from components.health_programs.internal.business_logic.health_program_progress import (
        create_or_update_health_program_progress,
    )

    program_progress = create_or_update_health_program_progress(
        user=user,
        program_slug=params["program_slug"],
        program_name=params.get("program_name"),
        program_status=params["program_status"],
        preferred_notification_time_in_minutes=params.get(
            "preferred_notification_time_in_minutes"
        ),
        tasks=params["tasks"],
        survey_source_type=params["survey_source_type"],
        last_updated_at=datetime.fromisoformat(params["last_updated_at"]),
        assigned_coach_medical_admin_id=params.get("assigned_coach_medical_admin_id"),
        current_day=params.get("current_day"),
    )

    return make_json_response(program_progress)

components.health_programs.public.entities

health_program_complete_data

HealthProgramCompleteData dataclass

HealthProgramCompleteData(
    program_slug,
    program_name,
    program_id,
    custom_program_id,
    overridden_segment_slug,
    program_status,
    preferred_notification_time_in_minutes,
    tasks,
    current_day,
    survey_source_type,
    last_updated_at,
    assigned_coach_medical_admin_id,
    dedicated_time,
)

Bases: DataClassJsonMixin

assigned_coach_medical_admin_id instance-attribute
assigned_coach_medical_admin_id
current_day instance-attribute
current_day
custom_program_id instance-attribute
custom_program_id
dedicated_time instance-attribute
dedicated_time
from_health_program_models classmethod
from_health_program_models(
    health_program_progress, health_program_override
)
Source code in components/health_programs/public/entities/health_program_complete_data.py
@classmethod
def from_health_program_models(  # noqa: D102
    cls,
    health_program_progress: "HealthProgramProgress",
    health_program_override: Optional["HealthProgramOverride"],
) -> "HealthProgramCompleteData":
    return cls(
        program_slug=health_program_progress.program_slug,
        program_name=health_program_progress.program_name,
        program_id="",  # mobile backward compatibility
        program_status=health_program_progress.program_status,
        preferred_notification_time_in_minutes=health_program_progress.preferred_notification_time_in_minutes,
        tasks=[
            HealthProgramTask(
                id=task["id"],
                status=task["status"],
                name=task["name"],
                day=task["day"],
                first_task_activity_date=task["first_task_activity_date"],
                last_task_activity_date=task["last_task_activity_date"],
                exercise_titles=task.get("exercise_titles"),
            )
            for task in health_program_progress.tasks
        ],
        survey_source_type=health_program_progress.survey_source_type,
        last_updated_at=health_program_progress.last_updated_at.replace(tzinfo=UTC),
        assigned_coach_medical_admin_id=health_program_progress.assigned_coach_medical_admin_id,
        current_day=health_program_progress.current_day,
        custom_program_id=(
            health_program_override.custom_program_id
            if health_program_override
            else None
        ),
        overridden_segment_slug=(
            health_program_override.segment_slug
            if health_program_override
            else None
        ),
        dedicated_time=(
            health_program_override.dedicated_time
            if health_program_override
            else None
        ),
    )
last_updated_at instance-attribute
last_updated_at
overridden_segment_slug instance-attribute
overridden_segment_slug
preferred_notification_time_in_minutes instance-attribute
preferred_notification_time_in_minutes
program_id instance-attribute
program_id
program_name instance-attribute
program_name
program_slug instance-attribute
program_slug
program_status instance-attribute
program_status
survey_source_type instance-attribute
survey_source_type
tasks instance-attribute
tasks

health_program_override

HealthProgramCustomTask dataclass

HealthProgramCustomTask(day, exercises_ids)

Bases: DataClassJsonMixin

day instance-attribute
day
exercises_ids instance-attribute
exercises_ids

HealthProgramOverrideData dataclass

HealthProgramOverrideData(
    program_slug,
    segment_slug,
    custom_program_id,
    custom_tasks,
    dedicated_time,
)

Bases: DataClassJsonMixin

custom_program_id instance-attribute
custom_program_id
custom_tasks instance-attribute
custom_tasks
dedicated_time instance-attribute
dedicated_time
from_health_program_override_model classmethod
from_health_program_override_model(health_program_override)
Source code in components/health_programs/public/entities/health_program_override.py
@classmethod
def from_health_program_override_model(  # noqa: D102
    cls, health_program_override: "HealthProgramOverride"
) -> "HealthProgramOverrideData":
    return cls(
        program_slug=health_program_override.program_slug,
        segment_slug=health_program_override.segment_slug,
        custom_program_id=health_program_override.custom_program_id,
        custom_tasks=[
            HealthProgramCustomTask(
                day=custom_task["day"], exercises_ids=custom_task["exercises_ids"]
            )
            for custom_task in health_program_override.custom_tasks
        ],
        dedicated_time=health_program_override.dedicated_time,
    )
program_slug instance-attribute
program_slug
segment_slug instance-attribute
segment_slug

health_program_progress

HealthProgramProgressData dataclass

HealthProgramProgressData(
    program_slug,
    program_name,
    program_status,
    preferred_notification_time_in_minutes,
    tasks,
    current_day,
    survey_source_type,
    last_updated_at,
    assigned_coach_medical_admin_id,
)

Bases: DataClassJsonMixin

assigned_coach_medical_admin_id instance-attribute
assigned_coach_medical_admin_id
current_day instance-attribute
current_day
from_health_program_progress_model classmethod
from_health_program_progress_model(health_program_progress)
Source code in components/health_programs/public/entities/health_program_progress.py
@classmethod
def from_health_program_progress_model(  # noqa: D102
    cls,
    health_program_progress: "HealthProgramProgress",
) -> "HealthProgramProgressData":
    return cls(
        program_slug=health_program_progress.program_slug,
        program_name=health_program_progress.program_name,
        program_status=health_program_progress.program_status,
        preferred_notification_time_in_minutes=health_program_progress.preferred_notification_time_in_minutes,
        tasks=[
            HealthProgramTask(
                id=task["id"],
                status=task["status"],
                name=task["name"],
                day=task["day"],
                first_task_activity_date=task["first_task_activity_date"],
                last_task_activity_date=task["last_task_activity_date"],
                exercise_titles=task.get("exercise_titles"),
            )
            for task in health_program_progress.tasks
        ],
        survey_source_type=health_program_progress.survey_source_type,
        last_updated_at=health_program_progress.last_updated_at.replace(tzinfo=UTC),
        assigned_coach_medical_admin_id=health_program_progress.assigned_coach_medical_admin_id,
        current_day=health_program_progress.current_day,
    )
last_updated_at instance-attribute
last_updated_at
preferred_notification_time_in_minutes instance-attribute
preferred_notification_time_in_minutes
program_name instance-attribute
program_name
program_slug instance-attribute
program_slug
program_status instance-attribute
program_status
survey_source_type instance-attribute
survey_source_type
tasks instance-attribute
tasks

HealthProgramTask dataclass

HealthProgramTask(
    id,
    status,
    name,
    day,
    exercise_titles,
    first_task_activity_date,
    last_task_activity_date,
)

Bases: DataClassJsonMixin

day instance-attribute
day
exercise_titles instance-attribute
exercise_titles
first_task_activity_date instance-attribute
first_task_activity_date
id instance-attribute
id
last_task_activity_date instance-attribute
last_task_activity_date
name instance-attribute
name
status instance-attribute
status

health_program_status

HealthProgramStatus

Bases: AlanBaseEnum

enrolled class-attribute instance-attribute
enrolled = 'enrolled'
not_started class-attribute instance-attribute
not_started = 'not-started'
program_in_preparation class-attribute instance-attribute
program_in_preparation = 'program-in-preparation'
program_ready class-attribute instance-attribute
program_ready = 'program-ready'