Skip to content

API Reference

User default gear module for activity type gear assignments.

This module provides CRUD operations and data models for managing user default gear settings per activity type (run, ride, swim, etc.).

Exports
  • CRUD: get_user_default_gear_by_user_id, create_user_default_gear, edit_user_default_gear
  • Schemas: UsersDefaultGearBase, UsersDefaultGearUpdate, UsersDefaultGearRead
  • Models: UsersDefaultGear (ORM model)
  • Utils: get_user_default_gear_by_activity_type
  • Constants: ACTIVITY_TYPE_TO_GEAR_ATTR

UsersDefaultGearBase

Bases: BaseModel

Base schema for users default gear assignments.

Attributes:

Name Type Description
run_gear_id StrictInt | None

Default gear for run activities.

trail_run_gear_id StrictInt | None

Default gear for trail run activities.

virtual_run_gear_id StrictInt | None

Default gear for virtual run activities.

ride_gear_id StrictInt | None

Default gear for ride activities.

gravel_ride_gear_id StrictInt | None

Default gear for gravel ride activities.

mtb_ride_gear_id StrictInt | None

Default gear for MTB ride activities.

virtual_ride_gear_id StrictInt | None

Default gear for virtual ride activities.

ows_gear_id StrictInt | None

Default gear for open water swim activities.

walk_gear_id StrictInt | None

Default gear for walk activities.

hike_gear_id StrictInt | None

Default gear for hike activities.

tennis_gear_id StrictInt | None

Default gear for tennis activities.

alpine_ski_gear_id StrictInt | None

Default gear for alpine ski activities.

nordic_ski_gear_id StrictInt | None

Default gear for nordic ski activities.

snowboard_gear_id StrictInt | None

Default gear for snowboard activities.

windsurf_gear_id StrictInt | None

Default gear for windsurf activities.

Source code in backend/app/users/users_default_gear/schema.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class UsersDefaultGearBase(BaseModel):
    """
    Base schema for users default gear assignments.

    Attributes:
        run_gear_id: Default gear for run activities.
        trail_run_gear_id: Default gear for trail run
            activities.
        virtual_run_gear_id: Default gear for virtual run
            activities.
        ride_gear_id: Default gear for ride activities.
        gravel_ride_gear_id: Default gear for gravel ride
            activities.
        mtb_ride_gear_id: Default gear for MTB ride activities.
        virtual_ride_gear_id: Default gear for virtual ride
            activities.
        ows_gear_id: Default gear for open water swim
            activities.
        walk_gear_id: Default gear for walk activities.
        hike_gear_id: Default gear for hike activities.
        tennis_gear_id: Default gear for tennis activities.
        alpine_ski_gear_id: Default gear for alpine ski
            activities.
        nordic_ski_gear_id: Default gear for nordic ski
            activities.
        snowboard_gear_id: Default gear for snowboard
            activities.
        windsurf_gear_id: Default gear for windsurf activities.
    """

    run_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for run activities",
    )
    trail_run_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for trail run activities",
    )
    virtual_run_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for virtual run activities",
    )
    ride_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for ride activities",
    )
    gravel_ride_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for gravel ride activities",
    )
    mtb_ride_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for MTB ride activities",
    )
    virtual_ride_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for virtual ride activities",
    )
    ows_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for OWS activities",
    )
    walk_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for walk activities",
    )
    hike_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for hike activities",
    )
    tennis_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for tennis activities",
    )
    alpine_ski_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for alpine ski activities",
    )
    nordic_ski_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for nordic ski activities",
    )
    snowboard_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for snowboard activities",
    )
    windsurf_gear_id: StrictInt | None = Field(
        default=None,
        ge=1,
        description="Default gear for windsurf activities",
    )

    model_config = ConfigDict(
        from_attributes=True,
        extra="forbid",
        validate_assignment=True,
    )

UsersDefaultGearModel

Bases: Base

User default gear assignments for activity types.

Attributes:

Name Type Description
id Mapped[int]

Primary key.

user_id Mapped[int]

Foreign key to users table.

run_gear_id Mapped[int | None]

Default gear for run activities.

trail_run_gear_id Mapped[int | None]

Default gear for trail run activities.

virtual_run_gear_id Mapped[int | None]

Default gear for virtual run activities.

ride_gear_id Mapped[int | None]

Default gear for ride activities.

gravel_ride_gear_id Mapped[int | None]

Default gear for gravel ride activities.

mtb_ride_gear_id Mapped[int | None]

Default gear for MTB ride activities.

virtual_ride_gear_id Mapped[int | None]

Default gear for virtual ride activities.

ows_gear_id Mapped[int | None]

Default gear for open water swim activities.

walk_gear_id Mapped[int | None]

Default gear for walk activities.

hike_gear_id Mapped[int | None]

Default gear for hike activities.

tennis_gear_id Mapped[int | None]

Default gear for tennis activities.

alpine_ski_gear_id Mapped[int | None]

Default gear for alpine ski activities.

nordic_ski_gear_id Mapped[int | None]

Default gear for nordic ski activities.

snowboard_gear_id Mapped[int | None]

Default gear for snowboard activities.

windsurf_gear_id Mapped[int | None]

Default gear for windsurf activities.

user Mapped[int | None]

Relationship to Users model.

run_gear

Relationship to run Gear model.

trail_run_gear

Relationship to trail run Gear model.

virtual_run_gear

Relationship to virtual run Gear model.

ride_gear

Relationship to ride Gear model.

gravel_ride_gear

Relationship to gravel ride Gear model.

mtb_ride_gear

Relationship to MTB ride Gear model.

virtual_ride_gear

Relationship to virtual ride Gear model.

ows_gear

Relationship to OWS Gear model.

walk_gear

Relationship to walk Gear model.

hike_gear

Relationship to hike Gear model.

tennis_gear

Relationship to tennis Gear model.

alpine_ski_gear

Relationship to alpine ski Gear model.

nordic_ski_gear

Relationship to nordic ski Gear model.

snowboard_gear

Relationship to snowboard Gear model.

windsurf_gear

Relationship to windsurf Gear model.

Source code in backend/app/users/users_default_gear/models.py
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
class UsersDefaultGear(Base):
    """
    User default gear assignments for activity types.

    Attributes:
        id: Primary key.
        user_id: Foreign key to users table.
        run_gear_id: Default gear for run activities.
        trail_run_gear_id: Default gear for trail run activities.
        virtual_run_gear_id: Default gear for virtual run
            activities.
        ride_gear_id: Default gear for ride activities.
        gravel_ride_gear_id: Default gear for gravel ride
            activities.
        mtb_ride_gear_id: Default gear for MTB ride activities.
        virtual_ride_gear_id: Default gear for virtual ride
            activities.
        ows_gear_id: Default gear for open water swim activities.
        walk_gear_id: Default gear for walk activities.
        hike_gear_id: Default gear for hike activities.
        tennis_gear_id: Default gear for tennis activities.
        alpine_ski_gear_id: Default gear for alpine ski
            activities.
        nordic_ski_gear_id: Default gear for nordic ski
            activities.
        snowboard_gear_id: Default gear for snowboard activities.
        windsurf_gear_id: Default gear for windsurf activities.
        user: Relationship to Users model.
        run_gear: Relationship to run Gear model.
        trail_run_gear: Relationship to trail run Gear model.
        virtual_run_gear: Relationship to virtual run Gear model.
        ride_gear: Relationship to ride Gear model.
        gravel_ride_gear: Relationship to gravel ride Gear model.
        mtb_ride_gear: Relationship to MTB ride Gear model.
        virtual_ride_gear: Relationship to virtual ride Gear
            model.
        ows_gear: Relationship to OWS Gear model.
        walk_gear: Relationship to walk Gear model.
        hike_gear: Relationship to hike Gear model.
        tennis_gear: Relationship to tennis Gear model.
        alpine_ski_gear: Relationship to alpine ski Gear model.
        nordic_ski_gear: Relationship to nordic ski Gear model.
        snowboard_gear: Relationship to snowboard Gear model.
        windsurf_gear: Relationship to windsurf Gear model.
    """

    __tablename__ = "users_default_gear"

    id: Mapped[int] = mapped_column(
        primary_key=True,
        autoincrement=True,
    )
    user_id: Mapped[int] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        comment="User ID that the default gear belongs",
    )
    run_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default run activity type belongs"),
    )
    trail_run_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default trail run activity type " "belongs"),
    )
    virtual_run_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default virtual run activity type " "belongs"),
    )
    ride_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default ride activity type belongs"),
    )
    gravel_ride_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default gravel ride activity type " "belongs"),
    )
    mtb_ride_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default MTB ride activity type " "belongs"),
    )
    virtual_ride_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default virtual ride activity type " "belongs"),
    )
    ows_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default OWS activity type belongs"),
    )
    walk_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default walk activity type belongs"),
    )
    hike_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default hike activity type belongs"),
    )
    tennis_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default tennis activity type " "belongs"),
    )
    alpine_ski_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default alpine ski activity type " "belongs"),
    )
    nordic_ski_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default nordic ski activity type " "belongs"),
    )
    snowboard_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default snowboard activity type " "belongs"),
    )
    windsurf_gear_id: Mapped[int | None] = mapped_column(
        ForeignKey("gear.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment=("Gear ID that the default windsurf activity type " "belongs"),
    )

    # Relationships
    # TODO: Change to Mapped["User"] when all modules use mapped
    users = relationship("Users", back_populates="users_default_gear")

    # TODO: Change to Mapped["Gear"] when all modules use mapped
    run_gear = relationship("Gear", foreign_keys=[run_gear_id])
    trail_run_gear = relationship(
        "Gear",
        foreign_keys=[trail_run_gear_id],
    )
    virtual_run_gear = relationship(
        "Gear",
        foreign_keys=[virtual_run_gear_id],
    )
    ride_gear = relationship("Gear", foreign_keys=[ride_gear_id])
    gravel_ride_gear = relationship(
        "Gear",
        foreign_keys=[gravel_ride_gear_id],
    )
    mtb_ride_gear = relationship(
        "Gear",
        foreign_keys=[mtb_ride_gear_id],
    )
    virtual_ride_gear = relationship(
        "Gear",
        foreign_keys=[virtual_ride_gear_id],
    )
    ows_gear = relationship("Gear", foreign_keys=[ows_gear_id])
    walk_gear = relationship("Gear", foreign_keys=[walk_gear_id])
    hike_gear = relationship("Gear", foreign_keys=[hike_gear_id])
    tennis_gear = relationship("Gear", foreign_keys=[tennis_gear_id])
    alpine_ski_gear = relationship(
        "Gear",
        foreign_keys=[alpine_ski_gear_id],
    )
    nordic_ski_gear = relationship(
        "Gear",
        foreign_keys=[nordic_ski_gear_id],
    )
    snowboard_gear = relationship(
        "Gear",
        foreign_keys=[snowboard_gear_id],
    )
    windsurf_gear = relationship(
        "Gear",
        foreign_keys=[windsurf_gear_id],
    )

UsersDefaultGearRead

Bases: UsersDefaultGearBase

Schema for reading user default gear settings.

Extends base with identifier fields.

Attributes:

Name Type Description
id StrictInt

Unique identifier for the record.

user_id StrictInt

User ID reference.

Source code in backend/app/users/users_default_gear/schema.py
124
125
126
127
128
129
130
131
132
133
134
135
136
class UsersDefaultGearRead(UsersDefaultGearBase):
    """
    Schema for reading user default gear settings.

    Extends base with identifier fields.

    Attributes:
        id: Unique identifier for the record.
        user_id: User ID reference.
    """

    id: StrictInt = Field(..., ge=1, description="Unique identifier")
    user_id: StrictInt = Field(..., ge=1, description="User ID")

UsersDefaultGearUpdate

Bases: UsersDefaultGearRead

Schema for updating user default gear settings.

Inherits all gear assignment fields from read schema. All fields are optional for partial updates.

Source code in backend/app/users/users_default_gear/schema.py
139
140
141
142
143
144
145
class UsersDefaultGearUpdate(UsersDefaultGearRead):
    """
    Schema for updating user default gear settings.

    Inherits all gear assignment fields from read schema.
    All fields are optional for partial updates.
    """

create_user_default_gear

create_user_default_gear(user_id, db)

Create default gear settings for a user.

Parameters:

Name Type Description Default
user_id int

The ID of the user to create settings for.

required
db Session

SQLAlchemy database session.

required

Returns:

Type Description
UsersDefaultGear

The created UsersDefaultGear model.

Raises:

Type Description
HTTPException

409 error if settings already exist.

HTTPException

500 error if database operation fails.

Source code in backend/app/users/users_default_gear/crud.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
@core_decorators.handle_db_errors
def create_user_default_gear(
    user_id: int,
    db: Session,
) -> user_default_gear_models.UsersDefaultGear:
    """
    Create default gear settings for a user.

    Args:
        user_id: The ID of the user to create settings for.
        db: SQLAlchemy database session.

    Returns:
        The created UsersDefaultGear model.

    Raises:
        HTTPException: 409 error if settings already exist.
        HTTPException: 500 error if database operation fails.
    """
    try:
        db_default_gear = user_default_gear_models.UsersDefaultGear(
            user_id=user_id,
        )

        db.add(db_default_gear)
        db.commit()
        db.refresh(db_default_gear)

        return db_default_gear
    except IntegrityError as integrity_error:
        # Rollback the transaction
        db.rollback()

        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=("Default gear settings already exist for this user"),
        ) from integrity_error

edit_user_default_gear

edit_user_default_gear(user_default_gear, user_id, db)

Update default gear settings for a user.

Parameters:

Name Type Description Default
user_default_gear UsersDefaultGearUpdate

Schema with gear fields to update.

required
user_id int

The ID of the user.

required
db Session

SQLAlchemy database session.

required

Returns:

Type Description
UsersDefaultGear

The updated UsersDefaultGear model.

Raises:

Type Description
HTTPException

404 error if settings not found.

HTTPException

500 error if database operation fails.

Source code in backend/app/users/users_default_gear/crud.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
@core_decorators.handle_db_errors
def edit_user_default_gear(
    user_default_gear: user_default_gear_schema.UsersDefaultGearUpdate,
    user_id: int,
    db: Session,
) -> user_default_gear_models.UsersDefaultGear:
    """
    Update default gear settings for a user.

    Args:
        user_default_gear: Schema with gear fields to update.
        user_id: The ID of the user.
        db: SQLAlchemy database session.

    Returns:
        The updated UsersDefaultGear model.

    Raises:
        HTTPException: 404 error if settings not found.
        HTTPException: 500 error if database operation fails.
    """
    if user_default_gear.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Cannot edit default gear for another user.",
        )

    db_user_default_gear = get_user_default_gear_by_user_id(user_id, db)

    if db_user_default_gear is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User default gear not found",
        )

    user_default_gear_data = user_default_gear.model_dump(
        exclude_unset=True, exclude={"user_id", "id"}
    )
    for key, value in user_default_gear_data.items():
        setattr(db_user_default_gear, key, value)

    db.commit()
    db.refresh(db_user_default_gear)

    return db_user_default_gear

get_user_default_gear_by_activity_type

get_user_default_gear_by_activity_type(user_id, activity_type, db)

Get default gear ID for a specific activity type.

Parameters:

Name Type Description Default
user_id int

The ID of the user.

required
activity_type int

The activity type code.

required
db Session

SQLAlchemy database session.

required

Returns:

Type Description
int | None

The gear ID for the activity type, or None if not set

int | None

or activity type is unknown.

Raises:

Type Description
HTTPException

If user default gear not found or database error occurs.

Source code in backend/app/users/users_default_gear/utils.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def get_user_default_gear_by_activity_type(
    user_id: int,
    activity_type: int,
    db: Session,
) -> int | None:
    """
    Get default gear ID for a specific activity type.

    Args:
        user_id: The ID of the user.
        activity_type: The activity type code.
        db: SQLAlchemy database session.

    Returns:
        The gear ID for the activity type, or None if not set
        or activity type is unknown.

    Raises:
        HTTPException: If user default gear not found or
            database error occurs.
    """
    try:
        user_default_gear = user_default_gear_crud.get_user_default_gear_by_user_id(
            user_id, db
        )

        if user_default_gear is None:
            return None

        attr_name = ACTIVITY_TYPE_TO_GEAR_ATTR.get(activity_type)
        if attr_name is None:
            return None

        return getattr(user_default_gear, attr_name, None)
    except HTTPException:
        raise
    except Exception as err:
        core_logger.print_to_log(
            f"Error in get_user_default_gear_by_activity_type: {err}",
            "error",
            exc=err,
        )
        raise

get_user_default_gear_by_user_id

get_user_default_gear_by_user_id(user_id, db)

Retrieve default gear settings for a specific user.

Parameters:

Name Type Description Default
user_id int

The ID of the user to fetch settings for.

required
db Session

SQLAlchemy database session.

required

Returns:

Type Description
UsersDefaultGear | None

The UsersDefaultGear model for the user or None if not found.

Raises:

Type Description
HTTPException

404 error if settings not found.

HTTPException

500 error if database query fails.

Source code in backend/app/users/users_default_gear/crud.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@core_decorators.handle_db_errors
def get_user_default_gear_by_user_id(
    user_id: int,
    db: Session,
) -> user_default_gear_models.UsersDefaultGear | None:
    """
    Retrieve default gear settings for a specific user.

    Args:
        user_id: The ID of the user to fetch settings for.
        db: SQLAlchemy database session.

    Returns:
        The UsersDefaultGear model for the user or None if not found.

    Raises:
        HTTPException: 404 error if settings not found.
        HTTPException: 500 error if database query fails.
    """
    stmt = select(user_default_gear_models.UsersDefaultGear).where(
        user_default_gear_models.UsersDefaultGear.user_id == user_id
    )
    return db.execute(stmt).scalar_one_or_none()