85 lines
3.2 KiB
Python
85 lines
3.2 KiB
Python
"""
|
|
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 |