Saltar al contenido
← Volver a proyectos
Before/after architecture: Salesforce Classic components (Visualforce, JavaScript button, Process Builder, 8 profiles, Custom Settings, unsecured Apex) and their Lightning Experience replacements (LWC, Quick Action and Screen Flow, Record-Triggered Flow, 5 Permission Set Groups, Named Credentials, Apex with sharing and stripInaccessible)
Caso de estudio reconstruido

Migración de Salesforce Classic a Lightning Experience (Nova Manufacturing)

Migración de Classic a Lightning y refuerzo de seguridad Apex para un fabricante internacional de equipos industriales.

Contexto

> Caso de estudio reconstruido: el escenario, la empresa y las cifras son ficticios. Se inspira en el tipo de trabajo que realizo en mi puesto, cuyos detalles siguen siendo confidenciales, y no describe un encargo de cliente. Nova Manufacturing es un fabricante internacional de equipos industriales (~150 comerciales repartidos en 3 sedes/polos en Europa). Su CRM Salesforce, todavía mayoritariamente en Classic, acumulaba varias generaciones de desarrollos: páginas Visualforce, botones JavaScript, Process Builder, perfiles muy personalizados, integraciones REST con sistemas externos (ERP, facturación). Con la progresiva desaparición de Classic, el escenario plantea la modernización de la aplicación — con un mandato explícito: no limitarse a migrar la interfaz, sino reforzar también la seguridad de los desarrollos Apex heredados, varios de los cuales nunca habían sido auditados desde su puesta en producción inicial.

Componentes identificados y soluciones propuestas

  • Página Visualforce Compte360 (objeto Account): búsqueda y visualización de pedidos y contratos vinculados a una cuenta, consulta SOQL construida dinámicamente en el controlador → convertida en un Lightning Web Component AccountOrdersOverview, conectado a AccountOrdersController.getOrders() (6 días)
  • Botón JavaScript UpdateContractStatus (objeto Contract): actualización del estado del contrato sin verificación de permisos ni confirmación del usuario → sustituido por una Quick Action que lanza un Screen Flow con un método Apex invocable (3 días)
  • Process Builder "Validación de pedido": flujo de aprobación multinivel disparado en la creación → migrado a un Record-Triggered Flow (before-save y after-save separados para respetar los Governor Limits) (4 días)
  • 4 controladores Apex heredados: auditoría sistemática, sin ninguna prueba de permisos CRUD/FLS implementada → reconstruidos con un patrón with sharing estricto. Más 4 controladores nuevos creados para este proyecto, con seguridad integrada desde el diseño (5 días en total)
  • Estimación total: 25 días (auditoría 2d, migración Visualforce→LWC 6d, botón JS→Quick Action/Flow 3d, Process Builder→Flow 4d, seguridad Apex 5d, pruebas 3d, documentación 2d), más 8h de formación de usuarios

Desarrollos entregados

  • LWC AccountOrdersOverview: lightning-datatable con paginación en el servidor y búsqueda por palabra clave, conectado a un método Apex @AuraEnabled(cacheable=true) con WITH SECURITY_ENFORCED
  • Record-Triggered Flow "Validación de pedido v2": lógica bulkificada que procesa la colección completa (el antiguo Process Builder no lo hacía y provocaba errores de Governor Limits en las importaciones masivas), con un sub-flow reutilizable para la parte de notificación
  • Permission Set Groups: consolidación de 8 perfiles heredados casi duplicados en 5 grupos, reduciendo la deuda de configuración y facilitando la auditoría de accesos
  • Named Credentials: sustitución de los endpoints REST codificados directamente (credenciales antes visibles en Custom Settings para cualquier administrador) por Named Credentials, con autenticación gestionada por la plataforma

Seguridad y buenas prácticas

  • ContractService.updateStatus(): antes de la reconstrucción, escribía directamente en Contract sin verificación, y la clase se ejecutaba en without sharing por defecto de un antiguo controlador Visualforce. Después: Security.stripInaccessible(AccessType.UPDATABLE, records) antes de cada DML, with sharing explícito en la clase
  • Prueba unitaria dedicada que simula un usuario sin permiso de edición sobre Contract.Statut__c para verificar que stripInaccessible() bloquea correctamente la escritura
  • Auditoría de los 4 controladores heredados: no existía ninguna prueba de permisos CRUD/FLS antes de este proyecto — se añadieron verificaciones explícitas allí donde las consultas no eran elegibles para WITH SECURITY_ENFORCED. Seguridad integrada desde el diseño en los 4 controladores nuevos creados para el proyecto
  • Matriz de comparación perfiles → permission sets validada con los responsables de negocio antes del cambio, para evitar cualquier regresión silenciosa en los derechos de acceso

Gestión de riesgos

  • Incompatibilidad de controladores Apex existentes (impacto medio) → pruebas de no regresión en sandbox antes de cada cambio, despliegue componente por componente en lugar de todo a la vez
  • Adopción por parte de los usuarios (probabilidad alta) → 8h de formación repartidas en 2 sesiones, documentación breve por rol en lugar de un manual único
  • Errores de Governor Limits en los Flows migrados (impacto bajo, ya detectado una vez en sandbox) → bulkificación sistemática desde el diseño, probada con conjuntos de 200+ registros
  • Regresión silenciosa en los derechos de acceso durante la consolidación de perfiles (impacto alto) → matriz de comparación perfiles → permission sets validada con los responsables de negocio antes de la puesta en producción

Stack y tecnologías

  • Lightning Web Components, Apex, SOQL
  • Flow (Record-Triggered, before-save/after-save)
  • Permission Set Groups, Named Credentials
  • Modelo de seguridad de Salesforce — CRUD/FLS, WITH SECURITY_ENFORCED, stripInaccessible()

Resultados

8
Clases Apex aseguradas
4 heredadas reforzadas + 4 nuevas creadas con seguridad desde el diseño
8 → 5
Perfiles consolidados
Permission Set Groups
25 días
Esfuerzo total
auditoría + migración + seguridad + pruebas + documentación
200+ registros
Probado en bloque
validación de Governor Limits en los Flows migrados

Limitaciones conocidas y decisiones

  • Migración progresiva componente por componente en lugar de un big bang: más lenta, pero permite un rollback específico si un componente migrado revela un problema no anticipado en producción
  • Páginas Visualforce simples sin valor añadido real de migrar se dejaron tal cual: Lightning Experience las soporta de forma nativa, migrar todo el alcance solo habría supuesto coste sin beneficio medible para el usuario
  • Named Credentials desplegadas únicamente en las integraciones REST identificadas como prioritarias durante la auditoría — las integraciones secundarias siguen con el mecanismo antiguo, migración documentada como siguiente paso
Migración de Salesforce Classic a Lightning Experience (Nova Manufacturing) — Aïcha Imène DAHOUMANE