latapp 9 meses atrás
pai
commit
53f9152b4e
13 arquivos alterados com 746 adições e 1291 exclusões
  1. 12 61
      app.py
  2. 8 101
      auth/security.py
  3. 1 0
      config/messages.py
  4. 8 72
      main.py
  5. 4 1
      models/user.py
  6. 604 0
      public/pin_forgot.html
  7. 2 57
      routes/chat.py
  8. 16 354
      routes/orders.py
  9. 44 187
      routes/users.py
  10. 11 121
      services/email_service.py
  11. 0 213
      services/logging_service.py
  12. 13 124
      services/print_service.py
  13. 23 0
      services/recovery_service.py

+ 12 - 61
app.py

@@ -1,10 +1,11 @@
+from math import log
 from fastapi import FastAPI
 from fastapi import FastAPI
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.middleware.cors import CORSMiddleware
 from starlette.middleware.sessions import SessionMiddleware
 from starlette.middleware.sessions import SessionMiddleware
 from config.settings import DEVELOPMENT, SECRET_KEY
 from config.settings import DEVELOPMENT, SECRET_KEY
+from models import user
 from routes import sales
 from routes import sales
 from services.email_service import initialize_email_sender
 from services.email_service import initialize_email_sender
-from services.logging_service import structured_logger, LogLevel
 from middleware.no_cache import NoCacheMiddleware
 from middleware.no_cache import NoCacheMiddleware
 from logging import getLogger
 from logging import getLogger
 
 
@@ -31,24 +32,12 @@ def create_app() -> FastAPI:
                 redoc_url=None
                 redoc_url=None
             )
             )
 
 
-        structured_logger.log_system_event(
-            "FastAPI application created",
-            LogLevel.INFO,
-            {
-                "development_mode": DEVELOPMENT,
-                "docs_enabled": DEVELOPMENT,
-                "title": "Web Pedidos Klein - FastAPI Backend"
-            }
-        )
 
 
         # Initialize email sender
         # Initialize email sender
         logger.info("Initializing email sender")
         logger.info("Initializing email sender")
         initialize_email_sender()
         initialize_email_sender()
-        
-        structured_logger.log_email_event(
-            "Email sender initialized",
-            LogLevel.INFO
-        )
+
+        logger.info("Email sender initialized")
 
 
         # Add CORS middleware
         # Add CORS middleware
         logger.info("Adding CORS middleware")
         logger.info("Adding CORS middleware")
@@ -60,14 +49,7 @@ def create_app() -> FastAPI:
             allow_headers=["*"],
             allow_headers=["*"],
         )
         )
         
         
-        structured_logger.log_system_event(
-            "CORS middleware configured",
-            LogLevel.INFO,
-            {
-                "allowed_origins": ["https://admin.kleinexpress.store"],
-                "allow_credentials": True
-            }
-        )
+        
         
         
         # Add SessionMiddleware
         # Add SessionMiddleware
         logger.info("Adding session middleware")
         logger.info("Adding session middleware")
@@ -77,21 +59,12 @@ def create_app() -> FastAPI:
             max_age=60 * 60  # max_age in seconds for Starlette
             max_age=60 * 60  # max_age in seconds for Starlette
         )
         )
         
         
-        structured_logger.log_system_event(
-            "Session middleware configured",
-            LogLevel.INFO,
-            {"max_age_seconds": 3600}
-        )
         
         
         # Add NoCacheMiddleware
         # Add NoCacheMiddleware
         logger.info("Adding no-cache middleware")
         logger.info("Adding no-cache middleware")
         app.add_middleware(NoCacheMiddleware)
         app.add_middleware(NoCacheMiddleware)
         
         
-        structured_logger.log_system_event(
-            "No-cache middleware configured",
-            LogLevel.INFO,
-            {"description": "Middleware for preventing cache on public files"}
-        )
+        
         
         
         logger.info("FastAPI application created successfully")
         logger.info("FastAPI application created successfully")
         return app
         return app
@@ -99,14 +72,7 @@ def create_app() -> FastAPI:
     except Exception as e:
     except Exception as e:
         error_msg = f"Error creating FastAPI application: {e}"
         error_msg = f"Error creating FastAPI application: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_system_event(
-            "FastAPI application creation failed",
-            LogLevel.ERROR,
-            {
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+        
         raise
         raise
 
 
 
 
@@ -162,7 +128,9 @@ def setup_routes(app: FastAPI):
         # Verification routes
         # Verification routes
         logger.info("Setting up verification routes")
         logger.info("Setting up verification routes")
         app.include_router(users.verify_router, prefix="/verify", tags=["Verification"])
         app.include_router(users.verify_router, prefix="/verify", tags=["Verification"])
-        
+
+        app.include_router(users.recovery_pin_router, prefix="/recovery", tags=["Recovery PIN"])
+
         # Static routes
         # Static routes
         logger.info("Setting up static routes")
         logger.info("Setting up static routes")
         from fastapi.responses import HTMLResponse
         from fastapi.responses import HTMLResponse
@@ -178,28 +146,11 @@ def setup_routes(app: FastAPI):
         static.mount_main_static_files(app)
         static.mount_main_static_files(app)
         static.mount_register_static_files(app)
         static.mount_register_static_files(app)
 
 
-        structured_logger.log_system_event(
-            "All application routes configured successfully",
-            LogLevel.INFO,
-            {
-                "route_groups": [
-                    "chat", "users", "products", "orders", 
-                    "sales", "verification", "static"
-                ]
-            }
-        )
         
         
         logger.info("Application routes setup completed successfully")
         logger.info("Application routes setup completed successfully")
         
         
     except Exception as e:
     except Exception as e:
-        error_msg = f"Error setting up application routes: {e}"
+        error_msg = f"Error setting up application routes: - {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_system_event(
-            "Route setup failed",
-            LogLevel.ERROR,
-            {
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+    
         raise
         raise

+ 8 - 101
auth/security.py

@@ -11,7 +11,6 @@ from passlib.context import CryptContext
 
 
 from models.user import User
 from models.user import User
 from services.data_service import UserDataService
 from services.data_service import UserDataService
-from services.logging_service import structured_logger, LogLevel
 
 
 logger = getLogger(__name__)
 logger = getLogger(__name__)
 
 
@@ -38,16 +37,6 @@ def generate_token(email: str):
         expires_delta = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
         expires_delta = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
         token = create_access_token(data=data, expires_delta=expires_delta)
         token = create_access_token(data=data, expires_delta=expires_delta)
         
         
-        structured_logger.log_security_event(
-            f"JWT token generated for user {email}",
-            LogLevel.INFO,
-            {
-                "email": email,
-                "token_length": len(token),
-                "expires_in_days": ACCESS_TOKEN_EXPIRE_DAYS
-            },
-            user_email=email
-        )
         
         
         logger.debug(f"Generated token for email {email}: {token[:20]}...")
         logger.debug(f"Generated token for email {email}: {token[:20]}...")
         return token
         return token
@@ -55,16 +44,7 @@ def generate_token(email: str):
     except Exception as e:
     except Exception as e:
         error_msg = f"Failed to generate token for {email}: {e}"
         error_msg = f"Failed to generate token for {email}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_security_event(
-            f"Token generation failed for user {email}",
-            LogLevel.ERROR,
-            {
-                "email": email,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_email=email
-        )
+        
         raise
         raise
 
 
 def create_access_token(data: dict, expires_delta: timedelta) -> str:
 def create_access_token(data: dict, expires_delta: timedelta) -> str:
@@ -88,45 +68,17 @@ def authenticate_user(email: str, password: str) -> bool:
         user = user_data_service.login(email, password)
         user = user_data_service.login(email, password)
         
         
         if user:
         if user:
-            structured_logger.log_security_event(
-                f"Successful authentication for user {email}",
-                LogLevel.INFO,
-                {
-                    "email": email,
-                    "user_id": user.id,
-                    "user_name": user.name
-                },
-                user_id=user.id,
-                user_email=email
-            )
             logger.info(f"Authentication successful for user: {email}")
             logger.info(f"Authentication successful for user: {email}")
             return True
             return True
         else:
         else:
-            structured_logger.log_security_event(
-                f"Failed authentication attempt for user {email}",
-                LogLevel.WARNING,
-                {
-                    "email": email,
-                    "reason": "Invalid credentials"
-                },
-                user_email=email
-            )
+            
             logger.warning(f"Authentication failed for user: {email}")
             logger.warning(f"Authentication failed for user: {email}")
             return False
             return False
             
             
     except Exception as e:
     except Exception as e:
         error_msg = f"Authentication error for {email}: {e}"
         error_msg = f"Authentication error for {email}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_security_event(
-            f"Authentication error for user {email}",
-            LogLevel.ERROR,
-            {
-                "email": email,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_email=email
-        )
+        
         return False
         return False
 
 
 async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)) -> User:
 async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)) -> User:
@@ -145,36 +97,18 @@ async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(s
         
         
         if email is None:
         if email is None:
             logger.error("Token does not contain email")
             logger.error("Token does not contain email")
-            structured_logger.log_security_event(
-                "Token validation failed: missing email",
-                LogLevel.WARNING,
-                {"reason": "Token missing email subject"}
-            )
+            
             raise credentials_exception
             raise credentials_exception
             
             
         token_data = TokenData(email=email)
         token_data = TokenData(email=email)
         
         
     except JWTError as e:
     except JWTError as e:
         logger.error(f"JWTError: Invalid token - {e}")
         logger.error(f"JWTError: Invalid token - {e}")
-        structured_logger.log_security_event(
-            "Token validation failed: JWT error",
-            LogLevel.WARNING,
-            {
-                "error": str(e),
-                "error_type": "JWTError"
-            }
-        )
+        
         raise credentials_exception
         raise credentials_exception
     except Exception as e:
     except Exception as e:
         logger.error(f"Unexpected error during token validation: {e}")
         logger.error(f"Unexpected error during token validation: {e}")
-        structured_logger.log_security_event(
-            "Token validation failed: unexpected error",
-            LogLevel.ERROR,
-            {
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+        
         raise credentials_exception
         raise credentials_exception
     
     
     try:
     try:
@@ -182,42 +116,15 @@ async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(s
         
         
         if user is None:
         if user is None:
             logger.error(f"User not found: {token_data.email}")
             logger.error(f"User not found: {token_data.email}")
-            structured_logger.log_security_event(
-                f"Token validation failed: user not found",
-                LogLevel.WARNING,
-                {
-                    "email": token_data.email,
-                    "reason": "User not found in database"
-                },
-                user_email=token_data.email
-            )
+            
             raise credentials_exception
             raise credentials_exception
             
             
         logger.debug(f"User authenticated successfully: {user.email}")
         logger.debug(f"User authenticated successfully: {user.email}")
-        structured_logger.log_security_event(
-            f"Token validation successful for user {user.email}",
-            LogLevel.DEBUG,
-            {
-                "user_id": user.id,
-                "email": user.email,
-                "permissions": user.permissions
-            },
-            user_id=user.id,
-            user_email=user.email
-        )
         
         
         return user
         return user
         
         
     except Exception as e:
     except Exception as e:
         logger.error(f"Database error during user lookup: {e}")
         logger.error(f"Database error during user lookup: {e}")
-        structured_logger.log_security_event(
-            "Token validation failed: database error",
-            LogLevel.ERROR,
-            {
-                "email": token_data.email if 'token_data' in locals() else "unknown",
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+    
         raise credentials_exception
         raise credentials_exception
 
 

+ 1 - 0
config/messages.py

@@ -28,6 +28,7 @@ class SuccessResponse:
     PRODUCT_CREATE_SUCCESS = "Producto creado exitosamente."
     PRODUCT_CREATE_SUCCESS = "Producto creado exitosamente."
     PRODUCT_DELETE_SUCCESS = "Producto eliminado exitosamente."
     PRODUCT_DELETE_SUCCESS = "Producto eliminado exitosamente."
     REWARD_SUCCESS = "Recompensa aplicada exitosamente."
     REWARD_SUCCESS = "Recompensa aplicada exitosamente."
+    RECOVERY_EMAIL_SENT = "Se ha enviado un correo electrónico de recuperación."
 class UserResponse:
 class UserResponse:
     """Class to handle user-related messages in the response."""
     """Class to handle user-related messages in the response."""
 
 

+ 8 - 72
main.py

@@ -1,10 +1,8 @@
+from config.settings import PORT, OPENAI_API_KEY, BG_DATA_PATH,DEVELOPMENT, validate_config
 import os
 import os
 import uvicorn
 import uvicorn
 from app import create_app, setup_routes
 from app import create_app, setup_routes
-from config.settings import PORT, OPENAI_API_KEY, BG_DATA_PATH,DEVELOPMENT, validate_config
 from logging import getLogger
 from logging import getLogger
-from threading import Thread
-from services.logging_service import structured_logger, LogLevel
 
 
 from services.data_service import initialize_db
 from services.data_service import initialize_db
 
 
@@ -14,35 +12,19 @@ def main():
     """Main application entry point"""
     """Main application entry point"""
     logger.info("Starting Pedidos Express application")
     logger.info("Starting Pedidos Express application")
     
     
-    structured_logger.log_system_event(
-        "Application startup initiated",
-        LogLevel.INFO,
-        {
-            "port": PORT,
-            "development_mode": DEVELOPMENT,
-            "bg_data_path": BG_DATA_PATH
-        }
-    )
     
     
     try:
     try:
         # Validate configuration
         # Validate configuration
         if not validate_config():
         if not validate_config():
             logger.critical("FATAL: Configuration validation failed.")
             logger.critical("FATAL: Configuration validation failed.")
-            structured_logger.log_system_event(
-                "Application startup failed: configuration validation error",
-                LogLevel.CRITICAL,
-                {"validation_step": "configuration"}
-            )
+            
             if not OPENAI_API_KEY:
             if not OPENAI_API_KEY:
                 logger.error("Please create a .env file with OPENAI_API_KEY='your_key_here'")
                 logger.error("Please create a .env file with OPENAI_API_KEY='your_key_here'")
                 with open(".env", "w") as f:
                 with open(".env", "w") as f:
                     f.write("OPENAI_API_KEY='your_key_here'")
                     f.write("OPENAI_API_KEY='your_key_here'")
             return None
             return None
         
         
-        structured_logger.log_system_event(
-            "Configuration validation successful",
-            LogLevel.INFO
-        )
+        
         
         
         # Create and configure app
         # Create and configure app
         logger.info("Creating FastAPI application")
         logger.info("Creating FastAPI application")
@@ -51,88 +33,42 @@ def main():
         logger.info("Setting up application routes")
         logger.info("Setting up application routes")
         setup_routes(app)
         setup_routes(app)
         
         
-        structured_logger.log_system_event(
-            "FastAPI application created and routes configured",
-            LogLevel.INFO
-        )
         
         
         # Initialize database
         # Initialize database
         logger.info("Initializing database")
         logger.info("Initializing database")
         initialize_db()
         initialize_db()
         
         
-        structured_logger.log_system_event(
-            "Database initialization completed",
-            LogLevel.INFO
-        )
         
         
         # Display startup information
         # Display startup information
         logger.info(f"Server starting on http://localhost:{PORT}")
         logger.info(f"Server starting on http://localhost:{PORT}")
         
         
         if not os.path.exists(BG_DATA_PATH):
         if not os.path.exists(BG_DATA_PATH):
             logger.warning(f"WARNING: {BG_DATA_PATH} not found. AI assistant will not have specific menu data.")
             logger.warning(f"WARNING: {BG_DATA_PATH} not found. AI assistant will not have specific menu data.")
-            structured_logger.log_system_event(
-                "AI assistant data file not found",
-                LogLevel.WARNING,
-                {
-                    "bg_data_path": BG_DATA_PATH,
-                    "impact": "AI assistant will have limited functionality"
-                }
-            )
+        
         else:
         else:
             logger.info(f"AI assistant data loaded from: {os.path.abspath(BG_DATA_PATH)}")
             logger.info(f"AI assistant data loaded from: {os.path.abspath(BG_DATA_PATH)}")
-            structured_logger.log_system_event(
-                "AI assistant data loaded successfully",
-                LogLevel.INFO,
-                {"bg_data_path": os.path.abspath(BG_DATA_PATH)}
-            )
+        
+
 
 
-        structured_logger.log_system_event(
-            "Application startup completed successfully",
-            LogLevel.INFO,
-            {
-                "server_url": f"http://localhost:{PORT}",
-                "development_mode": DEVELOPMENT
-            }
-        )
         
         
         logger.info("Pedidos Express application ready to serve requests")
         logger.info("Pedidos Express application ready to serve requests")
         return app
         return app
         
         
     except Exception as e:
     except Exception as e:
-        error_msg = f"Critical error during application startup: {e}"
+        error_msg = f"Critical error during application startup: - {e}"
         logger.critical(error_msg)
         logger.critical(error_msg)
         
         
-        structured_logger.log_system_event(
-            "Application startup failed with critical error",
-            LogLevel.CRITICAL,
-            {
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
         return None
         return None
 
 
 app = main()
 app = main()
 
 
 if not app:
 if not app:
     logger.critical("FATAL: Failed to create FastAPI app.")
     logger.critical("FATAL: Failed to create FastAPI app.")
-    structured_logger.log_system_event(
-        "Application failed to start - FastAPI app creation failed",
-        LogLevel.CRITICAL
-    )
+
     exit(1)
     exit(1)
 
 
 logger.info("Application initialized successfully")
 logger.info("Application initialized successfully")
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
     logger.info(f"Starting server with uvicorn on port {PORT}")
     logger.info(f"Starting server with uvicorn on port {PORT}")
-    structured_logger.log_system_event(
-        "Starting uvicorn server",
-        LogLevel.INFO,
-        {
-            "host": "0.0.0.0",
-            "port": PORT,
-            "log_level": "info"
-        }
-    )
     uvicorn.run(app, host="0.0.0.0", port=PORT, log_level="info", access_log=False)
     uvicorn.run(app, host="0.0.0.0", port=PORT, log_level="info", access_log=False)

+ 4 - 1
models/user.py

@@ -30,4 +30,7 @@ class User(BaseModel):
 
 
 class LoginRequest(BaseModel):
 class LoginRequest(BaseModel):
     email: str
     email: str
-    pin: str = Field(min_length=4, max_length=4, description="4-digit PIN for user authentication")
+    pin: str = Field(min_length=4, max_length=4, description="4-digit PIN for user authentication")
+
+class PinRecoveryRequest(BaseModel):
+    email: str

+ 604 - 0
public/pin_forgot.html

@@ -0,0 +1,604 @@
+<!DOCTYPE html>
+<html lang="es">
+<head>
+  <meta charset="UTF-8" />
+  <title>Recuperar PIN - Biergarten Klein</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  
+  <!-- Meta tags para evitar cache -->
+  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
+  <meta http-equiv="Pragma" content="no-cache">
+  <meta http-equiv="Expires" content="0">
+  
+  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+  <link rel="stylesheet" as="style" onload="this.rel='stylesheet'"
+        href="https://fonts.googleapis.com/css2?display=swap&family=Noto+Sans:wght@400;500;700;900&family=Spline+Sans:wght@400;500;700">
+  <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
+   <script>
+        tailwind.config = {
+            theme: {
+                extend: {
+                    colors: {
+                        'custom-dark': '#101419',
+                        'custom-dark-hover': '#37404a',
+                        'gray-50': '#f9fafb',
+                        'gray-100': '#f3f4f6',
+                    }
+                }
+            }
+        }
+    </script>
+</head>
+
+<body class="min-h-screen bg-gray-50 flex items-center justify-center p-4" style='font-family:"Spline Sans","Noto Sans",sans-serif;'>
+  
+  <div class="w-full max-w-md">
+    <!-- Header -->
+    <div class="text-center mb-8">
+      <div class="inline-flex items-center justify-center w-16 h-16 bg-[#101419] rounded-full mb-4">
+        <svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
+        </svg>
+      </div>
+      <h1 class="text-[26px] font-bold text-[#101419] tracking-tight mb-2">
+        ¿Olvidaste tu PIN?
+      </h1>
+      <p class="text-[#58728d] text-sm leading-relaxed">
+        No te preocupes, te ayudamos a recuperar el acceso a tu cuenta
+      </p>
+    </div>
+
+    <!-- Indicador de pasos -->
+    <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
+      <div class="space-y-4">
+        <div class="flex items-start space-x-3" id="step1Indicator">
+          <div class="flex-shrink-0 w-6 h-6 bg-[#101419] text-white rounded-full flex items-center justify-center text-xs font-medium">1</div>
+          <div class="text-sm">
+            <p class="font-medium text-[#101419]">Ingresa tu correo</p>
+            <p class="text-[#58728d] mt-1">Te enviaremos un código de verificación</p>
+          </div>
+        </div>
+        <div class="flex items-start space-x-3" id="step2Indicator">
+          <div class="flex-shrink-0 w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-medium">2</div>
+          <div class="text-sm">
+            <p class="font-medium text-gray-400">Código de verificación</p>
+            <p class="text-gray-400 mt-1">Ingresa el código de 6 dígitos</p>
+          </div>
+        </div>
+        <div class="flex items-start space-x-3" id="step3Indicator">
+          <div class="flex-shrink-0 w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-medium">3</div>
+          <div class="text-sm">
+            <p class="font-medium text-gray-400">Nuevo PIN</p>
+            <p class="text-gray-400 mt-1">Crea tu nuevo PIN de 4 dígitos</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- FASE 1: Ingreso de correo -->
+    <form id="emailForm" class="bg-white rounded-xl shadow-sm border border-gray-200 p-8 space-y-6">
+      <div class="text-center">
+        <h2 class="text-[19px] font-bold text-[#101419] mb-2">Ingresa tu correo electrónico</h2>
+        <p class="text-sm text-[#58728d]">
+          Te enviaremos un código de verificación a tu correo
+        </p>
+      </div>
+
+      <div class="space-y-4">
+        <div>
+          <label for="emailInput" class="block text-sm font-medium text-[#101419] mb-2">
+            Correo electrónico 
+          </label>
+          <input 
+            id="emailInput"
+            name="email"
+            type="email"
+            class="w-full border border-gray-300 px-4 py-3 rounded-lg focus:ring-2 focus:ring-[#101419] focus:border-transparent outline-none transition-all"
+            placeholder="tu@email.com"
+            required
+          />
+        </div>
+      </div>
+
+      <div class="space-y-3">
+        <button 
+          id="emailSubmitBtn"
+          type="submit"
+          class="w-full bg-[#101419] hover:bg-[#37404a] disabled:opacity-50 disabled:cursor-not-allowed text-white py-3 rounded-lg font-medium transition-colors duration-200 focus:ring-2 focus:ring-offset-2 focus:ring-[#101419]"
+        >
+          Enviar código
+        </button>
+        
+        <a 
+          href="/"
+          class="block w-full text-center border border-gray-300 hover:border-[#101419] text-[#101419] py-3 rounded-lg font-medium transition-colors duration-200"
+        >
+          Volver al inicio
+        </a>
+      </div>
+    </form>
+
+    <!-- FASE 2: Verificación de código -->
+    <form id="codeForm" class="bg-white rounded-xl shadow-sm border border-gray-200 p-8 space-y-6 hidden">
+      <div class="text-center">
+        <h2 class="text-[19px] font-bold text-[#101419] mb-2">Código de verificación</h2>
+        <p class="text-sm text-[#58728d]">
+          Ingresa el código de 6 dígitos que enviamos a <span id="emailDisplay" class="font-medium"></span>
+        </p>
+      </div>
+
+      <div class="space-y-4">
+        <div>
+          <label for="codeInput" class="block text-sm font-medium text-[#101419] mb-2">
+            Código de verificación
+          </label>
+          <input 
+            id="codeInput"
+            name="code"
+            type="text"
+            maxlength="6"
+            class="w-full border border-gray-300 px-4 py-3 rounded-lg focus:ring-2 focus:ring-[#101419] focus:border-transparent outline-none transition-all text-center text-2xl tracking-widest"
+            placeholder="000000"
+            required
+          />
+        </div>
+
+        <div class="text-center">
+          <button 
+            type="button"
+            id="resendCodeBtn"
+            class="text-sm text-[#58728d] hover:text-[#101419] transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:text-[#58728d]"
+          >
+            ¿No recibiste el código? <span class="font-medium" id="resendText">Reenviar</span>
+          </button>
+        </div>
+      </div>
+
+      <div class="space-y-3">
+        <button 
+          id="codeSubmitBtn"
+          type="submit"
+          class="w-full bg-[#101419] hover:bg-[#37404a] disabled:opacity-50 disabled:cursor-not-allowed text-white py-3 rounded-lg font-medium transition-colors duration-200 focus:ring-2 focus:ring-offset-2 focus:ring-[#101419]"
+        >
+          Verificar código
+        </button>
+        
+        <button 
+          type="button"
+          id="backToEmailBtn"
+          class="block w-full text-center border border-gray-300 hover:border-[#101419] text-[#101419] py-3 rounded-lg font-medium transition-colors duration-200"
+        >
+          Cambiar correo
+        </button>
+      </div>
+    </form>
+
+    <!-- FASE 3: Crear nuevo PIN -->
+    <form id="pinForm" class="bg-white rounded-xl shadow-sm border border-gray-200 p-8 space-y-6 hidden">
+      <div class="text-center">
+        <h2 class="text-[19px] font-bold text-[#101419] mb-2">Crea tu nuevo PIN</h2>
+        <p class="text-sm text-[#58728d]">
+          Ingresa un PIN de 4 dígitos que sea fácil de recordar para ti
+        </p>
+      </div>
+
+      <div class="space-y-4">
+        <div>
+          <label for="newPinInput" class="block text-sm font-medium text-[#101419] mb-2">
+            Nuevo PIN
+          </label>
+          <input 
+            id="newPinInput"
+            name="newPin"
+            type="password"
+            maxlength="4"
+            class="w-full border border-gray-300 px-4 py-3 rounded-lg focus:ring-2 focus:ring-[#101419] focus:border-transparent outline-none transition-all text-center text-2xl tracking-widest"
+            placeholder="••••"
+            required
+          />
+        </div>
+
+        <div>
+          <label for="confirmPinInput" class="block text-sm font-medium text-[#101419] mb-2">
+            Confirmar PIN
+          </label>
+          <input 
+            id="confirmPinInput"
+            name="confirmPin"
+            type="password"
+            maxlength="4"
+            class="w-full border border-gray-300 px-4 py-3 rounded-lg focus:ring-2 focus:ring-[#101419] focus:border-transparent outline-none transition-all text-center text-2xl tracking-widest"
+            placeholder="••••"
+            required
+          />
+        </div>
+
+        <div class="bg-blue-50 border border-blue-200 text-blue-800 px-4 py-3 rounded-lg text-sm">
+          <div class="flex items-start space-x-2">
+            <svg class="w-4 h-4 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
+              <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/>
+            </svg>
+            <p>Recuerda elegir un PIN que sea seguro pero fácil de recordar. Evita fechas obvias como tu cumpleaños.</p>
+          </div>
+        </div>
+      </div>
+
+      <div class="space-y-3">
+        <button 
+          id="pinSubmitBtn"
+          type="submit"
+          class="w-full bg-[#101419] hover:bg-[#37404a] disabled:opacity-50 disabled:cursor-not-allowed text-white py-3 rounded-lg font-medium transition-colors duration-200 focus:ring-2 focus:ring-offset-2 focus:ring-[#101419]"
+        >
+          Establecer nuevo PIN
+        </button>
+      </div>
+    </form>
+
+    <!-- Mensaje de error global -->
+    <div id="errorMessage" class="hidden bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg text-sm mt-4">
+    </div>
+
+    <!-- Mensaje de éxito -->
+    <div id="successMessage" class="hidden bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded-lg text-sm mt-4">
+    </div>
+  </div>
+
+  <script>
+    // Variables globales
+    let currentStep = 1;
+    let userEmail = '';
+    let verificationCode = '';
+    let resendTimer = null;
+    let resendCountdown = 0;
+
+    // Referencias a elementos del DOM
+    const emailForm = document.getElementById('emailForm');
+    const codeForm = document.getElementById('codeForm');
+    const pinForm = document.getElementById('pinForm');
+    
+    const emailInput = document.getElementById('emailInput');
+    const codeInput = document.getElementById('codeInput');
+    const newPinInput = document.getElementById('newPinInput');
+    const confirmPinInput = document.getElementById('confirmPinInput');
+    
+    const emailSubmitBtn = document.getElementById('emailSubmitBtn');
+    const codeSubmitBtn = document.getElementById('codeSubmitBtn');
+    const pinSubmitBtn = document.getElementById('pinSubmitBtn');
+    
+    const backToEmailBtn = document.getElementById('backToEmailBtn');
+    const resendCodeBtn = document.getElementById('resendCodeBtn');
+    const resendText = document.getElementById('resendText');
+    
+    const errorMessage = document.getElementById('errorMessage');
+    const successMessage = document.getElementById('successMessage');
+    const emailDisplay = document.getElementById('emailDisplay');
+
+    // Indicadores de pasos
+    const step1Indicator = document.getElementById('step1Indicator');
+    const step2Indicator = document.getElementById('step2Indicator');
+    const step3Indicator = document.getElementById('step3Indicator');
+
+    // Inicialización
+    emailInput.focus();
+
+    // Funciones de utilidad
+    function showError(message) {
+      errorMessage.textContent = message;
+      errorMessage.classList.remove('hidden');
+      successMessage.classList.add('hidden');
+    }
+
+    function showSuccess(message) {
+      successMessage.textContent = message;
+      successMessage.classList.remove('hidden');
+      errorMessage.classList.add('hidden');
+    }
+
+    function hideMessages() {
+      errorMessage.classList.add('hidden');
+      successMessage.classList.add('hidden');
+    }
+
+    function updateStepIndicators() {
+      // Resetear todos los indicadores
+      [step1Indicator, step2Indicator, step3Indicator].forEach((step, index) => {
+        const circle = step.querySelector('.w-6');
+        const texts = step.querySelectorAll('p');
+        
+        if (index + 1 < currentStep) {
+          // Paso completado
+          circle.className = 'flex-shrink-0 w-6 h-6 bg-green-500 text-white rounded-full flex items-center justify-center text-xs font-medium';
+          circle.innerHTML = '✓';
+          texts.forEach(text => {
+            text.className = text.className.replace('text-gray-400', 'text-green-600');
+            text.className = text.className.replace('text-[#58728d]', 'text-green-600');
+          });
+        } else if (index + 1 === currentStep) {
+          // Paso actual
+          circle.className = 'flex-shrink-0 w-6 h-6 bg-[#101419] text-white rounded-full flex items-center justify-center text-xs font-medium';
+          circle.textContent = index + 1;
+          texts.forEach(text => {
+            text.className = text.className.replace('text-gray-400', 'text-[#101419]');
+            if (text.className.includes('font-medium')) {
+              text.className = text.className.replace('text-gray-400', 'text-[#101419]');
+            } else {
+              text.className = text.className.replace('text-gray-400', 'text-[#58728d]');
+            }
+          });
+        } else {
+          // Paso pendiente
+          circle.className = 'flex-shrink-0 w-6 h-6 bg-gray-300 text-gray-600 rounded-full flex items-center justify-center text-xs font-medium';
+          circle.textContent = index + 1;
+          texts.forEach(text => {
+            text.className = text.className.replace('text-[#101419]', 'text-gray-400');
+            text.className = text.className.replace('text-[#58728d]', 'text-gray-400');
+            text.className = text.className.replace('text-green-600', 'text-gray-400');
+          });
+        }
+      });
+    }
+
+    function showStep(step) {
+      // Ocultar todos los formularios
+      emailForm.classList.add('hidden');
+      codeForm.classList.add('hidden');
+      pinForm.classList.add('hidden');
+      
+      // Detener timer si cambia de paso
+      if (step !== 2) {
+        stopResendTimer();
+      }
+      
+      // Mostrar el formulario correspondiente
+      switch(step) {
+        case 1:
+          emailForm.classList.remove('hidden');
+          emailInput.focus();
+          break;
+        case 2:
+          codeForm.classList.remove('hidden');
+          codeInput.focus();
+          break;
+        case 3:
+          pinForm.classList.remove('hidden');
+          newPinInput.focus();
+          break;
+      }
+      
+      currentStep = step;
+      updateStepIndicators();
+      hideMessages();
+    }
+
+    function generateVerificationCode() {
+      return Math.floor(100000 + Math.random() * 900000).toString();
+    }
+
+    function startResendTimer() {
+      resendCountdown = 60; // 1 minuto
+      resendCodeBtn.disabled = true;
+      
+      resendTimer = setInterval(() => {
+        if (resendCountdown > 0) {
+          resendText.textContent = `Reenviar (${resendCountdown}s)`;
+          resendCountdown--;
+        } else {
+          clearInterval(resendTimer);
+          resendCodeBtn.disabled = false;
+          resendText.textContent = 'Reenviar';
+        }
+      }, 1000);
+    }
+
+    function stopResendTimer() {
+      if (resendTimer) {
+        clearInterval(resendTimer);
+        resendTimer = null;
+      }
+      resendCountdown = 0;
+      resendCodeBtn.disabled = false;
+      resendText.textContent = 'Reenviar';
+    }
+
+    // FASE 1: Envío de correo
+    emailForm.addEventListener('submit', function(e) {
+      e.preventDefault();
+      
+      const email = emailInput.value.trim();
+      
+      if (!email) {
+        showError('Por favor ingresa tu correo electrónico');
+        emailInput.focus();
+        return;
+      }
+      
+      if (!isValidEmail(email)) {
+        showError('Por favor ingresa un correo electrónico válido');
+        emailInput.focus();
+        return;
+      }
+      
+      // Simular envío de código
+      emailSubmitBtn.disabled = true;
+      emailSubmitBtn.textContent = 'Enviando código...';
+      
+      setTimeout(() => {
+        userEmail = email;
+        verificationCode = generateVerificationCode();
+        emailDisplay.textContent = email;
+        
+        // En una aplicación real, aquí enviarías el código por email
+        fetch('/', {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/json'
+          },
+          body: JSON.stringify({ email })
+        });
+
+        showSuccess(`Código enviado a ${email}`);
+        
+        setTimeout(() => {
+          showStep(2);
+          startResendTimer(); // Iniciar el timer cuando se muestra la fase 2
+        }, 1500);
+        
+        emailSubmitBtn.disabled = false;
+        emailSubmitBtn.textContent = 'Enviar código';
+      }, 2000);
+    });
+
+    // FASE 2: Verificación de código
+    codeForm.addEventListener('submit', function(e) {
+      e.preventDefault();
+      
+      const code = codeInput.value.trim();
+      
+      if (!code || code.length !== 6) {
+        showError('Por favor ingresa el código de 6 dígitos');
+        codeInput.focus();
+        return;
+      }
+      
+      if (!/^\d{6}$/.test(code)) {
+        showError('El código debe contener solo números');
+        codeInput.focus();
+        return;
+      }
+      
+      codeSubmitBtn.disabled = true;
+      codeSubmitBtn.textContent = 'Verificando...';
+      
+      setTimeout(() => {
+        // En una aplicación real, verificarías el código con el servidor
+        if (code === verificationCode) {
+          showSuccess('Código verificado correctamente');
+          
+          setTimeout(() => {
+            showStep(3);
+          }, 1500);
+        } else {
+          showError('Código incorrecto. Por favor verifica e intenta nuevamente.');
+          codeInput.focus();
+          codeInput.select();
+        }
+        
+        codeSubmitBtn.disabled = false;
+        codeSubmitBtn.textContent = 'Verificar código';
+      }, 1500);
+    });
+
+    // FASE 3: Crear nuevo PIN
+    pinForm.addEventListener('submit', function(e) {
+      e.preventDefault();
+      
+      const newPin = newPinInput.value.trim();
+      const confirmPin = confirmPinInput.value.trim();
+      
+      if (!newPin || newPin.length !== 4) {
+        showError('El PIN debe tener 4 dígitos');
+        newPinInput.focus();
+        return;
+      }
+      
+      if (!/^\d{4}$/.test(newPin)) {
+        showError('El PIN debe contener solo números');
+        newPinInput.focus();
+        return;
+      }
+      
+      if (!confirmPin || confirmPin.length !== 4) {
+        showError('Por favor confirma tu PIN');
+        confirmPinInput.focus();
+        return;
+      }
+      
+      if (newPin !== confirmPin) {
+        showError('Los PINs no coinciden. Por favor verifica e intenta nuevamente.');
+        confirmPinInput.focus();
+        confirmPinInput.select();
+        return;
+      }
+      
+      // Validar que no sea un PIN muy obvio
+      if (newPin === '1234' || newPin === '0000' || newPin === '1111' || newPin === '2222' || 
+          newPin === '3333' || newPin === '4444' || newPin === '5555' || newPin === '6666' || 
+          newPin === '7777' || newPin === '8888' || newPin === '9999') {
+        showError('Por favor elige un PIN más seguro. Evita secuencias obvias.');
+        newPinInput.focus();
+        newPinInput.select();
+        return;
+      }
+      
+      pinSubmitBtn.disabled = true;
+      pinSubmitBtn.textContent = 'Estableciendo PIN...';
+      
+      setTimeout(() => {
+        // En una aplicación real, aquí guardarías el nuevo PIN
+        showSuccess('¡PIN establecido correctamente! Ya puedes acceder a tu cuenta.');
+        
+        setTimeout(() => {
+          // Redirigir al login o página principal
+          alert('PIN establecido correctamente. Serás redirigido al inicio de sesión.');
+          window.location.href = '/login';
+        }, 2000);
+        
+      }, 2000);
+    });
+
+    // Eventos adicionales
+    backToEmailBtn.addEventListener('click', function() {
+      stopResendTimer(); // Detener el timer si regresa al paso 1
+      showStep(1);
+    });
+
+    resendCodeBtn.addEventListener('click', function() {
+      if (resendCodeBtn.disabled) return; // Prevenir clics múltiples
+      
+      verificationCode = generateVerificationCode();
+      console.log('Nuevo código de verificación:', verificationCode);
+      showSuccess('Código reenviado a ' + userEmail);
+      startResendTimer(); // Reiniciar el timer
+    });
+
+    // Formatear inputs de PIN para que solo acepten números
+    [newPinInput, confirmPinInput].forEach(input => {
+      input.addEventListener('input', function(e) {
+        e.target.value = e.target.value.replace(/\D/g, '').slice(0, 4);
+        hideMessages();
+      });
+    });
+
+    // Formatear input de código para que solo acepte números
+    codeInput.addEventListener('input', function(e) {
+      e.target.value = e.target.value.replace(/\D/g, '').slice(0, 6);
+      hideMessages();
+    });
+
+    // Ocultar mensajes cuando el usuario escriba
+    [emailInput, codeInput, newPinInput, confirmPinInput].forEach(input => {
+      input.addEventListener('input', hideMessages);
+    });
+
+    // Validar email
+    function isValidEmail(email) {
+      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+      return emailRegex.test(email);
+    }
+
+    // Navegación con Enter entre campos de PIN
+    newPinInput.addEventListener('keypress', function(e) {
+      if (e.key === 'Enter' && this.value.length === 4) {
+        confirmPinInput.focus();
+      }
+    });
+
+    confirmPinInput.addEventListener('keypress', function(e) {
+      if (e.key === 'Enter' && this.value.length === 4) {
+        pinForm.dispatchEvent(new Event('submit'));
+      }
+    });
+  </script>
+
+</body>
+</html>

+ 2 - 57
routes/chat.py

@@ -4,7 +4,6 @@ from httpx import get
 from models.chat import ChatCompletionRequest
 from models.chat import ChatCompletionRequest
 from models.user import User
 from models.user import User
 from services.openai_service.openai_service import generate_completion
 from services.openai_service.openai_service import generate_completion
-from services.logging_service import log_llm_response, structured_logger, LogLevel
 from auth.security import get_current_user
 from auth.security import get_current_user
 import logging
 import logging
 from fastapi import APIRouter
 from fastapi import APIRouter
@@ -23,20 +22,6 @@ async def chat_completions(request_data: ChatCompletionRequest, request: Request
     
     
     logger.info(f"Chat completion request from user {current_user.email}")
     logger.info(f"Chat completion request from user {current_user.email}")
     
     
-    structured_logger.log_chat_event(
-        f"Chat completion request from user {current_user.email}",
-        LogLevel.INFO,
-        {
-            "user_id": current_user.id,
-            "user_email": current_user.email,
-            "session_identifier": session_identifier,
-            "messages_count": len(request_data.messages),
-            "user_agent": request.headers.get("user-agent", "unknown"),
-            "request_user": request_data.user
-        },
-        user_id=current_user.id,
-        user_email=current_user.email
-    )
 
 
     try:
     try:
         openai_response = await generate_completion(
         openai_response = await generate_completion(
@@ -46,60 +31,20 @@ async def chat_completions(request_data: ChatCompletionRequest, request: Request
             current_user.email
             current_user.email
         )
         )
         
         
-        structured_logger.log_chat_event(
-            f"Chat completion generated successfully",
-            LogLevel.INFO,
-            {
-                "user_id": current_user.id,
-                "user_email": current_user.email,
-                "session_identifier": session_identifier,
-                "response_length": len(openai_response),
-                "messages_processed": len(request_data.messages)
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        logger.info(f"OpenAI response generated for user {current_user.email}")
         
         
         # Legacy logging function
         # Legacy logging function
-        log_llm_response(request_data.user, openai_response)
+
         
         
         logger.info(f"Chat completion successful for user {current_user.email}")
         logger.info(f"Chat completion successful for user {current_user.email}")
         return JSONResponse({"response": openai_response, "message": SuccessResponse.CHAT_RESPONSE_SUCCESS})
         return JSONResponse({"response": openai_response, "message": SuccessResponse.CHAT_RESPONSE_SUCCESS})
         
         
     except HTTPException as e:
     except HTTPException as e:
         logger.error(f"HTTP error in chat completion for user {current_user.email}: {e.detail}")
         logger.error(f"HTTP error in chat completion for user {current_user.email}: {e.detail}")
-        structured_logger.log_chat_event(
-            f"Chat completion HTTP error",
-            LogLevel.ERROR,
-            {
-                "user_id": current_user.id,
-                "user_email": current_user.email,
-                "session_identifier": session_identifier,
-                "status_code": e.status_code,
-                "error_detail": e.detail
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
         raise
         raise
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Unexpected error in /api/chat/completions for user {current_user.email}: {e}"
         error_msg = f"Unexpected error in /api/chat/completions for user {current_user.email}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
         
         
-        structured_logger.log_chat_event(
-            f"Chat completion unexpected error",
-            LogLevel.ERROR,
-            {
-                "user_id": current_user.id,
-                "user_email": current_user.email,
-                "session_identifier": session_identifier,
-                "error": str(e),
-                "error_type": type(e).__name__,
-                "messages_count": len(request_data.messages)
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
-        
         raise HTTPException(status_code=500, detail="Error interno del servidor al procesar el chat.")
         raise HTTPException(status_code=500, detail="Error interno del servidor al procesar el chat.")

+ 16 - 354
routes/orders.py

@@ -12,7 +12,6 @@ from models.items import Item, Order
 from models.user import User
 from models.user import User
 from services.fudo_service import add_product_to_fudo
 from services.fudo_service import add_product_to_fudo
 from services.email_service import get_email_sender
 from services.email_service import get_email_sender
-from services.logging_service import log_order, structured_logger, LogLevel
 import services.print_service as ps
 import services.print_service as ps
 from services.data_service import DataServiceFactory
 from services.data_service import DataServiceFactory
 from config.mails import PRINTER_DISCONNECTED_MAIL
 from config.mails import PRINTER_DISCONNECTED_MAIL
@@ -37,19 +36,6 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
     """Process printer order"""
     """Process printer order"""
     logger.info(f"Printer order received from user {current_user.email} for table {order.table}")
     logger.info(f"Printer order received from user {current_user.email} for table {order.table}")
     
     
-    structured_logger.log_order_event(
-        f"Print order received for table {order.table}",
-        LogLevel.INFO,
-        {
-            "table": order.table,
-            "items_count": len(order.items),
-            "customer_id": order.customerId,
-            "total_amount": order.totalAmount,
-            "order_date": order.orderDate
-        },
-        user_id=current_user.id,
-        user_email=current_user.email
-    )
     
     
     # Printer status validation
     # Printer status validation
     if not DEVELOPMENT:
     if not DEVELOPMENT:
@@ -57,19 +43,7 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
             printer_status = ps.get_status()
             printer_status = ps.get_status()
             if not printer_status:
             if not printer_status:
                 logger.error(f"Printer is not connected. Order from user {current_user.email} cannot be processed.")
                 logger.error(f"Printer is not connected. Order from user {current_user.email} cannot be processed.")
-                
-                structured_logger.log_print_event(
-                    f"Order rejected due to printer disconnection",
-                    LogLevel.ERROR,
-                    {
-                        "table": order.table,
-                        "user_id": current_user.id,
-                        "user_email": current_user.email,
-                        "items_count": len(order.items)
-                    },
-                    user_id=current_user.id,
-                    user_email=current_user.email
-                )
+       
                 
                 
                 # Send notification email to admins
                 # Send notification email to admins
                 email_thread = Thread(
                 email_thread = Thread(
@@ -83,32 +57,11 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
                 )
                 )
                 email_thread.start()
                 email_thread.start()
                 
                 
-                structured_logger.log_email_event(
-                    "Printer disconnection notification sent to admins",
-                    LogLevel.WARNING,
-                    {
-                        "trigger_user": current_user.email,
-                        "admin_emails": ["erwinjacimino2003@gmail.com", "mompyn@gmail.com"]
-                    },
-                    user_id=current_user.id,
-                    user_email=current_user.email
-                )
                 
                 
                 return JSONResponse(status_code=424, content={"message": ErrorResponse.PRINTER_DISCONNECTED})
                 return JSONResponse(status_code=424, content={"message": ErrorResponse.PRINTER_DISCONNECTED})
                 
                 
         except Exception as e:
         except Exception as e:
             logger.error(f"Error checking printer status: {e}")
             logger.error(f"Error checking printer status: {e}")
-            structured_logger.log_print_event(
-                "Printer status check failed",
-                LogLevel.ERROR,
-                {
-                    "error": str(e),
-                    "error_type": type(e).__name__,
-                    "user_id": current_user.id
-                },
-                user_id=current_user.id,
-                user_email=current_user.email
-            )
             return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
             return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
 
 
     # Extract order data
     # Extract order data
@@ -118,46 +71,14 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
     # Input validation
     # Input validation
     if not items or not table:
     if not items or not table:
         logger.warning(f"Invalid order data from user {current_user.email}: missing items or table")
         logger.warning(f"Invalid order data from user {current_user.email}: missing items or table")
-        structured_logger.log_order_event(
-            "Order validation failed: missing items or table",
-            LogLevel.WARNING,
-            {
-                "has_items": bool(items),
-                "table": table,
-                "items_count": len(items) if items else 0
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
         return JSONResponse(status_code=400, content={"message": ErrorResponse.MISSING_FIELDS})
         return JSONResponse(status_code=400, content={"message": ErrorResponse.MISSING_FIELDS})
 
 
     if not isinstance(table, int):
     if not isinstance(table, int):
         logger.warning(f"Invalid table type from user {current_user.email}: {type(table)}")
         logger.warning(f"Invalid table type from user {current_user.email}: {type(table)}")
-        structured_logger.log_order_event(
-            "Order validation failed: invalid table type",
-            LogLevel.WARNING,
-            {
-                "table": table,
-                "table_type": str(type(table))
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+       
         return JSONResponse(status_code=400, content={"message": ErrorResponse.INVALID_TABLE_TYPE})
         return JSONResponse(status_code=400, content={"message": ErrorResponse.INVALID_TABLE_TYPE})
 
 
     logger.info(f"Processing order for table {table} with {len(items)} items")
     logger.info(f"Processing order for table {table} with {len(items)} items")
-    structured_logger.log_order_event(
-        f"Starting order processing for table {table}",
-        LogLevel.INFO,
-        {
-            "table": table,
-            "items_count": len(items),
-            "item_ids": [item.id for item in items],
-            "item_quantities": [item.quantity for item in items]
-        },
-        user_id=current_user.id,
-        user_email=current_user.email
-    )
 
 
     # Add products to Fudo
     # Add products to Fudo
     product_errors = []
     product_errors = []
@@ -167,34 +88,10 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
         products = product_data_service.get_products([item.id for item in items])
         products = product_data_service.get_products([item.id for item in items])
         logger.info(f"Retrieved {len(products)} products from database")
         logger.info(f"Retrieved {len(products)} products from database")
         
         
-        structured_logger.log_order_event(
-            f"Retrieved products for order processing",
-            LogLevel.INFO,
-            {
-                "table": table,
-                "requested_products": len(items),
-                "found_products": len(products),
-                "product_ids": [p.id for p in products]
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Error retrieving products: {e}"
         error_msg = f"Error retrieving products: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_database_event(
-            "Failed to retrieve products for order",
-            LogLevel.ERROR,
-            {
-                "table": table,
-                "requested_product_ids": [item.id for item in items],
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
 
 
     beers_for_promo = 0
     beers_for_promo = 0
@@ -210,20 +107,6 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
                     logger.info(f"Applying promotion for product {product.id} on table {table}")
                     logger.info(f"Applying promotion for product {product.id} on table {table}")
                     fudo_product = add_product_to_fudo(product.promo_id, item.quantity, table)
                     fudo_product = add_product_to_fudo(product.promo_id, item.quantity, table)
                     
                     
-                    structured_logger.log_order_event(
-                        f"Promotion applied for product {product.name}",
-                        LogLevel.INFO,
-                        {
-                            "product_id": product.id,
-                            "promo_id": product.promo_id,
-                            "table": table,
-                            "quantity": item.quantity,
-                            "promo_day": product.promo_day,
-                            "current_day": time.localtime().tm_wday + 1
-                        },
-                        user_id=current_user.id,
-                        user_email=current_user.email
-                    )
                 #en caso contrario
                 #en caso contrario
                 else:
                 else:
                     if product.type == name_promo:
                     if product.type == name_promo:
@@ -232,85 +115,29 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
                     
                     
                     fudo_product = add_product_to_fudo(item.id, item.quantity, table)
                     fudo_product = add_product_to_fudo(item.id, item.quantity, table)
                     
                     
-                    structured_logger.log_order_event(
-                        f"Added product {product.name} to Fudo",
-                        LogLevel.INFO,
-                        {
-                            "product_id": item.id,
-                            "product_name": product.name,
-                            "product_type": product.type,
-                            "table": table,
-                            "quantity": item.quantity,
-                            "is_beer": product.type == name_promo
-                        },
-                        user_id=current_user.id,
-                        user_email=current_user.email
-                    )
+                    logger.info(f"Added product {item.id} to table {table} with quantity {item.quantity} in fudo")
                 
                 
                 if not fudo_product:
                 if not fudo_product:
                     error_msg = f"Error adding product {item.id} to table {table}."
                     error_msg = f"Error adding product {item.id} to table {table}."
                     product_errors.append(error_msg)
                     product_errors.append(error_msg)
                     logger.error(error_msg)
                     logger.error(error_msg)
-                    
-                    structured_logger.log_order_event(
-                        f"Failed to add product to Fudo",
-                        LogLevel.ERROR,
-                        {
-                            "product_id": item.id,
-                            "table": table,
-                            "quantity": item.quantity
-                        },
-                        user_id=current_user.id,
-                        user_email=current_user.email
-                    )
+                   
                     
                     
             except Exception as e:
             except Exception as e:
                 error_msg = f"Error processing product {item.id}: {e}"
                 error_msg = f"Error processing product {item.id}: {e}"
                 logger.error(error_msg)
                 logger.error(error_msg)
                 product_errors.append(error_msg)
                 product_errors.append(error_msg)
                 
                 
-                structured_logger.log_order_event(
-                    f"Error processing product {item.id}",
-                    LogLevel.ERROR,
-                    {
-                        "product_id": item.id,
-                        "table": table,
-                        "error": str(e),
-                        "error_type": type(e).__name__
-                    },
-                    user_id=current_user.id,
-                    user_email=current_user.email
-                )
                 
                 
     except Exception as e:
     except Exception as e:
         error_msg = f"Error with Fudo integration: {e}"
         error_msg = f"Error with Fudo integration: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_order_event(
-            "Fudo integration error",
-            LogLevel.ERROR,
-            {
-                "table": table,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
 
 
     if product_errors:
     if product_errors:
         logger.error(f"Product errors occurred: {product_errors}")
         logger.error(f"Product errors occurred: {product_errors}")
-        structured_logger.log_order_event(
-            "Order processing failed due to product errors",
-            LogLevel.ERROR,
-            {
-                "table": table,
-                "product_errors": product_errors,
-                "error_count": len(product_errors)
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         return JSONResponse(
         return JSONResponse(
             status_code=424, 
             status_code=424, 
             content={"message": ErrorResponse.PRODUCT_ADD_ERROR, "errors": product_errors}
             content={"message": ErrorResponse.PRODUCT_ADD_ERROR, "errors": product_errors}
@@ -321,47 +148,16 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
         user = user_data_service.get_by_id(order.customerId)
         user = user_data_service.get_by_id(order.customerId)
         if not user:
         if not user:
             logger.warning(f"User not found: {order.customerId}")
             logger.warning(f"User not found: {order.customerId}")
-            structured_logger.log_user_event(
-                f"Order rejected: user not found",
-                LogLevel.WARNING,
-                {
-                    "requested_user_id": order.customerId,
-                    "table": table
-                },
-                user_id=current_user.id,
-                user_email=current_user.email
-            )
+            
             return JSONResponse(status_code=404, content={"message": UserResponse.USER_NOT_FOUND.format(user_id=order.customerId)})
             return JSONResponse(status_code=404, content={"message": UserResponse.USER_NOT_FOUND.format(user_id=order.customerId)})
         
         
         logger.info(f"Order customer validated: {user.email}")
         logger.info(f"Order customer validated: {user.email}")
-        structured_logger.log_user_event(
-            f"Order customer validated",
-            LogLevel.INFO,
-            {
-                "customer_id": user.id,
-                "customer_email": user.email,
-                "customer_name": user.name,
-                "table": table
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Error validating user {order.customerId}: {e}"
         error_msg = f"Error validating user {order.customerId}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_database_event(
-            "User validation error during order processing",
-            LogLevel.ERROR,
-            {
-                "requested_user_id": order.customerId,
-                "table": table,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
     
     
     # Get active sale
     # Get active sale
@@ -370,48 +166,19 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
         if not active_sale_id:
         if not active_sale_id:
             error_msg = f"No active sale found for table {table}"
             error_msg = f"No active sale found for table {table}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_order_event(
-                "Order failed: no active sale found",
-                LogLevel.ERROR,
-                {
-                    "table": table,
-                    "customer_id": order.customerId
-                },
-                user_id=current_user.id,
-                user_email=current_user.email
-            )
+            
             raise HTTPException(status_code=404, detail=error_msg)
             raise HTTPException(status_code=404, detail=error_msg)
             
             
         active_sale_id = active_sale_id['id']
         active_sale_id = active_sale_id['id']
         logger.info(f"Active sale found for table {table}: {active_sale_id}")
         logger.info(f"Active sale found for table {table}: {active_sale_id}")
         
         
-        structured_logger.log_order_event(
-            f"Active sale retrieved for table {table}",
-            LogLevel.INFO,
-            {
-                "table": table,
-                "sale_id": active_sale_id
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
         
         
     except HTTPException:
     except HTTPException:
         raise
         raise
     except Exception as e:
     except Exception as e:
         error_msg = f"Error retrieving active sale for table {table}: {e}"
         error_msg = f"Error retrieving active sale for table {table}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_order_event(
-            "Error retrieving active sale",
-            LogLevel.ERROR,
-            {
-                "table": table,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         raise HTTPException(status_code=500, detail="Error interno del servidor")
         raise HTTPException(status_code=500, detail="Error interno del servidor")
 
 
     # Update user reward progress
     # Update user reward progress
@@ -420,36 +187,11 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
         user_data_service.set_reward_progress(user.id, new_progress)
         user_data_service.set_reward_progress(user.id, new_progress)
         
         
         logger.info(f"Updated reward progress for user {user.email}: {user.reward_progress} -> {new_progress}")
         logger.info(f"Updated reward progress for user {user.email}: {user.reward_progress} -> {new_progress}")
-        structured_logger.log_user_event(
-            f"Reward progress updated",
-            LogLevel.INFO,
-            {
-                "user_id": user.id,
-                "old_progress": user.reward_progress,
-                "new_progress": new_progress,
-                "beers_count": beers_for_promo,
-                "points_added": beers_for_promo * 10,
-                "table": table
-            },
-            user_id=user.id,
-            user_email=user.email
-        )
+        
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Error updating reward progress for user {user.id}: {e}"
         error_msg = f"Error updating reward progress for user {user.id}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_database_event(
-            "Failed to update reward progress",
-            LogLevel.ERROR,
-            {
-                "user_id": user.id,
-                "beers_for_promo": beers_for_promo,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_id=user.id,
-            user_email=user.email
-        )
         # Don't fail the order for this, just log it
         # Don't fail the order for this, just log it
         new_progress = user.reward_progress
         new_progress = user.reward_progress
 
 
@@ -466,52 +208,15 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
         
         
         if sale > 0:
         if sale > 0:
             logger.info(f"Sale created successfully: ID {sale}")
             logger.info(f"Sale created successfully: ID {sale}")
-            structured_logger.log_order_event(
-                f"Sale record created successfully",
-                LogLevel.INFO,
-                {
-                    "sale_id": sale,
-                    "customer_id": order.customerId,
-                    "table": table,
-                    "total_amount": order.totalAmount,
-                    "fudo_sale_id": active_sale_id,
-                    "items_count": len(items)
-                },
-                user_id=current_user.id,
-                user_email=current_user.email
-            )
         else:
         else:
             error_msg = "Failed to create sale record"
             error_msg = "Failed to create sale record"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_database_event(
-                "Sale creation failed",
-                LogLevel.ERROR,
-                {
-                    "customer_id": order.customerId,
-                    "table": table,
-                    "total_amount": order.totalAmount,
-                    "fudo_sale_id": active_sale_id
-                },
-                user_id=current_user.id,
-                user_email=current_user.email
-            )
             return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
             return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
             
             
     except Exception as e:
     except Exception as e:
         error_msg = f"Error creating sale record: {e}"
         error_msg = f"Error creating sale record: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_database_event(
-            "Sale creation error",
-            LogLevel.ERROR,
-            {
-                "customer_id": order.customerId,
-                "table": table,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
 
 
     # Print order
     # Print order
@@ -527,59 +232,16 @@ async def printer_order(order: OrderWeb, current_user: User = Depends(get_curren
         ps.print_order(order_for_print)
         ps.print_order(order_for_print)
         
         
         logger.info(f"Order printed successfully for table {table}")
         logger.info(f"Order printed successfully for table {table}")
-        structured_logger.log_print_event(
-            f"Order printed successfully for table {table}",
-            LogLevel.INFO,
-            {
-                "table": table,
-                "customer_name": user.name,
-                "total_amount": order.totalAmount,
-                "items_count": len(items),
-                "sale_id": sale
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
+        
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Error printing order for table {table}: {e}"
         error_msg = f"Error printing order for table {table}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            f"Order print failed for table {table}",
-            LogLevel.ERROR,
-            {
-                "table": table,
-                "customer_name": user.name,
-                "error": str(e),
-                "error_type": type(e).__name__,
-                "sale_id": sale
-            },
-            user_id=current_user.id,
-            user_email=current_user.email
-        )
         # Don't fail the order for print issues, just log it
         # Don't fail the order for print issues, just log it
 
 
-    # Log order (legacy function)
+    # Log order
     try:
     try:
-        log_order(user.name, order.table, order_date=order.orderDate, items=[product.name for product in products])
-        
-        structured_logger.log_order_event(
-            f"Order completed successfully for table {table}",
-            LogLevel.INFO,
-            {
-                "table": table,
-                "customer_id": user.id,
-                "customer_name": user.name,
-                "customer_email": user.email,
-                "total_amount": order.totalAmount,
-                "items": [{"name": product.name, "quantity": item.quantity, "price": product.price} for product, item in zip(products, items)],
-                "sale_id": sale,
-                "new_reward_progress": new_progress,
-                "beers_for_promo": beers_for_promo
-            },
-            user_id=user.id,
-            user_email=user.email
-        )
+        logger.info(f"Logging order for table {table} with sale ID {sale}, products= {[(product.name, item.quantity) for product, item in zip(products, items)]}")
         
         
     except Exception as e:
     except Exception as e:
         logger.error(f"Error in legacy order logging: {e}")
         logger.error(f"Error in legacy order logging: {e}")

+ 44 - 187
routes/users.py

@@ -13,11 +13,11 @@ from auth.security import get_current_user
 from config.mails import REGISTER_MAIL
 from config.mails import REGISTER_MAIL
 from config.messages import ErrorResponse, SuccessResponse, UserResponse
 from config.messages import ErrorResponse, SuccessResponse, UserResponse
 from config.settings import APPNAME, PIN_KEY
 from config.settings import APPNAME, PIN_KEY
-from models.user import LoginRequest, PinUserRequest, RegisterUserRequest, User, User, UserIDRequest, UserRewardRequest
+from models.user import LoginRequest, PinRecoveryRequest, PinUserRequest, RegisterUserRequest, User, User, UserIDRequest, UserRewardRequest
 from services.data_service import BlacklistDataService, UserDataService
 from services.data_service import BlacklistDataService, UserDataService
 from services.email_service import get_email_sender
 from services.email_service import get_email_sender
 from services.print_service import print_ticket
 from services.print_service import print_ticket
-from services.logging_service import structured_logger, LogLevel
+import services.recovery_service as recovery_service
 from utils.rut import validate_rut
 from utils.rut import validate_rut
 
 
 fernet = Fernet(PIN_KEY.encode())
 fernet = Fernet(PIN_KEY.encode())
@@ -47,30 +47,12 @@ async def register_user(request: RegisterUserRequest):
     """Register a new user"""
     """Register a new user"""
     logger.info(f"Registration attempt for email: {request.email}")
     logger.info(f"Registration attempt for email: {request.email}")
     
     
-    structured_logger.log_user_event(
-        f"User registration attempt",
-        LogLevel.INFO,
-        {
-            "email": request.email,
-            "name": request.name,
-            "rut": request.rut
-        },
-        user_email=request.email
-    )
+    
     
     
     # Validate RUT
     # Validate RUT
     if not validate_rut(request.rut):
     if not validate_rut(request.rut):
         logger.warning(f"Registration failed for {request.email}: invalid RUT {request.rut}")
         logger.warning(f"Registration failed for {request.email}: invalid RUT {request.rut}")
-        structured_logger.log_user_event(
-            "Registration failed: invalid RUT",
-            LogLevel.WARNING,
-            {
-                "email": request.email,
-                "rut": request.rut,
-                "reason": "Invalid RUT format"
-            },
-            user_email=request.email
-        )
+        
         raise HTTPException(status_code=400, detail=ErrorResponse.INVALID_RUT)
         raise HTTPException(status_code=400, detail=ErrorResponse.INVALID_RUT)
 
 
     # Check if user already exists by email
     # Check if user already exists by email
@@ -78,50 +60,20 @@ async def register_user(request: RegisterUserRequest):
         user = user_data_service.get_by_email(request.email)
         user = user_data_service.get_by_email(request.email)
         if user:
         if user:
             logger.warning(f"Registration failed for {request.email}: user already exists")
             logger.warning(f"Registration failed for {request.email}: user already exists")
-            structured_logger.log_user_event(
-                "Registration failed: user already exists",
-                LogLevel.WARNING,
-                {
-                    "email": request.email,
-                    "existing_user_id": user.id,
-                    "reason": "Email already registered"
-                },
-                user_id=user.id,
-                user_email=request.email
-            )
+            
             return HTTPException(status_code=400, detail=UserResponse.USER_ALREADY_EXISTS)
             return HTTPException(status_code=400, detail=UserResponse.USER_ALREADY_EXISTS)
             
             
         # Check if RUT already exists
         # Check if RUT already exists
         user = user_data_service.get_by_rut(request.rut)
         user = user_data_service.get_by_rut(request.rut)
         if user:
         if user:
             logger.warning(f"Registration failed for {request.email}: RUT already exists")
             logger.warning(f"Registration failed for {request.email}: RUT already exists")
-            structured_logger.log_user_event(
-                "Registration failed: RUT already exists",
-                LogLevel.WARNING,
-                {
-                    "email": request.email,
-                    "rut": request.rut,
-                    "existing_user_id": user.id,
-                    "reason": "RUT already registered"
-                },
-                user_email=request.email
-            )
+            
             return HTTPException(status_code=400, detail=UserResponse.USER_ALREADY_EXISTS)
             return HTTPException(status_code=400, detail=UserResponse.USER_ALREADY_EXISTS)
 
 
     except Exception as e:
     except Exception as e:
         error_msg = f"Database error during user validation: {e}"
         error_msg = f"Database error during user validation: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_database_event(
-            "User validation error during registration",
-            LogLevel.ERROR,
-            {
-                "email": request.email,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_email=request.email
-        )
-        raise HTTPException(status_code=500, detail={"message": "Error interno del servidor"})
+        
 
 
     logger.info(f"Registering user: {request.email}")
     logger.info(f"Registering user: {request.email}")
     
     
@@ -139,16 +91,7 @@ async def register_user(request: RegisterUserRequest):
         redis_client.set(f"verify:{verification_code}", json.dumps(user_data))
         redis_client.set(f"verify:{verification_code}", json.dumps(user_data))
         redis_client.expire(f"verify:{verification_code}", 3600)  # Expire in 1 hour
         redis_client.expire(f"verify:{verification_code}", 3600)  # Expire in 1 hour
         
         
-        structured_logger.log_user_event(
-            "Verification code generated for user registration",
-            LogLevel.INFO,
-            {
-                "email": request.email,
-                "verification_code": verification_code,
-                "expires_in": 3600
-            },
-            user_email=request.email
-        )
+        logger.info(f"Verification code generated for {request.email}, code: {verification_code}")
 
 
         # Send verification email
         # Send verification email
         get_email_sender().send_email(
         get_email_sender().send_email(
@@ -160,33 +103,13 @@ async def register_user(request: RegisterUserRequest):
             verification_code=verification_code
             verification_code=verification_code
         )
         )
         
         
-        structured_logger.log_email_event(
-            "Registration verification email sent",
-            LogLevel.INFO,
-            {
-                "email": request.email,
-                "verification_code": verification_code
-            },
-            user_email=request.email
-        )
         
         
-        logger.info(f"Registration initiated successfully for {request.email}")
         return JSONResponse(status_code=201, content={"message": SuccessResponse.USER_CREATED_SUCCESS})
         return JSONResponse(status_code=201, content={"message": SuccessResponse.USER_CREATED_SUCCESS})
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Error during registration process for {request.email}: {e}"
         error_msg = f"Error during registration process for {request.email}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_user_event(
-            "Registration process failed",
-            LogLevel.ERROR,
-            {
-                "email": request.email,
-                "error": str(e),
-                "error_type": type(e).__name__,
-                "step": "verification_setup_or_email"
-            },
-            user_email=request.email
-        )
+        
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
 
 
 @user_router.post("/create-user")
 @user_router.post("/create-user")
@@ -198,7 +121,6 @@ async def create_user(request: PinUserRequest, q: str):
         return JSONResponse(status_code=400, content={"message": ErrorResponse.INVALID_VERIFICATION_CODE})
         return JSONResponse(status_code=400, content={"message": ErrorResponse.INVALID_VERIFICATION_CODE})
     else:
     else:
         data = json.loads(str(data))
         data = json.loads(str(data))
-    
     name = data.get("name")
     name = data.get("name")
     email = data.get("email")
     email = data.get("email")
     rut = data.get("rut")
     rut = data.get("rut")
@@ -210,8 +132,10 @@ async def create_user(request: PinUserRequest, q: str):
         return JSONResponse(status_code=400, content={"message": UserResponse.USER_ALREADY_EXISTS})
         return JSONResponse(status_code=400, content={"message": UserResponse.USER_ALREADY_EXISTS})
     user = user_data_service.get_by_id(userID)
     user = user_data_service.get_by_id(userID)
     if not user:
     if not user:
+        logger.error(f"User creation failed for {email}: user not found after creation")
         return JSONResponse(status_code=500, content={"message": ErrorResponse.USER_CREATION_ERROR})
         return JSONResponse(status_code=500, content={"message": ErrorResponse.USER_CREATION_ERROR})
 
 
+    logger.info(f"User created successfully: {email}")
     return JSONResponse(status_code=201, content={"message": SuccessResponse.USER_CREATED_SUCCESS, "data": {
     return JSONResponse(status_code=201, content={"message": SuccessResponse.USER_CREATED_SUCCESS, "data": {
         **user.model_dump(exclude={"pin_hash"}),
         **user.model_dump(exclude={"pin_hash"}),
         "token": generate_token(user.email)
         "token": generate_token(user.email)
@@ -222,17 +146,6 @@ async def login_user(request: LoginRequest, http_request: Request):
     """Login user with email and PIN"""
     """Login user with email and PIN"""
     logger.info(f"Login attempt for email: {request.email}")
     logger.info(f"Login attempt for email: {request.email}")
     
     
-    structured_logger.log_security_event(
-        f"Login attempt for user {request.email}",
-        LogLevel.INFO,
-        {
-            "email": request.email,
-            "user_agent": http_request.headers.get("user-agent", "unknown"),
-            "referer": http_request.headers.get("referer", "unknown"),
-            "client_ip": http_request.client.host if http_request.client else "unknown"
-        },
-        user_email=request.email
-    )
     
     
     try:
     try:
         redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
         redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
@@ -246,16 +159,7 @@ async def login_user(request: LoginRequest, http_request: Request):
                 blocked_minutes = 0
                 blocked_minutes = 0
             
             
             logger.warning(f"Login attempt for blocked user: {request.email}, blocked for {blocked_minutes} minutes")
             logger.warning(f"Login attempt for blocked user: {request.email}, blocked for {blocked_minutes} minutes")
-            structured_logger.log_security_event(
-                f"Login attempt by blocked user",
-                LogLevel.WARNING,
-                {
-                    "email": request.email,
-                    "blocked_time_remaining_minutes": blocked_minutes,
-                    "user_agent": http_request.headers.get("user-agent", "unknown")
-                },
-                user_email=request.email
-            )
+            
             return JSONResponse(
             return JSONResponse(
                 status_code=403, 
                 status_code=403, 
                 content={"message": UserResponse.USER_FORMAT_BLOCKED.format(time=f"{blocked_minutes} minutos")}
                 content={"message": UserResponse.USER_FORMAT_BLOCKED.format(time=f"{blocked_minutes} minutos")}
@@ -267,17 +171,7 @@ async def login_user(request: LoginRequest, http_request: Request):
         if user:
         if user:
             if blacklist_data_service.is_user_blacklisted(user.id):
             if blacklist_data_service.is_user_blacklisted(user.id):
                 logger.warning(f"Login attempt for blacklisted user: {request.email}")
                 logger.warning(f"Login attempt for blacklisted user: {request.email}")
-                structured_logger.log_security_event(
-                    f"Login attempt by blacklisted user",
-                    LogLevel.WARNING,
-                    {
-                        "email": request.email,
-                        "user_agent": http_request.headers.get("user-agent", "unknown"),
-                        "referer": http_request.headers.get("referer", "unknown"),
-                        "client_ip": http_request.client.host if http_request.client else "unknown"
-                    },
-                    user_email=request.email
-                )
+                
                 return JSONResponse(
                 return JSONResponse(
                     status_code=403,
                     status_code=403,
                     content={"message": UserResponse.USER_BLACKLISTED}
                     content={"message": UserResponse.USER_BLACKLISTED}
@@ -287,42 +181,19 @@ async def login_user(request: LoginRequest, http_request: Request):
             logger.info(f"Successful login for user: {request.email}")
             logger.info(f"Successful login for user: {request.email}")
             
             
             # Check admin access
             # Check admin access
-            referer = http_request.headers.get("referer", "")
+            referer = http_request.headers.get("Origin", "")
+            logger.info(f"Login request referer: {referer}")
             if referer and "admin" in referer:
             if referer and "admin" in referer:
                 user_permissions = user_data_service.permissions(user.id)
                 user_permissions = user_data_service.permissions(user.id)
                 if user_permissions == 0:
                 if user_permissions == 0:
                     logger.warning(f"Unauthorized admin access attempt by {request.email}")
                     logger.warning(f"Unauthorized admin access attempt by {request.email}")
-                    structured_logger.log_security_event(
-                        f"Unauthorized admin access attempt",
-                        LogLevel.WARNING,
-                        {
-                            "email": request.email,
-                            "user_id": user.id,
-                            "permissions": user_permissions,
-                            "referer": referer
-                        },
-                        user_id=user.id,
-                        user_email=request.email
-                    )
+                    
                     return JSONResponse(status_code=403, content={"message": UserResponse.NOT_PERMITTED})
                     return JSONResponse(status_code=403, content={"message": UserResponse.NOT_PERMITTED})
 
 
             # Clear login attempts and log successful login
             # Clear login attempts and log successful login
             redis_client.delete(f"login_attempts:{request.email}")
             redis_client.delete(f"login_attempts:{request.email}")
             
             
-            structured_logger.log_security_event(
-                f"Successful login",
-                LogLevel.INFO,
-                {
-                    "email": request.email,
-                    "user_id": user.id,
-                    "user_name": user.name,
-                    "permissions": user_data_service.permissions(user.id),
-                    "is_admin_login": "admin" in referer,
-                    "reward_progress": user.reward_progress
-                },
-                user_id=user.id,
-                user_email=request.email
-            )
+            
             
             
             return JSONResponse(status_code=200, content={
             return JSONResponse(status_code=200, content={
                 "message": SuccessResponse.LOGIN_SUCCESS, 
                 "message": SuccessResponse.LOGIN_SUCCESS, 
@@ -349,30 +220,11 @@ async def login_user(request: LoginRequest, http_request: Request):
                 redis_client.expire(f"blocked:{request.email}", 3600)
                 redis_client.expire(f"blocked:{request.email}", 3600)
                 
                 
                 logger.warning(f"Too many login attempts for {request.email}. User blocked.")
                 logger.warning(f"Too many login attempts for {request.email}. User blocked.")
-                structured_logger.log_security_event(
-                    f"User blocked due to too many failed login attempts",
-                    LogLevel.WARNING,
-                    {
-                        "email": request.email,
-                        "failed_attempts": attempts,
-                        "blocked_duration_seconds": 3600
-                    },
-                    user_email=request.email
-                )
+                
                 return JSONResponse(status_code=429, content={"message": ErrorResponse.TOO_MANY_ATTEMPTS})
                 return JSONResponse(status_code=429, content={"message": ErrorResponse.TOO_MANY_ATTEMPTS})
             else:
             else:
                 logger.warning(f"Failed login attempt for {request.email}. Attempts: {attempts}")
                 logger.warning(f"Failed login attempt for {request.email}. Attempts: {attempts}")
-                structured_logger.log_security_event(
-                    f"Failed login attempt",
-                    LogLevel.WARNING,
-                    {
-                        "email": request.email,
-                        "failed_attempts": attempts,
-                        "attempts_remaining": 5 - attempts,
-                        "reason": "Invalid credentials"
-                    },
-                    user_email=request.email
-                )
+                
             
             
             # Return unauthorized with attempts remaining
             # Return unauthorized with attempts remaining
             return JSONResponse(status_code=401, content={
             return JSONResponse(status_code=401, content={
@@ -383,30 +235,13 @@ async def login_user(request: LoginRequest, http_request: Request):
     except redis.RedisError as e:
     except redis.RedisError as e:
         error_msg = f"Redis error during login for {request.email}: {e}"
         error_msg = f"Redis error during login for {request.email}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_system_event(
-            "Redis error during login process",
-            LogLevel.ERROR,
-            {
-                "email": request.email,
-                "error": str(e),
-                "error_type": "RedisError"
-            }
-        )
+        
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         
         
     except Exception as e:
     except Exception as e:
         error_msg = f"Unexpected error during login for {request.email}: {e}"
         error_msg = f"Unexpected error during login for {request.email}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_security_event(
-            "Unexpected error during login",
-            LogLevel.ERROR,
-            {
-                "email": request.email,
-                "error": str(e),
-                "error_type": type(e).__name__
-            },
-            user_email=request.email
-        )
+        
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
         return JSONResponse(status_code=500, content={"message": "Error interno del servidor"})
 
 
 @user_router.delete("/delete")
 @user_router.delete("/delete")
@@ -463,4 +298,26 @@ async def verify_user(q: str = Query(..., description="q parameter")):
     return FileResponse(
     return FileResponse(
         "public/verify.html",
         "public/verify.html",
         media_type="text/html",
         media_type="text/html",
-    )
+    )
+
+recovery_pin_router = APIRouter()
+
+@recovery_pin_router.get("/")
+async def pin_forgot_get():
+    """Render the PIN forgot page"""
+    return FileResponse(
+        "public/pin_forgot.html",
+        media_type="text/html",
+    )
+
+@recovery_pin_router.post("/")
+async def pin_forgot_post(request: PinRecoveryRequest, http_request: Request):
+    """Handle the PIN forgot form submission"""
+
+    user = user_data_service.get_by_email(request.email)
+    if not user:
+        return JSONResponse(status_code=404, content={"message": UserResponse.USER_NOT_FOUND.format(user_id=request.email)})
+
+    recovery_key = recovery_service.generate_recovery_key(user.id)
+    # Send recovery_key to user's email
+    return JSONResponse(status_code=200, content={"message": SuccessResponse.RECOVERY_EMAIL_SENT})

+ 11 - 121
services/email_service.py

@@ -44,7 +44,6 @@ import smtplib
 from email.message import EmailMessage
 from email.message import EmailMessage
 from logging import getLogger
 from logging import getLogger
 from typing import Optional, Dict, Any
 from typing import Optional, Dict, Any
-from services.logging_service import structured_logger, LogLevel
 from queue import Queue, Empty
 from queue import Queue, Empty
 from threading import Thread, Lock, current_thread
 from threading import Thread, Lock, current_thread
 import time
 import time
@@ -66,11 +65,7 @@ class EmailSender:
     def connect(self):
     def connect(self):
         """Establish SMTP connection - kept for compatibility but not used for persistent connections"""
         """Establish SMTP connection - kept for compatibility but not used for persistent connections"""
         logger.info("Testing SMTP connection...")
         logger.info("Testing SMTP connection...")
-        structured_logger.log_email_event(
-            "Testing SMTP connection",
-            LogLevel.INFO,
-            {"email_server": "smtp.gmail.com", "port": 465, "sender_email": self.email}
-        )
+        
         
         
         try:
         try:
             # Test connection
             # Test connection
@@ -80,47 +75,23 @@ class EmailSender:
             test_smtp.quit()
             test_smtp.quit()
             
             
             logger.info("SMTP connection test successful.")
             logger.info("SMTP connection test successful.")
-            structured_logger.log_email_event(
-                "SMTP connection test successful",
-                LogLevel.INFO,
-                {"sender_email": self.email}
-            )
+            
             
             
         except smtplib.SMTPAuthenticationError as e:
         except smtplib.SMTPAuthenticationError as e:
             error_msg = f"SMTP authentication failed: {e}"
             error_msg = f"SMTP authentication failed: {e}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_email_event(
-                "SMTP authentication failed",
-                LogLevel.ERROR,
-                {
-                    "sender_email": self.email,
-                    "error": str(e),
-                    "error_type": "SMTPAuthenticationError"
-                }
-            )
+            
             raise
             raise
         except Exception as e:
         except Exception as e:
             error_msg = f"Failed to establish SMTP connection: {e}"
             error_msg = f"Failed to establish SMTP connection: {e}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_email_event(
-                "SMTP connection failed",
-                LogLevel.ERROR,
-                {
-                    "sender_email": self.email,
-                    "error": str(e),
-                    "error_type": type(e).__name__
-                }
-            )
+            
             raise
             raise
 
 
     def close(self):
     def close(self):
         """Close SMTP connection and stop queue worker"""
         """Close SMTP connection and stop queue worker"""
         logger.info("Closing email service.")
         logger.info("Closing email service.")
-        structured_logger.log_email_event(
-            "Closing email service",
-            LogLevel.INFO,
-            {"sender_email": self.email}
-        )
+        
         
         
         # Stop the queue worker
         # Stop the queue worker
         self._stop_queue_worker()
         self._stop_queue_worker()
@@ -231,18 +202,7 @@ class EmailSender:
     def _send_email_immediately(self, subject: str, body: str, to: list[str], kwargs: Dict[str, Any]) -> bool:
     def _send_email_immediately(self, subject: str, body: str, to: list[str], kwargs: Dict[str, Any]) -> bool:
         """Send email immediately using a fresh SMTP connection"""
         """Send email immediately using a fresh SMTP connection"""
         logger.debug(f"Sending queued email to: {to} with subject: '{subject}'")
         logger.debug(f"Sending queued email to: {to} with subject: '{subject}'")
-        structured_logger.log_email_event(
-            f"Sending queued email with subject: '{subject}'",
-            LogLevel.INFO,
-            {
-                "subject": subject,
-                "recipients": to,
-                "sender_email": self.email,
-                "body_length": len(body),
-                "kwargs_count": len(kwargs),
-                "queued": True
-            }
-        )
+        
         
         
         smtp = None
         smtp = None
         try:
         try:
@@ -259,34 +219,13 @@ class EmailSender:
             smtp.send_message(msg)
             smtp.send_message(msg)
             
             
             logger.info(f"Queued email sent to {to} with subject '{subject}'.")
             logger.info(f"Queued email sent to {to} with subject '{subject}'.")
-            structured_logger.log_email_event(
-                f"Queued email sent successfully",
-                LogLevel.INFO,
-                {
-                    "subject": subject,
-                    "recipients": to,
-                    "sender_email": self.email,
-                    "recipients_count": len(to),
-                    "queued": True
-                }
-            )
+            
             return True
             return True
             
             
         except Exception as e:
         except Exception as e:
             error_msg = f"Failed to send queued email to {to}: {e}"
             error_msg = f"Failed to send queued email to {to}: {e}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_email_event(
-                "Queued email send failed",
-                LogLevel.ERROR,
-                {
-                    "subject": subject,
-                    "recipients": to,
-                    "sender_email": self.email,
-                    "error": str(e),
-                    "error_type": type(e).__name__,
-                    "queued": True
-                }
-            )
+            
             raise
             raise
         finally:
         finally:
             # Always close the connection
             # Always close the connection
@@ -299,18 +238,7 @@ class EmailSender:
     def send_email(self, subject: str, body: str, to: list[str], **kwargs):
     def send_email(self, subject: str, body: str, to: list[str], **kwargs):
         """Add email to queue for asynchronous sending with 10-second delays"""
         """Add email to queue for asynchronous sending with 10-second delays"""
         logger.debug(f"Queuing email to: {to} with subject: '{subject}'")
         logger.debug(f"Queuing email to: {to} with subject: '{subject}'")
-        structured_logger.log_email_event(
-            f"Queuing email with subject: '{subject}'",
-            LogLevel.INFO,
-            {
-                "subject": subject,
-                "recipients": to,
-                "sender_email": self.email,
-                "body_length": len(body),
-                "kwargs_count": len(kwargs),
-                "queue_size": self._email_queue.qsize() + 1
-            }
-        )
+        
         
         
         # Add email to queue
         # Add email to queue
         email_data = {
         email_data = {
@@ -326,18 +254,7 @@ class EmailSender:
     def send_email_sync(self, subject: str, body: str, to: list[str], **kwargs):
     def send_email_sync(self, subject: str, body: str, to: list[str], **kwargs):
         """Send email immediately (synchronous) using fresh connection"""
         """Send email immediately (synchronous) using fresh connection"""
         logger.debug(f"Preparing to send email immediately to: {to} with subject: '{subject}'")
         logger.debug(f"Preparing to send email immediately to: {to} with subject: '{subject}'")
-        structured_logger.log_email_event(
-            f"Preparing to send email immediately with subject: '{subject}'",
-            LogLevel.INFO,
-            {
-                "subject": subject,
-                "recipients": to,
-                "sender_email": self.email,
-                "body_length": len(body),
-                "kwargs_count": len(kwargs),
-                "sync": True
-            }
-        )
+       
         
         
         smtp = None
         smtp = None
         try:
         try:
@@ -354,33 +271,10 @@ class EmailSender:
             smtp.send_message(msg)
             smtp.send_message(msg)
             
             
             logger.info(f"Email sent immediately to {to} with subject '{subject}'.")
             logger.info(f"Email sent immediately to {to} with subject '{subject}'.")
-            structured_logger.log_email_event(
-                f"Email sent immediately and successfully",
-                LogLevel.INFO,
-                {
-                    "subject": subject,
-                    "recipients": to,
-                    "sender_email": self.email,
-                    "recipients_count": len(to),
-                    "sync": True
-                }
-            )
             
             
         except Exception as e:
         except Exception as e:
             error_msg = f"Failed to send email immediately to {to}: {e}"
             error_msg = f"Failed to send email immediately to {to}: {e}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_email_event(
-                "Immediate email send failed",
-                LogLevel.ERROR,
-                {
-                    "subject": subject,
-                    "recipients": to,
-                    "sender_email": self.email,
-                    "error": str(e),
-                    "error_type": type(e).__name__,
-                    "sync": True
-                }
-            )
             raise
             raise
         finally:
         finally:
             # Always close the connection
             # Always close the connection
@@ -408,11 +302,7 @@ class EmailSender:
                 except:
                 except:
                     break
                     break
             logger.info("Email queue cleared")
             logger.info("Email queue cleared")
-            structured_logger.log_email_event(
-                "Email queue cleared",
-                LogLevel.INFO,
-                {"sender_email": self.email}
-            )
+            
 
 
 
 
 # Global email sender instance
 # Global email sender instance

+ 0 - 213
services/logging_service.py

@@ -1,213 +0,0 @@
-import csv
-import os
-import json
-from typing import List, Dict, Any, Optional
-from datetime import datetime
-from logging import getLogger
-from enum import Enum
-from models.sales import OrderWeb, ItemWeb
-
-logger = getLogger(__name__)
-
-class LogLevel(Enum):
-    """Log levels for structured logging"""
-    DEBUG = "DEBUG"
-    INFO = "INFO"
-    WARNING = "WARNING"
-    ERROR = "ERROR"
-    CRITICAL = "CRITICAL"
-
-class LogCategory(Enum):
-    """Categories for different types of logs"""
-    ORDER = "ORDER"
-    USER = "USER"
-    PAYMENT = "PAYMENT"
-    SECURITY = "SECURITY"
-    API = "API"
-    DATABASE = "DATABASE"
-    EMAIL = "EMAIL"
-    PRINT = "PRINT"
-    CHAT = "CHAT"
-    SYSTEM = "SYSTEM"
-
-class StructuredLogger:
-    """Enhanced logging service with structured logging capabilities"""
-    
-    def __init__(self):
-        self.logger = getLogger(__name__)
-        self.logs_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs')
-        self._ensure_logs_directory()
-    
-    def _ensure_logs_directory(self):
-        """Ensure logs directory exists"""
-        if not os.path.exists(self.logs_dir):
-            os.makedirs(self.logs_dir)
-            self.logger.info(f"Created logs directory: {self.logs_dir}")
-    
-    def _write_structured_log(self, category: LogCategory, level: LogLevel, 
-                            message: str, data: Optional[Dict[str, Any]] = None,
-                            user_id: Optional[int] = None, user_email: Optional[str] = None):
-        """Write structured log entry"""
-        log_entry = {
-            "timestamp": datetime.now().isoformat(),
-            "category": category.value,
-            "level": level.value,
-            "message": message,
-            "user_id": user_id,
-            "user_email": user_email,
-            "data": data or {}
-        }
-        
-        # Write to category-specific log file
-        log_file = os.path.join(self.logs_dir, f"{category.value.lower()}.log")
-        try:
-            with open(log_file, 'a', encoding='utf-8') as f:
-                f.write(json.dumps(log_entry, ensure_ascii=False) + '\n')
-        except Exception as e:
-            self.logger.error(f"Failed to write structured log: {e}")
-    
-    def log_order_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                       order_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                       user_email: Optional[str] = None):
-        """Log order-related events"""
-        self._write_structured_log(LogCategory.ORDER, level, message, order_data, user_id, user_email)
-        
-        # Also log to main logger
-        getattr(self.logger, level.value.lower())(
-            f"[ORDER] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_user_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                      user_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                      user_email: Optional[str] = None):
-        """Log user-related events"""
-        self._write_structured_log(LogCategory.USER, level, message, user_data, user_id, user_email)
-        
-        # Also log to main logger
-        getattr(self.logger, level.value.lower())(
-            f"[USER] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_security_event(self, message: str, level: LogLevel = LogLevel.WARNING,
-                          security_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                          user_email: Optional[str] = None):
-        """Log security-related events"""
-        self._write_structured_log(LogCategory.SECURITY, level, message, security_data, user_id, user_email)
-        
-        # Security events should always be logged to main logger
-        getattr(self.logger, level.value.lower())(
-            f"[SECURITY] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_api_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                     api_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                     user_email: Optional[str] = None):
-        """Log API-related events"""
-        self._write_structured_log(LogCategory.API, level, message, api_data, user_id, user_email)
-        
-        getattr(self.logger, level.value.lower())(
-            f"[API] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_database_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                          db_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                          user_email: Optional[str] = None):
-        """Log database-related events"""
-        self._write_structured_log(LogCategory.DATABASE, level, message, db_data, user_id, user_email)
-        
-        getattr(self.logger, level.value.lower())(
-            f"[DATABASE] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_email_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                       email_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                       user_email: Optional[str] = None):
-        """Log email-related events"""
-        self._write_structured_log(LogCategory.EMAIL, level, message, email_data, user_id, user_email)
-        
-        getattr(self.logger, level.value.lower())(
-            f"[EMAIL] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_print_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                       print_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                       user_email: Optional[str] = None):
-        """Log printer-related events"""
-        self._write_structured_log(LogCategory.PRINT, level, message, print_data, user_id, user_email)
-        
-        getattr(self.logger, level.value.lower())(
-            f"[PRINT] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_chat_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                      chat_data: Optional[Dict] = None, user_id: Optional[int] = None,
-                      user_email: Optional[str] = None):
-        """Log chat/LLM-related events"""
-        self._write_structured_log(LogCategory.CHAT, level, message, chat_data, user_id, user_email)
-        
-        getattr(self.logger, level.value.lower())(
-            f"[CHAT] {message} - User: {user_email or user_id or 'N/A'}"
-        )
-    
-    def log_system_event(self, message: str, level: LogLevel = LogLevel.INFO,
-                        system_data: Optional[Dict] = None):
-        """Log system-related events"""
-        self._write_structured_log(LogCategory.SYSTEM, level, message, system_data)
-        
-        getattr(self.logger, level.value.lower())(f"[SYSTEM] {message}")
-
-# Global instance
-structured_logger = StructuredLogger()
-
-# Legacy functions for backward compatibility
-def log_order(username, table, order_date, items: List[str]):
-    """Log order information to CSV file (legacy function)"""
-    try:
-        structured_logger.log_order_event(
-            f"Order placed for table {table}",
-            LogLevel.INFO,
-            {
-                "username": username,
-                "table": table,
-                "order_date": order_date,
-                "items": items,
-                "item_count": len(items) if isinstance(items, list) else 1
-            },
-            user_email=username
-        )
-        
-        # Still maintain CSV for backward compatibility
-        csv_file = os.path.join(structured_logger.logs_dir, 'orders.csv')
-        if not os.path.exists(csv_file):
-            with open(csv_file, 'w', newline='', encoding='utf-8') as f:
-                writer = csv.writer(f)
-                writer.writerow(['userName', 'table', 'orderDate', 'items'])
-        
-        with open(csv_file, 'a', newline='', encoding='utf-8') as f:
-            writer = csv.writer(f)
-            writer.writerow([username, table, order_date, items])
-            
-    except Exception as e:
-        logger.error(f"Failed to log order: {e}")
-
-def log_llm_response(user: str, response: str):
-    """Log LLM response to file (legacy function)"""
-    try:
-        structured_logger.log_chat_event(
-            f"LLM response generated for user {user}",
-            LogLevel.INFO,
-            {
-                "response_length": len(response),
-                "response_preview": response[:100] + "..." if len(response) > 100 else response
-            },
-            user_email=user
-        )
-        
-        # Still maintain text file for backward compatibility
-        llm_log_file = os.path.join(structured_logger.logs_dir, 'llm_responses.txt')
-        file_mode = "a" if os.path.exists(llm_log_file) else "w"
-        with open(llm_log_file, file_mode, encoding='utf-8') as f:
-            f.write(f"{datetime.now().isoformat()} - {user}: {response}\n")
-            
-    except Exception as e:
-        logger.error(f"Failed to log LLM response: {e}")

+ 13 - 124
services/print_service.py

@@ -4,7 +4,6 @@ from config.settings import DEVELOPMENT
 from models.sales import OrderWeb, ItemWeb
 from models.sales import OrderWeb, ItemWeb
 from services.data_service import DataServiceFactory
 from services.data_service import DataServiceFactory
 from models.items import Order
 from models.items import Order
-from services.logging_service import structured_logger, LogLevel
 
 
 logger = getLogger(__name__)
 logger = getLogger(__name__)
 user_data_service = DataServiceFactory.get_user_service()
 user_data_service = DataServiceFactory.get_user_service()
@@ -22,11 +21,7 @@ def print_order(order: Order):
         if not order.items or not order.table:
         if not order.items or not order.table:
             error_msg = "Order must have items and a table number"
             error_msg = "Order must have items and a table number"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_print_event(
-                f"Print order validation failed: {error_msg}",
-                LogLevel.ERROR,
-                {"table": order.table, "items_count": len(order.items) if order.items else 0}
-            )
+            
             raise ValueError(error_msg)
             raise ValueError(error_msg)
         
         
         # Prepare the order data for printing
         # Prepare the order data for printing
@@ -39,16 +34,7 @@ def print_order(order: Order):
         }
         }
         
         
         logger.info(f"Order data prepared for printing: table={order.table}, items={len(order.items)}, total={order.totalAmount}")
         logger.info(f"Order data prepared for printing: table={order.table}, items={len(order.items)}, total={order.totalAmount}")
-        structured_logger.log_print_event(
-            f"Sending order to printer for table {order.table}",
-            LogLevel.INFO,
-            {
-                "table": order.table,
-                "items_count": len(order.items),
-                "total_amount": order.totalAmount,
-                "customer_name": order.customerName
-            }
-        )
+        
 
 
         # Send the order data to the printer service
         # Send the order data to the printer service
         response = requests.post(
         response = requests.post(
@@ -61,55 +47,22 @@ def print_order(order: Order):
         if response.status_code != 200:
         if response.status_code != 200:
             error_msg = f"Failed to print order: HTTP {response.status_code} - {response.text}"
             error_msg = f"Failed to print order: HTTP {response.status_code} - {response.text}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_print_event(
-                f"Print order failed for table {order.table}",
-                LogLevel.ERROR,
-                {
-                    "table": order.table,
-                    "status_code": response.status_code,
-                    "error_message": response.text,
-                    "printer_url": printer_url
-                }
-            )
+            
             raise Exception(error_msg)
             raise Exception(error_msg)
 
 
         logger.info(f"Order printed successfully for table {order.table}")
         logger.info(f"Order printed successfully for table {order.table}")
-        structured_logger.log_print_event(
-            f"Order printed successfully for table {order.table}",
-            LogLevel.INFO,
-            {
-                "table": order.table,
-                "response": response.json() if response.headers.get('content-type', '').startswith('application/json') else str(response.text)
-            }
-        )
         
         
         return response.json()  # Return the response from the printer service
         return response.json()  # Return the response from the printer service
         
         
     except requests.RequestException as e:
     except requests.RequestException as e:
         error_msg = f"Network error while printing order for table {order.table}: {e}"
         error_msg = f"Network error while printing order for table {order.table}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            f"Network error during print for table {order.table}",
-            LogLevel.ERROR,
-            {
-                "table": order.table,
-                "error": str(e),
-                "printer_url": printer_url
-            }
-        )
+        
         raise Exception(error_msg)
         raise Exception(error_msg)
     except Exception as e:
     except Exception as e:
         error_msg = f"Unexpected error while printing order for table {order.table}: {e}"
         error_msg = f"Unexpected error while printing order for table {order.table}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            f"Unexpected print error for table {order.table}",
-            LogLevel.ERROR,
-            {
-                "table": order.table,
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+        
         raise
         raise
 
 
 def print_ticket(number_table: int):
 def print_ticket(number_table: int):
@@ -117,11 +70,7 @@ def print_ticket(number_table: int):
     logger.info(f"Attempting to print ticket for table {number_table}")
     logger.info(f"Attempting to print ticket for table {number_table}")
     
     
     try:
     try:
-        structured_logger.log_print_event(
-            f"Sending ticket print request for table {number_table}",
-            LogLevel.INFO,
-            {"table": number_table}
-        )
+
         
         
         response = requests.get(
         response = requests.get(
             f"{printer_url}/ticket/{number_table}", 
             f"{printer_url}/ticket/{number_table}", 
@@ -132,55 +81,22 @@ def print_ticket(number_table: int):
         if response.status_code != 200:
         if response.status_code != 200:
             error_msg = f"Failed to print ticket for table {number_table}: HTTP {response.status_code} - {response.text}"
             error_msg = f"Failed to print ticket for table {number_table}: HTTP {response.status_code} - {response.text}"
             logger.error(error_msg)
             logger.error(error_msg)
-            structured_logger.log_print_event(
-                f"Ticket print failed for table {number_table}",
-                LogLevel.ERROR,
-                {
-                    "table": number_table,
-                    "status_code": response.status_code,
-                    "error_message": response.text,
-                    "printer_url": printer_url
-                }
-            )
+            
             raise Exception(error_msg)
             raise Exception(error_msg)
 
 
         logger.info(f"Ticket printed successfully for table {number_table}")
         logger.info(f"Ticket printed successfully for table {number_table}")
-        structured_logger.log_print_event(
-            f"Ticket printed successfully for table {number_table}",
-            LogLevel.INFO,
-            {
-                "table": number_table,
-                "response": response.json() if response.headers.get('content-type', '').startswith('application/json') else str(response.text)
-            }
-        )
+        
         
         
         return response.json()  # Return the response from the printer service
         return response.json()  # Return the response from the printer service
         
         
     except requests.RequestException as e:
     except requests.RequestException as e:
         error_msg = f"Network error while printing ticket for table {number_table}: {e}"
         error_msg = f"Network error while printing ticket for table {number_table}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            f"Network error during ticket print for table {number_table}",
-            LogLevel.ERROR,
-            {
-                "table": number_table,
-                "error": str(e),
-                "printer_url": printer_url
-            }
-        )
         raise Exception(error_msg)
         raise Exception(error_msg)
     except Exception as e:
     except Exception as e:
         error_msg = f"Unexpected error while printing ticket for table {number_table}: {e}"
         error_msg = f"Unexpected error while printing ticket for table {number_table}: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            f"Unexpected ticket print error for table {number_table}",
-            LogLevel.ERROR,
-            {
-                "table": number_table,
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+        
         raise
         raise
 
 
 def get_status():
 def get_status():
@@ -188,11 +104,7 @@ def get_status():
     logger.info("Checking printer service status")
     logger.info("Checking printer service status")
     
     
     try:
     try:
-        structured_logger.log_print_event(
-            "Checking printer service status",
-            LogLevel.INFO,
-            {"printer_url": printer_url}
-        )
+        
         
         
         response = requests.get(
         response = requests.get(
             f"{printer_url}/status", 
             f"{printer_url}/status", 
@@ -204,40 +116,17 @@ def get_status():
         status = data.get("status", False)
         status = data.get("status", False)
         
         
         logger.info(f"Printer service status: {'online' if status else 'offline'}")
         logger.info(f"Printer service status: {'online' if status else 'offline'}")
-        structured_logger.log_print_event(
-            f"Printer service status check completed: {'online' if status else 'offline'}",
-            LogLevel.INFO if status else LogLevel.WARNING,
-            {
-                "status": status,
-                "response_data": data,
-                "status_code": response.status_code
-            }
-        )
+        
         
         
         return status
         return status
         
         
     except requests.RequestException as e:
     except requests.RequestException as e:
         error_msg = f"Error connecting to printer service: {e}"
         error_msg = f"Error connecting to printer service: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            "Failed to connect to printer service",
-            LogLevel.ERROR,
-            {
-                "error": str(e),
-                "error_type": type(e).__name__,
-                "printer_url": printer_url
-            }
-        )
+        
         raise Exception(error_msg)
         raise Exception(error_msg)
     except Exception as e:
     except Exception as e:
         error_msg = f"Unexpected error checking printer status: {e}"
         error_msg = f"Unexpected error checking printer status: {e}"
         logger.error(error_msg)
         logger.error(error_msg)
-        structured_logger.log_print_event(
-            "Unexpected error during printer status check",
-            LogLevel.ERROR,
-            {
-                "error": str(e),
-                "error_type": type(e).__name__
-            }
-        )
+        
         raise Exception(error_msg)
         raise Exception(error_msg)

+ 23 - 0
services/recovery_service.py

@@ -0,0 +1,23 @@
+import json
+import redis
+from pydantic import BaseModel
+import random
+class RedisRecoveryData(BaseModel):
+    user_id: int
+
+RECOVERY_REDIS_KEY = "pin_recovery:{pin_code}"
+
+def generate_recovery_key(user_id) -> str:
+    pin_code = str(random.randint(100000, 999999))
+    redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
+    redis_client.set(RECOVERY_REDIS_KEY.format(pin_code=pin_code), json.dumps({"user_id": user_id}))
+    redis_client.expire(RECOVERY_REDIS_KEY.format(pin_code=pin_code), 1800)  # Expire in 30 minutes
+    return RECOVERY_REDIS_KEY.format(pin_code=pin_code)
+
+def get_recovery_data(pin_code: str) -> RedisRecoveryData:
+    redis_client = redis.Redis(host='localhost', port=6379, db=0)
+    data = redis_client.get(RECOVERY_REDIS_KEY.format(pin_code=pin_code))
+    json_data = json.loads(str(data)) if data else None
+    if json_data:
+        return RedisRecoveryData(**json_data)
+    return RedisRecoveryData(user_id=-1)