diff --git a/backend/routers/goals.py b/backend/routers/goals.py index c17a089..5611d6e 100644 --- a/backend/routers/goals.py +++ b/backend/routers/goals.py @@ -395,11 +395,16 @@ def create_goal(data: GoalCreate, session: dict = Depends(require_auth)): start_value = data.start_value elif start_date < date.today(): # Historical start date - try to get historical value - start_value = _get_historical_value_for_goal_type(conn, pid, data.goal_type, start_date) - if start_value is None: - # No data on that date, fall back to current value + historical_data = _get_historical_value_for_goal_type(conn, pid, data.goal_type, start_date) + if historical_data is not None: + # Use the actual measurement date and value + start_date = historical_data['date'] + start_value = historical_data['value'] + print(f"[INFO] Auto-adjusted start_date to {start_date} (first measurement)") + else: + # No data found, fall back to current value and keep original date start_value = current_value - print(f"[WARN] No historical data for {data.goal_type} on {start_date}, using current value") + print(f"[WARN] No historical data for {data.goal_type} on or after {start_date}, using current value") else: # Start date is today, use current value start_value = current_value @@ -514,15 +519,23 @@ def update_goal(goal_id: str, data: GoalUpdate, session: dict = Depends(require_ goal_row = cur.fetchone() if goal_row: goal_type = goal_row['goal_type'] - print(f"[DEBUG] Looking up historical value for {goal_type} on {data.start_date}") - historical_value = _get_historical_value_for_goal_type(conn, pid, goal_type, data.start_date) - print(f"[DEBUG] Historical value result: {historical_value}") - if historical_value is not None: + print(f"[DEBUG] Looking up historical value for {goal_type} on or after {data.start_date}") + historical_data = _get_historical_value_for_goal_type(conn, pid, goal_type, data.start_date) + print(f"[DEBUG] Historical data result: {historical_data}") + if historical_data is not None: + # Update both start_date and start_value with actual measurement + actual_date = historical_data['date'] + actual_value = historical_data['value'] + + # Replace the start_date in updates with the actual measurement date + updates[-1] = "start_date = %s" # Update the last added start_date + params[-1] = actual_date + updates.append("start_value = %s") - params.append(historical_value) - print(f"[INFO] Auto-populated start_value from {data.start_date}: {historical_value}") + params.append(actual_value) + print(f"[INFO] Auto-adjusted to first measurement: {actual_date} = {actual_value}") else: - print(f"[WARN] No historical data found for {goal_type} around {data.start_date}") + print(f"[WARN] No historical data found for {goal_type} on or after {data.start_date}") else: print(f"[ERROR] Could not find goal with id {goal_id}") @@ -683,19 +696,19 @@ def _get_current_value_for_goal_type(conn, profile_id: str, goal_type: str) -> O # Delegate to universal fetcher (Phase 1.5) return get_current_value_for_goal(conn, profile_id, goal_type) -def _get_historical_value_for_goal_type(conn, profile_id: str, goal_type: str, target_date: date) -> Optional[float]: +def _get_historical_value_for_goal_type(conn, profile_id: str, goal_type: str, target_date: date) -> Optional[dict]: """ - Get historical value for a goal type on a specific date. - Looks for closest value within ±7 days window. + Get historical value for a goal type on or after a specific date. + Finds the FIRST available measurement >= target_date. Args: conn: Database connection profile_id: User's profile ID goal_type: Goal type key (e.g., 'weight', 'body_fat') - target_date: Date to query (can be historical) + target_date: Desired start date (will find first measurement on or after this date) Returns: - Historical value or None if not found + Dict with {'value': float, 'date': date} or None if not found """ from goal_utils import get_goal_type_config, get_cursor @@ -726,20 +739,16 @@ def _get_historical_value_for_goal_type(conn, profile_id: str, goal_type: str, t else: date_col = 'date' + # Find first measurement on or after target_date query = f""" - SELECT {source_column} + SELECT {source_column}, {date_col} as measurement_date FROM {source_table} WHERE profile_id = %s - AND {date_col} BETWEEN %s AND %s - ORDER BY ABS({date_col} - %s::date) + AND {date_col} >= %s + ORDER BY {date_col} ASC LIMIT 1 """ - params = ( - profile_id, - target_date - timedelta(days=7), - target_date + timedelta(days=7), - target_date - ) + params = (profile_id, target_date) print(f"[DEBUG] Query: {query}") print(f"[DEBUG] Params: {params}") @@ -751,12 +760,24 @@ def _get_historical_value_for_goal_type(conn, profile_id: str, goal_type: str, t if row: value = row[source_column] + measurement_date = row['measurement_date'] + # Convert Decimal to float - result = float(value) if value is not None else None - print(f"[DEBUG] Returning value: {result}") + result_value = float(value) if value is not None else None + + # Handle different date types (date vs datetime) + if hasattr(measurement_date, 'date'): + # It's a datetime, extract date + result_date = measurement_date.date() + else: + # It's already a date + result_date = measurement_date + + result = {'value': result_value, 'date': result_date} + print(f"[DEBUG] Returning: {result}") return result - print(f"[DEBUG] No data found in date range") + print(f"[DEBUG] No data found on or after {target_date}") return None except Exception as e: print(f"[ERROR] Failed to get historical value for {goal_type} on {target_date}: {e}")