Emmanuel Frimpong Asante commited on
Commit
318368c
·
1 Parent(s): 7fc8dba

"Update space"

Browse files

Signed-off-by: Emmanuel Frimpong Asante <[email protected]>

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 (e.g., a user performs an action in the system)
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 information about the action.
19
- :return: JSON response indicating success or failure.
20
  """
21
  try:
22
- ip_address = request.remote_addr # Get the user's IP address from the request
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: The ID of the user managing the poultry.
35
- :param poultry_id: The unique identifier for the poultry bird.
36
- :param disease_name: The name of the detected disease.
37
- :param status: The health status of the bird (e.g., "Critical", "No issue").
38
- :param recommendation: The recommended treatment or action.
39
- :param image_path: Optional. The path to an image related to the health record.
40
- :return: JSON response indicating success or failure.
41
  """
42
  try:
 
43
  record_id = create_health_record(user_id, poultry_id, disease_name, status, recommendation, image_path)
44
- # Log the health record creation action
 
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, medicine).
56
-
57
- :param user_id: The ID of the user managing the inventory.
58
- :param item_name: The name of the inventory item.
59
- :param category: The category of the item (e.g., "Feed", "Medicine").
60
- :param quantity: The quantity added.
61
- :param unit: The unit of measurement (e.g., "kg", "liters").
62
- :param description: Optional. Additional notes or description of the item.
63
- :return: JSON response indicating success or failure.
64
  """
65
  try:
66
- item_id = create_inventory_item(item_name, category, quantity, unit, user_id, description=description)
67
- # Log the inventory addition action
 
 
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 (e.g., usage or quantity adjustment)
76
  def log_inventory_update(user_id, item_id, updated_fields):
77
  """
78
- Logs an update to an inventory item (e.g., when quantity is used).
79
 
80
- :param user_id: The ID of the user managing the inventory.
81
- :param item_id: The ID of the inventory item being updated.
82
- :param updated_fields: The fields to be updated (e.g., "used_quantity", "quantity").
83
- :return: JSON response indicating success or failure.
84
  """
85
  try:
 
86
  update_success = update_inventory_item(item_id, updated_fields)
87
  if update_success:
88
- # Log the inventory update action
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 the usage of the assistant by a user.
102
 
103
- :param user_id: The ID of the user interacting with the assistant.
104
- :param manager_id: The ID of the manager overseeing the user.
105
- :param interaction_type: The type of interaction (e.g., "disease_detection", "inventory_management").
106
- :param metadata: Optional. Additional details about the interaction.
107
- :return: JSON response indicating success or failure.
108
  """
109
  try:
 
110
  usage_record_id = create_usage_record(user_id, manager_id, interaction_type, metadata)
111
- # Log the assistant usage action
 
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
- Detect disease from the provided image and log the health record.
13
- Expects a POST request with the following fields:
14
  - user_id: ID of the user submitting the disease detection request.
15
- - poultry_id: The ID of the poultry bird.
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
- # Extract the data from the request
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 or not poultry_id or not image:
28
  return jsonify({"error": "Missing required fields: user_id, poultry_id, or image"}), 400
29
 
30
- # Run disease detection
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
- return jsonify({"error": str(e)}), 500
 
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({"message": "Health record not found"}), 404
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 not found.
86
  """
87
  try:
88
  health_records = get_health_records_by_user(user_id)
89
  if not health_records:
90
- return jsonify({"message": "No health records found for this user"}), 404
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 create_inventory_item, update_inventory_item, get_inventory_item_by_id, \
 
 
 
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: Name of the inventory item.
17
- - category: Category of the item (e.g., "Feed", "Medicine").
18
- - quantity: Total quantity of the item.
19
- - unit: Unit of measurement (e.g., "kg", "liters").
20
- - description: Optional. Additional notes or description about the item.
21
 
22
  Returns:
23
  - JSON response with the result of the addition.
24
  """
25
  try:
26
- # Extract data from the request
27
- user_id = request.json.get('user_id')
28
- item_name = request.json.get('item_name')
29
- category = request.json.get('category')
30
- quantity = request.json.get('quantity')
31
- unit = request.json.get('unit')
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
- # Add the inventory item
 
 
 
 
 
 
 
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 from the request
64
- user_id = request.json.get('user_id')
65
- item_id = request.json.get('item_id')
66
- updated_fields = request.json.get('updated_fields')
 
67
 
68
- if not user_id or not item_id or not updated_fields:
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 create_usage_record, get_usage_by_user, get_usage_by_manager, \
 
 
 
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
- user_id = request.json.get('user_id')
26
- manager_id = request.json.get('manager_id')
27
- interaction_type = request.json.get('interaction_type')
28
- metadata = request.json.get('metadata')
 
29
 
30
- if not user_id or not manager_id or not interaction_type:
31
- return jsonify({"error": "Missing required fields"}), 400
 
32
 
33
- # Log assistant usage
34
  usage_record_id = create_usage_record(user_id, manager_id, interaction_type, metadata)
35
 
36
- # Log the usage in the system log
37
  log_assistant_usage(user_id, manager_id, interaction_type, metadata)
38
 
39
- return jsonify({"message": "Assistant usage logged successfully", "usage_record_id": usage_record_id}), 201
 
 
 
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
- return detect_and_log_disease()
 
 
 
 
 
 
 
 
 
 
 
18
 
19
 
20
  @api_bp.route('/health-record/<record_id>', methods=['GET'])
21
  def get_health_record_route(record_id):
22
- return get_health_record(record_id)
 
 
 
 
 
 
 
23
 
24
 
25
  @api_bp.route('/health-records/<user_id>', methods=['GET'])
26
  def get_health_records_for_user_route(user_id):
27
- return get_health_records_for_user(user_id)
 
 
 
 
 
 
 
28
 
29
 
30
  # Inventory Management Routes
31
  @api_bp.route('/add-inventory-item', methods=['POST'])
32
  def add_inventory_item_route():
33
- return add_inventory_item()
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
 
36
  @api_bp.route('/update-inventory-item', methods=['PUT'])
37
  def update_inventory_item_route():
38
- return update_inventory_item_by_id()
 
 
 
 
 
 
 
 
 
 
 
39
 
40
 
41
  @api_bp.route('/inventory-item/<item_id>', methods=['GET'])
42
  def get_inventory_item_route(item_id):
43
- return get_inventory_by_id(item_id)
 
 
 
 
 
 
 
44
 
45
 
46
  @api_bp.route('/inventory', methods=['GET'])
47
  def get_all_inventory_route():
48
- return get_all_inventory()
 
 
 
 
 
 
 
49
 
50
 
51
  # Assistant Usage Tracking Routes
52
  @api_bp.route('/log-usage', methods=['POST'])
53
  def log_usage_route():
54
- return log_usage()
 
 
 
 
 
 
 
 
 
 
 
55
 
56
 
57
  @api_bp.route('/usage/<user_id>', methods=['GET'])
58
  def get_usage_for_user_route(user_id):
59
- return get_usage_for_user(user_id)
 
 
 
 
 
 
 
60
 
61
 
62
  @api_bp.route('/manager-usage/<manager_id>', methods=['GET'])
63
  def get_usage_for_manager_route(manager_id):
64
- return get_usage_for_manager(manager_id)
 
 
 
 
 
 
 
65
 
66
 
67
  @api_bp.route('/usage-type/<interaction_type>', methods=['GET'])
68
  def get_usage_by_type_route(interaction_type):
69
- return get_usage_by_type(interaction_type)
 
 
 
 
 
 
 
70
 
71
 
72
  # User Action Logging Route
73
  @api_bp.route('/log-user-action', methods=['POST'])
74
  def log_user_action_route():
75
- user_id = request.json.get('user_id')
76
- message = request.json.get('message')
77
- level = request.json.get('level', 'INFO')
78
- metadata = request.json.get('metadata', {})
79
- return log_user_action(user_id, message, level, metadata)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
 
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
- Expects a POST request with the following fields:
16
- - user_id: ID of the user.
17
- - poultry_id: ID of the poultry.
 
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
- return detect_and_log_disease()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  except Exception as e:
24
- return jsonify({"error": str(e)}), 500
 
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
- return get_health_record(record_id)
 
 
 
 
36
  except Exception as e:
37
- return jsonify({"error": str(e)}), 500
 
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
- return get_health_records_for_user(user_id)
 
 
 
 
49
  except Exception as e:
50
- return jsonify({"error": str(e)}), 500
 
 
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
- return add_inventory_item()
 
 
 
 
 
 
 
 
 
 
 
32
  except Exception as e:
33
- return jsonify({"error": str(e)}), 500
 
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
- return update_inventory_item_by_id()
 
 
 
 
 
 
 
 
49
  except Exception as e:
50
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
 
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
- return log_usage()
 
 
 
 
 
 
 
 
 
26
  except Exception as e:
27
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
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
- return jsonify({"error": str(e)}), 500
 
 
 
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
- # Check your model optimizer configuration
10
- optimizer = tf.keras.optimizers.Adam() # Default optimizer without weight_decay
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
- print(f"Error loading models: {e}")
 
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
- result = {0: 'Critical', 1: 'No issue', 2: 'Critical', 3: 'Critical'}
25
- recommend = {
26
  0: 'Panadol', # Treatment for Coccidiosis
27
- 1: 'You have no need for Medicine', # Healthy case
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
- image_check = cv2.resize(image, (224, 224)) # Resize image
51
- image_check = np.expand_dims(image_check, axis=0) # Add batch dimension
52
- return image_check
53
  except Exception as e:
54
- print(f"Error in image preprocessing: {e}")
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
- # Preprocess the image
65
- image_check = self.preprocess_image(image)
66
 
67
- if image_check is None:
68
  return "Image preprocessing failed.", None, None, None
69
 
 
 
 
 
70
  try:
71
  # Predict disease using the loaded model
72
- indx = my_model.predict(image_check).argmax()
73
 
74
- # Get the disease name, status, and recommended treatment
75
- name = name_disease.get(indx, "Unknown disease")
76
- status = result.get(indx, "Unknown condition")
77
- recom = recommend.get(indx, "No recommendation available")
78
 
79
- return name, status, recom
80
  except Exception as e:
81
- print(f"Error during disease prediction: {e}")
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
- print(f"Error generating detailed response: {e}")
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: Tuple of diagnosis result and detailed response if applicable.
115
  """
116
- if image is not None and image.size > 0: # Ensure the image is valid and has elements
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 an image of poultry fecal matter for disease detection.", None, None, None
 
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
- print(f"Error adding inventory item: {e}")
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
- print(f"Error updating inventory item: {e}")
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
- print(f"Error retrieving inventory item: {e}")
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
- return list(self.collection.find({"user_id": ObjectId(user_id)}))
93
- return list(self.collection.find())
94
  except Exception as e:
95
- print(f"Error retrieving inventory items: {e}")
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
- print(f"Error deleting inventory item: {e}")
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
- tok = os.getenv('HF_Token')
11
- if tok:
12
- login(token=tok, add_to_git_credential=True)
 
 
 
 
13
  else:
14
- print("Warning: Hugging Face token not found in environment variables.")
15
 
16
- tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-1B")
17
- model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")
 
 
 
 
 
 
18
 
19
- # Ensure the tokenizer has a padding token; if not, add a new padding token
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 datetime
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
- try:
33
- query = {"user_id": ObjectId(user_id)} if user_id else {}
34
- inventory_items = list(self.inventory_collection.find(query))
35
-
36
- if not inventory_items:
37
- return pd.DataFrame([])
38
 
39
- # Convert MongoDB documents to a pandas DataFrame
40
- df = pd.DataFrame(inventory_items)
41
- df = df.drop(columns=['_id', 'user_id']) # Drop internal fields
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
- try:
55
- query = {"user_id": ObjectId(user_id)} if user_id else {}
56
- health_records = list(self.health_collection.find(query))
57
 
58
- if not health_records:
59
- return pd.DataFrame([])
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
- try:
79
- query = {}
80
- if user_id:
81
- query['user_id'] = ObjectId(user_id)
82
- if manager_id:
83
- query['manager_id'] = ObjectId(manager_id)
84
- if interaction_type:
85
- query['interaction_type'] = interaction_type
86
-
87
- usage_records = list(self.usage_collection.find(query))
88
 
89
- if not usage_records:
90
- return pd.DataFrame([])
91
 
92
- # Convert MongoDB documents to a pandas DataFrame
93
- df = pd.DataFrame(usage_records)
94
- df = df.drop(columns=['_id', 'user_id', 'manager_id']) # Drop internal fields
95
- return df
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
- print(f"Error generating combined report: {e}")
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
- print(f"Error exporting report to CSV: {e}")
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 if metadata else {},
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
- print(f"Error logging usage: {e}")
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
- return list(self.collection.find({"user_id": ObjectId(user_id)}))
 
 
53
  except Exception as e:
54
- print(f"Error retrieving usage logs for user: {e}")
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
- return list(self.collection.find({"manager_id": ObjectId(manager_id)}))
 
 
66
  except Exception as e:
67
- print(f"Error retrieving usage logs for manager: {e}")
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
- return list(self.collection.find({"interaction_type": interaction_type}))
 
 
79
  except Exception as e:
80
- print(f"Error retrieving usage logs by interaction type: {e}")
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
- return list(self.collection.find(query))
 
 
 
102
  except Exception as e:
103
- print(f"Error retrieving usage logs: {e}")
 
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
- return result.deleted_count > 0
 
 
 
 
 
116
  except Exception as e:
117
- print(f"Error deleting usage log: {e}")
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