Files
erp_ai/src/api/routes/sops.py
T

521 lines
23 KiB
Python
Raw Normal View History

2024-08-31 01:29:39 +00:00
import os
from flask import Blueprint, request, jsonify, current_app
from werkzeug.utils import secure_filename
2024-09-09 14:03:14 +01:00
from src.services.sop_generator import (SopPersonalAssessment,SopGeneratorExecutive)
2024-09-10 01:00:08 +01:00
from src.services.sop_document_parser import DocumentParser
2024-08-31 01:29:39 +00:00
from src.utils.utils import delete_all_files_in_directory
from src.utils.document_loader import load_document
import json
# Initialize the Blueprint
sops_bp = Blueprint('sops', __name__)
# Initialize SopGenerator
2024-09-06 01:48:32 +00:00
2024-08-31 01:29:39 +00:00
ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx'}
def allowed_file(filename):
"""Check if the file has an allowed extension."""
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@sops_bp.route('/get_roles', methods=['POST'])
def get_roles():
# Check if the post request has the file part
if 'document' not in request.files:
return jsonify({"error": "No file part", "message": "Please upload a file with the key 'document'."}), 400
file = request.files['document']
# If the user does not select a file, the browser may also submit an empty part without filename
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
# Save the file to the upload folder
file.save(file_path)
try:
# Use the utility function to generate docs from the file
docs = load_document(file_path)
# Generate roles from the docs
roles = sop_generator.get_roles(docs)["roles"]
# Cleanup: Delete all files in the upload directory after processing
delete_all_files_in_directory(upload_folder)
return jsonify({"roles": roles, "message": "Roles successfully extracted from the document."}), 200
except Exception as e:
# Cleanup: Delete all files in the upload directory if an error occurs
delete_all_files_in_directory(upload_folder)
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the document: {str(e)}"}), 500
return jsonify({"error": "File type not allowed", "message": "The uploaded file type is not allowed. Please upload a PDF, DOC, or DOCX file."}), 400
@sops_bp.route('/generate_questions_from_doc', methods=['POST'])
def generate_questions_from_sop():
2024-08-31 01:29:39 +00:00
# Check if the POST request has the file part
if 'document' not in request.files:
return jsonify({"error": "No file part", "message": "Please upload a file with the key 'document'."}), 400
print("Running................")
file = request.files['document']
roles_json = request.form.get('roles') # Get the roles as a JSON string
if not roles_json:
return jsonify({"error": "No roles provided", "message": "Please provide a list of roles in the 'roles' field."}), 400
try:
roles = json.loads(roles_json) # Parse the roles from JSON string to a list
print(f"Roles are:{roles}")
except json.JSONDecodeError:
return jsonify({"error": "Invalid JSON", "message": "The 'roles' field contains invalid JSON."}), 400
# If the user does not select a file, the browser may also submit an empty part without a filename
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
# Save the file to the upload folder
file.save(file_path)
try:
# Use the utility function to generate docs from the file
docs = load_document(file_path)
# Check if the document can generate SOPs for the roles
status_check = sop_generator.check_role_sop(roles=roles, docs=docs)
if not status_check["status"]:
return jsonify({"error": "Document cannot extract SOPs", "message": status_check["message"]}), 400
# Generate SOPs based on the roles provided
2024-09-09 14:03:14 +01:00
sop_generator = DocumentParser()
sops = sop_generator.generate_sops_from_doc(docs)
# Cleanup: Delete all files in the upload directory after processing
delete_all_files_in_directory(upload_folder)
return jsonify({"sops": sops, "message": "SOPs successfully generated for the roles from the document."}), 200
except Exception as e:
# Cleanup: Delete all files in the upload directory if an error occurs
delete_all_files_in_directory(upload_folder)
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the document: {str(e)}"}), 500
return jsonify({"error": "File type not allowed", "message": "The uploaded file type is not allowed. Please upload a PDF, DOC, or DOCX file."}), 400
2024-09-06 01:48:32 +00:00
@sops_bp.route('/personal_assessment/generate_sops_from_doc', methods=['POST'])
def generate_sops():
# Check if the POST request has the file part
if 'document' not in request.files:
return jsonify({"error": "No file part", "message": "Please upload a file with the key 'document'."}), 400
print("Running................")
file = request.files['document']
# If the user does not select a file, the browser may also submit an empty part without a filename
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
# Save the file to the upload folder
file.save(file_path)
try:
# Use the utility function to generate docs from the file
docs = load_document(file_path)
2024-08-31 01:29:39 +00:00
# Generate SOPs based on the roles provided
2024-09-09 14:03:14 +01:00
sop_generator = DocumentParser()
sops = sop_generator.extract_sops_from_doc(docs)
2024-08-31 01:29:39 +00:00
# Cleanup: Delete all files in the upload directory after processing
delete_all_files_in_directory(upload_folder)
if not sops:
return jsonify({"error":"Error in generating sops"})
2024-08-31 01:29:39 +00:00
return jsonify({"sops": sops, "message": "SOPs successfully generated for the roles from the document."}), 200
except Exception as e:
# Cleanup: Delete all files in the upload directory if an error occurs
delete_all_files_in_directory(upload_folder)
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the document: {str(e)}"}), 500
return jsonify({"error": "File type not allowed", "message": "The uploaded file type is not allowed. Please upload a PDF, DOC, or DOCX file."}), 400
2024-09-04 01:22:36 +00:00
@sops_bp.route('/personal_assessment/generate_sops_from_questionnaire', methods=['POST'])
2024-09-06 01:48:32 +00:00
def generate_sops_from_questionnaire_per():
2024-09-04 01:22:36 +00:00
"""
Generate SOPs based on the questionnaire data provided in the request body.
The request body is expected to contain plain-text information for vision, roles, responsibilities, and project details.
2024-09-04 01:22:36 +00:00
"""
try:
# Get the questionnaire data from the request body
questionnaire_data = request.json
# Validate the required fields in the questionnaire data
if not questionnaire_data.get('vision') or not questionnaire_data.get('roles') or not questionnaire_data.get('responsibilities'):
return jsonify({
"error": "Missing required fields",
"message": "Please provide 'vision', 'roles', and 'responsibilities' in the request body."
}), 400
# Step 1: Call the function from the sop_generator
sop_generator = SopPersonalAssessment()
sops_response = sop_generator.extract_sops_from_questionnaire(questionnaire_data)
# Step 2: Return the SOPs if the extraction is successful
if not sops_response:
return jsonify({
"error": "SOP generation failed",
"message": "Failed to generate SOPs based on the provided questionnaire data."
}), 500
return jsonify({
"sops": sops_response,
"message": "SOPs successfully generated based on the provided questionnaire data."
}), 200
2024-09-04 01:22:36 +00:00
except Exception as e:
return jsonify({
"error": "Processing error",
"message": f"An error occurred while generating SOPs: {str(e)}"
}), 500
2024-09-04 01:22:36 +00:00
@sops_bp.route('/personal_assessment/generate_sops_by_roles_and_areas', methods=['POST'])
def generate_sops_by_roles_and_areas():
"""
Generate SOPs based on the roles, SOP types (will, shall, must), and areas provided in the request body.
"""
2024-09-04 01:22:36 +00:00
try:
# Get the roles data from the request body
roles = request.json.get('roles', None)
sop_generator = SopPersonalAssessment()
2024-09-04 01:22:36 +00:00
# Validate the presence of roles data
if not roles or not isinstance(roles, list):
return jsonify({"error": "Invalid input", "message": "The 'roles' field should be a non-empty list."}), 400
2024-09-04 01:22:36 +00:00
# Generate SOPs for all roles at once
sops_response = sop_generator.generate_sops_by_role_and_area(roles=roles)
return jsonify({
"sops": sops_response,
"message": "SOPs successfully generated for all provided roles."
}), 200
except Exception as e:
return jsonify({
"error": "Processing error",
"message": f"An error occurred while generating SOPs: {str(e)}"
}), 500
2024-09-04 01:22:36 +00:00
2024-09-06 01:48:32 +00:00
@sops_bp.route('/executive/generate_sop_mission_from_vision', methods=['POST'])
2024-09-04 01:22:36 +00:00
def generate_executive_sops_from_doc():
"""
Generate SOPs for executives based on a document containing vision and mission.
"""
2024-09-06 01:48:32 +00:00
# Check if the POST request has the file part and roles
2024-09-04 01:22:36 +00:00
if 'document' not in request.files:
return jsonify({"error": "No file part", "message": "Please upload a file with the key 'document'."}), 400
2024-09-06 01:48:32 +00:00
if 'executives' not in request.form:
return jsonify({"error": "No roles provided", "message": "Please provide roles as a JSON array."}), 400
try:
executives = request.form.get('executives')
# Manually load roles from the string to JSON
executives = json.loads(executives)
except json.JSONDecodeError:
return jsonify({"error": "Invalid JSON", "message": "The roles must be a valid JSON array."}), 400
except ValueError as e:
return jsonify({"error": "Invalid roles format", "message": str(e)}), 400
2024-09-04 01:22:36 +00:00
file = request.files['document']
# If the user does not select a file, the browser may also submit an empty part without filename
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
# Save the file to the upload folder
file.save(file_path)
try:
# Use the utility function to generate docs from the file
docs = load_document(file_path)
2024-09-09 14:03:14 +01:00
sop_doc = DocumentParser()
2024-09-06 01:48:32 +00:00
vision_mission = sop_doc.extract_vision_mission(docs)
if not vision_mission:
return jsonify({"error": "Vision and Mission generation error ", "message": "Error in generating mssion and viso."}), 400
2024-09-04 01:22:36 +00:00
2024-09-06 01:48:32 +00:00
# Check if both vision and mission are empty
if not vision_mission.get('vision') and not vision_mission.get('mission'):
2024-09-04 01:22:36 +00:00
# Cleanup: Delete all files in the upload directory if parsing fails
delete_all_files_in_directory(upload_folder)
2024-09-06 01:48:32 +00:00
return jsonify({"error": "Missing Vision and Mission", "message": "The document does not contain mission and vision."}), 400
print(f"Vision and mission: {vision_mission}")
2024-09-04 01:22:36 +00:00
2024-09-06 01:48:32 +00:00
ex_sop = SopGeneratorExecutive()
2024-09-04 01:22:36 +00:00
2024-09-06 01:48:32 +00:00
result = {}
for exe in executives:
sops = ex_sop.extract_sops_from_executive_vision_goals_doc(vision_mission, exe)
result[exe] = sops
2024-09-04 01:22:36 +00:00
# Cleanup: Delete all files in the upload directory after processing
delete_all_files_in_directory(upload_folder)
2024-09-06 01:48:32 +00:00
return jsonify({"sops": result, "message": "SOPs successfully generated from the document."}), 200
2024-09-04 01:22:36 +00:00
except Exception as e:
# Cleanup: Delete all files in the upload directory if an error occurs
delete_all_files_in_directory(upload_folder)
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the document: {str(e)}"}), 500
return jsonify({"error": "File type not allowed", "message": "The uploaded file type is not allowed. Please upload a PDF, DOC, or DOCX file."}), 400
2024-09-06 01:48:32 +00:00
@sops_bp.route('/executive/generate_sop_managers_doc', methods=['POST'])
def generate_sop_managers_doc():
if 'document' not in request.files:
return jsonify({"error": "No file part", "message": "Please upload a file with the key 'document'."}), 400
file = request.files['document']
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
file.save(file_path)
try:
docs = load_document(file_path)
sop_generator = SopGeneratorExecutive()
result = sop_generator.generate_sops_for_department_managers(docs)
delete_all_files_in_directory(upload_folder)
if not result:
return jsonify({"error": "Processing error", "message": "Failed to generate SOPs for department managers."}), 500
return jsonify({"sops": result.dict(), "message": "SOPs successfully generated for department managers."}), 200
except Exception as e:
delete_all_files_in_directory(upload_folder)
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the document: {str(e)}"}), 500
return jsonify({"error": "File type not allowed", "message": "The uploaded file type is not allowed. Please upload a PDF, DOC, or DOCX file."}), 400
@sops_bp.route('/executive/generate_sops_from_questionnaire', methods=['POST'])
def generate_sops_from_questionnaire():
try:
data = request.json
questionnaire_data = data.get('questionnaire')
executives = data.get('executives', [])
managers = data.get('managers', [])
departments = data.get('departments', [])
if not questionnaire_data or not executives or not managers or not departments:
return jsonify({"error": "Missing data", "message": "Please provide questionnaire data, executives, managers, and departments."}), 400
sop_generator = SopGeneratorExecutive()
result = sop_generator.generate_sops_from_questionnaire(questionnaire_data, executives, managers, departments)
if not result:
return jsonify({"error": "Processing error", "message": "Failed to generate SOPs from questionnaire."}), 500
# Convert Pydantic models to dictionaries
serializable_result = {
"executive_sops": {exec: sops.dict() for exec, sops in result["executive_sops"].items()},
"department_sops": result["department_sops"].dict()
}
return jsonify({"sops": serializable_result, "message": "SOPs successfully generated from questionnaire."}), 200
except Exception as e:
2024-09-09 14:03:14 +01:00
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
2024-09-10 01:00:08 +01:00
@sops_bp.route('/executive/get_roles_for_reference_managers', methods=['POST'])
def get_roles_for_reference_managers():
2024-09-09 14:03:14 +01:00
try:
# Retrieve form data
2024-09-10 01:00:08 +01:00
reference_roles_text = request.form.get('reference_roles') # Reference roles sent as text
file = request.files.get('document') # The uploaded document
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
if not reference_roles_text or not file:
2024-09-09 14:03:14 +01:00
return jsonify({"error": "Missing data", "message": "Reference roles or document not provided."}), 400
2024-09-10 01:00:08 +01:00
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
# Convert reference_roles_text to JSON (list)
try:
reference_roles = json.loads(reference_roles_text) # Convert text to JSON (list)
except json.JSONDecodeError:
return jsonify({"error": "Invalid format", "message": "The reference roles should be in a valid JSON format."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
file.save(file_path)
docs = load_document(file_path)
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
# Use extractor to extract roles from the document
extractor = DocumentParser()
roles_comparison_with_doc = extractor.extract_roles_with_reference_managers(docs=docs, reference_roles=reference_roles)
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
if not roles_comparison_with_doc:
return jsonify({"error": "Processing error", "message": "No roles found matching the reference roles."}), 404
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
return jsonify({"roles_info": roles_comparison_with_doc, "message": "Roles comparison successfully generated."}), 200
2024-09-09 14:03:14 +01:00
except Exception as e:
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
2024-09-10 01:00:08 +01:00
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
@sops_bp.route('/manager/get_roles_for_reference_workers', methods=['POST'])
def get_roles_for_reference_workers():
try:
# Retrieve form data
reference_roles_text = request.form.get('reference_roles') # Reference roles sent as text
file = request.files.get('document') # The uploaded document
if not reference_roles_text or not file:
return jsonify({"error": "Missing data", "message": "Reference roles or document not provided."}), 400
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
# Convert reference_roles_text to JSON (list)
try:
reference_roles = json.loads(reference_roles_text) # Convert text to JSON (list)
except json.JSONDecodeError:
return jsonify({"error": "Invalid format", "message": "The reference roles should be in a valid JSON format."}), 400
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
file.save(file_path)
docs = load_document(file_path)
# Use extractor to extract roles from the document
extractor = DocumentParser()
roles_comparison_with_doc = extractor.extract_roles_with_reference_workers(docs=docs, reference_roles=reference_roles)
if not roles_comparison_with_doc:
return jsonify({"error": "Processing error", "message": "No roles found matching the reference roles."}), 404
return jsonify({"roles_info": roles_comparison_with_doc, "message": "Roles comparison successfully generated."}), 200
2024-09-09 14:03:14 +01:00
except Exception as e:
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the request: {str(e)}"}), 500
2024-09-10 01:00:08 +01:00
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
@sops_bp.route('/manager/generate_sop_workers_doc', methods=['POST'])
def generate_sop_workers_doc():
try:
# Check if the document is provided
if 'document' not in request.files:
return jsonify({"error": "No file part", "message": "Please upload a file with the key 'document'."}), 400
2024-09-09 14:03:14 +01:00
2024-09-10 01:00:08 +01:00
file = request.files['document']
# Check if the file is selected
if file.filename == '':
return jsonify({"error": "No selected file", "message": "A file was not selected for upload. Please select a valid file."}), 400
# Check if the file type is allowed
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
upload_folder = current_app.config['UPLOAD_FOLDER']
file_path = os.path.join(upload_folder, filename)
file.save(file_path)
else:
return jsonify({"error": "File type not allowed", "message": "The uploaded file type is not allowed. Please upload a PDF, DOC, or DOCX file."}), 400
# Get workers information from the form data (passed as JSON text)
workers_info_text = request.form.get('workers_info')
if not workers_info_text:
return jsonify({"error": "Missing data", "message": "Workers info is required in the form data."}), 400
# Load workers information as a list of dictionaries
try:
workers_list = json.loads(workers_info_text)
except json.JSONDecodeError:
return jsonify({"error": "Invalid data format", "message": "Workers info should be a valid JSON array."}), 400
# Now load the document
docs = load_document(file_path)
# Generate SOPs for workers by department using SopGeneratorExecutive
sop_generator = DocumentParser()
result = sop_generator.extract_sops_for_workers_by_department(docs, workers_list)
# Clean up the file
delete_all_files_in_directory(upload_folder)
if not result:
return jsonify({"error": "Processing error", "message": "Failed to generate SOPs for workers."}), 500
return jsonify({"sops": result, "message": "SOPs successfully generated for workers."}), 200
except Exception as e:
delete_all_files_in_directory(upload_folder)
return jsonify({"error": "Processing error", "message": f"An error occurred while processing the document: {str(e)}"}), 500