Files
MexusNuevo/docs/ARQUITECTURA.md
José Jiménez Salinas a1dde36ddc CRANEGOO v3.0 — Plataforma completa de gestión para grúas y elevadores
13 módulos, 6 roles, 5 idiomas, 4 temas visuales
Creador: José Jiménez Salinas — Consultoría Alcaraz Salazar
2026-03-25 03:36:07 +00:00

9.0 KiB
Raw Blame History

CRANEGOO — Documentación Técnica para Desarrollador

Arquitectura General

La app es un Single-File React Component (src/App.jsx) con todo el estado en memoria. No hay backend, base de datos ni API. Esto es un prototipo funcional que debe migrarse a una arquitectura cliente-servidor.


Mapa del Archivo (por líneas aproximadas)

Líneas 1-18      → Constantes de color (C), estilos base
Líneas 19-148    → ROLES, EQ_TYPES, SVC_TYPES, PRIORITY, EMP_ROLES, EXCLUSIVE_ROLES, etc.
Líneas 149-230   → INIT_EMPLOYEES, INIT_CLIENTS (vacíos en versión limpia)
Líneas 231-410   → INIT_SERVICES, INIT_MAINTENANCE, INIT_SUPPLIERS, INIT_PURCHASE_ORDERS, etc.
Líneas 410-535   → TRANSLATIONS (90 claves × 5 idiomas), THEMES (4), INIT_COMPANY
Líneas 535-600   → Hooks (useIsMobile), GSComp (global styles dinámicos por tema)
Líneas 600-640   → SignaturePad component (canvas touch+mouse)
Líneas 640-680   → Field, Modal, StatusBadge, SvcStatusBadge, PriorityBadge
Líneas 680-850   → Calendar component (con festivos 2026, domingos, modales)
Líneas 850-1500  → ServicesModule (OpsServicesView, EmpServicesView, VentasServicesView, ClientServicesView)
Líneas 1500-2100 → InventoryModule (EquipmentForm, PartForm)
Líneas 2100-2500 → MaintenanceModule (OpsMaintenanceView, ClientMaintenanceView, EmpMaintenanceView)
Líneas 2500-2950 → ComprasModule (OCs, proveedores, fotos)
Líneas 2950-3400 → CotizacionesModule (catálogo, PDF, cláusulas)
Líneas 3400-4600 → ContableModule (6 pestañas: resumen, facturas, edocuenta, tesorería, SAT/IMSS, nómina)
Líneas 4600-4850 → PersonalModule (CRUD empleados)
Líneas 4850-5200 → ClientesModule (CRUD clientes, proyectos, appUsers)
Líneas 5200-5400 → Sidebar, Header
Líneas 5400-5850 → Dashboard (KPIs, panel financiero, alertas)
Líneas 5850-6000 → GPSModule
Líneas 6000-6500 → ManualesModule
Líneas 6500-6900 → ReportesModule (checklists grúa/elevador, firmas, PDF)
Líneas 6900-7200 → ConfigModule (idiomas, temas, empresa, fiscal, acerca de)
Líneas 7200-7300 → Login (usuario + contraseña)
Líneas 7300-7450 → App (estado global, routing)

Estado Global (en App component)

Todos estos useState viven en App() y se pasan como props:

State Tipo Descripción
role string Rol activo (admin, operaciones, ventas, contador, empleado, cliente)
mod string Módulo activo del sidebar
equipment array Equipos (grúas, elevadores)
parts array Refacciones
services array Servicios programados
maintenance array Mantenimientos
employees array Empleados con credenciales
clients array Clientes con proyectos y appUsers
invoices array Facturas (ingreso/egreso)
quotations array Cotizaciones
purchaseOrders array Órdenes de compra
suppliers array Proveedores
messages array Mensajes internos
accounts array Cuentas bancarias
credits array Créditos y tarjetas
transactions array Movimientos bancarios
obligations array Obligaciones SAT/IMSS
nomina array Registros de nómina semanal
lang string Idioma activo (es-MX, en, ru, fr, es-ES)
theme string Tema visual (dark, light, mexus, blue)
company object Datos de la empresa
clientLangs object Idioma por cliente/obra
loggedUserId string ID del usuario logueado
loggedUserProject string Proyecto del cliente logueado

Flujo de Autenticación

Login → usuario + contraseña
  ├─ Match ADMIN_CREDS? → onLogin("admin", null, null)
  ├─ Match employee.user + employee.pass? → onLogin(emp.systemRole, emp.id, null)
  ├─ Match client appUser.user + appUser.pass? → onLogin("cliente", cli.id, project)
  └─ Fallback: Match employee.email + employee.pass? → onLogin(emp.systemRole, emp.id, null)

Para migración: Reemplazar con JWT + bcrypt. La estructura de roles ya está definida.


Modelo de Datos Clave

Employee

{
  id: "EMP-001",
  name: "Carlos Mendoza",
  role: "Operador de Grúa",          // Puesto laboral
  systemRole: "operaciones",          // Rol en la app (empleado|operaciones|ventas|contador)
  phone, email, curp, nss,
  emergencyContact, startDate,
  status: "activo"|"inactivo",
  user: "carlos.mendoza",             // Login
  pass: "mexus2024",                  // Contraseña (migrar a hash)
  comprasAccess: false                // Acceso al módulo de compras
}

Client

{
  id: "CLI-001",
  company: "Hermosillo y Asociados",
  contact, phone, email, rfc, address,
  projects: ["WESTIN Tijuana"],
  status: "activo",
  projectDetails: {
    "WESTIN Tijuana": {
      equipmentIds: ["MX-GT-001"],
      notifEmails: ["correo@empresa.mx"],
      appUsers: [
        { name: "Fernando", email: "f@h.mx", user: "fhermosillo", pass: "westin2024" }
      ]  // Máximo 2 por proyecto
    }
  }
}

Service

{
  id: "SVC-001",
  type: "elevacion_grua",             // De SVC_TYPES
  clientName, project, equipmentId,
  date, endDate, timeSlot: "07:00-15:00",
  priority: "alta"|"media"|"baja",
  status: "pendiente"|"aprobado"|"en_proceso"|"en_sitio"|"completado"|"rechazado",
  assignedTo: ["EMP-001", "EMP-005"],
  tracking: {
    inSite: false,
    inSiteTime: null,
    startTime: null, endTime: null,
    photosStart: [], photosDuring: [], photosEnd: [],
    employeeNotes: "",
    checklist: null,                   // Se genera al iniciar (GRUA o ELEVADOR)
    empSignature: null,                // PNG data URL de firma
    empSignName: "",
    approverSignature: null,
    approverSignName: "",
    reportApproved: false,
    reportApprovedAt: null,
    opsNotes: ""
  }
}

Account (Tesorería)

{
  id: "CTA-001",
  name: "BBVA Empresarial Pesos",
  bank: "BBVA",
  type: "pesos"|"dolares",
  number: "**** 4521",
  balance: 485000,                    // Se actualiza con transacciones
  clabe: "012180001234567890"
}

Obligation (SAT/IMSS)

{
  id: "OBL-001",
  entity: "SAT"|"IMSS"|"Estatal",
  type: "ISR Retenciones",
  period: "Marzo 2026",
  amount: 18500,
  dueDate: "2026-04-17",
  status: "pendiente"|"pagado",
  receipt: null                        // { name, data } archivo subido
}

Nomina

{
  id: "NOM-001",
  week: "Semana 9 (24 Feb — 2 Mar)",
  period: "2026-03-02",
  totalBruto: 95000, totalNeto: 78500,
  isr: 8500, imss: 4200, infonavit: 3800,
  employees: 6,
  timbrada: true, timbreXML: { name, date },
  complemento: false, compXML: null,
  receipt: null,
  notes: ""
}

Permisos — Tabla de Referencia

canEdit / canOperate / canGrantAccess (ContableModule)

const canEdit = isAdmin || isContador;     // Editar/eliminar cuentas, créditos, obligaciones, nómina
const canOperate = isAdmin || isContador;  // Crear, registrar transacciones, subir comprobantes
const canGrantAccess = isAdmin;            // Activar visualización a otros roles

Compras — Acciones de pago

(role === "admin" || role === "contador")   // Marcar pagado, subir comprobante
(role === "admin" || role === "operaciones") // Cancelar/eliminar OC

Roles exclusivos en Scheduling

const EXCLUSIVE_ROLES = ["Operador", "Maniobrista", "Operador de Grúa", ...];
// Si un operador tiene cualquier asignación en un día → bloqueado TODO el día
// Otros roles (Técnicos, Montadores): disponibles fuera de sus slots asignados

Internacionalización

const t = (key) => TRANSLATIONS[key]?.[activeLang] || TRANSLATIONS[key]?.["es-MX"] || key;

// activeLang se resuelve:
// 1. Si es cliente → clientLangs[clientId+"|"+project] || clientLangs[clientId] || lang
// 2. Todos los demás → lang (idioma global del sistema)

Claves traducidas: sidebar (13), login (6), common (20), roles (6), dashboard (8), services (6), contable (5), config (10), priority (3), reports (5).


Generación de PDF

Se usa window.open() + document.write() para generar HTML imprimible. Los PDFs incluyen:

  • Logo de la empresa (del cliente, no CRANEGOO)
  • Checklist completo con OK/Defecto
  • Firmas digitales (imágenes PNG incrustadas)
  • Datos del equipo, cliente, inspector

Para migración: Reemplazar con librería como jsPDF o generación server-side.


Notas para el Programador

  1. Todo el estado es en memoria — al recargar se pierde. Prioridad #1: base de datos.
  2. Las contraseñas están en texto plano — migrar a bcrypt + JWT inmediatamente.
  3. Las firmas son PNG data URLs — almacenar en object storage (S3/Firebase Storage).
  4. Los archivos subidos (XML, fotos) son data URLs en memoria — migrar a file storage.
  5. El CSS es inline — considerar migrar a Tailwind CSS o CSS modules.
  6. No hay tests — agregar tests unitarios y de integración.
  7. El routing es un switch/case interno — migrar a React Router.
  8. No hay error boundaries — agregar para producción.