Emmanuel Frimpong Asante
commited on
Commit
·
318368c
1
Parent(s):
7fc8dba
"Update space"
Browse filesSigned-off-by: Emmanuel Frimpong Asante <[email protected]>
- controllers/data_logging.py +62 -42
- controllers/health_management.py +20 -13
- controllers/inventory.py +47 -31
- controllers/usage_tracking.py +31 -14
- routes/api.py +132 -16
- routes/data_logging_routes.py +64 -7
- routes/health_routes.py +46 -11
- routes/inventory_routes.py +38 -7
- routes/usage_routes.py +24 -6
- services/disease_detection.py +41 -27
- services/gradio_interface.py +0 -37
- services/inventory_manager.py +11 -8
- services/llama_service.py +28 -7
- services/report_generator.py +48 -48
- services/usage_tracker.py +35 -15
controllers/data_logging.py
CHANGED
|
@@ -7,7 +7,7 @@ from models.schemas.inventory_schema import create_inventory_item, update_invent
|
|
| 7 |
from models.schemas.usage_schema import create_usage_record
|
| 8 |
|
| 9 |
|
| 10 |
-
# Log a general user action
|
| 11 |
def log_user_action(user_id, message, level="INFO", metadata=None):
|
| 12 |
"""
|
| 13 |
Logs a general user action.
|
|
@@ -15,15 +15,17 @@ def log_user_action(user_id, message, level="INFO", metadata=None):
|
|
| 15 |
:param user_id: The ID of the user performing the action.
|
| 16 |
:param message: Description of the action.
|
| 17 |
:param level: Log level (default is "INFO").
|
| 18 |
-
:param metadata: Additional
|
| 19 |
-
:return: JSON response
|
| 20 |
"""
|
| 21 |
try:
|
| 22 |
-
ip_address = request.remote_addr #
|
| 23 |
log_id = create_log(level, message, metadata, ip_address, user_id)
|
| 24 |
return jsonify({"message": "Action logged successfully", "log_id": log_id}), 201
|
|
|
|
|
|
|
| 25 |
except Exception as e:
|
| 26 |
-
return jsonify({"error": str(e)}), 500
|
| 27 |
|
| 28 |
|
| 29 |
# Log a health record for a poultry bird
|
|
@@ -31,86 +33,104 @@ def log_health_record(user_id, poultry_id, disease_name, status, recommendation,
|
|
| 31 |
"""
|
| 32 |
Logs a health record for a poultry bird.
|
| 33 |
|
| 34 |
-
:param user_id:
|
| 35 |
-
:param poultry_id:
|
| 36 |
-
:param disease_name:
|
| 37 |
-
:param status:
|
| 38 |
-
:param recommendation:
|
| 39 |
-
:param image_path: Optional
|
| 40 |
-
:return: JSON response
|
| 41 |
"""
|
| 42 |
try:
|
|
|
|
| 43 |
record_id = create_health_record(user_id, poultry_id, disease_name, status, recommendation, image_path)
|
| 44 |
-
|
|
|
|
| 45 |
log_message = f"Health record created for poultry ID {poultry_id} - Disease: {disease_name}"
|
| 46 |
log_user_action(user_id, log_message, "INFO")
|
|
|
|
| 47 |
return jsonify({"message": "Health record logged successfully", "record_id": record_id}), 201
|
|
|
|
|
|
|
| 48 |
except Exception as e:
|
| 49 |
-
return jsonify({"error": str(e)}), 500
|
| 50 |
|
| 51 |
|
| 52 |
# Log an addition to the inventory
|
| 53 |
def log_inventory_addition(user_id, item_name, category, quantity, unit, description=None):
|
| 54 |
"""
|
| 55 |
-
Logs an inventory addition (e.g., adding feed
|
| 56 |
-
|
| 57 |
-
:param user_id:
|
| 58 |
-
:param item_name:
|
| 59 |
-
:param category:
|
| 60 |
-
:param quantity:
|
| 61 |
-
:param unit:
|
| 62 |
-
:param description: Optional
|
| 63 |
-
:return: JSON response
|
| 64 |
"""
|
| 65 |
try:
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
| 68 |
log_message = f"Inventory item added: {item_name}, Quantity: {quantity} {unit}"
|
| 69 |
log_user_action(user_id, log_message, "INFO")
|
|
|
|
| 70 |
return jsonify({"message": "Inventory item logged successfully", "item_id": item_id}), 201
|
|
|
|
|
|
|
| 71 |
except Exception as e:
|
| 72 |
-
return jsonify({"error": str(e)}), 500
|
| 73 |
|
| 74 |
|
| 75 |
-
# Log updates to an inventory item
|
| 76 |
def log_inventory_update(user_id, item_id, updated_fields):
|
| 77 |
"""
|
| 78 |
-
Logs
|
| 79 |
|
| 80 |
-
:param user_id:
|
| 81 |
-
:param item_id:
|
| 82 |
-
:param updated_fields:
|
| 83 |
-
:return: JSON response
|
| 84 |
"""
|
| 85 |
try:
|
|
|
|
| 86 |
update_success = update_inventory_item(item_id, updated_fields)
|
| 87 |
if update_success:
|
| 88 |
-
# Log
|
| 89 |
log_message = f"Inventory item updated: {item_id} - {updated_fields}"
|
| 90 |
log_user_action(user_id, log_message, "INFO")
|
| 91 |
return jsonify({"message": "Inventory item updated successfully"}), 200
|
| 92 |
else:
|
| 93 |
return jsonify({"message": "Inventory item update failed"}), 400
|
|
|
|
|
|
|
| 94 |
except Exception as e:
|
| 95 |
-
return jsonify({"error": str(e)}), 500
|
| 96 |
|
| 97 |
|
| 98 |
# Log assistant usage by a user
|
| 99 |
def log_assistant_usage(user_id, manager_id, interaction_type, metadata=None):
|
| 100 |
"""
|
| 101 |
-
Logs
|
| 102 |
|
| 103 |
-
:param user_id:
|
| 104 |
-
:param manager_id:
|
| 105 |
-
:param interaction_type:
|
| 106 |
-
:param metadata: Optional
|
| 107 |
-
:return: JSON response
|
| 108 |
"""
|
| 109 |
try:
|
|
|
|
| 110 |
usage_record_id = create_usage_record(user_id, manager_id, interaction_type, metadata)
|
| 111 |
-
|
|
|
|
| 112 |
log_message = f"Assistant interaction logged: {interaction_type} by user {user_id}"
|
| 113 |
log_user_action(user_id, log_message, "INFO", metadata)
|
|
|
|
| 114 |
return jsonify({"message": "Assistant usage logged successfully", "usage_record_id": usage_record_id}), 201
|
|
|
|
|
|
|
| 115 |
except Exception as e:
|
| 116 |
-
return jsonify({"error": str(e)}), 500
|
|
|
|
| 7 |
from models.schemas.usage_schema import create_usage_record
|
| 8 |
|
| 9 |
|
| 10 |
+
# Log a general user action
|
| 11 |
def log_user_action(user_id, message, level="INFO", metadata=None):
|
| 12 |
"""
|
| 13 |
Logs a general user action.
|
|
|
|
| 15 |
:param user_id: The ID of the user performing the action.
|
| 16 |
:param message: Description of the action.
|
| 17 |
:param level: Log level (default is "INFO").
|
| 18 |
+
:param metadata: Additional metadata or context for the action.
|
| 19 |
+
:return: JSON response with log creation result.
|
| 20 |
"""
|
| 21 |
try:
|
| 22 |
+
ip_address = request.remote_addr # Capture user's IP address
|
| 23 |
log_id = create_log(level, message, metadata, ip_address, user_id)
|
| 24 |
return jsonify({"message": "Action logged successfully", "log_id": log_id}), 201
|
| 25 |
+
except KeyError as e:
|
| 26 |
+
return jsonify({"error": f"Missing field: {str(e)}"}), 400
|
| 27 |
except Exception as e:
|
| 28 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 29 |
|
| 30 |
|
| 31 |
# Log a health record for a poultry bird
|
|
|
|
| 33 |
"""
|
| 34 |
Logs a health record for a poultry bird.
|
| 35 |
|
| 36 |
+
:param user_id: ID of the user managing the poultry.
|
| 37 |
+
:param poultry_id: Unique identifier for the poultry.
|
| 38 |
+
:param disease_name: Detected disease name.
|
| 39 |
+
:param status: Health status of the poultry.
|
| 40 |
+
:param recommendation: Recommended treatment or action.
|
| 41 |
+
:param image_path: Optional image related to the health record.
|
| 42 |
+
:return: JSON response with health record logging result.
|
| 43 |
"""
|
| 44 |
try:
|
| 45 |
+
# Create health record in database
|
| 46 |
record_id = create_health_record(user_id, poultry_id, disease_name, status, recommendation, image_path)
|
| 47 |
+
|
| 48 |
+
# Log action for health record creation
|
| 49 |
log_message = f"Health record created for poultry ID {poultry_id} - Disease: {disease_name}"
|
| 50 |
log_user_action(user_id, log_message, "INFO")
|
| 51 |
+
|
| 52 |
return jsonify({"message": "Health record logged successfully", "record_id": record_id}), 201
|
| 53 |
+
except KeyError as e:
|
| 54 |
+
return jsonify({"error": f"Missing field: {str(e)}"}), 400
|
| 55 |
except Exception as e:
|
| 56 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 57 |
|
| 58 |
|
| 59 |
# Log an addition to the inventory
|
| 60 |
def log_inventory_addition(user_id, item_name, category, quantity, unit, description=None):
|
| 61 |
"""
|
| 62 |
+
Logs an inventory addition (e.g., adding feed or medicine).
|
| 63 |
+
|
| 64 |
+
:param user_id: ID of the user managing the inventory.
|
| 65 |
+
:param item_name: Name of the inventory item.
|
| 66 |
+
:param category: Category of the item (e.g., "Feed", "Medicine").
|
| 67 |
+
:param quantity: Quantity added.
|
| 68 |
+
:param unit: Unit of measurement (e.g., "kg", "liters").
|
| 69 |
+
:param description: Optional notes or description of the item.
|
| 70 |
+
:return: JSON response with inventory addition result.
|
| 71 |
"""
|
| 72 |
try:
|
| 73 |
+
# Add inventory item to database
|
| 74 |
+
item_id = create_inventory_item(item_name, category, quantity, unit, user_id, description)
|
| 75 |
+
|
| 76 |
+
# Log action for inventory addition
|
| 77 |
log_message = f"Inventory item added: {item_name}, Quantity: {quantity} {unit}"
|
| 78 |
log_user_action(user_id, log_message, "INFO")
|
| 79 |
+
|
| 80 |
return jsonify({"message": "Inventory item logged successfully", "item_id": item_id}), 201
|
| 81 |
+
except KeyError as e:
|
| 82 |
+
return jsonify({"error": f"Missing field: {str(e)}"}), 400
|
| 83 |
except Exception as e:
|
| 84 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 85 |
|
| 86 |
|
| 87 |
+
# Log updates to an inventory item
|
| 88 |
def log_inventory_update(user_id, item_id, updated_fields):
|
| 89 |
"""
|
| 90 |
+
Logs updates to an existing inventory item.
|
| 91 |
|
| 92 |
+
:param user_id: ID of the user managing the inventory.
|
| 93 |
+
:param item_id: ID of the inventory item being updated.
|
| 94 |
+
:param updated_fields: Dictionary containing updated fields (e.g., "quantity", "used_quantity").
|
| 95 |
+
:return: JSON response with inventory update result.
|
| 96 |
"""
|
| 97 |
try:
|
| 98 |
+
# Update inventory item in database
|
| 99 |
update_success = update_inventory_item(item_id, updated_fields)
|
| 100 |
if update_success:
|
| 101 |
+
# Log action for inventory update
|
| 102 |
log_message = f"Inventory item updated: {item_id} - {updated_fields}"
|
| 103 |
log_user_action(user_id, log_message, "INFO")
|
| 104 |
return jsonify({"message": "Inventory item updated successfully"}), 200
|
| 105 |
else:
|
| 106 |
return jsonify({"message": "Inventory item update failed"}), 400
|
| 107 |
+
except KeyError as e:
|
| 108 |
+
return jsonify({"error": f"Missing field: {str(e)}"}), 400
|
| 109 |
except Exception as e:
|
| 110 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 111 |
|
| 112 |
|
| 113 |
# Log assistant usage by a user
|
| 114 |
def log_assistant_usage(user_id, manager_id, interaction_type, metadata=None):
|
| 115 |
"""
|
| 116 |
+
Logs usage of the assistant by a user.
|
| 117 |
|
| 118 |
+
:param user_id: ID of the user interacting with the assistant.
|
| 119 |
+
:param manager_id: ID of the user's manager.
|
| 120 |
+
:param interaction_type: Type of interaction (e.g., "disease_detection", "inventory_management").
|
| 121 |
+
:param metadata: Optional additional details about the interaction.
|
| 122 |
+
:return: JSON response with assistant usage logging result.
|
| 123 |
"""
|
| 124 |
try:
|
| 125 |
+
# Log assistant usage in database
|
| 126 |
usage_record_id = create_usage_record(user_id, manager_id, interaction_type, metadata)
|
| 127 |
+
|
| 128 |
+
# Log action for assistant usage
|
| 129 |
log_message = f"Assistant interaction logged: {interaction_type} by user {user_id}"
|
| 130 |
log_user_action(user_id, log_message, "INFO", metadata)
|
| 131 |
+
|
| 132 |
return jsonify({"message": "Assistant usage logged successfully", "usage_record_id": usage_record_id}), 201
|
| 133 |
+
except KeyError as e:
|
| 134 |
+
return jsonify({"error": f"Missing field: {str(e)}"}), 400
|
| 135 |
except Exception as e:
|
| 136 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
controllers/health_management.py
CHANGED
|
@@ -5,29 +5,28 @@ from models.schemas.health_schema import create_health_record, get_health_record
|
|
| 5 |
from services.disease_detection import detect_disease
|
| 6 |
from controllers.data_logging import log_health_record
|
| 7 |
|
| 8 |
-
|
| 9 |
# Detect Disease and Log Health Record
|
| 10 |
def detect_and_log_disease():
|
| 11 |
"""
|
| 12 |
-
|
| 13 |
-
Expects a POST request with
|
| 14 |
- user_id: ID of the user submitting the disease detection request.
|
| 15 |
-
- poultry_id:
|
| 16 |
- image: Image of the poultry feces for disease detection (binary file).
|
| 17 |
|
| 18 |
Returns:
|
| 19 |
- JSON response with the disease detection result and health record logging status.
|
| 20 |
"""
|
| 21 |
try:
|
| 22 |
-
#
|
| 23 |
user_id = request.form.get('user_id')
|
| 24 |
poultry_id = request.form.get('poultry_id')
|
| 25 |
image = request.files.get('image')
|
| 26 |
|
| 27 |
-
if not user_id
|
| 28 |
return jsonify({"error": "Missing required fields: user_id, poultry_id, or image"}), 400
|
| 29 |
|
| 30 |
-
#
|
| 31 |
disease_name, status, recommendation = detect_disease(image)
|
| 32 |
|
| 33 |
# Log the health record
|
|
@@ -47,8 +46,12 @@ def detect_and_log_disease():
|
|
| 47 |
"record_id": record_id
|
| 48 |
}), 201
|
| 49 |
|
|
|
|
|
|
|
|
|
|
| 50 |
except Exception as e:
|
| 51 |
-
|
|
|
|
| 52 |
|
| 53 |
|
| 54 |
# Get Health Record by ID
|
|
@@ -65,12 +68,14 @@ def get_health_record(record_id):
|
|
| 65 |
try:
|
| 66 |
health_record = get_health_record_by_id(record_id)
|
| 67 |
if not health_record:
|
| 68 |
-
return jsonify({"
|
| 69 |
|
| 70 |
return jsonify(health_record), 200
|
| 71 |
|
|
|
|
|
|
|
| 72 |
except Exception as e:
|
| 73 |
-
return jsonify({"error": str(e)}), 500
|
| 74 |
|
| 75 |
|
| 76 |
# Get Health Records by User
|
|
@@ -82,14 +87,16 @@ def get_health_records_for_user(user_id):
|
|
| 82 |
- user_id: ID of the user whose records are being requested.
|
| 83 |
|
| 84 |
Returns:
|
| 85 |
-
- JSON response with the list of health records for the user or an error message if
|
| 86 |
"""
|
| 87 |
try:
|
| 88 |
health_records = get_health_records_by_user(user_id)
|
| 89 |
if not health_records:
|
| 90 |
-
return jsonify({"
|
| 91 |
|
| 92 |
return jsonify(health_records), 200
|
| 93 |
|
|
|
|
|
|
|
| 94 |
except Exception as e:
|
| 95 |
-
return jsonify({"error": str(e)}), 500
|
|
|
|
| 5 |
from services.disease_detection import detect_disease
|
| 6 |
from controllers.data_logging import log_health_record
|
| 7 |
|
|
|
|
| 8 |
# Detect Disease and Log Health Record
|
| 9 |
def detect_and_log_disease():
|
| 10 |
"""
|
| 11 |
+
Detects disease from the provided image and logs the health record.
|
| 12 |
+
Expects a POST request with:
|
| 13 |
- user_id: ID of the user submitting the disease detection request.
|
| 14 |
+
- poultry_id: ID of the poultry bird.
|
| 15 |
- image: Image of the poultry feces for disease detection (binary file).
|
| 16 |
|
| 17 |
Returns:
|
| 18 |
- JSON response with the disease detection result and health record logging status.
|
| 19 |
"""
|
| 20 |
try:
|
| 21 |
+
# Validate the input
|
| 22 |
user_id = request.form.get('user_id')
|
| 23 |
poultry_id = request.form.get('poultry_id')
|
| 24 |
image = request.files.get('image')
|
| 25 |
|
| 26 |
+
if not all([user_id, poultry_id, image]):
|
| 27 |
return jsonify({"error": "Missing required fields: user_id, poultry_id, or image"}), 400
|
| 28 |
|
| 29 |
+
# Detect disease
|
| 30 |
disease_name, status, recommendation = detect_disease(image)
|
| 31 |
|
| 32 |
# Log the health record
|
|
|
|
| 46 |
"record_id": record_id
|
| 47 |
}), 201
|
| 48 |
|
| 49 |
+
except KeyError as e:
|
| 50 |
+
# Specific handling for missing fields
|
| 51 |
+
return jsonify({"error": f"Missing field in request: {str(e)}"}), 400
|
| 52 |
except Exception as e:
|
| 53 |
+
# General error handling
|
| 54 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 55 |
|
| 56 |
|
| 57 |
# Get Health Record by ID
|
|
|
|
| 68 |
try:
|
| 69 |
health_record = get_health_record_by_id(record_id)
|
| 70 |
if not health_record:
|
| 71 |
+
return jsonify({"error": "Health record not found"}), 404
|
| 72 |
|
| 73 |
return jsonify(health_record), 200
|
| 74 |
|
| 75 |
+
except ValueError:
|
| 76 |
+
return jsonify({"error": "Invalid record ID format"}), 400
|
| 77 |
except Exception as e:
|
| 78 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 79 |
|
| 80 |
|
| 81 |
# Get Health Records by User
|
|
|
|
| 87 |
- user_id: ID of the user whose records are being requested.
|
| 88 |
|
| 89 |
Returns:
|
| 90 |
+
- JSON response with the list of health records for the user or an error message if none are found.
|
| 91 |
"""
|
| 92 |
try:
|
| 93 |
health_records = get_health_records_by_user(user_id)
|
| 94 |
if not health_records:
|
| 95 |
+
return jsonify({"error": "No health records found for this user"}), 404
|
| 96 |
|
| 97 |
return jsonify(health_records), 200
|
| 98 |
|
| 99 |
+
except ValueError:
|
| 100 |
+
return jsonify({"error": "Invalid user ID format"}), 400
|
| 101 |
except Exception as e:
|
| 102 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
controllers/inventory.py
CHANGED
|
@@ -1,8 +1,12 @@
|
|
| 1 |
# controllers/inventory.py
|
| 2 |
|
| 3 |
from flask import request, jsonify
|
| 4 |
-
from models.schemas.inventory_schema import
|
|
|
|
|
|
|
|
|
|
| 5 |
get_all_inventory_items
|
|
|
|
| 6 |
from controllers.data_logging import log_inventory_addition, log_inventory_update
|
| 7 |
|
| 8 |
|
|
@@ -11,30 +15,34 @@ def add_inventory_item():
|
|
| 11 |
"""
|
| 12 |
Adds a new inventory item to the system.
|
| 13 |
|
| 14 |
-
Expects:
|
| 15 |
- user_id: The ID of the user adding the item.
|
| 16 |
-
- item_name:
|
| 17 |
-
- category:
|
| 18 |
-
- quantity:
|
| 19 |
-
- unit:
|
| 20 |
-
- description: Optional
|
| 21 |
|
| 22 |
Returns:
|
| 23 |
- JSON response with the result of the addition.
|
| 24 |
"""
|
| 25 |
try:
|
| 26 |
-
# Extract data
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
description = request.json.get('description')
|
| 33 |
-
|
| 34 |
-
if not user_id or not item_name or not category or not quantity or not unit:
|
| 35 |
return jsonify({"error": "Missing required fields"}), 400
|
| 36 |
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
item_id = create_inventory_item(item_name, category, quantity, unit, user_id, description)
|
| 39 |
|
| 40 |
# Log the inventory addition
|
|
@@ -42,16 +50,18 @@ def add_inventory_item():
|
|
| 42 |
|
| 43 |
return jsonify({"message": "Inventory item added successfully", "item_id": item_id}), 201
|
| 44 |
|
|
|
|
|
|
|
| 45 |
except Exception as e:
|
| 46 |
-
return jsonify({"error": str(e)}), 500
|
| 47 |
|
| 48 |
|
| 49 |
# Update an existing inventory item
|
| 50 |
def update_inventory_item_by_id():
|
| 51 |
"""
|
| 52 |
-
Updates an existing inventory item.
|
| 53 |
|
| 54 |
-
Expects:
|
| 55 |
- user_id: The ID of the user updating the item.
|
| 56 |
- item_id: The ID of the inventory item to update.
|
| 57 |
- updated_fields: Dictionary containing fields to update (e.g., "quantity", "used_quantity").
|
|
@@ -60,16 +70,18 @@ def update_inventory_item_by_id():
|
|
| 60 |
- JSON response with the result of the update.
|
| 61 |
"""
|
| 62 |
try:
|
| 63 |
-
# Extract data
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
|
|
|
| 67 |
|
| 68 |
-
if not user_id
|
| 69 |
return jsonify({"error": "Missing required fields"}), 400
|
| 70 |
|
| 71 |
-
# Update the inventory item
|
| 72 |
update_success = update_inventory_item(item_id, updated_fields)
|
|
|
|
| 73 |
if update_success:
|
| 74 |
# Log the inventory update
|
| 75 |
log_inventory_update(user_id, item_id, updated_fields)
|
|
@@ -77,8 +89,10 @@ def update_inventory_item_by_id():
|
|
| 77 |
else:
|
| 78 |
return jsonify({"message": "Inventory item update failed"}), 400
|
| 79 |
|
|
|
|
|
|
|
| 80 |
except Exception as e:
|
| 81 |
-
return jsonify({"error": str(e)}), 500
|
| 82 |
|
| 83 |
|
| 84 |
# Get an inventory item by its ID
|
|
@@ -87,7 +101,7 @@ def get_inventory_by_id(item_id):
|
|
| 87 |
Retrieves an inventory item by its item_id (MongoDB ObjectId).
|
| 88 |
|
| 89 |
Expects:
|
| 90 |
-
- item_id: ID of the inventory item.
|
| 91 |
|
| 92 |
Returns:
|
| 93 |
- JSON response with the inventory item details.
|
|
@@ -99,14 +113,16 @@ def get_inventory_by_id(item_id):
|
|
| 99 |
|
| 100 |
return jsonify(inventory_item), 200
|
| 101 |
|
|
|
|
|
|
|
| 102 |
except Exception as e:
|
| 103 |
-
return jsonify({"error": str(e)}), 500
|
| 104 |
|
| 105 |
|
| 106 |
# Get all inventory items
|
| 107 |
def get_all_inventory():
|
| 108 |
"""
|
| 109 |
-
Retrieves all inventory items.
|
| 110 |
|
| 111 |
Returns:
|
| 112 |
- JSON response with the list of all inventory items.
|
|
@@ -119,4 +135,4 @@ def get_all_inventory():
|
|
| 119 |
return jsonify(inventory_items), 200
|
| 120 |
|
| 121 |
except Exception as e:
|
| 122 |
-
return jsonify({"error": str(e)}), 500
|
|
|
|
| 1 |
# controllers/inventory.py
|
| 2 |
|
| 3 |
from flask import request, jsonify
|
| 4 |
+
from models.schemas.inventory_schema import (
|
| 5 |
+
create_inventory_item,
|
| 6 |
+
update_inventory_item,
|
| 7 |
+
get_inventory_item_by_id,
|
| 8 |
get_all_inventory_items
|
| 9 |
+
)
|
| 10 |
from controllers.data_logging import log_inventory_addition, log_inventory_update
|
| 11 |
|
| 12 |
|
|
|
|
| 15 |
"""
|
| 16 |
Adds a new inventory item to the system.
|
| 17 |
|
| 18 |
+
Expects a POST request with:
|
| 19 |
- user_id: The ID of the user adding the item.
|
| 20 |
+
- item_name: The name of the inventory item.
|
| 21 |
+
- category: The category of the item (e.g., "Feed", "Medicine").
|
| 22 |
+
- quantity: The total quantity of the item.
|
| 23 |
+
- unit: The unit of measurement (e.g., "kg", "liters").
|
| 24 |
+
- description: Optional additional notes about the item.
|
| 25 |
|
| 26 |
Returns:
|
| 27 |
- JSON response with the result of the addition.
|
| 28 |
"""
|
| 29 |
try:
|
| 30 |
+
# Extract request data
|
| 31 |
+
data = request.json
|
| 32 |
+
required_fields = ['user_id', 'item_name', 'category', 'quantity', 'unit']
|
| 33 |
+
|
| 34 |
+
# Validate required fields
|
| 35 |
+
if not all(field in data for field in required_fields):
|
|
|
|
|
|
|
|
|
|
| 36 |
return jsonify({"error": "Missing required fields"}), 400
|
| 37 |
|
| 38 |
+
user_id = data['user_id']
|
| 39 |
+
item_name = data['item_name']
|
| 40 |
+
category = data['category']
|
| 41 |
+
quantity = data['quantity']
|
| 42 |
+
unit = data['unit']
|
| 43 |
+
description = data.get('description', '')
|
| 44 |
+
|
| 45 |
+
# Add the inventory item to the database
|
| 46 |
item_id = create_inventory_item(item_name, category, quantity, unit, user_id, description)
|
| 47 |
|
| 48 |
# Log the inventory addition
|
|
|
|
| 50 |
|
| 51 |
return jsonify({"message": "Inventory item added successfully", "item_id": item_id}), 201
|
| 52 |
|
| 53 |
+
except KeyError as e:
|
| 54 |
+
return jsonify({"error": f"Missing field in request: {str(e)}"}), 400
|
| 55 |
except Exception as e:
|
| 56 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 57 |
|
| 58 |
|
| 59 |
# Update an existing inventory item
|
| 60 |
def update_inventory_item_by_id():
|
| 61 |
"""
|
| 62 |
+
Updates an existing inventory item in the system.
|
| 63 |
|
| 64 |
+
Expects a PUT request with:
|
| 65 |
- user_id: The ID of the user updating the item.
|
| 66 |
- item_id: The ID of the inventory item to update.
|
| 67 |
- updated_fields: Dictionary containing fields to update (e.g., "quantity", "used_quantity").
|
|
|
|
| 70 |
- JSON response with the result of the update.
|
| 71 |
"""
|
| 72 |
try:
|
| 73 |
+
# Extract request data
|
| 74 |
+
data = request.json
|
| 75 |
+
user_id = data.get('user_id')
|
| 76 |
+
item_id = data.get('item_id')
|
| 77 |
+
updated_fields = data.get('updated_fields')
|
| 78 |
|
| 79 |
+
if not all([user_id, item_id, updated_fields]):
|
| 80 |
return jsonify({"error": "Missing required fields"}), 400
|
| 81 |
|
| 82 |
+
# Update the inventory item in the database
|
| 83 |
update_success = update_inventory_item(item_id, updated_fields)
|
| 84 |
+
|
| 85 |
if update_success:
|
| 86 |
# Log the inventory update
|
| 87 |
log_inventory_update(user_id, item_id, updated_fields)
|
|
|
|
| 89 |
else:
|
| 90 |
return jsonify({"message": "Inventory item update failed"}), 400
|
| 91 |
|
| 92 |
+
except KeyError as e:
|
| 93 |
+
return jsonify({"error": f"Missing field in request: {str(e)}"}), 400
|
| 94 |
except Exception as e:
|
| 95 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 96 |
|
| 97 |
|
| 98 |
# Get an inventory item by its ID
|
|
|
|
| 101 |
Retrieves an inventory item by its item_id (MongoDB ObjectId).
|
| 102 |
|
| 103 |
Expects:
|
| 104 |
+
- item_id: The ID of the inventory item.
|
| 105 |
|
| 106 |
Returns:
|
| 107 |
- JSON response with the inventory item details.
|
|
|
|
| 113 |
|
| 114 |
return jsonify(inventory_item), 200
|
| 115 |
|
| 116 |
+
except ValueError:
|
| 117 |
+
return jsonify({"error": "Invalid item ID format"}), 400
|
| 118 |
except Exception as e:
|
| 119 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 120 |
|
| 121 |
|
| 122 |
# Get all inventory items
|
| 123 |
def get_all_inventory():
|
| 124 |
"""
|
| 125 |
+
Retrieves all inventory items in the system.
|
| 126 |
|
| 127 |
Returns:
|
| 128 |
- JSON response with the list of all inventory items.
|
|
|
|
| 135 |
return jsonify(inventory_items), 200
|
| 136 |
|
| 137 |
except Exception as e:
|
| 138 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
controllers/usage_tracking.py
CHANGED
|
@@ -1,8 +1,12 @@
|
|
| 1 |
# controllers/usage_tracking.py
|
| 2 |
|
| 3 |
from flask import request, jsonify
|
| 4 |
-
from models.schemas.usage_schema import
|
|
|
|
|
|
|
|
|
|
| 5 |
get_usage_by_interaction_type
|
|
|
|
| 6 |
from controllers.data_logging import log_assistant_usage
|
| 7 |
|
| 8 |
|
|
@@ -22,24 +26,31 @@ def log_usage():
|
|
| 22 |
"""
|
| 23 |
try:
|
| 24 |
# Extract data from the request
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
|
|
| 29 |
|
| 30 |
-
|
| 31 |
-
|
|
|
|
| 32 |
|
| 33 |
-
# Log assistant usage
|
| 34 |
usage_record_id = create_usage_record(user_id, manager_id, interaction_type, metadata)
|
| 35 |
|
| 36 |
-
# Log the usage
|
| 37 |
log_assistant_usage(user_id, manager_id, interaction_type, metadata)
|
| 38 |
|
| 39 |
-
return jsonify({
|
|
|
|
|
|
|
|
|
|
| 40 |
|
|
|
|
|
|
|
| 41 |
except Exception as e:
|
| 42 |
-
return jsonify({"error": str(e)}), 500
|
| 43 |
|
| 44 |
|
| 45 |
# Get usage records by user
|
|
@@ -60,8 +71,10 @@ def get_usage_for_user(user_id):
|
|
| 60 |
|
| 61 |
return jsonify(usage_records), 200
|
| 62 |
|
|
|
|
|
|
|
| 63 |
except Exception as e:
|
| 64 |
-
return jsonify({"error": str(e)}), 500
|
| 65 |
|
| 66 |
|
| 67 |
# Get usage records for all users managed by a specific manager
|
|
@@ -82,8 +95,10 @@ def get_usage_for_manager(manager_id):
|
|
| 82 |
|
| 83 |
return jsonify(usage_records), 200
|
| 84 |
|
|
|
|
|
|
|
| 85 |
except Exception as e:
|
| 86 |
-
return jsonify({"error": str(e)}), 500
|
| 87 |
|
| 88 |
|
| 89 |
# Get usage records by interaction type
|
|
@@ -104,5 +119,7 @@ def get_usage_by_type(interaction_type):
|
|
| 104 |
|
| 105 |
return jsonify(usage_records), 200
|
| 106 |
|
|
|
|
|
|
|
| 107 |
except Exception as e:
|
| 108 |
-
return jsonify({"error": str(e)}), 500
|
|
|
|
| 1 |
# controllers/usage_tracking.py
|
| 2 |
|
| 3 |
from flask import request, jsonify
|
| 4 |
+
from models.schemas.usage_schema import (
|
| 5 |
+
create_usage_record,
|
| 6 |
+
get_usage_by_user,
|
| 7 |
+
get_usage_by_manager,
|
| 8 |
get_usage_by_interaction_type
|
| 9 |
+
)
|
| 10 |
from controllers.data_logging import log_assistant_usage
|
| 11 |
|
| 12 |
|
|
|
|
| 26 |
"""
|
| 27 |
try:
|
| 28 |
# Extract data from the request
|
| 29 |
+
data = request.json
|
| 30 |
+
user_id = data.get('user_id')
|
| 31 |
+
manager_id = data.get('manager_id')
|
| 32 |
+
interaction_type = data.get('interaction_type')
|
| 33 |
+
metadata = data.get('metadata', {})
|
| 34 |
|
| 35 |
+
# Check for missing fields
|
| 36 |
+
if not all([user_id, manager_id, interaction_type]):
|
| 37 |
+
return jsonify({"error": "Missing required fields: 'user_id', 'manager_id', or 'interaction_type'"}), 400
|
| 38 |
|
| 39 |
+
# Log assistant usage in the system
|
| 40 |
usage_record_id = create_usage_record(user_id, manager_id, interaction_type, metadata)
|
| 41 |
|
| 42 |
+
# Log the usage for auditing or tracking purposes
|
| 43 |
log_assistant_usage(user_id, manager_id, interaction_type, metadata)
|
| 44 |
|
| 45 |
+
return jsonify({
|
| 46 |
+
"message": "Assistant usage logged successfully",
|
| 47 |
+
"usage_record_id": usage_record_id
|
| 48 |
+
}), 201
|
| 49 |
|
| 50 |
+
except KeyError as e:
|
| 51 |
+
return jsonify({"error": f"Missing field in request: {str(e)}"}), 400
|
| 52 |
except Exception as e:
|
| 53 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 54 |
|
| 55 |
|
| 56 |
# Get usage records by user
|
|
|
|
| 71 |
|
| 72 |
return jsonify(usage_records), 200
|
| 73 |
|
| 74 |
+
except ValueError:
|
| 75 |
+
return jsonify({"error": "Invalid user ID format"}), 400
|
| 76 |
except Exception as e:
|
| 77 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 78 |
|
| 79 |
|
| 80 |
# Get usage records for all users managed by a specific manager
|
|
|
|
| 95 |
|
| 96 |
return jsonify(usage_records), 200
|
| 97 |
|
| 98 |
+
except ValueError:
|
| 99 |
+
return jsonify({"error": "Invalid manager ID format"}), 400
|
| 100 |
except Exception as e:
|
| 101 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
| 102 |
|
| 103 |
|
| 104 |
# Get usage records by interaction type
|
|
|
|
| 119 |
|
| 120 |
return jsonify(usage_records), 200
|
| 121 |
|
| 122 |
+
except ValueError:
|
| 123 |
+
return jsonify({"error": f"Invalid interaction type: {interaction_type}"}), 400
|
| 124 |
except Exception as e:
|
| 125 |
+
return jsonify({"error": f"An error occurred: {str(e)}"}), 500
|
routes/api.py
CHANGED
|
@@ -6,6 +6,10 @@ from controllers.inventory import add_inventory_item, update_inventory_item_by_i
|
|
| 6 |
get_all_inventory
|
| 7 |
from controllers.usage_tracking import log_usage, get_usage_for_user, get_usage_for_manager, get_usage_by_type
|
| 8 |
from controllers.data_logging import log_user_action
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
# Create a Blueprint for the API routes
|
| 11 |
api_bp = Blueprint('api', __name__)
|
|
@@ -14,66 +18,178 @@ api_bp = Blueprint('api', __name__)
|
|
| 14 |
# Health Management Routes
|
| 15 |
@api_bp.route('/detect-disease', methods=['POST'])
|
| 16 |
def detect_disease_route():
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
|
| 20 |
@api_bp.route('/health-record/<record_id>', methods=['GET'])
|
| 21 |
def get_health_record_route(record_id):
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
|
| 25 |
@api_bp.route('/health-records/<user_id>', methods=['GET'])
|
| 26 |
def get_health_records_for_user_route(user_id):
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
|
| 30 |
# Inventory Management Routes
|
| 31 |
@api_bp.route('/add-inventory-item', methods=['POST'])
|
| 32 |
def add_inventory_item_route():
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
@api_bp.route('/update-inventory-item', methods=['PUT'])
|
| 37 |
def update_inventory_item_route():
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
|
| 41 |
@api_bp.route('/inventory-item/<item_id>', methods=['GET'])
|
| 42 |
def get_inventory_item_route(item_id):
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
|
| 46 |
@api_bp.route('/inventory', methods=['GET'])
|
| 47 |
def get_all_inventory_route():
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
|
| 51 |
# Assistant Usage Tracking Routes
|
| 52 |
@api_bp.route('/log-usage', methods=['POST'])
|
| 53 |
def log_usage_route():
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
|
| 57 |
@api_bp.route('/usage/<user_id>', methods=['GET'])
|
| 58 |
def get_usage_for_user_route(user_id):
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
|
| 62 |
@api_bp.route('/manager-usage/<manager_id>', methods=['GET'])
|
| 63 |
def get_usage_for_manager_route(manager_id):
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
|
| 67 |
@api_bp.route('/usage-type/<interaction_type>', methods=['GET'])
|
| 68 |
def get_usage_by_type_route(interaction_type):
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
|
| 72 |
# User Action Logging Route
|
| 73 |
@api_bp.route('/log-user-action', methods=['POST'])
|
| 74 |
def log_user_action_route():
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
get_all_inventory
|
| 7 |
from controllers.usage_tracking import log_usage, get_usage_for_user, get_usage_for_manager, get_usage_by_type
|
| 8 |
from controllers.data_logging import log_user_action
|
| 9 |
+
import logging
|
| 10 |
+
|
| 11 |
+
# Initialize logger for API routes
|
| 12 |
+
logger = logging.getLogger(__name__)
|
| 13 |
|
| 14 |
# Create a Blueprint for the API routes
|
| 15 |
api_bp = Blueprint('api', __name__)
|
|
|
|
| 18 |
# Health Management Routes
|
| 19 |
@api_bp.route('/detect-disease', methods=['POST'])
|
| 20 |
def detect_disease_route():
|
| 21 |
+
"""
|
| 22 |
+
Detect a disease and log the health record.
|
| 23 |
+
Expects a POST request with:
|
| 24 |
+
- user_id: ID of the user
|
| 25 |
+
- poultry_id: ID of the poultry
|
| 26 |
+
- image: Image of poultry feces for disease detection
|
| 27 |
+
"""
|
| 28 |
+
try:
|
| 29 |
+
return detect_and_log_disease()
|
| 30 |
+
except Exception as e:
|
| 31 |
+
logger.error(f"Error detecting disease: {str(e)}", exc_info=True)
|
| 32 |
+
return jsonify({"error": "An error occurred while detecting the disease."}), 500
|
| 33 |
|
| 34 |
|
| 35 |
@api_bp.route('/health-record/<record_id>', methods=['GET'])
|
| 36 |
def get_health_record_route(record_id):
|
| 37 |
+
"""
|
| 38 |
+
Retrieve a health record by its ID.
|
| 39 |
+
"""
|
| 40 |
+
try:
|
| 41 |
+
return get_health_record(record_id)
|
| 42 |
+
except Exception as e:
|
| 43 |
+
logger.error(f"Error fetching health record {record_id}: {str(e)}", exc_info=True)
|
| 44 |
+
return jsonify({"error": "An error occurred while retrieving the health record."}), 500
|
| 45 |
|
| 46 |
|
| 47 |
@api_bp.route('/health-records/<user_id>', methods=['GET'])
|
| 48 |
def get_health_records_for_user_route(user_id):
|
| 49 |
+
"""
|
| 50 |
+
Retrieve all health records for a specific user.
|
| 51 |
+
"""
|
| 52 |
+
try:
|
| 53 |
+
return get_health_records_for_user(user_id)
|
| 54 |
+
except Exception as e:
|
| 55 |
+
logger.error(f"Error fetching health records for user {user_id}: {str(e)}", exc_info=True)
|
| 56 |
+
return jsonify({"error": "An error occurred while retrieving health records."}), 500
|
| 57 |
|
| 58 |
|
| 59 |
# Inventory Management Routes
|
| 60 |
@api_bp.route('/add-inventory-item', methods=['POST'])
|
| 61 |
def add_inventory_item_route():
|
| 62 |
+
"""
|
| 63 |
+
Add a new inventory item.
|
| 64 |
+
Expects a POST request with:
|
| 65 |
+
- user_id: ID of the user
|
| 66 |
+
- item_name: Name of the inventory item
|
| 67 |
+
- category: Category of the item
|
| 68 |
+
- quantity: Total quantity
|
| 69 |
+
- unit: Unit of measurement
|
| 70 |
+
"""
|
| 71 |
+
try:
|
| 72 |
+
return add_inventory_item()
|
| 73 |
+
except Exception as e:
|
| 74 |
+
logger.error(f"Error adding inventory item: {str(e)}", exc_info=True)
|
| 75 |
+
return jsonify({"error": "An error occurred while adding the inventory item."}), 500
|
| 76 |
|
| 77 |
|
| 78 |
@api_bp.route('/update-inventory-item', methods=['PUT'])
|
| 79 |
def update_inventory_item_route():
|
| 80 |
+
"""
|
| 81 |
+
Update an existing inventory item.
|
| 82 |
+
Expects a PUT request with:
|
| 83 |
+
- user_id: ID of the user
|
| 84 |
+
- item_id: ID of the inventory item
|
| 85 |
+
- updated_fields: Fields to be updated
|
| 86 |
+
"""
|
| 87 |
+
try:
|
| 88 |
+
return update_inventory_item_by_id()
|
| 89 |
+
except Exception as e:
|
| 90 |
+
logger.error(f"Error updating inventory item: {str(e)}", exc_info=True)
|
| 91 |
+
return jsonify({"error": "An error occurred while updating the inventory item."}), 500
|
| 92 |
|
| 93 |
|
| 94 |
@api_bp.route('/inventory-item/<item_id>', methods=['GET'])
|
| 95 |
def get_inventory_item_route(item_id):
|
| 96 |
+
"""
|
| 97 |
+
Retrieve an inventory item by its ID.
|
| 98 |
+
"""
|
| 99 |
+
try:
|
| 100 |
+
return get_inventory_by_id(item_id)
|
| 101 |
+
except Exception as e:
|
| 102 |
+
logger.error(f"Error fetching inventory item {item_id}: {str(e)}", exc_info=True)
|
| 103 |
+
return jsonify({"error": "An error occurred while retrieving the inventory item."}), 500
|
| 104 |
|
| 105 |
|
| 106 |
@api_bp.route('/inventory', methods=['GET'])
|
| 107 |
def get_all_inventory_route():
|
| 108 |
+
"""
|
| 109 |
+
Retrieve all inventory items.
|
| 110 |
+
"""
|
| 111 |
+
try:
|
| 112 |
+
return get_all_inventory()
|
| 113 |
+
except Exception as e:
|
| 114 |
+
logger.error(f"Error fetching all inventory items: {str(e)}", exc_info=True)
|
| 115 |
+
return jsonify({"error": "An error occurred while retrieving the inventory items."}), 500
|
| 116 |
|
| 117 |
|
| 118 |
# Assistant Usage Tracking Routes
|
| 119 |
@api_bp.route('/log-usage', methods=['POST'])
|
| 120 |
def log_usage_route():
|
| 121 |
+
"""
|
| 122 |
+
Log the usage of the assistant by a user.
|
| 123 |
+
Expects a POST request with:
|
| 124 |
+
- user_id: ID of the user
|
| 125 |
+
- manager_id: ID of the manager
|
| 126 |
+
- interaction_type: Type of interaction (e.g., "disease_detection", "inventory_management")
|
| 127 |
+
"""
|
| 128 |
+
try:
|
| 129 |
+
return log_usage()
|
| 130 |
+
except Exception as e:
|
| 131 |
+
logger.error(f"Error logging usage: {str(e)}", exc_info=True)
|
| 132 |
+
return jsonify({"error": "An error occurred while logging the assistant usage."}), 500
|
| 133 |
|
| 134 |
|
| 135 |
@api_bp.route('/usage/<user_id>', methods=['GET'])
|
| 136 |
def get_usage_for_user_route(user_id):
|
| 137 |
+
"""
|
| 138 |
+
Retrieve all usage logs for a specific user.
|
| 139 |
+
"""
|
| 140 |
+
try:
|
| 141 |
+
return get_usage_for_user(user_id)
|
| 142 |
+
except Exception as e:
|
| 143 |
+
logger.error(f"Error fetching usage logs for user {user_id}: {str(e)}", exc_info=True)
|
| 144 |
+
return jsonify({"error": "An error occurred while retrieving usage logs for the user."}), 500
|
| 145 |
|
| 146 |
|
| 147 |
@api_bp.route('/manager-usage/<manager_id>', methods=['GET'])
|
| 148 |
def get_usage_for_manager_route(manager_id):
|
| 149 |
+
"""
|
| 150 |
+
Retrieve all usage logs for users managed by a specific manager.
|
| 151 |
+
"""
|
| 152 |
+
try:
|
| 153 |
+
return get_usage_for_manager(manager_id)
|
| 154 |
+
except Exception as e:
|
| 155 |
+
logger.error(f"Error fetching usage logs for manager {manager_id}: {str(e)}", exc_info=True)
|
| 156 |
+
return jsonify({"error": "An error occurred while retrieving usage logs for the manager."}), 500
|
| 157 |
|
| 158 |
|
| 159 |
@api_bp.route('/usage-type/<interaction_type>', methods=['GET'])
|
| 160 |
def get_usage_by_type_route(interaction_type):
|
| 161 |
+
"""
|
| 162 |
+
Retrieve all usage logs for a specific interaction type.
|
| 163 |
+
"""
|
| 164 |
+
try:
|
| 165 |
+
return get_usage_by_type(interaction_type)
|
| 166 |
+
except Exception as e:
|
| 167 |
+
logger.error(f"Error fetching usage logs by interaction type {interaction_type}: {str(e)}", exc_info=True)
|
| 168 |
+
return jsonify({"error": "An error occurred while retrieving usage logs for the interaction type."}), 500
|
| 169 |
|
| 170 |
|
| 171 |
# User Action Logging Route
|
| 172 |
@api_bp.route('/log-user-action', methods=['POST'])
|
| 173 |
def log_user_action_route():
|
| 174 |
+
"""
|
| 175 |
+
Log user actions with metadata.
|
| 176 |
+
Expects a POST request with:
|
| 177 |
+
- user_id: ID of the user performing the action
|
| 178 |
+
- message: Description of the action
|
| 179 |
+
- level: Logging level (default: "INFO")
|
| 180 |
+
- metadata: Optional metadata related to the action
|
| 181 |
+
"""
|
| 182 |
+
try:
|
| 183 |
+
user_id = request.json.get('user_id')
|
| 184 |
+
message = request.json.get('message')
|
| 185 |
+
level = request.json.get('level', 'INFO')
|
| 186 |
+
metadata = request.json.get('metadata', {})
|
| 187 |
+
|
| 188 |
+
# Validate required fields
|
| 189 |
+
if not user_id or not message:
|
| 190 |
+
return jsonify({"error": "Missing required fields: user_id and message"}), 400
|
| 191 |
+
|
| 192 |
+
return log_user_action(user_id, message, level, metadata)
|
| 193 |
+
except Exception as e:
|
| 194 |
+
logger.error(f"Error logging user action: {str(e)}", exc_info=True)
|
| 195 |
+
return jsonify({"error": "An error occurred while logging the user action."}), 500
|
routes/data_logging_routes.py
CHANGED
|
@@ -9,6 +9,10 @@ from controllers.data_logging import (
|
|
| 9 |
log_inventory_update,
|
| 10 |
log_assistant_usage
|
| 11 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
# Create a Blueprint for the data logging routes
|
| 14 |
data_logging_bp = Blueprint('data_logging', __name__)
|
|
@@ -17,23 +21,43 @@ data_logging_bp = Blueprint('data_logging', __name__)
|
|
| 17 |
# Route to log user actions
|
| 18 |
@data_logging_bp.route('/log-user-action', methods=['POST'])
|
| 19 |
def log_user_action_route():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
try:
|
| 21 |
user_id = request.json.get('user_id')
|
| 22 |
message = request.json.get('message')
|
| 23 |
level = request.json.get('level', 'INFO')
|
| 24 |
metadata = request.json.get('metadata', {})
|
| 25 |
|
|
|
|
| 26 |
if not user_id or not message:
|
| 27 |
-
return jsonify({"error": "Missing required fields"}), 400
|
| 28 |
|
| 29 |
return log_user_action(user_id, message, level, metadata)
|
| 30 |
except Exception as e:
|
| 31 |
-
|
|
|
|
| 32 |
|
| 33 |
|
| 34 |
# Route to log a health record
|
| 35 |
@data_logging_bp.route('/log-health-record', methods=['POST'])
|
| 36 |
def log_health_record_route():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
try:
|
| 38 |
user_id = request.json.get('user_id')
|
| 39 |
poultry_id = request.json.get('poultry_id')
|
|
@@ -42,17 +66,29 @@ def log_health_record_route():
|
|
| 42 |
recommendation = request.json.get('recommendation')
|
| 43 |
image_path = request.json.get('image_path')
|
| 44 |
|
|
|
|
| 45 |
if not all([user_id, poultry_id, disease_name, status, recommendation]):
|
| 46 |
return jsonify({"error": "Missing required fields"}), 400
|
| 47 |
|
| 48 |
return log_health_record(user_id, poultry_id, disease_name, status, recommendation, image_path)
|
| 49 |
except Exception as e:
|
| 50 |
-
|
|
|
|
| 51 |
|
| 52 |
|
| 53 |
# Route to log inventory addition
|
| 54 |
@data_logging_bp.route('/log-inventory-addition', methods=['POST'])
|
| 55 |
def log_inventory_addition_route():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
try:
|
| 57 |
user_id = request.json.get('user_id')
|
| 58 |
item_name = request.json.get('item_name')
|
|
@@ -61,42 +97,63 @@ def log_inventory_addition_route():
|
|
| 61 |
unit = request.json.get('unit')
|
| 62 |
description = request.json.get('description')
|
| 63 |
|
|
|
|
| 64 |
if not all([user_id, item_name, category, quantity, unit]):
|
| 65 |
return jsonify({"error": "Missing required fields"}), 400
|
| 66 |
|
| 67 |
return log_inventory_addition(user_id, item_name, category, quantity, unit, description)
|
| 68 |
except Exception as e:
|
| 69 |
-
|
|
|
|
| 70 |
|
| 71 |
|
| 72 |
# Route to log inventory update
|
| 73 |
@data_logging_bp.route('/log-inventory-update', methods=['PUT'])
|
| 74 |
def log_inventory_update_route():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
try:
|
| 76 |
user_id = request.json.get('user_id')
|
| 77 |
item_id = request.json.get('item_id')
|
| 78 |
updated_fields = request.json.get('updated_fields')
|
| 79 |
|
|
|
|
| 80 |
if not all([user_id, item_id, updated_fields]):
|
| 81 |
return jsonify({"error": "Missing required fields"}), 400
|
| 82 |
|
| 83 |
return log_inventory_update(user_id, item_id, updated_fields)
|
| 84 |
except Exception as e:
|
| 85 |
-
|
|
|
|
| 86 |
|
| 87 |
|
| 88 |
# Route to log assistant usage
|
| 89 |
@data_logging_bp.route('/log-assistant-usage', methods=['POST'])
|
| 90 |
def log_assistant_usage_route():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
try:
|
| 92 |
user_id = request.json.get('user_id')
|
| 93 |
manager_id = request.json.get('manager_id')
|
| 94 |
interaction_type = request.json.get('interaction_type')
|
| 95 |
-
metadata = request.json.get('metadata')
|
| 96 |
|
|
|
|
| 97 |
if not all([user_id, manager_id, interaction_type]):
|
| 98 |
return jsonify({"error": "Missing required fields"}), 400
|
| 99 |
|
| 100 |
return log_assistant_usage(user_id, manager_id, interaction_type, metadata)
|
| 101 |
except Exception as e:
|
| 102 |
-
|
|
|
|
|
|
| 9 |
log_inventory_update,
|
| 10 |
log_assistant_usage
|
| 11 |
)
|
| 12 |
+
import logging
|
| 13 |
+
|
| 14 |
+
# Initialize logger for data logging routes
|
| 15 |
+
logger = logging.getLogger(__name__)
|
| 16 |
|
| 17 |
# Create a Blueprint for the data logging routes
|
| 18 |
data_logging_bp = Blueprint('data_logging', __name__)
|
|
|
|
| 21 |
# Route to log user actions
|
| 22 |
@data_logging_bp.route('/log-user-action', methods=['POST'])
|
| 23 |
def log_user_action_route():
|
| 24 |
+
"""
|
| 25 |
+
Log a user action with optional metadata.
|
| 26 |
+
Expects JSON input:
|
| 27 |
+
- user_id: ID of the user
|
| 28 |
+
- message: Action description
|
| 29 |
+
- level: Logging level (default: "INFO")
|
| 30 |
+
- metadata: Additional details (optional)
|
| 31 |
+
"""
|
| 32 |
try:
|
| 33 |
user_id = request.json.get('user_id')
|
| 34 |
message = request.json.get('message')
|
| 35 |
level = request.json.get('level', 'INFO')
|
| 36 |
metadata = request.json.get('metadata', {})
|
| 37 |
|
| 38 |
+
# Validate required fields
|
| 39 |
if not user_id or not message:
|
| 40 |
+
return jsonify({"error": "Missing required fields: user_id and message"}), 400
|
| 41 |
|
| 42 |
return log_user_action(user_id, message, level, metadata)
|
| 43 |
except Exception as e:
|
| 44 |
+
logger.error(f"Error logging user action: {str(e)}", exc_info=True)
|
| 45 |
+
return jsonify({"error": "An error occurred while logging the user action."}), 500
|
| 46 |
|
| 47 |
|
| 48 |
# Route to log a health record
|
| 49 |
@data_logging_bp.route('/log-health-record', methods=['POST'])
|
| 50 |
def log_health_record_route():
|
| 51 |
+
"""
|
| 52 |
+
Log a health record for poultry.
|
| 53 |
+
Expects JSON input:
|
| 54 |
+
- user_id: ID of the user
|
| 55 |
+
- poultry_id: ID of the poultry
|
| 56 |
+
- disease_name: Name of the detected disease
|
| 57 |
+
- status: Health status of the poultry
|
| 58 |
+
- recommendation: Treatment recommendation
|
| 59 |
+
- image_path: Optional image path
|
| 60 |
+
"""
|
| 61 |
try:
|
| 62 |
user_id = request.json.get('user_id')
|
| 63 |
poultry_id = request.json.get('poultry_id')
|
|
|
|
| 66 |
recommendation = request.json.get('recommendation')
|
| 67 |
image_path = request.json.get('image_path')
|
| 68 |
|
| 69 |
+
# Validate required fields
|
| 70 |
if not all([user_id, poultry_id, disease_name, status, recommendation]):
|
| 71 |
return jsonify({"error": "Missing required fields"}), 400
|
| 72 |
|
| 73 |
return log_health_record(user_id, poultry_id, disease_name, status, recommendation, image_path)
|
| 74 |
except Exception as e:
|
| 75 |
+
logger.error(f"Error logging health record: {str(e)}", exc_info=True)
|
| 76 |
+
return jsonify({"error": "An error occurred while logging the health record."}), 500
|
| 77 |
|
| 78 |
|
| 79 |
# Route to log inventory addition
|
| 80 |
@data_logging_bp.route('/log-inventory-addition', methods=['POST'])
|
| 81 |
def log_inventory_addition_route():
|
| 82 |
+
"""
|
| 83 |
+
Log the addition of an inventory item.
|
| 84 |
+
Expects JSON input:
|
| 85 |
+
- user_id: ID of the user
|
| 86 |
+
- item_name: Name of the inventory item
|
| 87 |
+
- category: Category of the item (e.g., Feed, Medicine)
|
| 88 |
+
- quantity: Total quantity added
|
| 89 |
+
- unit: Unit of measurement (e.g., kg, liters)
|
| 90 |
+
- description: Optional description or notes
|
| 91 |
+
"""
|
| 92 |
try:
|
| 93 |
user_id = request.json.get('user_id')
|
| 94 |
item_name = request.json.get('item_name')
|
|
|
|
| 97 |
unit = request.json.get('unit')
|
| 98 |
description = request.json.get('description')
|
| 99 |
|
| 100 |
+
# Validate required fields
|
| 101 |
if not all([user_id, item_name, category, quantity, unit]):
|
| 102 |
return jsonify({"error": "Missing required fields"}), 400
|
| 103 |
|
| 104 |
return log_inventory_addition(user_id, item_name, category, quantity, unit, description)
|
| 105 |
except Exception as e:
|
| 106 |
+
logger.error(f"Error logging inventory addition: {str(e)}", exc_info=True)
|
| 107 |
+
return jsonify({"error": "An error occurred while logging the inventory addition."}), 500
|
| 108 |
|
| 109 |
|
| 110 |
# Route to log inventory update
|
| 111 |
@data_logging_bp.route('/log-inventory-update', methods=['PUT'])
|
| 112 |
def log_inventory_update_route():
|
| 113 |
+
"""
|
| 114 |
+
Log an update to an existing inventory item.
|
| 115 |
+
Expects JSON input:
|
| 116 |
+
- user_id: ID of the user
|
| 117 |
+
- item_id: ID of the inventory item
|
| 118 |
+
- updated_fields: Dictionary containing fields to be updated (e.g., quantity, used_quantity)
|
| 119 |
+
"""
|
| 120 |
try:
|
| 121 |
user_id = request.json.get('user_id')
|
| 122 |
item_id = request.json.get('item_id')
|
| 123 |
updated_fields = request.json.get('updated_fields')
|
| 124 |
|
| 125 |
+
# Validate required fields
|
| 126 |
if not all([user_id, item_id, updated_fields]):
|
| 127 |
return jsonify({"error": "Missing required fields"}), 400
|
| 128 |
|
| 129 |
return log_inventory_update(user_id, item_id, updated_fields)
|
| 130 |
except Exception as e:
|
| 131 |
+
logger.error(f"Error logging inventory update: {str(e)}", exc_info=True)
|
| 132 |
+
return jsonify({"error": "An error occurred while logging the inventory update."}), 500
|
| 133 |
|
| 134 |
|
| 135 |
# Route to log assistant usage
|
| 136 |
@data_logging_bp.route('/log-assistant-usage', methods=['POST'])
|
| 137 |
def log_assistant_usage_route():
|
| 138 |
+
"""
|
| 139 |
+
Log the usage of the assistant by a user.
|
| 140 |
+
Expects JSON input:
|
| 141 |
+
- user_id: ID of the user
|
| 142 |
+
- manager_id: ID of the manager overseeing the user
|
| 143 |
+
- interaction_type: Type of interaction (e.g., disease_detection, inventory_management)
|
| 144 |
+
- metadata: Optional metadata for additional details
|
| 145 |
+
"""
|
| 146 |
try:
|
| 147 |
user_id = request.json.get('user_id')
|
| 148 |
manager_id = request.json.get('manager_id')
|
| 149 |
interaction_type = request.json.get('interaction_type')
|
| 150 |
+
metadata = request.json.get('metadata', {})
|
| 151 |
|
| 152 |
+
# Validate required fields
|
| 153 |
if not all([user_id, manager_id, interaction_type]):
|
| 154 |
return jsonify({"error": "Missing required fields"}), 400
|
| 155 |
|
| 156 |
return log_assistant_usage(user_id, manager_id, interaction_type, metadata)
|
| 157 |
except Exception as e:
|
| 158 |
+
logger.error(f"Error logging assistant usage: {str(e)}", exc_info=True)
|
| 159 |
+
return jsonify({"error": "An error occurred while logging the assistant usage."}), 500
|
routes/health_routes.py
CHANGED
|
@@ -1,7 +1,12 @@
|
|
| 1 |
# routes/health_routes.py
|
| 2 |
|
| 3 |
-
from flask import Blueprint, jsonify
|
| 4 |
from controllers.health_management import detect_and_log_disease, get_health_record, get_health_records_for_user
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
# Create a Blueprint for the health-related routes
|
| 7 |
health_bp = Blueprint('health', __name__)
|
|
@@ -11,17 +16,35 @@ health_bp = Blueprint('health', __name__)
|
|
| 11 |
@health_bp.route('/detect-disease', methods=['POST'])
|
| 12 |
def detect_disease_route():
|
| 13 |
"""
|
| 14 |
-
Detect a poultry disease and log the health record.
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
-
|
|
|
|
| 18 |
- image: Image of poultry feces for disease detection.
|
|
|
|
| 19 |
Returns: JSON response with disease detection result and health record log status.
|
| 20 |
"""
|
| 21 |
try:
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
except Exception as e:
|
| 24 |
-
|
|
|
|
| 25 |
|
| 26 |
|
| 27 |
# Route to get a health record by its ID
|
|
@@ -29,12 +52,18 @@ def detect_disease_route():
|
|
| 29 |
def get_health_record_route(record_id):
|
| 30 |
"""
|
| 31 |
Retrieve a health record by its ID.
|
|
|
|
| 32 |
Returns: JSON response with the health record details.
|
| 33 |
"""
|
| 34 |
try:
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
except Exception as e:
|
| 37 |
-
|
|
|
|
| 38 |
|
| 39 |
|
| 40 |
# Route to get all health records for a specific user
|
|
@@ -42,9 +71,15 @@ def get_health_record_route(record_id):
|
|
| 42 |
def get_health_records_for_user_route(user_id):
|
| 43 |
"""
|
| 44 |
Retrieve all health records for a specific user.
|
|
|
|
| 45 |
Returns: JSON response with the list of health records for the user.
|
| 46 |
"""
|
| 47 |
try:
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
except Exception as e:
|
| 50 |
-
|
|
|
|
|
|
| 1 |
# routes/health_routes.py
|
| 2 |
|
| 3 |
+
from flask import Blueprint, jsonify, request
|
| 4 |
from controllers.health_management import detect_and_log_disease, get_health_record, get_health_records_for_user
|
| 5 |
+
from services.disease_detection import detect_disease
|
| 6 |
+
import logging
|
| 7 |
+
|
| 8 |
+
# Initialize logger for the health routes
|
| 9 |
+
logger = logging.getLogger(__name__)
|
| 10 |
|
| 11 |
# Create a Blueprint for the health-related routes
|
| 12 |
health_bp = Blueprint('health', __name__)
|
|
|
|
| 16 |
@health_bp.route('/detect-disease', methods=['POST'])
|
| 17 |
def detect_disease_route():
|
| 18 |
"""
|
| 19 |
+
Detect a poultry disease from an uploaded image and log the health record.
|
| 20 |
+
|
| 21 |
+
Expects a POST request with:
|
| 22 |
+
- user_id: ID of the user (in request form data or headers).
|
| 23 |
+
- poultry_id: ID of the poultry (in request form data or headers).
|
| 24 |
- image: Image of poultry feces for disease detection.
|
| 25 |
+
|
| 26 |
Returns: JSON response with disease detection result and health record log status.
|
| 27 |
"""
|
| 28 |
try:
|
| 29 |
+
# Get the uploaded image and other request data
|
| 30 |
+
image = request.files.get('image')
|
| 31 |
+
user_id = request.form.get('user_id')
|
| 32 |
+
poultry_id = request.form.get('poultry_id')
|
| 33 |
+
|
| 34 |
+
# Validate required fields
|
| 35 |
+
if not image or not user_id or not poultry_id:
|
| 36 |
+
return jsonify({"error": "Missing required fields: image, user_id, or poultry_id"}), 400
|
| 37 |
+
|
| 38 |
+
# Assuming 'db' is accessible or passed via the route (refactor to pass db as a dependency)
|
| 39 |
+
result = detect_disease(image, db)
|
| 40 |
+
|
| 41 |
+
# Log the disease detection result in the health records
|
| 42 |
+
log_result = detect_and_log_disease(user_id, poultry_id, result)
|
| 43 |
+
return jsonify(log_result), 201
|
| 44 |
+
|
| 45 |
except Exception as e:
|
| 46 |
+
logger.error(f"Error in disease detection: {str(e)}", exc_info=True)
|
| 47 |
+
return jsonify({"error": "An error occurred during disease detection. Please try again."}), 500
|
| 48 |
|
| 49 |
|
| 50 |
# Route to get a health record by its ID
|
|
|
|
| 52 |
def get_health_record_route(record_id):
|
| 53 |
"""
|
| 54 |
Retrieve a health record by its ID.
|
| 55 |
+
|
| 56 |
Returns: JSON response with the health record details.
|
| 57 |
"""
|
| 58 |
try:
|
| 59 |
+
health_record = get_health_record(record_id)
|
| 60 |
+
if not health_record:
|
| 61 |
+
return jsonify({"error": "Health record not found"}), 404
|
| 62 |
+
return jsonify(health_record), 200
|
| 63 |
+
|
| 64 |
except Exception as e:
|
| 65 |
+
logger.error(f"Error retrieving health record: {str(e)}", exc_info=True)
|
| 66 |
+
return jsonify({"error": "An error occurred while fetching the health record."}), 500
|
| 67 |
|
| 68 |
|
| 69 |
# Route to get all health records for a specific user
|
|
|
|
| 71 |
def get_health_records_for_user_route(user_id):
|
| 72 |
"""
|
| 73 |
Retrieve all health records for a specific user.
|
| 74 |
+
|
| 75 |
Returns: JSON response with the list of health records for the user.
|
| 76 |
"""
|
| 77 |
try:
|
| 78 |
+
health_records = get_health_records_for_user(user_id)
|
| 79 |
+
if not health_records:
|
| 80 |
+
return jsonify({"message": "No health records found for this user"}), 404
|
| 81 |
+
return jsonify(health_records), 200
|
| 82 |
+
|
| 83 |
except Exception as e:
|
| 84 |
+
logger.error(f"Error retrieving health records for user {user_id}: {str(e)}", exc_info=True)
|
| 85 |
+
return jsonify({"error": "An error occurred while fetching the health records."}), 500
|
routes/inventory_routes.py
CHANGED
|
@@ -1,13 +1,17 @@
|
|
| 1 |
# routes/inventory_routes.py
|
| 2 |
|
| 3 |
|
| 4 |
-
from flask import Blueprint, jsonify
|
| 5 |
from controllers.inventory import (
|
| 6 |
add_inventory_item,
|
| 7 |
update_inventory_item_by_id,
|
| 8 |
get_inventory_by_id,
|
| 9 |
get_all_inventory
|
| 10 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
# Create a Blueprint for the inventory-related routes
|
| 13 |
inventory_bp = Blueprint('inventory', __name__)
|
|
@@ -25,12 +29,25 @@ def add_inventory_item_route():
|
|
| 25 |
- quantity: The total quantity of the item.
|
| 26 |
- unit: The unit of measurement (e.g., "kg", "liters").
|
| 27 |
- description: Optional. Additional description or notes about the item.
|
|
|
|
| 28 |
Returns: JSON response with the status of the addition.
|
| 29 |
"""
|
| 30 |
try:
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
except Exception as e:
|
| 33 |
-
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
# Route to update an existing inventory item
|
|
@@ -42,12 +59,22 @@ def update_inventory_item_route():
|
|
| 42 |
- user_id: The ID of the user updating the item.
|
| 43 |
- item_id: The ID of the inventory item to be updated.
|
| 44 |
- updated_fields: Dictionary containing fields to be updated (e.g., quantity, used_quantity).
|
|
|
|
| 45 |
Returns: JSON response with the status of the update.
|
| 46 |
"""
|
| 47 |
try:
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
except Exception as e:
|
| 50 |
-
|
|
|
|
| 51 |
|
| 52 |
|
| 53 |
# Route to get an inventory item by its ID
|
|
@@ -56,12 +83,14 @@ def get_inventory_item_route(item_id):
|
|
| 56 |
"""
|
| 57 |
Retrieve an inventory item by its ID.
|
| 58 |
Expects a GET request with the item_id as a URL parameter.
|
|
|
|
| 59 |
Returns: JSON response with the inventory item details.
|
| 60 |
"""
|
| 61 |
try:
|
| 62 |
return get_inventory_by_id(item_id)
|
| 63 |
except Exception as e:
|
| 64 |
-
|
|
|
|
| 65 |
|
| 66 |
|
| 67 |
# Route to get all inventory items
|
|
@@ -69,9 +98,11 @@ def get_inventory_item_route(item_id):
|
|
| 69 |
def get_all_inventory_route():
|
| 70 |
"""
|
| 71 |
Retrieve all inventory items in the system.
|
|
|
|
| 72 |
Returns: JSON response with the list of all inventory items.
|
| 73 |
"""
|
| 74 |
try:
|
| 75 |
return get_all_inventory()
|
| 76 |
except Exception as e:
|
| 77 |
-
|
|
|
|
|
|
| 1 |
# routes/inventory_routes.py
|
| 2 |
|
| 3 |
|
| 4 |
+
from flask import Blueprint, request, jsonify
|
| 5 |
from controllers.inventory import (
|
| 6 |
add_inventory_item,
|
| 7 |
update_inventory_item_by_id,
|
| 8 |
get_inventory_by_id,
|
| 9 |
get_all_inventory
|
| 10 |
)
|
| 11 |
+
import logging
|
| 12 |
+
|
| 13 |
+
# Initialize logger for inventory routes
|
| 14 |
+
logger = logging.getLogger(__name__)
|
| 15 |
|
| 16 |
# Create a Blueprint for the inventory-related routes
|
| 17 |
inventory_bp = Blueprint('inventory', __name__)
|
|
|
|
| 29 |
- quantity: The total quantity of the item.
|
| 30 |
- unit: The unit of measurement (e.g., "kg", "liters").
|
| 31 |
- description: Optional. Additional description or notes about the item.
|
| 32 |
+
|
| 33 |
Returns: JSON response with the status of the addition.
|
| 34 |
"""
|
| 35 |
try:
|
| 36 |
+
user_id = request.json.get('user_id')
|
| 37 |
+
item_name = request.json.get('item_name')
|
| 38 |
+
category = request.json.get('category')
|
| 39 |
+
quantity = request.json.get('quantity')
|
| 40 |
+
unit = request.json.get('unit')
|
| 41 |
+
description = request.json.get('description')
|
| 42 |
+
|
| 43 |
+
# Validate required fields
|
| 44 |
+
if not all([user_id, item_name, category, quantity, unit]):
|
| 45 |
+
return jsonify({"error": "Missing required fields"}), 400
|
| 46 |
+
|
| 47 |
+
return add_inventory_item(user_id, item_name, category, quantity, unit, description)
|
| 48 |
except Exception as e:
|
| 49 |
+
logger.error(f"Error adding inventory item: {str(e)}", exc_info=True)
|
| 50 |
+
return jsonify({"error": "An error occurred while adding the inventory item."}), 500
|
| 51 |
|
| 52 |
|
| 53 |
# Route to update an existing inventory item
|
|
|
|
| 59 |
- user_id: The ID of the user updating the item.
|
| 60 |
- item_id: The ID of the inventory item to be updated.
|
| 61 |
- updated_fields: Dictionary containing fields to be updated (e.g., quantity, used_quantity).
|
| 62 |
+
|
| 63 |
Returns: JSON response with the status of the update.
|
| 64 |
"""
|
| 65 |
try:
|
| 66 |
+
user_id = request.json.get('user_id')
|
| 67 |
+
item_id = request.json.get('item_id')
|
| 68 |
+
updated_fields = request.json.get('updated_fields')
|
| 69 |
+
|
| 70 |
+
# Validate required fields
|
| 71 |
+
if not all([user_id, item_id, updated_fields]):
|
| 72 |
+
return jsonify({"error": "Missing required fields"}), 400
|
| 73 |
+
|
| 74 |
+
return update_inventory_item_by_id(user_id, item_id, updated_fields)
|
| 75 |
except Exception as e:
|
| 76 |
+
logger.error(f"Error updating inventory item: {str(e)}", exc_info=True)
|
| 77 |
+
return jsonify({"error": "An error occurred while updating the inventory item."}), 500
|
| 78 |
|
| 79 |
|
| 80 |
# Route to get an inventory item by its ID
|
|
|
|
| 83 |
"""
|
| 84 |
Retrieve an inventory item by its ID.
|
| 85 |
Expects a GET request with the item_id as a URL parameter.
|
| 86 |
+
|
| 87 |
Returns: JSON response with the inventory item details.
|
| 88 |
"""
|
| 89 |
try:
|
| 90 |
return get_inventory_by_id(item_id)
|
| 91 |
except Exception as e:
|
| 92 |
+
logger.error(f"Error retrieving inventory item: {str(e)}", exc_info=True)
|
| 93 |
+
return jsonify({"error": "An error occurred while retrieving the inventory item."}), 500
|
| 94 |
|
| 95 |
|
| 96 |
# Route to get all inventory items
|
|
|
|
| 98 |
def get_all_inventory_route():
|
| 99 |
"""
|
| 100 |
Retrieve all inventory items in the system.
|
| 101 |
+
|
| 102 |
Returns: JSON response with the list of all inventory items.
|
| 103 |
"""
|
| 104 |
try:
|
| 105 |
return get_all_inventory()
|
| 106 |
except Exception as e:
|
| 107 |
+
logger.error(f"Error retrieving all inventory items: {str(e)}", exc_info=True)
|
| 108 |
+
return jsonify({"error": "An error occurred while retrieving the inventory items."}), 500
|
routes/usage_routes.py
CHANGED
|
@@ -1,7 +1,11 @@
|
|
| 1 |
# routes/usage_routes.py
|
| 2 |
|
| 3 |
-
from flask import Blueprint, jsonify
|
| 4 |
from controllers.usage_tracking import log_usage, get_usage_for_user, get_usage_for_manager, get_usage_by_type
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
# Create a Blueprint for the usage-related routes
|
| 7 |
usage_bp = Blueprint('usage', __name__)
|
|
@@ -22,9 +26,19 @@ def log_usage_route():
|
|
| 22 |
Returns: JSON response indicating success or failure.
|
| 23 |
"""
|
| 24 |
try:
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
except Exception as e:
|
| 27 |
-
|
|
|
|
| 28 |
|
| 29 |
|
| 30 |
# Route to get all assistant usage logs for a specific user
|
|
@@ -40,7 +54,8 @@ def get_usage_for_user_route(user_id):
|
|
| 40 |
try:
|
| 41 |
return get_usage_for_user(user_id)
|
| 42 |
except Exception as e:
|
| 43 |
-
|
|
|
|
| 44 |
|
| 45 |
|
| 46 |
# Route to get all assistant usage logs for users managed by a specific manager
|
|
@@ -56,7 +71,8 @@ def get_usage_for_manager_route(manager_id):
|
|
| 56 |
try:
|
| 57 |
return get_usage_for_manager(manager_id)
|
| 58 |
except Exception as e:
|
| 59 |
-
|
|
|
|
| 60 |
|
| 61 |
|
| 62 |
# Route to get all assistant usage logs for a specific interaction type
|
|
@@ -72,4 +88,6 @@ def get_usage_by_type_route(interaction_type):
|
|
| 72 |
try:
|
| 73 |
return get_usage_by_type(interaction_type)
|
| 74 |
except Exception as e:
|
| 75 |
-
|
|
|
|
|
|
|
|
|
| 1 |
# routes/usage_routes.py
|
| 2 |
|
| 3 |
+
from flask import Blueprint, jsonify, request
|
| 4 |
from controllers.usage_tracking import log_usage, get_usage_for_user, get_usage_for_manager, get_usage_by_type
|
| 5 |
+
import logging
|
| 6 |
+
|
| 7 |
+
# Initialize logger for usage routes
|
| 8 |
+
logger = logging.getLogger(__name__)
|
| 9 |
|
| 10 |
# Create a Blueprint for the usage-related routes
|
| 11 |
usage_bp = Blueprint('usage', __name__)
|
|
|
|
| 26 |
Returns: JSON response indicating success or failure.
|
| 27 |
"""
|
| 28 |
try:
|
| 29 |
+
user_id = request.json.get('user_id')
|
| 30 |
+
manager_id = request.json.get('manager_id')
|
| 31 |
+
interaction_type = request.json.get('interaction_type')
|
| 32 |
+
metadata = request.json.get('metadata', {})
|
| 33 |
+
|
| 34 |
+
# Validate required fields
|
| 35 |
+
if not all([user_id, manager_id, interaction_type]):
|
| 36 |
+
return jsonify({"error": "Missing required fields"}), 400
|
| 37 |
+
|
| 38 |
+
return log_usage(user_id, manager_id, interaction_type, metadata)
|
| 39 |
except Exception as e:
|
| 40 |
+
logger.error(f"Error logging usage: {str(e)}", exc_info=True)
|
| 41 |
+
return jsonify({"error": "An error occurred while logging the usage."}), 500
|
| 42 |
|
| 43 |
|
| 44 |
# Route to get all assistant usage logs for a specific user
|
|
|
|
| 54 |
try:
|
| 55 |
return get_usage_for_user(user_id)
|
| 56 |
except Exception as e:
|
| 57 |
+
logger.error(f"Error retrieving usage logs for user {user_id}: {str(e)}", exc_info=True)
|
| 58 |
+
return jsonify({"error": "An error occurred while retrieving the usage logs for the user."}), 500
|
| 59 |
|
| 60 |
|
| 61 |
# Route to get all assistant usage logs for users managed by a specific manager
|
|
|
|
| 71 |
try:
|
| 72 |
return get_usage_for_manager(manager_id)
|
| 73 |
except Exception as e:
|
| 74 |
+
logger.error(f"Error retrieving usage logs for manager {manager_id}: {str(e)}", exc_info=True)
|
| 75 |
+
return jsonify({"error": "An error occurred while retrieving the usage logs for the manager's users."}), 500
|
| 76 |
|
| 77 |
|
| 78 |
# Route to get all assistant usage logs for a specific interaction type
|
|
|
|
| 88 |
try:
|
| 89 |
return get_usage_by_type(interaction_type)
|
| 90 |
except Exception as e:
|
| 91 |
+
logger.error(f"Error retrieving usage logs for interaction type {interaction_type}: {str(e)}", exc_info=True)
|
| 92 |
+
return jsonify(
|
| 93 |
+
{"error": "An error occurred while retrieving the usage logs for the specified interaction type."}), 500
|
services/disease_detection.py
CHANGED
|
@@ -5,31 +5,45 @@ import numpy as np
|
|
| 5 |
import tensorflow as tf
|
| 6 |
from keras.models import load_model
|
| 7 |
from services.llama_service import llama2_response
|
|
|
|
| 8 |
|
| 9 |
-
#
|
| 10 |
-
|
| 11 |
|
| 12 |
# Load TensorFlow/Keras models with GPU support if available, otherwise use CPU
|
| 13 |
try:
|
| 14 |
device_name = '/GPU:0' if len(tf.config.list_physical_devices('GPU')) > 0 else '/CPU:0'
|
| 15 |
with tf.device(device_name):
|
|
|
|
| 16 |
my_model = load_model('models/Final_Chicken_disease_model.h5', compile=True)
|
| 17 |
auth_model = load_model('models/auth_model.h5', compile=True)
|
| 18 |
print(f"Models loaded successfully on {device_name}.")
|
| 19 |
except Exception as e:
|
| 20 |
-
|
|
|
|
| 21 |
|
| 22 |
# Mapping of disease labels to disease names, health status, and treatment recommendations
|
| 23 |
name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
|
| 24 |
-
|
| 25 |
-
|
| 26 |
0: 'Panadol', # Treatment for Coccidiosis
|
| 27 |
-
1: '
|
| 28 |
2: 'Percetamol', # Treatment for New Castle Disease
|
| 29 |
3: 'Ponston' # Treatment for Salmonella
|
| 30 |
}
|
| 31 |
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
class PoultryFarmBot:
|
| 34 |
def __init__(self, db):
|
| 35 |
"""
|
|
@@ -47,11 +61,11 @@ class PoultryFarmBot:
|
|
| 47 |
:return: Preprocessed image ready for prediction or None if an error occurs.
|
| 48 |
"""
|
| 49 |
try:
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
return
|
| 53 |
except Exception as e:
|
| 54 |
-
|
| 55 |
return None
|
| 56 |
|
| 57 |
def predict(self, image):
|
|
@@ -61,27 +75,29 @@ class PoultryFarmBot:
|
|
| 61 |
:param image: Input image (numpy array).
|
| 62 |
:return: Tuple of predicted disease name, health status, and treatment recommendation.
|
| 63 |
"""
|
| 64 |
-
|
| 65 |
-
image_check = self.preprocess_image(image)
|
| 66 |
|
| 67 |
-
if
|
| 68 |
return "Image preprocessing failed.", None, None, None
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
try:
|
| 71 |
# Predict disease using the loaded model
|
| 72 |
-
indx = my_model.predict(
|
| 73 |
|
| 74 |
-
#
|
| 75 |
-
|
| 76 |
-
status =
|
| 77 |
-
|
| 78 |
|
| 79 |
-
return
|
| 80 |
except Exception as e:
|
| 81 |
-
|
| 82 |
return "Prediction failed.", None, None, None
|
| 83 |
|
| 84 |
-
# Generate a detailed response using Llama 2 for disease information and recommendations
|
| 85 |
def generate_disease_response(self, disease_name, status, recommendation):
|
| 86 |
"""
|
| 87 |
Generates a detailed response using Llama 2 model for disease information and recommendations.
|
|
@@ -99,21 +115,19 @@ class PoultryFarmBot:
|
|
| 99 |
"to effectively manage this condition on a poultry farm."
|
| 100 |
)
|
| 101 |
response = llama2_response(prompt)
|
| 102 |
-
# Post-process to remove the prompt if accidentally included in the response
|
| 103 |
return response.replace(prompt, "").strip()
|
| 104 |
except Exception as e:
|
| 105 |
-
|
| 106 |
return "Unable to generate detailed response."
|
| 107 |
|
| 108 |
-
# Diagnose Disease Using Fecal Image
|
| 109 |
def diagnose_disease(self, image):
|
| 110 |
"""
|
| 111 |
Diagnose a disease using a fecal image.
|
| 112 |
|
| 113 |
:param image: The image of poultry feces to detect a disease.
|
| 114 |
-
:return:
|
| 115 |
"""
|
| 116 |
-
if image is not None and image.size > 0: # Ensure the image is valid
|
| 117 |
disease_name, status, recommendation = self.predict(image)
|
| 118 |
if disease_name and status and recommendation:
|
| 119 |
detailed_response = self.generate_disease_response(disease_name, status, recommendation)
|
|
@@ -123,4 +137,4 @@ class PoultryFarmBot:
|
|
| 123 |
"recommendation": recommendation,
|
| 124 |
"detailed_response": detailed_response
|
| 125 |
}
|
| 126 |
-
return "Please provide
|
|
|
|
| 5 |
import tensorflow as tf
|
| 6 |
from keras.models import load_model
|
| 7 |
from services.llama_service import llama2_response
|
| 8 |
+
import logging
|
| 9 |
|
| 10 |
+
# Initialize logger for better error tracking
|
| 11 |
+
logger = logging.getLogger(__name__)
|
| 12 |
|
| 13 |
# Load TensorFlow/Keras models with GPU support if available, otherwise use CPU
|
| 14 |
try:
|
| 15 |
device_name = '/GPU:0' if len(tf.config.list_physical_devices('GPU')) > 0 else '/CPU:0'
|
| 16 |
with tf.device(device_name):
|
| 17 |
+
# Load models
|
| 18 |
my_model = load_model('models/Final_Chicken_disease_model.h5', compile=True)
|
| 19 |
auth_model = load_model('models/auth_model.h5', compile=True)
|
| 20 |
print(f"Models loaded successfully on {device_name}.")
|
| 21 |
except Exception as e:
|
| 22 |
+
logger.error(f"Error loading models: {e}")
|
| 23 |
+
my_model = None # Ensure there's a fallback in case model loading fails
|
| 24 |
|
| 25 |
# Mapping of disease labels to disease names, health status, and treatment recommendations
|
| 26 |
name_disease = {0: 'Coccidiosis', 1: 'Healthy', 2: 'New Castle Disease', 3: 'Salmonella'}
|
| 27 |
+
status_map = {0: 'Critical', 1: 'No issue', 2: 'Critical', 3: 'Critical'}
|
| 28 |
+
recommendations = {
|
| 29 |
0: 'Panadol', # Treatment for Coccidiosis
|
| 30 |
+
1: 'No treatment needed', # Healthy case
|
| 31 |
2: 'Percetamol', # Treatment for New Castle Disease
|
| 32 |
3: 'Ponston' # Treatment for Salmonella
|
| 33 |
}
|
| 34 |
|
| 35 |
|
| 36 |
+
def detect_disease(image, db):
|
| 37 |
+
"""
|
| 38 |
+
Function to create an instance of PoultryFarmBot and detect disease.
|
| 39 |
+
:param image: Image of poultry feces for disease detection.
|
| 40 |
+
:param db: Database connection to pass into the bot.
|
| 41 |
+
:return: Result of disease detection.
|
| 42 |
+
"""
|
| 43 |
+
bot = PoultryFarmBot(db)
|
| 44 |
+
return bot.diagnose_disease(image)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
class PoultryFarmBot:
|
| 48 |
def __init__(self, db):
|
| 49 |
"""
|
|
|
|
| 61 |
:return: Preprocessed image ready for prediction or None if an error occurs.
|
| 62 |
"""
|
| 63 |
try:
|
| 64 |
+
image_resized = cv2.resize(image, (224, 224)) # Resize image
|
| 65 |
+
image_expanded = np.expand_dims(image_resized, axis=0) # Add batch dimension
|
| 66 |
+
return image_expanded
|
| 67 |
except Exception as e:
|
| 68 |
+
logger.error(f"Error in image preprocessing: {e}")
|
| 69 |
return None
|
| 70 |
|
| 71 |
def predict(self, image):
|
|
|
|
| 75 |
:param image: Input image (numpy array).
|
| 76 |
:return: Tuple of predicted disease name, health status, and treatment recommendation.
|
| 77 |
"""
|
| 78 |
+
image_preprocessed = self.preprocess_image(image)
|
|
|
|
| 79 |
|
| 80 |
+
if image_preprocessed is None:
|
| 81 |
return "Image preprocessing failed.", None, None, None
|
| 82 |
|
| 83 |
+
if my_model is None:
|
| 84 |
+
logger.error("Disease detection model is not loaded.")
|
| 85 |
+
return "Model not loaded.", None, None, None
|
| 86 |
+
|
| 87 |
try:
|
| 88 |
# Predict disease using the loaded model
|
| 89 |
+
indx = my_model.predict(image_preprocessed).argmax()
|
| 90 |
|
| 91 |
+
# Retrieve the disease name, status, and recommended treatment
|
| 92 |
+
disease_name = name_disease.get(indx, "Unknown disease")
|
| 93 |
+
status = status_map.get(indx, "Unknown condition")
|
| 94 |
+
recommendation = recommendations.get(indx, "No recommendation available")
|
| 95 |
|
| 96 |
+
return disease_name, status, recommendation
|
| 97 |
except Exception as e:
|
| 98 |
+
logger.error(f"Error during disease prediction: {e}")
|
| 99 |
return "Prediction failed.", None, None, None
|
| 100 |
|
|
|
|
| 101 |
def generate_disease_response(self, disease_name, status, recommendation):
|
| 102 |
"""
|
| 103 |
Generates a detailed response using Llama 2 model for disease information and recommendations.
|
|
|
|
| 115 |
"to effectively manage this condition on a poultry farm."
|
| 116 |
)
|
| 117 |
response = llama2_response(prompt)
|
|
|
|
| 118 |
return response.replace(prompt, "").strip()
|
| 119 |
except Exception as e:
|
| 120 |
+
logger.error(f"Error generating detailed response: {e}")
|
| 121 |
return "Unable to generate detailed response."
|
| 122 |
|
|
|
|
| 123 |
def diagnose_disease(self, image):
|
| 124 |
"""
|
| 125 |
Diagnose a disease using a fecal image.
|
| 126 |
|
| 127 |
:param image: The image of poultry feces to detect a disease.
|
| 128 |
+
:return: Dictionary containing diagnosis result and detailed response if applicable.
|
| 129 |
"""
|
| 130 |
+
if image is not None and image.size > 0: # Ensure the image is valid
|
| 131 |
disease_name, status, recommendation = self.predict(image)
|
| 132 |
if disease_name and status and recommendation:
|
| 133 |
detailed_response = self.generate_disease_response(disease_name, status, recommendation)
|
|
|
|
| 137 |
"recommendation": recommendation,
|
| 138 |
"detailed_response": detailed_response
|
| 139 |
}
|
| 140 |
+
return {"error": "Please provide a valid image for disease detection."}
|
services/gradio_interface.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
| 1 |
-
# services/gradio_interface.py
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
import gradio as gr
|
| 5 |
-
from services.disease_detection import PoultryFarmBot
|
| 6 |
-
from services.llama_service import llama2_response
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
def chatbot_response(image, text, bot):
|
| 10 |
-
if image is not None:
|
| 11 |
-
diagnosis, name, status, recom = bot.predict(image)
|
| 12 |
-
return f"Disease: {name}, Status: {status}, Recommendation: {recom}" if name else "No disease detected."
|
| 13 |
-
else:
|
| 14 |
-
return llama2_response(text)
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
def create_gradio_interface():
|
| 18 |
-
bot = PoultryFarmBot(db=None) # Pass your MongoDB instance here if needed
|
| 19 |
-
|
| 20 |
-
with gr.Blocks(theme=gr.themes.Soft(primary_hue="green", neutral_hue="slate")) as interface:
|
| 21 |
-
gr.Markdown("# 🐔 Poultry Management Chatbot")
|
| 22 |
-
gr.Markdown(
|
| 23 |
-
"This chatbot can help you manage your poultry with conversational AI. Upload an image or ask a question!")
|
| 24 |
-
|
| 25 |
-
with gr.Row():
|
| 26 |
-
with gr.Column(scale=1):
|
| 27 |
-
fecal_image = gr.Image(label="Upload Image of Poultry Feces (Optional)", type="numpy", show_label=True)
|
| 28 |
-
with gr.Column(scale=2):
|
| 29 |
-
user_input = gr.Textbox(label="Type your question", placeholder="Ask about poultry management...",
|
| 30 |
-
lines=3)
|
| 31 |
-
|
| 32 |
-
output_box = gr.Textbox(label="Response", interactive=False, lines=10)
|
| 33 |
-
submit_button = gr.Button("Submit")
|
| 34 |
-
submit_button.click(fn=lambda image, text: chatbot_response(image, text, bot),
|
| 35 |
-
inputs=[fecal_image, user_input], outputs=[output_box])
|
| 36 |
-
|
| 37 |
-
return interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
services/inventory_manager.py
CHANGED
|
@@ -3,10 +3,14 @@
|
|
| 3 |
|
| 4 |
from bson.objectid import ObjectId
|
| 5 |
import datetime
|
|
|
|
| 6 |
|
| 7 |
# MongoDB Setup (import from your db configuration)
|
| 8 |
from config.db import db
|
| 9 |
|
|
|
|
|
|
|
|
|
|
| 10 |
# Define the inventory collection
|
| 11 |
inventory_collection = db.inventory # MongoDB collection to store inventory items
|
| 12 |
|
|
@@ -45,7 +49,7 @@ class InventoryManager:
|
|
| 45 |
result = self.collection.insert_one(new_item)
|
| 46 |
return str(result.inserted_id)
|
| 47 |
except Exception as e:
|
| 48 |
-
|
| 49 |
return None
|
| 50 |
|
| 51 |
def update_inventory_item(self, item_id, updated_fields):
|
|
@@ -64,7 +68,7 @@ class InventoryManager:
|
|
| 64 |
)
|
| 65 |
return result.modified_count > 0
|
| 66 |
except Exception as e:
|
| 67 |
-
|
| 68 |
return False
|
| 69 |
|
| 70 |
def get_inventory_item_by_id(self, item_id):
|
|
@@ -77,7 +81,7 @@ class InventoryManager:
|
|
| 77 |
try:
|
| 78 |
return self.collection.find_one({"_id": ObjectId(item_id)})
|
| 79 |
except Exception as e:
|
| 80 |
-
|
| 81 |
return None
|
| 82 |
|
| 83 |
def get_all_inventory_items(self, user_id=None):
|
|
@@ -88,11 +92,10 @@ class InventoryManager:
|
|
| 88 |
:return: A list of inventory items or an empty list if none are found.
|
| 89 |
"""
|
| 90 |
try:
|
| 91 |
-
if user_id
|
| 92 |
-
|
| 93 |
-
return list(self.collection.find())
|
| 94 |
except Exception as e:
|
| 95 |
-
|
| 96 |
return []
|
| 97 |
|
| 98 |
def delete_inventory_item(self, item_id):
|
|
@@ -106,5 +109,5 @@ class InventoryManager:
|
|
| 106 |
result = self.collection.delete_one({"_id": ObjectId(item_id)})
|
| 107 |
return result.deleted_count > 0
|
| 108 |
except Exception as e:
|
| 109 |
-
|
| 110 |
return False
|
|
|
|
| 3 |
|
| 4 |
from bson.objectid import ObjectId
|
| 5 |
import datetime
|
| 6 |
+
import logging
|
| 7 |
|
| 8 |
# MongoDB Setup (import from your db configuration)
|
| 9 |
from config.db import db
|
| 10 |
|
| 11 |
+
# Define logger
|
| 12 |
+
logger = logging.getLogger(__name__)
|
| 13 |
+
|
| 14 |
# Define the inventory collection
|
| 15 |
inventory_collection = db.inventory # MongoDB collection to store inventory items
|
| 16 |
|
|
|
|
| 49 |
result = self.collection.insert_one(new_item)
|
| 50 |
return str(result.inserted_id)
|
| 51 |
except Exception as e:
|
| 52 |
+
logger.error(f"Error adding inventory item for user {user_id}: {e}")
|
| 53 |
return None
|
| 54 |
|
| 55 |
def update_inventory_item(self, item_id, updated_fields):
|
|
|
|
| 68 |
)
|
| 69 |
return result.modified_count > 0
|
| 70 |
except Exception as e:
|
| 71 |
+
logger.error(f"Error updating inventory item {item_id}: {e}")
|
| 72 |
return False
|
| 73 |
|
| 74 |
def get_inventory_item_by_id(self, item_id):
|
|
|
|
| 81 |
try:
|
| 82 |
return self.collection.find_one({"_id": ObjectId(item_id)})
|
| 83 |
except Exception as e:
|
| 84 |
+
logger.error(f"Error retrieving inventory item {item_id}: {e}")
|
| 85 |
return None
|
| 86 |
|
| 87 |
def get_all_inventory_items(self, user_id=None):
|
|
|
|
| 92 |
:return: A list of inventory items or an empty list if none are found.
|
| 93 |
"""
|
| 94 |
try:
|
| 95 |
+
query = {"user_id": ObjectId(user_id)} if user_id else {}
|
| 96 |
+
return list(self.collection.find(query))
|
|
|
|
| 97 |
except Exception as e:
|
| 98 |
+
logger.error(f"Error retrieving inventory items for user {user_id}: {e}")
|
| 99 |
return []
|
| 100 |
|
| 101 |
def delete_inventory_item(self, item_id):
|
|
|
|
| 109 |
result = self.collection.delete_one({"_id": ObjectId(item_id)})
|
| 110 |
return result.deleted_count > 0
|
| 111 |
except Exception as e:
|
| 112 |
+
logger.error(f"Error deleting inventory item {item_id}: {e}")
|
| 113 |
return False
|
services/llama_service.py
CHANGED
|
@@ -1,25 +1,42 @@
|
|
| 1 |
# services/llama_service.py
|
| 2 |
|
| 3 |
import os
|
|
|
|
| 4 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 5 |
from huggingface_hub import login
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
# Load Llama model and tokenizer for text generation
|
|
|
|
| 8 |
|
| 9 |
# Ensure the Hugging Face token is set
|
| 10 |
-
|
| 11 |
-
if
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
else:
|
| 14 |
-
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
# Ensure the tokenizer has a padding token; if not, add
|
| 20 |
if tokenizer.pad_token is None:
|
| 21 |
tokenizer.add_special_tokens({'pad_token': '[PAD]'})
|
| 22 |
model.resize_token_embeddings(len(tokenizer))
|
|
|
|
| 23 |
|
| 24 |
|
| 25 |
def llama2_response(user_input):
|
|
@@ -32,6 +49,7 @@ def llama2_response(user_input):
|
|
| 32 |
try:
|
| 33 |
# Tokenize the input text, ensuring truncation and padding
|
| 34 |
inputs = tokenizer(user_input, return_tensors="pt", truncation=True, max_length=150, padding=True)
|
|
|
|
| 35 |
|
| 36 |
# Generate the model's response
|
| 37 |
outputs = model.generate(
|
|
@@ -42,9 +60,12 @@ def llama2_response(user_input):
|
|
| 42 |
pad_token_id=tokenizer.pad_token_id, # Ensure the use of a valid pad token
|
| 43 |
attention_mask=inputs["attention_mask"] # Use attention mask for padded tokens
|
| 44 |
)
|
|
|
|
| 45 |
|
| 46 |
# Decode the generated response, skipping special tokens
|
| 47 |
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 48 |
return response
|
|
|
|
| 49 |
except Exception as e:
|
|
|
|
| 50 |
return f"Error generating response: {str(e)}"
|
|
|
|
| 1 |
# services/llama_service.py
|
| 2 |
|
| 3 |
import os
|
| 4 |
+
import logging
|
| 5 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 6 |
from huggingface_hub import login
|
| 7 |
|
| 8 |
+
# Configure logging
|
| 9 |
+
logging.basicConfig(level=logging.INFO)
|
| 10 |
+
logger = logging.getLogger(__name__)
|
| 11 |
+
|
| 12 |
# Load Llama model and tokenizer for text generation
|
| 13 |
+
model_name = "meta-llama/Llama-3.2-1B"
|
| 14 |
|
| 15 |
# Ensure the Hugging Face token is set
|
| 16 |
+
hf_token = os.getenv('HF_Token')
|
| 17 |
+
if hf_token:
|
| 18 |
+
try:
|
| 19 |
+
login(token=hf_token, add_to_git_credential=True)
|
| 20 |
+
logger.info("Successfully logged into Hugging Face Hub.")
|
| 21 |
+
except Exception as e:
|
| 22 |
+
logger.error(f"Error logging into Hugging Face Hub: {e}")
|
| 23 |
else:
|
| 24 |
+
logger.warning("Warning: Hugging Face token not found in environment variables.")
|
| 25 |
|
| 26 |
+
try:
|
| 27 |
+
# Load tokenizer and model
|
| 28 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 29 |
+
model = AutoModelForCausalLM.from_pretrained(model_name)
|
| 30 |
+
logger.info(f"Successfully loaded model and tokenizer: {model_name}")
|
| 31 |
+
except Exception as e:
|
| 32 |
+
logger.error(f"Error loading model or tokenizer: {e}")
|
| 33 |
+
raise
|
| 34 |
|
| 35 |
+
# Ensure the tokenizer has a padding token; if not, add one
|
| 36 |
if tokenizer.pad_token is None:
|
| 37 |
tokenizer.add_special_tokens({'pad_token': '[PAD]'})
|
| 38 |
model.resize_token_embeddings(len(tokenizer))
|
| 39 |
+
logger.info("Added a padding token to the tokenizer.")
|
| 40 |
|
| 41 |
|
| 42 |
def llama2_response(user_input):
|
|
|
|
| 49 |
try:
|
| 50 |
# Tokenize the input text, ensuring truncation and padding
|
| 51 |
inputs = tokenizer(user_input, return_tensors="pt", truncation=True, max_length=150, padding=True)
|
| 52 |
+
logger.info("Successfully tokenized the input.")
|
| 53 |
|
| 54 |
# Generate the model's response
|
| 55 |
outputs = model.generate(
|
|
|
|
| 60 |
pad_token_id=tokenizer.pad_token_id, # Ensure the use of a valid pad token
|
| 61 |
attention_mask=inputs["attention_mask"] # Use attention mask for padded tokens
|
| 62 |
)
|
| 63 |
+
logger.info("Response generation successful.")
|
| 64 |
|
| 65 |
# Decode the generated response, skipping special tokens
|
| 66 |
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 67 |
return response
|
| 68 |
+
|
| 69 |
except Exception as e:
|
| 70 |
+
logger.error(f"Error generating response: {e}")
|
| 71 |
return f"Error generating response: {str(e)}"
|
services/report_generator.py
CHANGED
|
@@ -3,9 +3,13 @@
|
|
| 3 |
|
| 4 |
import pandas as pd
|
| 5 |
from bson.objectid import ObjectId
|
| 6 |
-
import
|
| 7 |
from config.db import db
|
| 8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
# Define collections for report generation
|
| 10 |
inventory_collection = db.inventory
|
| 11 |
health_collection = db.health
|
|
@@ -22,6 +26,24 @@ class ReportGenerator:
|
|
| 22 |
self.health_collection = health_collection
|
| 23 |
self.usage_collection = usage_collection
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
def generate_inventory_report(self, user_id=None):
|
| 26 |
"""
|
| 27 |
Generates a report of all inventory items, optionally filtered by user.
|
|
@@ -29,20 +51,12 @@ class ReportGenerator:
|
|
| 29 |
:param user_id: Optional. The ID of the user to filter the inventory report.
|
| 30 |
:return: A pandas DataFrame containing the inventory report.
|
| 31 |
"""
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
inventory_items = list(self.inventory_collection.find(query))
|
| 35 |
-
|
| 36 |
-
if not inventory_items:
|
| 37 |
-
return pd.DataFrame([])
|
| 38 |
|
| 39 |
-
|
| 40 |
-
df =
|
| 41 |
-
|
| 42 |
-
return df
|
| 43 |
-
except Exception as e:
|
| 44 |
-
print(f"Error generating inventory report: {e}")
|
| 45 |
-
return pd.DataFrame([])
|
| 46 |
|
| 47 |
def generate_health_report(self, user_id=None):
|
| 48 |
"""
|
|
@@ -51,20 +65,12 @@ class ReportGenerator:
|
|
| 51 |
:param user_id: Optional. The ID of the user to filter the health report.
|
| 52 |
:return: A pandas DataFrame containing the health report.
|
| 53 |
"""
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
health_records = list(self.health_collection.find(query))
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
# Convert MongoDB documents to a pandas DataFrame
|
| 62 |
-
df = pd.DataFrame(health_records)
|
| 63 |
-
df = df.drop(columns=['_id', 'user_id']) # Drop internal fields
|
| 64 |
-
return df
|
| 65 |
-
except Exception as e:
|
| 66 |
-
print(f"Error generating health report: {e}")
|
| 67 |
-
return pd.DataFrame([])
|
| 68 |
|
| 69 |
def generate_usage_report(self, user_id=None, manager_id=None, interaction_type=None):
|
| 70 |
"""
|
|
@@ -75,27 +81,20 @@ class ReportGenerator:
|
|
| 75 |
:param interaction_type: Optional. Filter by interaction type (e.g., "disease_detection").
|
| 76 |
:return: A pandas DataFrame containing the assistant usage report.
|
| 77 |
"""
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
query['interaction_type'] = interaction_type
|
| 86 |
-
|
| 87 |
-
usage_records = list(self.usage_collection.find(query))
|
| 88 |
|
| 89 |
-
|
| 90 |
-
return pd.DataFrame([])
|
| 91 |
|
| 92 |
-
|
| 93 |
-
df =
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
except Exception as e:
|
| 97 |
-
print(f"Error generating usage report: {e}")
|
| 98 |
-
return pd.DataFrame([])
|
| 99 |
|
| 100 |
def generate_combined_report(self, user_id=None, manager_id=None):
|
| 101 |
"""
|
|
@@ -116,7 +115,7 @@ class ReportGenerator:
|
|
| 116 |
"usage_report": usage_report
|
| 117 |
}
|
| 118 |
except Exception as e:
|
| 119 |
-
|
| 120 |
return {
|
| 121 |
"inventory_report": pd.DataFrame([]),
|
| 122 |
"health_report": pd.DataFrame([]),
|
|
@@ -133,7 +132,8 @@ class ReportGenerator:
|
|
| 133 |
"""
|
| 134 |
try:
|
| 135 |
report_df.to_csv(file_path, index=False)
|
|
|
|
| 136 |
return True
|
| 137 |
except Exception as e:
|
| 138 |
-
|
| 139 |
return False
|
|
|
|
| 3 |
|
| 4 |
import pandas as pd
|
| 5 |
from bson.objectid import ObjectId
|
| 6 |
+
import logging
|
| 7 |
from config.db import db
|
| 8 |
|
| 9 |
+
# Setup logging
|
| 10 |
+
logging.basicConfig(level=logging.INFO)
|
| 11 |
+
logger = logging.getLogger(__name__)
|
| 12 |
+
|
| 13 |
# Define collections for report generation
|
| 14 |
inventory_collection = db.inventory
|
| 15 |
health_collection = db.health
|
|
|
|
| 26 |
self.health_collection = health_collection
|
| 27 |
self.usage_collection = usage_collection
|
| 28 |
|
| 29 |
+
def _fetch_data(self, collection, query):
|
| 30 |
+
"""
|
| 31 |
+
Private helper function to fetch data from MongoDB and convert it to a pandas DataFrame.
|
| 32 |
+
|
| 33 |
+
:param collection: MongoDB collection to query.
|
| 34 |
+
:param query: MongoDB query for filtering data.
|
| 35 |
+
:return: A pandas DataFrame or an empty DataFrame if no data is found.
|
| 36 |
+
"""
|
| 37 |
+
try:
|
| 38 |
+
data = list(collection.find(query))
|
| 39 |
+
if not data:
|
| 40 |
+
logger.info("No data found for query: %s", query)
|
| 41 |
+
return pd.DataFrame([])
|
| 42 |
+
return pd.DataFrame(data)
|
| 43 |
+
except Exception as e:
|
| 44 |
+
logger.error(f"Error fetching data from {collection.name}: {e}")
|
| 45 |
+
return pd.DataFrame([])
|
| 46 |
+
|
| 47 |
def generate_inventory_report(self, user_id=None):
|
| 48 |
"""
|
| 49 |
Generates a report of all inventory items, optionally filtered by user.
|
|
|
|
| 51 |
:param user_id: Optional. The ID of the user to filter the inventory report.
|
| 52 |
:return: A pandas DataFrame containing the inventory report.
|
| 53 |
"""
|
| 54 |
+
query = {"user_id": ObjectId(user_id)} if user_id else {}
|
| 55 |
+
df = self._fetch_data(self.inventory_collection, query)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
+
if not df.empty:
|
| 58 |
+
df = df.drop(columns=['_id', 'user_id'], errors='ignore') # Drop internal fields if they exist
|
| 59 |
+
return df
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
def generate_health_report(self, user_id=None):
|
| 62 |
"""
|
|
|
|
| 65 |
:param user_id: Optional. The ID of the user to filter the health report.
|
| 66 |
:return: A pandas DataFrame containing the health report.
|
| 67 |
"""
|
| 68 |
+
query = {"user_id": ObjectId(user_id)} if user_id else {}
|
| 69 |
+
df = self._fetch_data(self.health_collection, query)
|
|
|
|
| 70 |
|
| 71 |
+
if not df.empty:
|
| 72 |
+
df = df.drop(columns=['_id', 'user_id'], errors='ignore') # Drop internal fields if they exist
|
| 73 |
+
return df
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
def generate_usage_report(self, user_id=None, manager_id=None, interaction_type=None):
|
| 76 |
"""
|
|
|
|
| 81 |
:param interaction_type: Optional. Filter by interaction type (e.g., "disease_detection").
|
| 82 |
:return: A pandas DataFrame containing the assistant usage report.
|
| 83 |
"""
|
| 84 |
+
query = {}
|
| 85 |
+
if user_id:
|
| 86 |
+
query['user_id'] = ObjectId(user_id)
|
| 87 |
+
if manager_id:
|
| 88 |
+
query['manager_id'] = ObjectId(manager_id)
|
| 89 |
+
if interaction_type:
|
| 90 |
+
query['interaction_type'] = interaction_type
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
+
df = self._fetch_data(self.usage_collection, query)
|
|
|
|
| 93 |
|
| 94 |
+
if not df.empty:
|
| 95 |
+
df = df.drop(columns=['_id', 'user_id', 'manager_id'],
|
| 96 |
+
errors='ignore') # Drop internal fields if they exist
|
| 97 |
+
return df
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
def generate_combined_report(self, user_id=None, manager_id=None):
|
| 100 |
"""
|
|
|
|
| 115 |
"usage_report": usage_report
|
| 116 |
}
|
| 117 |
except Exception as e:
|
| 118 |
+
logger.error(f"Error generating combined report: {e}")
|
| 119 |
return {
|
| 120 |
"inventory_report": pd.DataFrame([]),
|
| 121 |
"health_report": pd.DataFrame([]),
|
|
|
|
| 132 |
"""
|
| 133 |
try:
|
| 134 |
report_df.to_csv(file_path, index=False)
|
| 135 |
+
logger.info(f"Report successfully exported to {file_path}")
|
| 136 |
return True
|
| 137 |
except Exception as e:
|
| 138 |
+
logger.error(f"Error exporting report to CSV: {e}")
|
| 139 |
return False
|
services/usage_tracker.py
CHANGED
|
@@ -1,10 +1,14 @@
|
|
| 1 |
# services/usage_tracker.py
|
| 2 |
|
| 3 |
-
from pymongo import MongoClient
|
| 4 |
-
from bson.objectid import ObjectId
|
| 5 |
import datetime
|
|
|
|
|
|
|
| 6 |
from config.db import db
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
# Define the usage tracking collection
|
| 9 |
usage_collection = db.user_usage # MongoDB collection to store assistant usage logs
|
| 10 |
|
|
@@ -25,20 +29,21 @@ class UsageTracker:
|
|
| 25 |
:param manager_id: The ID of the user's manager.
|
| 26 |
:param interaction_type: The type of interaction (e.g., "disease_detection", "inventory_management").
|
| 27 |
:param metadata: Optional. Additional details related to the interaction (e.g., query details, result).
|
| 28 |
-
:return: The inserted usage log's ID (MongoDB ObjectId).
|
| 29 |
"""
|
| 30 |
try:
|
| 31 |
log_entry = {
|
| 32 |
"user_id": ObjectId(user_id),
|
| 33 |
"manager_id": ObjectId(manager_id),
|
| 34 |
"interaction_type": interaction_type,
|
| 35 |
-
"metadata": metadata
|
| 36 |
"timestamp": datetime.datetime.utcnow()
|
| 37 |
}
|
| 38 |
result = self.collection.insert_one(log_entry)
|
|
|
|
| 39 |
return str(result.inserted_id)
|
| 40 |
except Exception as e:
|
| 41 |
-
|
| 42 |
return None
|
| 43 |
|
| 44 |
def get_usage_by_user(self, user_id):
|
|
@@ -49,9 +54,11 @@ class UsageTracker:
|
|
| 49 |
:return: A list of usage logs for the user or an empty list if none are found.
|
| 50 |
"""
|
| 51 |
try:
|
| 52 |
-
|
|
|
|
|
|
|
| 53 |
except Exception as e:
|
| 54 |
-
|
| 55 |
return []
|
| 56 |
|
| 57 |
def get_usage_by_manager(self, manager_id):
|
|
@@ -62,9 +69,11 @@ class UsageTracker:
|
|
| 62 |
:return: A list of usage logs for the manager's users or an empty list if none are found.
|
| 63 |
"""
|
| 64 |
try:
|
| 65 |
-
|
|
|
|
|
|
|
| 66 |
except Exception as e:
|
| 67 |
-
|
| 68 |
return []
|
| 69 |
|
| 70 |
def get_usage_by_interaction_type(self, interaction_type):
|
|
@@ -75,9 +84,11 @@ class UsageTracker:
|
|
| 75 |
:return: A list of usage logs for the interaction type or an empty list if none are found.
|
| 76 |
"""
|
| 77 |
try:
|
| 78 |
-
|
|
|
|
|
|
|
| 79 |
except Exception as e:
|
| 80 |
-
|
| 81 |
return []
|
| 82 |
|
| 83 |
def get_usage_logs(self, user_id=None, manager_id=None, interaction_type=None):
|
|
@@ -98,9 +109,13 @@ class UsageTracker:
|
|
| 98 |
if interaction_type:
|
| 99 |
query["interaction_type"] = interaction_type
|
| 100 |
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
| 102 |
except Exception as e:
|
| 103 |
-
|
|
|
|
| 104 |
return []
|
| 105 |
|
| 106 |
def delete_usage_log(self, log_id):
|
|
@@ -112,7 +127,12 @@ class UsageTracker:
|
|
| 112 |
"""
|
| 113 |
try:
|
| 114 |
result = self.collection.delete_one({"_id": ObjectId(log_id)})
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
except Exception as e:
|
| 117 |
-
|
| 118 |
return False
|
|
|
|
| 1 |
# services/usage_tracker.py
|
| 2 |
|
|
|
|
|
|
|
| 3 |
import datetime
|
| 4 |
+
from bson.objectid import ObjectId
|
| 5 |
+
import logging
|
| 6 |
from config.db import db
|
| 7 |
|
| 8 |
+
# Setup logging
|
| 9 |
+
logging.basicConfig(level=logging.INFO)
|
| 10 |
+
logger = logging.getLogger(__name__)
|
| 11 |
+
|
| 12 |
# Define the usage tracking collection
|
| 13 |
usage_collection = db.user_usage # MongoDB collection to store assistant usage logs
|
| 14 |
|
|
|
|
| 29 |
:param manager_id: The ID of the user's manager.
|
| 30 |
:param interaction_type: The type of interaction (e.g., "disease_detection", "inventory_management").
|
| 31 |
:param metadata: Optional. Additional details related to the interaction (e.g., query details, result).
|
| 32 |
+
:return: The inserted usage log's ID (MongoDB ObjectId) or None if there's an error.
|
| 33 |
"""
|
| 34 |
try:
|
| 35 |
log_entry = {
|
| 36 |
"user_id": ObjectId(user_id),
|
| 37 |
"manager_id": ObjectId(manager_id),
|
| 38 |
"interaction_type": interaction_type,
|
| 39 |
+
"metadata": metadata or {},
|
| 40 |
"timestamp": datetime.datetime.utcnow()
|
| 41 |
}
|
| 42 |
result = self.collection.insert_one(log_entry)
|
| 43 |
+
logger.info(f"Successfully logged usage for user {user_id} with interaction type {interaction_type}.")
|
| 44 |
return str(result.inserted_id)
|
| 45 |
except Exception as e:
|
| 46 |
+
logger.error(f"Error logging usage for user {user_id}: {e}")
|
| 47 |
return None
|
| 48 |
|
| 49 |
def get_usage_by_user(self, user_id):
|
|
|
|
| 54 |
:return: A list of usage logs for the user or an empty list if none are found.
|
| 55 |
"""
|
| 56 |
try:
|
| 57 |
+
logs = list(self.collection.find({"user_id": ObjectId(user_id)}))
|
| 58 |
+
logger.info(f"Retrieved {len(logs)} usage logs for user {user_id}.")
|
| 59 |
+
return logs
|
| 60 |
except Exception as e:
|
| 61 |
+
logger.error(f"Error retrieving usage logs for user {user_id}: {e}")
|
| 62 |
return []
|
| 63 |
|
| 64 |
def get_usage_by_manager(self, manager_id):
|
|
|
|
| 69 |
:return: A list of usage logs for the manager's users or an empty list if none are found.
|
| 70 |
"""
|
| 71 |
try:
|
| 72 |
+
logs = list(self.collection.find({"manager_id": ObjectId(manager_id)}))
|
| 73 |
+
logger.info(f"Retrieved {len(logs)} usage logs for manager {manager_id}.")
|
| 74 |
+
return logs
|
| 75 |
except Exception as e:
|
| 76 |
+
logger.error(f"Error retrieving usage logs for manager {manager_id}: {e}")
|
| 77 |
return []
|
| 78 |
|
| 79 |
def get_usage_by_interaction_type(self, interaction_type):
|
|
|
|
| 84 |
:return: A list of usage logs for the interaction type or an empty list if none are found.
|
| 85 |
"""
|
| 86 |
try:
|
| 87 |
+
logs = list(self.collection.find({"interaction_type": interaction_type}))
|
| 88 |
+
logger.info(f"Retrieved {len(logs)} usage logs for interaction type {interaction_type}.")
|
| 89 |
+
return logs
|
| 90 |
except Exception as e:
|
| 91 |
+
logger.error(f"Error retrieving usage logs for interaction type {interaction_type}: {e}")
|
| 92 |
return []
|
| 93 |
|
| 94 |
def get_usage_logs(self, user_id=None, manager_id=None, interaction_type=None):
|
|
|
|
| 109 |
if interaction_type:
|
| 110 |
query["interaction_type"] = interaction_type
|
| 111 |
|
| 112 |
+
logs = list(self.collection.find(query))
|
| 113 |
+
logger.info(
|
| 114 |
+
f"Retrieved {len(logs)} usage logs with filters user_id={user_id}, manager_id={manager_id}, interaction_type={interaction_type}.")
|
| 115 |
+
return logs
|
| 116 |
except Exception as e:
|
| 117 |
+
logger.error(
|
| 118 |
+
f"Error retrieving usage logs with filters user_id={user_id}, manager_id={manager_id}, interaction_type={interaction_type}: {e}")
|
| 119 |
return []
|
| 120 |
|
| 121 |
def delete_usage_log(self, log_id):
|
|
|
|
| 127 |
"""
|
| 128 |
try:
|
| 129 |
result = self.collection.delete_one({"_id": ObjectId(log_id)})
|
| 130 |
+
if result.deleted_count > 0:
|
| 131 |
+
logger.info(f"Successfully deleted usage log with ID {log_id}.")
|
| 132 |
+
return True
|
| 133 |
+
else:
|
| 134 |
+
logger.warning(f"Usage log with ID {log_id} not found for deletion.")
|
| 135 |
+
return False
|
| 136 |
except Exception as e:
|
| 137 |
+
logger.error(f"Error deleting usage log with ID {log_id}: {e}")
|
| 138 |
return False
|