AIdeaText commited on
Commit
08564de
verified
1 Parent(s): f41246a

Update modules/database/sql_db.py

Browse files
Files changed (1) hide show
  1. modules/database/sql_db.py +154 -85
modules/database/sql_db.py CHANGED
@@ -8,36 +8,30 @@ import uuid
8
 
9
  logger = logging.getLogger(__name__)
10
 
11
- ###########################################
12
-
13
  def get_user(username, role=None):
14
  container = get_container("users")
15
  try:
 
16
  if role:
17
  query += f" AND c.role = '{role}'"
18
  items = list(container.query_items(
19
- query=query # Removido enable_cross_partition_query
20
-
21
  ))
22
  return items[0] if items else None
23
  except Exception as e:
24
  logger.error(f"Error al obtener usuario {username}: {str(e)}")
25
  return None
26
 
27
- ###########################################
28
-
29
-
30
  def get_admin_user(username):
31
  return get_user(username, role='Administrador')
32
 
 
 
 
33
  def get_teacher_user(username):
34
  return get_user(username, role='Profesor')
35
 
36
-
37
-
38
-
39
-
40
-
41
  def create_user(username, password, role, additional_info=None):
42
  """Crea un nuevo usuario"""
43
  container = get_container("users")
@@ -46,19 +40,12 @@ def create_user(username, password, role, additional_info=None):
46
  return False
47
 
48
  try:
49
-
50
-
51
-
52
-
53
  user_data = {
54
  'id': username,
55
  'password': password,
56
-
57
  'role': role,
58
  'timestamp': datetime.now(timezone.utc).isoformat(),
59
  'additional_info': additional_info or {}
60
-
61
-
62
  }
63
 
64
  container.create_item(
@@ -68,27 +55,50 @@ def create_user(username, password, role, additional_info=None):
68
  logger.info(f"Usuario {role} creado: {username}")
69
  return True
70
 
 
71
  logger.error(f"Error al crear usuario {role}: {str(e)}")
72
  return False
73
 
74
-
75
  def create_student_user(username, password, additional_info=None):
76
  return create_user(username, password, 'Estudiante', additional_info)
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  "username": username,
79
  "loginTime": datetime.now(timezone.utc).isoformat(),
80
  "additional_info": {},
81
-
82
  "partitionKey": username
83
  }
84
 
85
-
86
  result = container.create_item(
87
- body=session_doc # Solo el body
88
-
89
  )
90
  logger.info(f"Sesi贸n {session_id} registrada para {username}")
91
  return session_id
 
92
  logger.error(f"Error registrando login: {str(e)}")
93
  return None
94
 
@@ -96,134 +106,193 @@ def create_student_user(username, password, additional_info=None):
96
  ###########################################################
97
 
98
  def record_logout(username, session_id):
 
 
 
 
99
  logger.error("No se pudo obtener el contenedor users_sessions")
100
  return False
101
 
102
-
103
  query = "SELECT * FROM c WHERE c.id = @id AND c.username = @username"
104
  params = [
105
  {"name": "@id", "value": session_id},
 
 
106
 
107
  items = list(container.query_items(
108
  query=query,
109
- parameters=params # Removido enable_cross_partition_query
110
-
111
  ))
112
 
113
  if not items:
 
 
 
 
 
 
 
114
 
115
  session.update({
116
  "logoutTime": logout_time.isoformat(),
117
- "sessionDuration": duration,
118
- "partitionKey": username # Asegurar que partitionKey est茅 presente
119
  })
120
 
121
-
122
  container.upsert_item(
123
- body=session # Solo el body
124
  )
125
  logger.info(f"Sesi贸n {session_id} cerrada para {username}, duraci贸n: {duration}s")
126
  return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  sessions = list(container.query_items(
129
  query=query,
130
- parameters=[{"name": "@limit", "value": limit}] # Removido enable_cross_partition_query
131
-
132
  ))
133
 
134
-
135
  clean_sessions = []
136
  for session in sessions:
137
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  result = list(container.query_items(
140
  query=query,
141
- parameters=[{"name": "@username", "value": username}] # Removido enable_cross_partition_query
142
-
143
  ))
144
 
145
  return result[0] if result and result[0] is not None else 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  return False
147
 
148
 
149
- #########################################################
150
  def delete_student_user(username):
151
  user_container, _, _ = get_sql_containers()
152
  try:
 
 
 
 
 
 
 
 
 
153
  logger.error(f"Error al eliminar estudiante {username}: {str(e)}")
154
  return False
155
 
156
-
157
-
158
- #########################################################
159
-
160
  def store_application_request(name, lastname, email, institution, current_role, desired_role, reason):
161
- """Almacena una solicitud de aplicaci贸n"""
162
  try:
163
- # Obtener el contenedor usando get_container() que s铆 funciona
164
- container = get_container("application_requests")
165
- if not container:
166
- logger.error("No se pudo obtener el contenedor de solicitudes")
167
- return False
168
-
169
- # Crear documento con la solicitud
170
- # N贸tese que incluimos email como partition key en el cuerpo del documento
171
  application_request = {
172
  "id": str(uuid.uuid4()),
173
  "name": name,
 
 
 
174
  "current_role": current_role,
175
  "desired_role": desired_role,
176
  "reason": reason,
177
- "requestDate": datetime.utcnow().isoformat(),
178
- # El campo para partition key debe estar en el documento
179
- "partitionKey": email
180
  }
181
-
182
- # Crear el item en el contenedor - sin el par谩metro enable_cross_partition_query
183
- container.create_item(
184
- body=application_request # Solo pasamos el body
185
- )
186
- logger.info(f"Solicitud de aplicaci贸n almacenada para: {email}")
187
  return True
188
-
189
  except Exception as e:
190
  logger.error(f"Error al almacenar la solicitud de aplicaci贸n: {str(e)}")
191
- logger.error(f"Detalles del error: {str(e)}")
192
  return False
193
 
194
- ############################################################
195
  def store_student_feedback(username, name, email, feedback):
196
- """Almacena el feedback de un estudiante"""
197
  try:
198
- # Obtener el contenedor - verificar disponibilidad
199
- logger.info(f"Intentando obtener contenedor user_feedback para usuario: {username}")
200
- container = get_container("user_feedback")
201
- if not container:
202
- logger.error("No se pudo obtener el contenedor user_feedback")
203
- return False
204
-
205
- # Crear documento de feedback - asegurar que el username est茅 como partition key
206
  feedback_item = {
207
  "id": str(uuid.uuid4()),
208
- "username": username, # Campo regular
209
  "name": name,
210
  "email": email,
211
  "feedback": feedback,
212
  "role": "Estudiante",
213
- "timestamp": datetime.now(timezone.utc).isoformat(),
214
- "partitionKey": username # Campo de partici贸n
215
  }
216
-
217
- # Crear el item - sin el par谩metro enable_cross_partition_query
218
- logger.info(f"Intentando almacenar feedback para usuario: {username}")
219
- result = container.create_item(
220
- body=feedback_item # Solo el body, no par谩metros adicionales
221
- )
222
-
223
- logger.info(f"Feedback almacenado exitosamente para el usuario: {username}")
224
  return True
225
-
226
  except Exception as e:
227
- logger.error(f"Error al almacenar el feedback del estudiante {username}")
228
- logger.error(f"Detalles del error: {str(e)}")
229
  return False
 
8
 
9
  logger = logging.getLogger(__name__)
10
 
 
 
11
  def get_user(username, role=None):
12
  container = get_container("users")
13
  try:
14
+ query = f"SELECT * FROM c WHERE c.id = '{username}'"
15
  if role:
16
  query += f" AND c.role = '{role}'"
17
  items = list(container.query_items(
18
+ query=query,
19
+ enable_cross_partition_query=True
20
  ))
21
  return items[0] if items else None
22
  except Exception as e:
23
  logger.error(f"Error al obtener usuario {username}: {str(e)}")
24
  return None
25
 
 
 
 
26
  def get_admin_user(username):
27
  return get_user(username, role='Administrador')
28
 
29
+ def get_student_user(username):
30
+ return get_user(username, role='Estudiante')
31
+
32
  def get_teacher_user(username):
33
  return get_user(username, role='Profesor')
34
 
 
 
 
 
 
35
  def create_user(username, password, role, additional_info=None):
36
  """Crea un nuevo usuario"""
37
  container = get_container("users")
 
40
  return False
41
 
42
  try:
 
 
 
 
43
  user_data = {
44
  'id': username,
45
  'password': password,
 
46
  'role': role,
47
  'timestamp': datetime.now(timezone.utc).isoformat(),
48
  'additional_info': additional_info or {}
 
 
49
  }
50
 
51
  container.create_item(
 
55
  logger.info(f"Usuario {role} creado: {username}")
56
  return True
57
 
58
+ except Exception as e:
59
  logger.error(f"Error al crear usuario {role}: {str(e)}")
60
  return False
61
 
 
62
  def create_student_user(username, password, additional_info=None):
63
  return create_user(username, password, 'Estudiante', additional_info)
64
 
65
+ def create_teacher_user(username, password, additional_info=None):
66
+ return create_user(username, password, 'Profesor', additional_info)
67
+
68
+ def create_admin_user(username, password, additional_info=None):
69
+ return create_user(username, password, 'Administrador', additional_info)
70
+
71
+ ############-- Funciones de control del tiempo de sesi贸n ##################
72
+
73
+ ###########################################################
74
+
75
+ def record_login(username):
76
+ """Registra el inicio de sesi贸n de un usuario"""
77
+ try:
78
+ container = get_container("users_sessions")
79
+ if not container:
80
+ logger.error("No se pudo obtener el contenedor users_sessions")
81
+ return None
82
+
83
+ session_id = str(uuid.uuid4())
84
+ session_doc = {
85
+ "id": session_id,
86
+ "type": "session",
87
  "username": username,
88
  "loginTime": datetime.now(timezone.utc).isoformat(),
89
  "additional_info": {},
90
+ # El campo para partition key debe estar en el documento
91
  "partitionKey": username
92
  }
93
 
94
+ # Crear el documento usando options
95
  result = container.create_item(
96
+ body=session_doc,
97
+ enable_cross_partition_query=True
98
  )
99
  logger.info(f"Sesi贸n {session_id} registrada para {username}")
100
  return session_id
101
+ except Exception as e:
102
  logger.error(f"Error registrando login: {str(e)}")
103
  return None
104
 
 
106
  ###########################################################
107
 
108
  def record_logout(username, session_id):
109
+ """Registra el cierre de sesi贸n y calcula la duraci贸n"""
110
+ try:
111
+ container = get_container("users_sessions")
112
+ if not container:
113
  logger.error("No se pudo obtener el contenedor users_sessions")
114
  return False
115
 
116
+ # Obtener la sesi贸n actual
117
  query = "SELECT * FROM c WHERE c.id = @id AND c.username = @username"
118
  params = [
119
  {"name": "@id", "value": session_id},
120
+ {"name": "@username", "value": username}
121
+ ]
122
 
123
  items = list(container.query_items(
124
  query=query,
125
+ parameters=params,
126
+ enable_cross_partition_query=True
127
  ))
128
 
129
  if not items:
130
+ logger.warning(f"Sesi贸n no encontrada: {session_id}")
131
+ return False
132
+
133
+ session = items[0]
134
+ login_time = datetime.fromisoformat(session['loginTime'].rstrip('Z'))
135
+ logout_time = datetime.now(timezone.utc)
136
+ duration = int((logout_time - login_time).total_seconds())
137
 
138
  session.update({
139
  "logoutTime": logout_time.isoformat(),
140
+ "sessionDuration": duration
 
141
  })
142
 
143
+ # Actualizar el documento
144
  container.upsert_item(
145
+ body=session
146
  )
147
  logger.info(f"Sesi贸n {session_id} cerrada para {username}, duraci贸n: {duration}s")
148
  return True
149
+ except Exception as e:
150
+ logger.error(f"Error registrando logout: {str(e)}")
151
+ return False
152
+
153
+
154
+ ###########################################################
155
+
156
+ def get_recent_sessions(limit=10):
157
+ """Obtiene las sesiones m谩s recientes"""
158
+ try:
159
+ container = get_container("users_sessions")
160
+ if not container:
161
+ logger.error("No se pudo obtener el contenedor users_sessions")
162
+ return []
163
+
164
+ query = """
165
+ SELECT c.username, c.loginTime, c.logoutTime, c.sessionDuration
166
+ FROM c
167
+ WHERE c.type = 'session'
168
+ ORDER BY c.loginTime DESC
169
+ OFFSET 0 LIMIT @limit
170
+ """
171
 
172
  sessions = list(container.query_items(
173
  query=query,
174
+ parameters=[{"name": "@limit", "value": limit}],
175
+ enable_cross_partition_query=True
176
  ))
177
 
178
+ # Validar y limpiar los datos
179
  clean_sessions = []
180
  for session in sessions:
181
  try:
182
+ clean_sessions.append({
183
+ "username": session["username"],
184
+ "loginTime": session["loginTime"],
185
+ "logoutTime": session.get("logoutTime", "Activo"),
186
+ "sessionDuration": session.get("sessionDuration", 0)
187
+ })
188
+ except KeyError as e:
189
+ logger.warning(f"Sesi贸n con datos incompletos: {e}")
190
+ continue
191
+
192
+ return clean_sessions
193
+ except Exception as e:
194
+ logger.error(f"Error obteniendo sesiones recientes: {str(e)}")
195
+ return []
196
+
197
+
198
+
199
+ ###########################################################
200
+
201
+ def get_user_total_time(username):
202
+ """Obtiene el tiempo total que un usuario ha pasado en la plataforma"""
203
+ try:
204
+ container = get_container("users_sessions")
205
+ if not container:
206
+ return None
207
+
208
+ query = """
209
+ SELECT VALUE SUM(c.sessionDuration)
210
+ FROM c
211
+ WHERE c.type = 'session'
212
+ AND c.username = @username
213
+ AND IS_DEFINED(c.sessionDuration)
214
+ """
215
 
216
  result = list(container.query_items(
217
  query=query,
218
+ parameters=[{"name": "@username", "value": username}],
219
+ enable_cross_partition_query=True
220
  ))
221
 
222
  return result[0] if result and result[0] is not None else 0
223
+ except Exception as e:
224
+ logger.error(f"Error obteniendo tiempo total: {str(e)}")
225
+ return 0
226
+
227
+ ###########################################################
228
+ def update_student_user(username, new_info):
229
+ user_container, _, _ = get_sql_containers()
230
+ try:
231
+ user = get_student_user(username)
232
+ if user:
233
+ user['additional_info'].update(new_info)
234
+ user_container.upsert_item(body=user)
235
+ logger.info(f"Informaci贸n del estudiante actualizada: {username}")
236
+ return True
237
+ else:
238
+ logger.warning(f"Intento de actualizar estudiante no existente: {username}")
239
+ return False
240
+ except Exception as e:
241
+ logger.error(f"Error al actualizar informaci贸n del estudiante {username}: {str(e)}")
242
  return False
243
 
244
 
 
245
  def delete_student_user(username):
246
  user_container, _, _ = get_sql_containers()
247
  try:
248
+ user = get_student_user(username)
249
+ if user:
250
+ user_container.delete_item(item=user['id'], partition_key=username)
251
+ logger.info(f"Estudiante eliminado: {username}")
252
+ return True
253
+ else:
254
+ logger.warning(f"Intento de eliminar estudiante no existente: {username}")
255
+ return False
256
+ except Exception as e:
257
  logger.error(f"Error al eliminar estudiante {username}: {str(e)}")
258
  return False
259
 
 
 
 
 
260
  def store_application_request(name, lastname, email, institution, current_role, desired_role, reason):
261
+ _, application_requests_container, _ = get_sql_containers()
262
  try:
 
 
 
 
 
 
 
 
263
  application_request = {
264
  "id": str(uuid.uuid4()),
265
  "name": name,
266
+ "lastname": lastname,
267
+ "email": email,
268
+ "institution": institution,
269
  "current_role": current_role,
270
  "desired_role": desired_role,
271
  "reason": reason,
272
+ "requestDate": datetime.utcnow().isoformat()
 
 
273
  }
274
+ application_requests_container.create_item(body=application_request)
275
+ logger.info(f"Solicitud de aplicaci贸n almacenada para el email: {email}")
 
 
 
 
276
  return True
 
277
  except Exception as e:
278
  logger.error(f"Error al almacenar la solicitud de aplicaci贸n: {str(e)}")
 
279
  return False
280
 
 
281
  def store_student_feedback(username, name, email, feedback):
282
+ _, _, user_feedback_container = get_sql_containers()
283
  try:
 
 
 
 
 
 
 
 
284
  feedback_item = {
285
  "id": str(uuid.uuid4()),
286
+ "username": username,
287
  "name": name,
288
  "email": email,
289
  "feedback": feedback,
290
  "role": "Estudiante",
291
+ 'timestamp': datetime.now(timezone.utc).isoformat(),
 
292
  }
293
+ result = user_feedback_container.create_item(body=feedback_item)
294
+ logger.info(f"Feedback de estudiante almacenado con ID: {result['id']} para el usuario: {username}")
 
 
 
 
 
 
295
  return True
 
296
  except Exception as e:
297
+ logger.error(f"Error al almacenar el feedback del estudiante {username}: {str(e)}")
 
298
  return False