Files
endurain/backend/app/gears/crud.py
João Vitória Silva 746cf47da6 BMI logic + fixes
[aux] added auxiliary scripts
[backend] added error logic to error printing
[backend] rollbacked changes from Datetime to Timestamp
[backend] added body composition sync from Garmin
[backend] added additional validations for empty .gpx files
[backend] add calculate BMI logic
[backend] add BMI calculation in migration
[backend] added Timezone logic to Strava activity import
[frontend] removed block that prevent deleting Strava or GC activity
[frontend] added new generic modal for single number input
[frontend] replaced modal that retrieves Strava and GC activities for number of days with new generic modal
[frontend] added shoes gear in add gear to walk and hike activities
[frontend] minor bug fixes
2024-12-10 17:35:56 +00:00

440 lines
14 KiB
Python

import logging
from fastapi import HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from urllib.parse import unquote
import gears.schema as gears_schema
import gears.utils as gears_utils
import gears.models as gears_models
import core.logger as core_logger
def get_gear_user_by_id(gear_id: int, db: Session) -> gears_schema.Gear | None:
try:
gear = db.query(gears_models.Gear).filter(gears_models.Gear.id == gear_id).first()
# Check if gear is None and return None if it is
if gear is None:
return None
gear = gears_utils.serialize_gear(gear)
# Return the gear
return gear
except Exception as err:
# Log the exception
core_logger.print_to_log(f"Error in get_gear_user_by_id: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def get_gear_users_with_pagination(
user_id: int, db: Session, page_number: int = 1, num_records: int = 5
) -> list[gears_schema.Gear] | None:
try:
# Get the gear by user ID from the database
gear = (
db.query(gears_models.Gear)
.filter(gears_models.Gear.user_id == user_id)
.order_by(gears_models.Gear.nickname.asc())
.offset((page_number - 1) * num_records)
.limit(num_records)
.all()
)
# Check if gear is None and return None if it is
if gear is None:
return None
# Format the created_at date
for g in gear:
g = gears_utils.serialize_gear(g)
# Return the gear
return gear
except Exception as err:
# Log the exception
core_logger.print_to_log(
f"Error in get_gear_users_with_pagination: {err}", "error", exc=err
)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def get_gear_user(user_id: int, db: Session) -> list[gears_schema.Gear] | None:
try:
# Get the gear by user ID from the database
gears = db.query(gears_models.Gear).filter(gears_models.Gear.user_id == user_id).all()
# Check if gear is None and return None if it is
if gears is None:
return None
# Format the created_at date
for g in gears:
g = gears_utils.serialize_gear(g)
# Return the gear
return gears
except Exception as err:
# Log the exception
core_logger.print_to_log(f"Error in get_gear_user: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def get_gear_user_by_nickname(
user_id: int, nickname: str, db: Session
) -> list[gears_schema.Gear] | None:
try:
# Unquote the nickname and change "+" to whitespace
parsed_nickname = unquote(nickname).replace("+", " ")
# Get the gear by user ID and nickname from the database
gears = (
db.query(gears_models.Gear)
.filter(
gears_models.Gear.nickname.like(f"%{parsed_nickname}%"),
gears_models.Gear.user_id == user_id,
)
.all()
)
# Check if gear is None and return None if it is
if gears is None:
return None
# Format the created_at date
for g in gears:
g = gears_utils.serialize_gear(g)
# return the gear
return gears
except Exception as err:
# Log the exception
core_logger.print_to_log(f"Error in get_gear_user_by_nickname: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def get_gear_by_type_and_user(gear_type: int, user_id: int, db: Session):
try:
# Get the gear by type from the database
gear = (
db.query(gears_models.Gear)
.filter(gears_models.Gear.gear_type == gear_type, gears_models.Gear.user_id == user_id)
.order_by(gears_models.Gear.nickname)
.all()
)
# Check if gear is None and return None if it is
if gear is None:
return None
# Format the created_at date
for g in gear:
g = gears_utils.serialize_gear(g)
# Return the gear
return gear
except Exception as err:
# Log the exception
core_logger.print_to_log(f"Error in get_gear_by_type_and_user: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def get_gear_by_strava_id_from_user_id(
gear_strava_id: str, user_id: int, db: Session
) -> gears_schema.Gear | None:
try:
# Get the gear from the database
gear = (
db.query(gears_models.Gear)
.filter(
gears_models.Gear.user_id == user_id,
gears_models.Gear.strava_gear_id == gear_strava_id,
)
.first()
)
# Check if there is gear
if not gear:
return None
gear = gears_utils.serialize_gear(gear)
# Return gear
return gear
except Exception as err:
# Log the exception
core_logger.print_to_log(
f"Error in get_gear_by_strava_id_from_user_id: {err}", "error", exc=err
)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def get_gear_by_garminconnect_id_from_user_id(
gear_garminconnect_id: str, user_id: int, db: Session
) -> gears_schema.Gear | None:
try:
# Get the gear from the database
gear = (
db.query(gears_models.Gear)
.filter(
gears_models.Gear.user_id == user_id,
gears_models.Gear.garminconnect_gear_id == gear_garminconnect_id,
)
.first()
)
# Check if there is gear
if not gear:
return None
gear = gears_utils.serialize_gear(gear)
# Return gear
return gear
except Exception as err:
# Log the exception
core_logger.print_to_log(
f"Error in get_gear_by_garminconnect_id_from_user_id: {err}", "error", exc=err
)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def create_multiple_gears(gears: list[gears_schema.Gear], user_id: int, db: Session):
try:
# Filter out None values from the gears list
valid_gears = [gear for gear in gears if gear is not None]
# Create a list of gear objects
new_gears = [
gears_utils.transform_schema_gear_to_model_gear(gear, user_id)
for gear in valid_gears
]
# Add the gears to the database
db.add_all(new_gears)
db.commit()
except IntegrityError as integrity_error:
# Rollback the transaction
db.rollback()
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Duplicate entry error. Check if nickname, strava_gear_id or garminconnect_gear_id are unique",
) from integrity_error
except Exception as err:
# Rollback the transaction
db.rollback()
# Log the exception
core_logger.print_to_log(f"Error in create_multiple_gears: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def create_gear(gear: gears_schema.Gear, user_id: int, db: Session):
try:
new_gear = gears_utils.transform_schema_gear_to_model_gear(gear, user_id)
# Add the gear to the database
db.add(new_gear)
db.commit()
db.refresh(new_gear)
# Return the gear
return new_gear
except IntegrityError as integrity_error:
# Rollback the transaction
db.rollback()
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
detail="Duplicate entry error. Check if nickname, strava_gear_id or garminconnect_gear_id are unique",
) from integrity_error
except Exception as err:
# Rollback the transaction
db.rollback()
# Log the exception
core_logger.print_to_log(f"Error in create_gear: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def edit_gear(gear_id: int, gear: gears_schema.Gear, db: Session):
try:
# Get the gear from the database
db_gear = db.query(gears_models.Gear).filter(gears_models.Gear.id == gear_id).first()
# Update the gear
if gear.brand is not None:
db_gear.brand = unquote(gear.brand).replace("+", " ")
if gear.model is not None:
db_gear.model = unquote(gear.model).replace("+", " ")
if gear.nickname is not None:
db_gear.nickname = unquote(gear.nickname).replace("+", " ")
if gear.gear_type is not None:
db_gear.gear_type = gear.gear_type
if gear.created_at is not None:
db_gear.created_at = gear.created_at
if gear.is_active is not None:
db_gear.is_active = gear.is_active
if gear.initial_kms is not None:
db_gear.initial_kms = gear.initial_kms
if gear.strava_gear_id is not None:
db_gear.strava_gear_id = gear.strava_gear_id
if gear.garminconnect_gear_id is not None:
db_gear.garminconnect_gear_id = gear.garminconnect_gear_id
# Commit the transaction
db.commit()
except Exception as err:
# Rollback the transaction
db.rollback()
# Log the exception
core_logger.print_to_log(f"Error in edit_gear: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def delete_gear(gear_id: int, db: Session):
try:
# Delete the gear
num_deleted = db.query(gears_models.Gear).filter(gears_models.Gear.id == gear_id).delete()
# Check if the gear was found and deleted
if num_deleted == 0:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Gear with id {gear_id} not found",
)
# Commit the transaction
db.commit()
except Exception as err:
# Rollback the transaction
db.rollback()
# Log the exception
core_logger.print_to_log(f"Error in delete_gear: {err}", "error", exc=err)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def delete_all_strava_gear_for_user(user_id: int, db: Session):
try:
# Delete the gear records with strava_gear_id not null for the user
num_deleted = (
db.query(gears_models.Gear)
.filter(
gears_models.Gear.user_id == user_id, gears_models.Gear.strava_gear_id.isnot(None)
)
.delete()
)
# Check if any records were deleted and commit the transaction
if num_deleted != 0:
# Commit the transaction
db.commit()
except Exception as err:
# Rollback the transaction
db.rollback()
# Log the exception
core_logger.print_to_log(
f"Error in delete_all_strava_gear_for_user: {err}", "error", exc=err
)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err
def delete_all_garminconnect_gear_for_user(user_id: int, db: Session):
try:
# Delete the gear records with garminconnect_gear_id not null for the user
num_deleted = (
db.query(gears_models.Gear)
.filter(
gears_models.Gear.user_id == user_id,
gears_models.Gear.garminconnect_gear_id.isnot(None),
)
.delete()
)
# Check if any records were deleted and commit the transaction
if num_deleted != 0:
# Commit the transaction
db.commit()
except Exception as err:
# Rollback the transaction
db.rollback()
# Log the exception
core_logger.print_to_log(
f"Error in delete_all_garminconnect_gear_for_user: {err}", "error", exc=err
)
# Raise an HTTPException with a 500 Internal Server Error status code
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal Server Error",
) from err