import os from flask import Blueprint, request, jsonify, current_app from werkzeug.utils import secure_filename from src.services.sop_generator import (SopGenerator,SopGeneratorDocument, SopPersonalAssessment) 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 sop_generator = SopGenerator() 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(): # 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 sop_generator = SopGeneratorDocument() 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 @sops_bp.route('/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) # Generate SOPs based on the roles provided sop_generator = SopGeneratorDocument() sops = sop_generator.extract_sops_from_doc(docs) # 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"}) 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 @sops_bp.route('/personal_assessment/generate_sops_from_questionnaire', methods=['POST']) def generate_sops_from_questionnaire(): """ 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. """ 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 except Exception as e: return jsonify({ "error": "Processing error", "message": f"An error occurred while generating SOPs: {str(e)}" }), 500 @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. """ try: # Get the roles data from the request body roles = request.json.get('roles', None) sop_generator = SopPersonalAssessment() # 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 # 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 @sops_bp.route('/executive/generate_sops_from_questionnaire', methods=['POST']) def generate_executive_sops_from_questionnaire(): try: # Get data from the request body data = request.json # Generate SOPs based on the questionnaire answers sops_response = sop_generator.generate_executive_sops_from_questionnaire(data) return jsonify({"sops": sops_response, "message": "SOPs successfully generated from the questionnaire."}), 200 except Exception as e: return jsonify({"error": "Processing error", "message": f"An error occurred while generating SOPs: {str(e)}"}), 500 @sops_bp.route('/executive/generate_sops_from_doc', methods=['POST']) def generate_executive_sops_from_doc(): """ Generate SOPs for executives based on a document containing vision and mission. """ # 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) # Use LLM to extract Vision and Mission sections from the document vision_section, mission_section = sop_generator.extract_vision_and_mission(docs) if not vision_section or not mission_section: # Cleanup: Delete all files in the upload directory if parsing fails delete_all_files_in_directory(upload_folder) return jsonify({"error": "Missing Vision and Mission", "message": "The document does not contain or properly define the company's vision and mission."}), 400 # Organize extracted data extracted_data = { "role": "Executive", "organization vision": [vision_section], "organization strategic goals": [mission_section] } # Generate SOPs based on the extracted vision and goals sops_response = sop_generator.generate_executive_sops_from_questionnaire(extracted_data) # Cleanup: Delete all files in the upload directory after processing delete_all_files_in_directory(upload_folder) return jsonify({"sops": sops_response, "message": "SOPs successfully generated 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