Manual Técnico

Documentación Técnica Avanzada

Especificaciones técnicas, arquitectura del sistema y soluciones avanzadas para administradores y técnicos

20+
Especificaciones
100%
API Documentada
24/7
Soporte Técnico

1. ARQUITECTURA DEL SISTEMA

Diagramas Detallados

Documentación técnica especializada para desarrolladores que incluye diagramas detallados de la estructura en capas del Sistema Antonella.

Arquitectura Moderna

El sistema Antonella utiliza una arquitectura moderna basada en Flutter y Firebase, diseñada para garantizar escalabilidad, mantenibilidad y alta disponibilidad.

Estructura en Capas

Capa de Presentación (Flutter)

UI Components (Widgets)
State Management (Providers)
Navigation (Routes)
Responsive Design

Capa de Servicios

DatabaseService (Firestore)
WhatsAppService (API Integration)
AuthenticationService (Firebase Auth)
StorageService (Firebase Storage)

Capa de Datos (Firebase)

Firestore Database
Firebase Authentication
Firebase Storage
Firebase Hosting

Componentes Principales

Aplicación Flutter

Desarrollada con Flutter 3.x, proporciona una experiencia de usuario nativa en múltiples plataformas con un solo código base.

Flutter 3.x Dart 3.x Provider

Firebase Backend

Backend as a Service que proporciona autenticación, base de datos en tiempo real, almacenamiento y hosting.

Firestore Firebase Auth Firebase Storage

WhatsApp Integration

Integración con WhatsApp Business API para notificaciones y comunicación con clientes.

WhatsApp API HTTP Requests JSON

Arquitectura Escalable

Esta arquitectura permite escalar horizontalmente y agregar nuevas funcionalidades sin afectar el sistema existente.

Redux

Base de Datos

PostgreSQL como base de datos principal con Redis para cache y sesiones, garantizando alto rendimiento.

PostgreSQL Redis Sequelize

2. STACK TECNOLÓGICO

Flutter & Firebase

Stack tecnológico completo con Flutter, Firebase, dependencias específicas con versiones y configuraciones optimizadas.

Stack Moderno y Escalable

El sistema Antonella utiliza las últimas tecnologías para garantizar rendimiento, seguridad y facilidad de mantenimiento.

Frontend - Flutter

Framework Principal

Flutter: 3.16.0 o superior
Dart: 3.2.0 o superior
SDK: Android 21+, iOS 12+
Plataformas: Android, iOS, Web

Dependencias Principales

provider: ^6.1.1 (State Management)
firebase_core: ^2.24.2 (Firebase Core)
cloud_firestore: ^4.13.6 (Database)
firebase_auth: ^4.15.3 (Authentication)
firebase_storage: ^11.5.6 (File Storage)
http: ^1.1.0 (HTTP Requests)

Backend - Firebase

Firestore Database

Base de datos NoSQL en tiempo real con reglas de seguridad avanzadas y sincronización automática.

NoSQL Real-time Security Rules

Firebase Authentication

Sistema de autenticación robusto con múltiples proveedores y gestión de usuarios.

Email/Password Google Sign-In Phone Auth

Firebase Storage

Almacenamiento de archivos seguro con reglas de acceso y optimización automática.

File Storage Security Rules CDN

Integraciones Externas

WhatsApp Business API

Integración completa para envío de notificaciones y comunicación con clientes

Analytics

Firebase Analytics para seguimiento de métricas y comportamiento de usuarios

Crashlytics

Monitoreo de errores y crashes en tiempo real

Cloud Messaging

Notificaciones push para Android e iOS

Versiones Compatibles

Todas las dependencias están probadas y son compatibles entre sí. Se recomienda mantener las versiones especificadas para evitar conflictos.

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+
  • Dispositivos Móviles

    3. ESTRUCTURA DEL PROYECTO

    Organización Completa

    Organización completa de directorios y archivos del proyecto Flutter con Firebase, siguiendo las mejores prácticas de desarrollo.

    Estructura Modular

    El proyecto está organizado en módulos independientes que facilitan el mantenimiento y la escalabilidad del código.

    Estructura de Directorios

    Estructura del Proyecto
    antonella_app/
    ├── android/                    # Configuración Android
    │   ├── app/
    │   │   ├── src/
    │   │   │   ├── main/
    │   │   │   │   ├── kotlin/
    │   │   │   │   ├── res/
    │   │   │   │   └── AndroidManifest.xml
    │   │   │   └── debug/
    │   │   ├── build.gradle
    │   │   └── proguard-rules.pro
    │   ├── gradle/
    │   ├── build.gradle
    │   └── settings.gradle
    ├── ios/                       # Configuración iOS
    │   ├── Runner/
    │   │   ├── Assets.xcassets/
    │   │   ├── Base.lproj/
    │   │   ├── Info.plist
    │   │   └── Runner.entitlements
    │   ├── Runner.xcodeproj/
    │   └── Runner.xcworkspace/
    ├── lib/                       # Código fuente Dart
    │   ├── main.dart             # Punto de entrada
    │   ├── app.dart              # Configuración de la app
    │   ├── core/                 # Funcionalidades core
    │   │   ├── constants/
    │   │   │   ├── app_colors.dart
    │   │   │   ├── app_strings.dart
    │   │   │   └── app_constants.dart
    │   │   ├── utils/
    │   │   │   ├── validators.dart
    │   │   │   ├── helpers.dart
    │   │   │   └── extensions.dart
    │   │   └── services/
    │   │       ├── database_service.dart
    │   │       ├── auth_service.dart
    │   │       ├── storage_service.dart
    │   │       └── whatsapp_service.dart
    │   ├── models/               # Modelos de datos
    │   │   ├── user.dart
    │   │   ├── product.dart
    │   │   ├── order.dart
    │   │   ├── cart.dart
    │   │   └── chat_message.dart
    │   ├── providers/            # State management
    │   │   ├── auth_provider.dart
    │   │   ├── cart_provider.dart
    │   │   ├── product_provider.dart
    │   │   └── chat_provider.dart
    │   ├── screens/              # Pantallas de la app
    │   │   ├── auth/
    │   │   │   ├── login_screen.dart
    │   │   │   └── register_screen.dart
    │   │   ├── home/
    │   │   │   ├── home_screen.dart
    │   │   │   └── dashboard_screen.dart
    │   │   ├── products/
    │   │   │   ├── product_list_screen.dart
    │   │   │   ├── product_detail_screen.dart
    │   │   │   └── add_product_screen.dart
    │   │   ├── cart/
    │   │   │   ├── cart_screen.dart
    │   │   │   └── checkout_screen.dart
    │   │   └── chat/
    │   │       ├── chat_screen.dart
    │   │       └── chat_list_screen.dart
    │   ├── widgets/              # Widgets reutilizables
    │   │   ├── common/
    │   │   │   ├── custom_button.dart
    │   │   │   ├── custom_text_field.dart
    │   │   │   └── loading_widget.dart
    │   │   ├── product/
    │   │   │   ├── product_card.dart
    │   │   │   └── product_grid.dart
    │   │   └── chat/
    │   │       ├── message_bubble.dart
    │   │       └── chat_input.dart
    │   └── routes/               # Configuración de rutas
    │       ├── app_routes.dart
    │       └── route_generator.dart
    ├── assets/                   # Recursos estáticos
    │   ├── images/
    │   │   ├── logo.png
    │   │   ├── products/
    │   │   └── icons/
    │   ├── fonts/
    │   │   └── custom_fonts.ttf
    │   └── data/
    │       └── initial_data.json
    ├── test/                     # Tests
    │   ├── unit/
    │   ├── widget/
    │   └── integration/
    ├── pubspec.yaml              # Dependencias
    ├── pubspec.lock              # Versiones bloqueadas
    ├── analysis_options.yaml     # Reglas de análisis
    ├── .gitignore               # Archivos ignorados
    ├── README.md                # Documentación
    └── firebase_options.dart    # Configuración Firebase

    Archivos de Configuración

    pubspec.yaml

    Flutter SDK: >=3.16.0 <4.0.0
    Dart SDK: >=3.2.0 <4.0.0
    Dependencias: 25+ paquetes
    Dev Dependencies: 10+ paquetes

    Firebase

    google-services.json: Android config
    GoogleService-Info.plist: iOS config
    firebase_options.dart: Flutter config
    firestore.rules: Security rules

    Patrones de Diseño

    Clean Architecture

    Separación clara entre presentación, lógica de negocio y datos

    Provider Pattern

    State management con Provider para gestión de estado

    Repository Pattern

    Abstracción de acceso a datos con servicios

    Dependency Injection

    Inyección de dependencias para testing y mantenibilidad

    Organización Recomendada

    Mantén esta estructura de directorios para facilitar la navegación y el mantenimiento del código. Cada carpeta tiene una responsabilidad específica.

    Obtener lista de productos

    Parámetros: page, limit, category
    POST /api/products

    Crear nuevo producto

    Body: name, price, category, stock
    PUT /api/products/:id

    Actualizar producto

    Body: name, price, category, stock
    DELETE /api/products/:id

    Eliminar producto

    Headers: Authorization required

    Códigos de Respuesta

    200 OK - Operación exitosa
    201 Created - Recurso creado
    400 Bad Request - Datos inválidos
    401 Unauthorized - No autorizado
    404 Not Found - Recurso no encontrado
    500 Internal Server Error - Error del servidor

    4. MODELOS DE DATOS

    Estructura Completa

    Estructura completa de Firestore con reglas de seguridad, modelos de datos optimizados y relaciones entre colecciones.

    Firestore NoSQL

    Base de datos NoSQL en tiempo real con reglas de seguridad avanzadas y sincronización automática entre dispositivos.

    Colecciones Principales

    Colección: users

    uid String (Document ID)
    name String (Required)
    email String (Required, Unique)
    phone String (Optional)
    role String (admin/user)
    createdAt Timestamp
    lastLogin Timestamp

    Colección: products

    id String (Document ID)
    name String (Required)
    description String
    price Number (Required)
    stock Number (Default: 0)
    category String (Required)
    imageUrl String (Firebase Storage)
    isActive Boolean (Default: true)
    createdAt Timestamp

    Colección: orders

    id String (Document ID)
    userId String (Reference)
    items Array (Product IDs)
    total Number (Required)
    status String (pending/completed/cancelled)
    paymentMethod String (cash/card/transfer)
    createdAt Timestamp

    Reglas de Seguridad Firestore

    firestore.rules
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // Usuarios pueden leer/editar solo sus propios datos
        match /users/{userId} {
          allow read, write: if request.auth != null && request.auth.uid == userId;
        }
        
        // Productos: lectura pública, escritura solo para admins
        match /products/{productId} {
          allow read: if true;
          allow write: if request.auth != null && 
            get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
        }
        
        // Órdenes: usuarios pueden crear y leer sus propias órdenes
        match /orders/{orderId} {
          allow read, create: if request.auth != null && 
            request.auth.uid == resource.data.userId;
          allow update: if request.auth != null && 
            get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
        }
        
        // Chat: usuarios pueden leer/escribir mensajes
        match /chat/{messageId} {
          allow read, write: if request.auth != null;
        }
      }
    }

    Modelos Dart

    lib/models/user.dart
    import 'package:cloud_firestore/cloud_firestore.dart';
    
    class User {
      final String uid;
      final String name;
      final String email;
      final String? phone;
      final String role;
      final DateTime createdAt;
      final DateTime? lastLogin;
    
      User({
        required this.uid,
        required this.name,
        required this.email,
        this.phone,
        required this.role,
        required this.createdAt,
        this.lastLogin,
      });
    
      factory User.fromFirestore(DocumentSnapshot doc) {
        Map data = doc.data() as Map;
        return User(
          uid: doc.id,
          name: data['name'] ?? '',
          email: data['email'] ?? '',
          phone: data['phone'],
          role: data['role'] ?? 'user',
          createdAt: (data['createdAt'] as Timestamp).toDate(),
          lastLogin: data['lastLogin'] != null 
            ? (data['lastLogin'] as Timestamp).toDate() 
            : null,
        );
      }
    
      Map toMap() {
        return {
          'name': name,
          'email': email,
          'phone': phone,
          'role': role,
          'createdAt': Timestamp.fromDate(createdAt),
          'lastLogin': lastLogin != null ? Timestamp.fromDate(lastLogin!) : null,
        };
      }
    }

    Optimización de Datos

    Utiliza índices compuestos para consultas frecuentes y mantén las reglas de seguridad actualizadas para proteger los datos.

  • Usar EXPLAIN para analizar consultas
  • 5. SERVICIOS Y PROVIDERS

    Código Completo

    Código completo de DatabaseService, WhatsAppService, CartProvider, ChatProvider y otros servicios esenciales del sistema.

    Arquitectura de Servicios

    Servicios modulares y reutilizables que manejan la lógica de negocio y la comunicación con APIs externas.

    DatabaseService

    lib/core/services/database_service.dart
    import 'package:cloud_firestore/cloud_firestore.dart';
    import '../models/user.dart';
    import '../models/product.dart';
    import '../models/order.dart';
    
    class DatabaseService {
      final FirebaseFirestore _firestore = FirebaseFirestore.instance;
    
      // Users
      Future createUser(User user) async {
        await _firestore.collection('users').doc(user.uid).set(user.toMap());
      }
    
      Future getUser(String uid) async {
        DocumentSnapshot doc = await _firestore.collection('users').doc(uid).get();
        if (doc.exists) {
          return User.fromFirestore(doc);
        }
        return null;
      }
    
      Future updateUser(String uid, Map data) async {
        await _firestore.collection('users').doc(uid).update(data);
      }
    
      // Products
      Stream> getProducts() {
        return _firestore
            .collection('products')
            .where('isActive', isEqualTo: true)
            .orderBy('createdAt', descending: true)
            .snapshots()
            .map((snapshot) => snapshot.docs
                .map((doc) => Product.fromFirestore(doc))
                .toList());
      }
    
      Future addProduct(Product product) async {
        await _firestore.collection('products').add(product.toMap());
      }
    
      Future updateProduct(String id, Map data) async {
        await _firestore.collection('products').doc(id).update(data);
      }
    
      Future deleteProduct(String id) async {
        await _firestore.collection('products').doc(id).update({'isActive': false});
      }
    
      // Orders
      Future createOrder(Order order) async {
        await _firestore.collection('orders').add(order.toMap());
      }
    
      Stream> getUserOrders(String userId) {
        return _firestore
            .collection('orders')
            .where('userId', isEqualTo: userId)
            .orderBy('createdAt', descending: true)
            .snapshots()
            .map((snapshot) => snapshot.docs
                .map((doc) => Order.fromFirestore(doc))
                .toList());
      }
    
      Future updateOrderStatus(String orderId, String status) async {
        await _firestore.collection('orders').doc(orderId).update({'status': status});
      }
    }

    WhatsAppService

    lib/core/services/whatsapp_service.dart
    import 'dart:convert';
    import 'package:http/http.dart' as http;
    
    class WhatsAppService {
      static const String _baseUrl = 'https://graph.facebook.com/v17.0';
      static const String _phoneNumberId = 'YOUR_PHONE_NUMBER_ID';
      static const String _accessToken = 'YOUR_ACCESS_TOKEN';
    
      static Future sendMessage({
        required String to,
        required String message,
      }) async {
        try {
          final response = await http.post(
            Uri.parse('$_baseUrl/$_phoneNumberId/messages'),
            headers: {
              'Authorization': 'Bearer $_accessToken',
              'Content-Type': 'application/json',
            },
            body: jsonEncode({
              'messaging_product': 'whatsapp',
              'to': to,
              'type': 'text',
              'text': {'body': message},
            }),
          );
    
          if (response.statusCode == 200) {
            print('WhatsApp message sent successfully');
            return true;
          } else {
            print('Failed to send WhatsApp message: ${response.body}');
            return false;
          }
        } catch (e) {
          print('Error sending WhatsApp message: $e');
          return false;
        }
      }
    
      static Future sendOrderNotification({
        required String phone,
        required String orderId,
        required double total,
      }) async {
        final message = '''
    ¡Hola! Tu pedido #$orderId ha sido confirmado.
    
    Total: \$${total.toStringAsFixed(2)}
    
    Gracias por elegir Panadería Antonella.
    Te notificaremos cuando tu pedido esté listo.
    ''';
    
        return await sendMessage(to: phone, message: message);
      }
    
      static Future sendOrderReadyNotification({
        required String phone,
        required String orderId,
      }) async {
        final message = '''
    ¡Tu pedido #$orderId está listo!
    
    Puedes pasar a recogerlo en Panadería Antonella.
    
    ¡Gracias por tu paciencia!
    ''';
    
        return await sendMessage(to: phone, message: message);
      }
    }

    CartProvider

    lib/providers/cart_provider.dart
    import 'package:flutter/foundation.dart';
    import '../models/product.dart';
    import '../models/cart_item.dart';
    
    class CartProvider with ChangeNotifier {
      List _items = [];
      double _total = 0.0;
    
      List get items => _items;
      double get total => _total;
      int get itemCount => _items.length;
    
      void addItem(Product product, {int quantity = 1}) {
        final existingIndex = _items.indexWhere((item) => item.product.id == product.id);
        
        if (existingIndex >= 0) {
          _items[existingIndex].quantity += quantity;
        } else {
          _items.add(CartItem(product: product, quantity: quantity));
        }
        
        _calculateTotal();
        notifyListeners();
      }
    
      void removeItem(String productId) {
        _items.removeWhere((item) => item.product.id == productId);
        _calculateTotal();
        notifyListeners();
      }
    
      void updateQuantity(String productId, int quantity) {
        final index = _items.indexWhere((item) => item.product.id == productId);
        if (index >= 0) {
          if (quantity <= 0) {
            _items.removeAt(index);
          } else {
            _items[index].quantity = quantity;
          }
          _calculateTotal();
          notifyListeners();
        }
      }
    
      void clearCart() {
        _items.clear();
        _total = 0.0;
        notifyListeners();
      }
    
      void _calculateTotal() {
        _total = _items.fold(0.0, (sum, item) => sum + (item.product.price * item.quantity));
      }
    
      bool get isEmpty => _items.isEmpty;
      bool get isNotEmpty => _items.isNotEmpty;
    }

    ChatProvider

    lib/providers/chat_provider.dart
    import 'package:flutter/foundation.dart';
    import '../models/chat_message.dart';
    import '../core/services/database_service.dart';
    
    class ChatProvider with ChangeNotifier {
      final DatabaseService _databaseService = DatabaseService();
      List _messages = [];
      bool _isLoading = false;
    
      List get messages => _messages;
      bool get isLoading => _isLoading;
    
      Future loadMessages() async {
        _isLoading = true;
        notifyListeners();
    
        try {
          // Cargar mensajes desde Firestore
          // Implementar según la estructura de datos
          _isLoading = false;
          notifyListeners();
        } catch (e) {
          _isLoading = false;
          notifyListeners();
          print('Error loading messages: $e');
        }
      }
    
      Future sendMessage(String text, String userId) async {
        final message = ChatMessage(
          id: DateTime.now().millisecondsSinceEpoch.toString(),
          text: text,
          userId: userId,
          timestamp: DateTime.now(),
          isUser: true,
        );
    
        _messages.add(message);
        notifyListeners();
    
        try {
          // Guardar mensaje en Firestore
          // await _databaseService.saveMessage(message);
    
          // Simular respuesta del bot
          await Future.delayed(Duration(seconds: 2));
          
          final botResponse = ChatMessage(
            id: DateTime.now().millisecondsSinceEpoch.toString(),
            text: _generateBotResponse(text),
            userId: 'bot',
            timestamp: DateTime.now(),
            isUser: false,
          );
    
          _messages.add(botResponse);
          notifyListeners();
        } catch (e) {
          print('Error sending message: $e');
        }
      }
    
      String _generateBotResponse(String userMessage) {
        final message = userMessage.toLowerCase();
        
        if (message.contains('hola') || message.contains('buenos días')) {
          return '¡Hola! Bienvenido a Panadería Antonella. ¿En qué puedo ayudarte?';
        } else if (message.contains('producto') || message.contains('pan')) {
          return 'Tenemos una gran variedad de productos frescos. ¿Te gustaría ver nuestro catálogo?';
        } else if (message.contains('precio') || message.contains('costo')) {
          return 'Los precios varían según el producto. ¿Qué te interesa específicamente?';
        } else if (message.contains('horario') || message.contains('abierto')) {
          return 'Estamos abiertos de lunes a domingo de 6:00 AM a 8:00 PM.';
        } else {
          return 'Gracias por tu mensaje. Un representante te contactará pronto.';
        }
      }
    
      void clearMessages() {
        _messages.clear();
        notifyListeners();
      }
    }

    Patrones de Diseño

    Utiliza el patrón Provider para state management y el patrón Repository para abstraer el acceso a datos. Esto facilita el testing y mantenimiento.

    Autenticación JWT

    Tokens JWT con expiración configurable y refresh tokens para mantener sesiones seguras.

    Duración del token: 24 horas
    Refresh token: 7 días

    Encriptación de Contraseñas

    Contraseñas encriptadas usando bcrypt con salt rounds de 12 para máxima seguridad.

    Control de Acceso (RBAC)

    Sistema de roles y permisos para controlar el acceso a diferentes funcionalidades.

    Roles: admin, manager, user
    Permisos: read, write, delete

    Configuración de Seguridad

    Headers de Seguridad

    // Configuración de headers de seguridad
    app.use(helmet({
      contentSecurityPolicy: {
        directives: {
          defaultSrc: ["'self'"],
          styleSrc: ["'self'", "'unsafe-inline'"],
          scriptSrc: ["'self'"],
          imgSrc: ["'self'", "data:", "https:"],
        },
      },
    }));

    Rate Limiting

    // Configuración de rate limiting
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutos
      max: 100, // máximo 100 requests por ventana
      message: 'Demasiadas solicitudes desde esta IP'
    });

    6. Configuración Avanzada

    Personalización

    Variables de Entorno

    .env

    # Configuración de la base de datos
    DB_HOST=localhost
    DB_PORT=5432
    DB_NAME=antonella
    DB_USER=postgres
    DB_PASSWORD=your_password
    
    # Configuración de Redis
    REDIS_HOST=localhost
    REDIS_PORT=6379
    
    # Configuración JWT
    JWT_SECRET=your_jwt_secret_key
    JWT_EXPIRES_IN=24h
    
    # Configuración del servidor
    PORT=3000
    NODE_ENV=production
    
    # Configuración de email
    SMTP_HOST=smtp.gmail.com
    SMTP_PORT=587
    SMTP_USER=your_email@gmail.com
    SMTP_PASS=your_email_password

    Configuración de Nginx

    server {
        listen 80;
        server_name your-domain.com;
        
        location / {
            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_cache_bypass $http_upgrade;
        }
        
        # Configuración para archivos estáticos
        location /static/ {
            alias /path/to/your/static/files/;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }

    7. Monitoreo y Logs

    Supervisión

    Sistema de Logs

    Niveles de Log

    ERROR Errores críticos que requieren atención inmediata
    WARN Advertencias que no son críticas pero requieren monitoreo
    INFO Información general sobre el funcionamiento del sistema
    DEBUG Información detallada para desarrollo y debugging

    Configuración de Logs

    // Configuración de Winston para logs
    const winston = require('winston');
    
    const logger = winston.createLogger({
      level: 'info',
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
      ),
      transports: [
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
      ]
    });

    Métricas de Rendimiento

    Métricas del Sistema

    • Uso de CPU y memoria
    • Tiempo de respuesta de la API
    • Número de conexiones activas
    • Errores por minuto

    Métricas de Base de Datos

    • Tiempo de consulta promedio
    • Número de conexiones activas
    • Consultas lentas
    • Uso de espacio en disco

    8. Troubleshooting

    Solución de Problemas

    Problemas Comunes y Soluciones

    Error de Conexión a Base de Datos

    Alto

    Síntomas: La aplicación no puede conectarse a PostgreSQL

    Causas:

    • Servicio PostgreSQL no está ejecutándose
    • Credenciales incorrectas
    • Puerto bloqueado por firewall

    Solución:

    # Verificar estado del servicio
    sudo systemctl status postgresql
    
    # Reiniciar servicio si es necesario
    sudo systemctl restart postgresql
    
    # Verificar conexión
    psql -h localhost -U postgres -d antonella

    Alto Uso de Memoria

    Medio

    Síntomas: La aplicación consume mucha memoria RAM

    Causas:

    • Memory leaks en el código
    • Cache no configurado correctamente
    • Consultas N+1 en la base de datos

    Solución:

    • Revisar logs de memoria
    • Optimizar consultas de base de datos
    • Configurar límites de memoria en Node.js

    Errores de Autenticación JWT

    Bajo

    Síntomas: Usuarios no pueden iniciar sesión

    Causas:

    • JWT_SECRET incorrecto
    • Token expirado
    • Problemas de sincronización de tiempo

    Solución:

    • Verificar variable JWT_SECRET
    • Revisar configuración de expiración
    • Sincronizar reloj del servidor

    9. Mantenimiento

    Mantenimiento

    Tareas de Mantenimiento Regular

    Diario

    • Revisar logs de errores
    • Verificar espacio en disco
    • Monitorear uso de recursos
    • Verificar backups automáticos

    Semanal

    • Análisis de rendimiento
    • Limpieza de logs antiguos
    • Verificación de integridad de base de datos
    • Actualización de dependencias de seguridad

    Mensual

    • Revisión completa de seguridad
    • Optimización de base de datos
    • Análisis de métricas de uso
    • Planificación de actualizaciones

    Scripts de Mantenimiento

    Backup de Base de Datos

    #!/bin/bash
    # Script de backup automático
    DATE=$(date +%Y%m%d_%H%M%S)
    BACKUP_DIR="/backups"
    DB_NAME="antonella"
    
    pg_dump -h localhost -U postgres $DB_NAME > $BACKUP_DIR/backup_$DATE.sql
    
    # Mantener solo los últimos 7 backups
    find $BACKUP_DIR -name "backup_*.sql" -mtime +7 -delete

    Limpieza de Logs

    #!/bin/bash
    # Script de limpieza de logs
    LOG_DIR="/var/log/antonella"
    
    # Eliminar logs de más de 30 días
    find $LOG_DIR -name "*.log" -mtime +30 -delete
    
    # Comprimir logs de más de 7 días
    find $LOG_DIR -name "*.log" -mtime +7 -exec gzip {} \;