many updates
This commit is contained in:
@@ -141,6 +141,7 @@ async def query_activities(
|
||||
start_date: Optional[str] = Query(None),
|
||||
end_date: Optional[str] = Query(None),
|
||||
download_status: Optional[str] = Query(None),
|
||||
bike_setup_id: Optional[int] = Query(None),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
@@ -154,7 +155,21 @@ async def query_activities(
|
||||
|
||||
# Apply filters based on parameters
|
||||
if activity_type:
|
||||
query = query.filter(Activity.activity_type == activity_type)
|
||||
if activity_type == 'cycling':
|
||||
# Match outdoor cycling types
|
||||
# Using OR filtering for various sub-types
|
||||
from sqlalchemy import or_
|
||||
query = query.filter(or_(
|
||||
Activity.activity_type == 'cycling',
|
||||
Activity.activity_type == 'road_biking',
|
||||
Activity.activity_type == 'mountain_biking',
|
||||
Activity.activity_type == 'gravel_cycling',
|
||||
Activity.activity_type == 'cyclocross',
|
||||
Activity.activity_type == 'track_cycling',
|
||||
Activity.activity_type == 'commuting'
|
||||
))
|
||||
else:
|
||||
query = query.filter(Activity.activity_type == activity_type)
|
||||
|
||||
if start_date:
|
||||
from datetime import datetime
|
||||
@@ -168,6 +183,9 @@ async def query_activities(
|
||||
|
||||
if download_status:
|
||||
query = query.filter(Activity.download_status == download_status)
|
||||
|
||||
if bike_setup_id:
|
||||
query = query.filter(Activity.bike_setup_id == bike_setup_id)
|
||||
|
||||
# Execute the query
|
||||
activities = query.all()
|
||||
@@ -376,7 +394,20 @@ async def redownload_activity_endpoint(activity_id: str, db: Session = Depends(g
|
||||
success = sync_app.redownload_activity(activity_id)
|
||||
|
||||
if success:
|
||||
return {"message": f"Successfully redownloaded activity {activity_id}", "status": "success"}
|
||||
# Trigger bike matching
|
||||
try:
|
||||
from ..services.bike_matching import process_activity_matching
|
||||
|
||||
# Fetch fresh activity object using new session logic or flush/commit handled by sync_app
|
||||
# Just query by garmin_id
|
||||
act_obj = db.query(Activity).filter(Activity.garmin_activity_id == activity_id).first()
|
||||
if act_obj:
|
||||
process_activity_matching(db, act_obj.id)
|
||||
logger.info(f"Retriggered bike match for {activity_id} after redownload")
|
||||
except Exception as match_err:
|
||||
logger.error(f"Error matching bike after redownload: {match_err}")
|
||||
|
||||
return {"message": f"Successfully redownloaded and matched activity {activity_id}", "status": "success"}
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail="Failed to redownload activity. Check logs for details.")
|
||||
|
||||
@@ -389,6 +420,48 @@ async def redownload_activity_endpoint(activity_id: str, db: Session = Depends(g
|
||||
|
||||
# New Sync Endpoints
|
||||
|
||||
class BikeMatchUpdate(BaseModel):
|
||||
bike_setup_id: Optional[int] = None
|
||||
manual_override: bool = True
|
||||
|
||||
@router.put("/activities/{activity_id}/bike")
|
||||
async def update_activity_bike(activity_id: str, update: BikeMatchUpdate, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Manually update the bike setup for an activity.
|
||||
Sets bike_match_confidence to 2.0 to indicate manual override.
|
||||
"""
|
||||
try:
|
||||
activity = db.query(Activity).filter(Activity.garmin_activity_id == activity_id).first()
|
||||
if not activity:
|
||||
raise HTTPException(status_code=404, detail="Activity not found")
|
||||
|
||||
# Verify bike setup exists if provided
|
||||
if update.bike_setup_id:
|
||||
from ..models.bike_setup import BikeSetup
|
||||
setup = db.query(BikeSetup).filter(BikeSetup.id == update.bike_setup_id).first()
|
||||
if not setup:
|
||||
raise HTTPException(status_code=404, detail="Bike Setup not found")
|
||||
|
||||
activity.bike_setup_id = setup.id
|
||||
activity.bike_match_confidence = 2.0 # Manual Override
|
||||
logger.info(f"Manual bike override for {activity_id} to setup {setup.id}")
|
||||
else:
|
||||
# Clear setup
|
||||
activity.bike_setup_id = None
|
||||
activity.bike_match_confidence = 2.0 # Manual Clear
|
||||
logger.info(f"Manual bike override for {activity_id} to cleared")
|
||||
|
||||
db.commit()
|
||||
return {"message": "Bike setup updated successfully", "status": "success"}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating activity bike: {e}")
|
||||
db.rollback()
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
|
||||
def run_scan_job(job_id: str, days_back: int, db_session_factory):
|
||||
"""Background task wrapper for scan"""
|
||||
try:
|
||||
@@ -685,6 +758,23 @@ async def get_activity_streams(activity_id: str, db: Session = Depends(get_db)):
|
||||
logger.error(f"Error getting streams: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.post("/activities/{activity_id}/estimate_power")
|
||||
async def estimate_activity_power(activity_id: int, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Trigger physics-based power estimation.
|
||||
"""
|
||||
from ..services.power_estimator import PowerEstimatorService
|
||||
|
||||
try:
|
||||
service = PowerEstimatorService(db)
|
||||
result = service.estimate_power_for_activity(activity_id)
|
||||
return {"message": "Power estimated successfully", "stats": result}
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"Error estimating power: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.get("/activities/{activity_id}/navigation")
|
||||
async def get_activity_navigation(activity_id: str, db: Session = Depends(get_db)):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user