enflow-api / controllers /incident_controller.py
dhruv575
Fix the string
df49293
from flask import jsonify, request
import logging
from datetime import datetime
from models.incident import Incident
from models.workflow import Workflow
from models.log import Log
from utils.celery_tasks import process_incident_forms
from models.user import User
from models.department import Department
from utils.pdf_utils import fill_markdown_form, extract_required_data, save_filled_form
from db import get_gridfs
from bson.objectid import ObjectId
import os
import openai
# Configure logging
logger = logging.getLogger(__name__)
def get_incident(current_user, incident_id):
"""Get incident by ID"""
try:
# Find incident by ID
incident = Incident.find_by_id(incident_id)
if not incident:
return jsonify({'message': 'Incident not found'}), 404
# Check if user has permission to access this incident
# An Admin can access any incident in their department.
# A regular user can only access their own incidents.
is_admin = current_user.permissions == 'Admin'
is_owner = str(incident.user_id) == str(current_user._id)
in_department = str(incident.department_id) == str(current_user.department_id)
if not in_department:
return jsonify({'message': 'Cannot access incidents outside your department'}), 403
if not is_admin and not is_owner:
return jsonify({'message': 'You do not have permission to access this incident'}), 403
# Return incident
return jsonify({'incident': incident.to_dict()}), 200
except Exception as e:
logger.error(f"Error getting incident: {str(e)}")
return jsonify({'message': f'Error getting incident: {str(e)}'}), 500
def delete_incident(current_user, incident_id):
"""Delete incident by ID"""
try:
# Find incident by ID
incident = Incident.find_by_id(incident_id)
if not incident:
return jsonify({'message': 'Incident not found'}), 404
# Check if user has access to this incident
if not current_user.is_admin and str(incident.user_id) != str(current_user._id):
return jsonify({'message': 'You do not have permission to delete this incident'}), 403
# Delete incident
if incident.delete():
return jsonify({'message': 'Incident deleted successfully'}), 200
else:
return jsonify({'message': 'Failed to delete incident'}), 500
except Exception as e:
logger.error(f"Error deleting incident: {str(e)}")
return jsonify({'message': f'Error deleting incident: {str(e)}'}), 500
def process_incident_sync(current_user, incident_id):
"""Process an incident synchronously (fill form with LLM)"""
try:
# Check if OpenAI API key is set
api_key = os.environ.get('OPENAI_API_KEY')
if not api_key:
logger.error("OPENAI_API_KEY environment variable is not set")
return jsonify({'message': 'OpenAI API key not configured'}), 500
# Create OpenAI client - removed any proxies parameter
client = openai.OpenAI(api_key=api_key)
# Find incident by ID
incident = Incident.find_by_id(incident_id)
if not incident:
return jsonify({'message': 'Incident not found'}), 404
# Check if user has permission to process this incident
# An Admin can process any incident in their department.
# A regular user can only process their own incidents.
is_admin = current_user.permissions == 'Admin'
is_owner = str(incident.user_id) == str(current_user._id)
in_department = str(incident.department_id) == str(current_user.department_id)
# Check permissions based on role
if not in_department:
# Should generally not happen if incidents are fetched correctly, but good failsafe
return jsonify({'message': 'Cannot process incidents outside your department'}), 403
if not is_admin and not is_owner:
return jsonify({'message': 'You do not have permission to process this incident'}), 403
# Get the workflow for this incident
workflow = Workflow.find_by_id(incident.workflow_id)
if not workflow:
return jsonify({'message': 'Workflow not found for this incident'}), 404
# Check if workflow has a template
if not workflow.markdown_template:
return jsonify({'message': 'No form template found for this workflow'}), 404
# Extract required data from incident
logger.info(f"Extracting required data for incident {incident_id}")
required_data = extract_required_data(incident.activity_text, workflow.data_requirements)
# Store the extracted data in the incident
incident.extracted_data = required_data
# Fill markdown form
logger.info(f"Filling form for incident {incident_id}")
filled_markdown = fill_markdown_form(workflow.markdown_template, required_data)
# Update incident status
incident.status = "completed"
if incident.save():
return jsonify({
'message': 'Incident processed successfully',
'incident': incident.to_dict(),
'filled_markdown': filled_markdown
}), 200
else:
return jsonify({'message': 'Failed to update incident'}), 500
except Exception as e:
logger.error(f"Error processing incident {incident_id}: {str(e)}")
return jsonify({'message': f'Error processing incident: {str(e)}'}), 500
def get_user_incidents(current_user):
"""Get all incidents for the current user"""
try:
# Find incidents by user ID
incidents = Incident.find_by_user(current_user._id)
# Convert incidents to dict
incidents_dict = [incident.to_dict() for incident in incidents]
return jsonify({'incidents': incidents_dict}), 200
except Exception as e:
logger.error(f"Error getting user incidents: {str(e)}")
return jsonify({'message': f'Error getting user incidents: {str(e)}'}), 500
def get_department_incidents(current_user):
"""Get all incidents for the user's department"""
incidents = Incident.find_by_department(current_user.department_id)
return jsonify({'incidents': [incident.to_dict() for incident in incidents]}), 200
def get_workflow_incidents(current_user, workflow_id):
"""Get all incidents for a specific workflow"""
# Check if workflow exists and belongs to user's department
workflow = Workflow.find_by_id(workflow_id)
if not workflow:
return jsonify({'message': 'Workflow not found'}), 404
if str(workflow.department_id) != str(current_user.department_id):
return jsonify({'message': 'Access denied to workflows from other departments'}), 403
incidents = Incident.find_by_workflow(workflow_id)
return jsonify({'incidents': [incident.to_dict() for incident in incidents]}), 200
def get_incidents_by_date_range(current_user):
"""Get incidents by date range"""
data = request.get_json()
# Check if required fields are present
if 'start_date' not in data or 'end_date' not in data:
return jsonify({'message': 'Start date and end date are required'}), 400
try:
# Parse date strings
start_date = datetime.strptime(data['start_date'], '%Y-%m-%d').date()
end_date = datetime.strptime(data['end_date'], '%Y-%m-%d').date()
# Get incidents by date range
incidents = Incident.find_by_date_range(current_user.department_id, start_date, end_date)
return jsonify({'incidents': [incident.to_dict() for incident in incidents]}), 200
except ValueError:
return jsonify({'message': 'Invalid date format. Please use YYYY-MM-DD'}), 400
except Exception as e:
logger.error(f"Error fetching incidents by date range: {str(e)}")
return jsonify({'message': f'Error fetching incidents: {str(e)}'}), 500
def reprocess_incident(current_user, incident_id):
"""Reprocess an incident to generate forms"""
# Check if user has admin permissions
if current_user.permissions != 'Admin':
return jsonify({'message': 'Admin permissions required'}), 403
incident = Incident.find_by_id(incident_id)
if not incident:
return jsonify({'message': 'Incident not found'}), 404
# Check if user has access to this incident
if str(incident.department_id) != str(current_user.department_id):
return jsonify({'message': 'Access denied to incidents from other departments'}), 403
try:
# Update incident status
incident.update_status("processing")
# Queue incident for processing
process_incident_forms.delay(str(incident._id))
return jsonify({
'message': 'Incident reprocessing started',
'incident': incident.to_dict()
}), 200
except Exception as e:
logger.error(f"Error reprocessing incident {incident_id}: {str(e)}")
incident.update_status("failed")
return jsonify({'message': f'Error reprocessing incident: {str(e)}'}), 500
def create_incident_from_activity(current_user):
"""Create an incident from activity data and workflow ID"""
try:
data = request.get_json()
# Check if required fields are present
required_fields = ['activity', 'workflow_id', 'date', 'log_text']
for field in required_fields:
if field not in data:
return jsonify({'message': f'Missing required field: {field}'}), 400
# Validate date format
try:
if isinstance(data['date'], str):
date = datetime.strptime(data['date'], '%Y-%m-%d').date()
else:
date = data['date']
except ValueError:
return jsonify({'message': 'Invalid date format. Please use YYYY-MM-DD'}), 400
# Check if workflow exists and user has access
workflow = Workflow.find_by_id(data['workflow_id'])
if not workflow:
return jsonify({'message': 'Workflow not found'}), 404
# Check if user has access to this workflow
if str(workflow.department_id) != str(current_user.department_id):
return jsonify({'message': 'Access denied to workflows from other departments'}), 403
# Create log entry first if log_id is not provided
log_id = data.get('log_id')
if not log_id:
log = Log(
user_id=current_user._id,
department_id=current_user.department_id,
log_date=date,
log_text=data['log_text']
)
if log.save():
log_id = log._id
# Create the incident
incident = Incident(
department_id=current_user.department_id,
user_id=current_user._id,
workflow_id=ObjectId(data['workflow_id']),
description=data['activity'].get('activity', 'No description'),
date=date,
activity_text=data['activity'].get('text', ''),
log_id=log_id,
status="pending"
)
if incident.save():
# Add incident to log if log exists
if log_id:
log = Log.find_by_id(log_id)
if log:
log.add_incident(incident._id)
return jsonify({
'message': 'Incident created successfully',
'incident': incident.to_dict()
}), 201
else:
return jsonify({'message': 'Failed to create incident'}), 500
except Exception as e:
logger.error(f"Error creating incident from activity: {str(e)}")
return jsonify({'message': f'Error creating incident: {str(e)}'}), 500