""" API endpoints for reporting user activity events. This module provides endpoints for clients to report state changes (working/stopped). """ from datetime import datetime from flask import Blueprint, request, jsonify, current_app from sqlalchemy.exc import SQLAlchemyError from app import db from app.models import WorkEvent # Create a blueprint for event-related API endpoints events_bp = Blueprint('events', __name__, url_prefix='/api') @events_bp.route('/report', methods=['POST']) def report_event(): """ Endpoint for clients to report activity state changes. Expected JSON payload: { "user": "username", "state": "working|stopped", "ts": "2023-07-08T12:30:45Z" (optional, ISO 8601) } """ data = request.get_json() current_app.logger.info(f"Received report request: {data}") # Log request if not data or 'user' not in data or 'state' not in data: current_app.logger.warning("Invalid report request payload.") return jsonify({ 'success': False, 'message': 'Missing required fields: user, state' }), 400 # Validate state value if data['state'] not in ['working', 'stopped']: return jsonify({ 'success': False, 'message': 'Invalid state value. Must be "working" or "stopped"' }), 400 # Parse timestamp if provided, otherwise use current time timestamp = None if 'ts' in data and data['ts']: try: timestamp = datetime.fromisoformat(data['ts'].replace('Z', '+00:00')) except ValueError: return jsonify({ 'success': False, 'message': 'Invalid timestamp format. Use ISO 8601 (YYYY-MM-DDTHH:MM:SSZ)' }), 400 # Create and store the event user = data['user'] state = data['state'] ts_str = data.get('ts') # Optional timestamp event_ts = datetime.utcnow() if ts_str: try: # Attempt to parse ISO 8601 format event_ts = datetime.fromisoformat(ts_str.replace('Z', '+00:00')) except ValueError: current_app.logger.warning(f"Invalid timestamp format received: {ts_str}. Using current UTC time.") # Optionally return an error here if strict timestamp validation is needed # return jsonify({"success": False, "message": "Invalid timestamp format"}), 400 new_event = WorkEvent(user=user, state=state, ts=event_ts) try: current_app.logger.info(f"Attempting to add event to database: User={user}, State={state}, TS={event_ts}") db.session.add(new_event) db.session.commit() current_app.logger.info(f"Successfully recorded event: User={user}, State={state}") return jsonify({"success": True}), 201 except SQLAlchemyError as e: db.session.rollback() current_app.logger.error(f"Database error while recording event: {e}") return jsonify({"success": False, "message": "Database error"}), 500 except Exception as e: current_app.logger.error(f"Unexpected error processing report request: {e}") return jsonify({"success": False, "message": "Internal server error"}), 500