🏢 InmoCRM
CRM inmobiliario con segundo factor de autenticación implementado desde cero y motor de matching demanda-cartera
Escala del Proyecto
Descripción General
InmoCRM es un CRM inmobiliario más contenido que TinoProp, pero con dos piezas que aquél no tiene: segundo factor de autenticación TOTP implementado a mano y un módulo de auditoría que deja constancia de quién tocó qué.
El foco está en el ciclo comercial: prospectos de captación, clientes, cartera de propiedades, visitas, tareas, calendario, documentos y facturación. El módulo de seguimiento añade plantillas de mensaje reutilizables y una agenda de contactos programados para que ningún propietario se quede sin llamada.
El aporte técnico que más me interesa de este proyecto es el TOTP: implementar el algoritmo del segundo factor sin librería obliga a entender HMAC, la ventana de tiempo y la codificación base32 que hay detrás de cualquier app de autenticación.
Tecnologías Utilizadas
PHP
MySQL
PDO
TOTP / HMAC
JavaScript
CSS3
Facturación
Los 14 Módulos
Captación con historial de contactos y registro de cambios de precio de la propiedad.
Compradores, vendedores e inversores con sus preferencias de búsqueda.
Cartera con fotos y estado de disponibilidad.
Estado, mensajes, envíos y agenda de contactos programados con plantillas.
Programación y resultado de cada visita.
Trabajo pendiente con prioridad y asignación.
Eventos, visitas y vencimientos en una vista mensual.
Documentación por entidad y plantillas de contrato.
Emisión de facturas, conversión desde presupuesto e impresión.
Estadísticas de cartera, clientes y actividad comercial.
Avisos internos por vencimiento y actividad.
Log de actividad con usuario, acción y fecha.
Cuentas, permisos por usuario y perfil con activación del 2FA.
Preferencias por usuario y configuración de facturación.
Arquitectura
Patrón de módulo autocontenido: cada carpeta de modules/ agrupa su
listado, formulario y vista de detalle, y se apoya en un núcleo compartido de
includes/. Los ficheros clave del núcleo son totp.php (el
segundo factor), matching.php (el cruce demanda-cartera) y
seguimiento.php.
InmoCRM/ ├── index.php # redirige a app/login.php └── app/ ├── login.php # credenciales + verificación TOTP ├── install.php # instalador del esquema ├── includes/ # auth, totp, matching, seguimiento, helpers ├── modules/ # los 14 módulos funcionales ├── api/ # endpoints AJAX por recurso ├── database/ # install.sql + migraciones puntuales ├── tests/ # run.php: runner de pruebas propio ├── assets/ # css, js, img, uploads └── logs/
Base de Datos
23 tablas en install.sql, más migraciones puntuales
para los cambios aplicados sobre instalaciones ya en uso (activación del 2FA, fotos
de propiedad, edad del inquilino, datos extra de demanda).
| Tabla | Contenido |
|---|---|
| usuarios | Cuentas con su secreto TOTP cuando activan el 2FA |
| permisos_usuario | Permisos concedidos por usuario |
| ajustes_usuario | Preferencias individuales de interfaz |
| actividad_log | Registro de auditoría: usuario, acción y fecha |
| prospectos | Captación con su etapa comercial |
| historial_prospectos | Contactos realizados por tipo y fecha |
| historial_propiedad_prospecto | Cambios de precio y de datos de la propiedad |
| clientes | Compradores, vendedores e inversores |
| propiedades | Cartera de inmuebles |
| propiedad_fotos | Galería por propiedad |
| visitas | Visitas programadas y su resultado |
| tareas | Trabajo pendiente con prioridad |
| calendario_eventos | Eventos del calendario |
| documentos | Documentación adjunta |
| plantillas_contrato | Plantillas de contrato con variables |
| facturacion | Facturas emitidas |
| configuracion_facturacion | Datos fiscales y series de facturación |
| seguimiento_estado | Estado de seguimiento por contacto |
| seguimiento_mensajes | Mensajes enviados |
| seguimiento_envios | Registro de envíos realizados |
| seguimiento_agenda | Contactos programados |
| seguimiento_meta | Metadatos de la campaña de seguimiento |
| notificaciones | Avisos internos |
Seguridad Implementada
- Segundo factor TOTP implementado desde cero en
includes/totp.php: sin librerías externas. - Activación del 2FA desde el perfil del usuario, opcional y por cuenta.
- Contraseñas con
password_hash()y bcrypt. - Auditoría completa en
actividad_log: cada acción queda registrada con su autor. - Permisos granulares por usuario, no solo por rol.
- Consultas con prepared statements PDO.
- Instalador con clave y separado de la aplicación.
- Configuración en
.env, fuera del control de versiones, conAPP_SECRETpropio.
Retos Técnicos y Decisiones de Diseño
Implementar TOTP sin librería
Es el reto que da carácter al proyecto. El código de seis dígitos que muestra Google Authenticator es un HMAC-SHA1 del contador de tiempo troceado en ventanas de 30 segundos, truncado dinámicamente y con el secreto codificado en base32. Escribirlo a mano obliga a implementar la codificación base32, la generación del secreto, el HMAC y la tolerancia a desfase de reloj entre servidor y móvil.
Matching sin motor de reglas
El cruce demanda-cartera vive en includes/matching.php y se resuelve
con SQL puntuado: presupuesto, zona, tipo de operación y requisitos generan una
consulta que devuelve los inmuebles ordenados por afinidad. Es menos flexible que un
motor de reglas, pero cabe en una consulta y es trivial de depurar.
Auditoría sin duplicar código
Registrar cada acción en 14 módulos invita a repetir la misma llamada 200 veces. La escritura del log se centralizó en el núcleo, junto a la capa de acceso a datos, de modo que un módulo nuevo queda auditado sin que haya que acordarse de nada.
Mi Rol
Desarrollador full stack — autor único.
Modelo de datos, los 14 módulos, el segundo factor TOTP, el motor de matching, el módulo de auditoría, el instalador y el runner de pruebas.
Estado del Proyecto
Aplicación funcional con esquema instalable y migraciones para actualizar instancias
existentes. Incluye un runner de pruebas propio en app/tests/run.php.
Código y Enlaces
Repositorio no publicado. El proyecto contiene configuración de despliegue; puedo enseñar el código, y en particular la implementación del TOTP, en una entrevista.