- Script sync-obra-estatus.py (idempotente, --dry-run, retry/backoff): parsea ESTATUS OBRA, SENDA-ACT-AGO2026, SENDA/SOLE DG, Diagonal 38 y las hojas de ventas; mapea a Unidades vía maestro-unidades.json - Board Unidades: +12 columnas (% avance obra, meses atraso, contratista, clave catastral, no. oficial, vendedor, broker, venc. autorización, fecha entrega obra, 4 checkboxes de hitos documentales) — 147 items actualizados (DIAGONAL 38/38, SENDA 109/142) - Board nuevo 'Flujo Escrituras' (18429252054): 32 items mayo–ago/2026 por proyecto/semana con escrituras e ingreso - Board nuevo 'Saldos a Favor' (18429252069): 7 pendientes (Estanza/Sole) - Receta nativa documentada: recordatorio 7 días antes de Venc. autorización al coordinador - SOLE y MUTUO no existen como inventario en Monday: sus datos de obra se reportan como saltados (no se crean unidades)
6.4 KiB
FRASA Ecosystem
Ecosistema comercial de Frasa Desarrollos S.A.P.I. de C.V.
Componentes
| Componente | Ruta | Descripción |
|---|---|---|
apps/landing |
/ |
Entrada al ecosistema |
apps/cotizador |
/quote/ |
Cotizador financiero (4 propuestas, PDF ANEXO A) |
apps/alta-clientes |
/client/ |
Alta de clientes (wizard, firma digital, PDFs PLD) |
apps/cobranza |
/pay/ |
Planes de enganche, vencidos, estados de cuenta |
apps/dashboards |
/dash/ |
Tableros KPI (leads, oportunidades, inventario, cobranza) |
apps/mi-dia |
/hoy/ |
Agenda del vendedor (mis leads, actividades, acciones CRM) |
apps/agente-ia |
/ai/ |
Asistente IA con documentos del ecosistema |
api-gateway |
/api/ |
Express 5 + Prisma + integración Monday.com |
PWA (instalabilidad básica)
Las 7 apps son instalables (manifest + íconos): cada una tiene
public/manifest.webmanifest ("Frasa · <app>", display: standalone,
theme_color/background_color) e íconos 192/512 en public/icons/
(generados con scripts/generar-iconos-pwa.py, venv /root/.venv-tools).
Decisión: NO hay service worker. Solo se busca instalabilidad básica (ícono en el teléfono que abre la app a pantalla completa). Un SW con caché arriesga servir bundles viejos tras cada deploy (los usuarios son vendedores en campo; no van a limpiar caché a mano). Si algún día se quiere modo offline, hay que diseñar primero la estrategia de invalidación de caché.
Desarrollo local
Cada app es un proyecto Vite independiente: npm install && npm run dev (o npm run preview tras npm run build). Tests: npx vitest run en cada paquete. El API: cd api-gateway && npm install && npx prisma migrate dev && npm run dev.
Variables de entorno: copiar .env.example a .env y completar (el .env nunca se commitea).
Servidor actual (LXC sin Docker)
Esta máquina es un contenedor LXC sin nesting: Docker no puede correr contenedores. El stack corre directo en el host:
- NGINX (apt) sirve los
dist/de las apps y proxifica/api/→127.0.0.1:3000. Config:deploy/nginx-host.conf→/etc/nginx/sites-available/frasa. - API como servicio systemd:
deploy/frasa-api.service→frasa-api.service(systemctl status frasa-api, logs en/var/log/frasa-api.log). - Rebuild de apps tras cambios:
VITE_API_URL=/api npm run builden cada app +systemctl reload nginx(no requiere restart).
Acceso público: Cloudflare Tunnel
El stack se expone en https://frasa.consultoria-as.com mediante Cloudflare Tunnel (Zero Trust), sin abrir puertos ni depender del DDNS:
- Túnel administrado desde el dashboard (Zero Trust → Networks → Tunnels);
el ingress vive en Cloudflare: public hostname
frasa.consultoria-as.com→http://localhost:80. No hayconfig.ymllocal. - Servicio systemd
cloudflared(instalado concloudflared service install <token>, token en/etc/cloudflared/token). SSL lo termina Cloudflare automáticamente; Certbot ya no aplica en este servidor. - NGINX de host sigue en puerto 80 con
server_name _(catch-all), así que cualquier hostname del túnel funciona sin cambios. - Las ligas de firma remota se construyen con
window.location.origin, así que ya salen con el dominio público al usarlas desde ahí.
El docker-compose.yml queda listo para cuando el stack se mude a una VM con Docker.
Deploy con Docker (VM futura)
git clone https://git.consultoria-as.com/consultoria-as/FRASA-CAS.git /opt/frasa-ecosystem
cd /opt/frasa-ecosystem
cp .env.example .env && nano .env # completar secretos
# SSL: webroot (funciona con nginx corriendo y renueva sin downtime)
docker compose up -d nginx # primer arranque SIN ssl: ver nota abajo
certbot certonly --webroot -w /var/www/certbot -d frasadesarrollos.ddns.net
docker compose build && docker compose up -d
docker compose logs -f api
curl https://frasadesarrollos.ddns.net/api/health
Modo local sin SSL (LAN): .env con NGINX_CONF=nginx.http.conf hace que NGINX
sirva todo por HTTP en el puerto 80. Cuando el DDNS apunte a este servidor:
certbot certonly --webroot -w /var/www/certbot -d frasadesarrollos.ddns.net,
quita NGINX_CONF del .env (vuelve nginx.conf con 443) y
docker compose restart nginx. Renovación: certbot renew --deploy-hook "docker compose -f /opt/frasa-ecosystem/docker-compose.yml restart nginx".
Backup: scripts/backup.sh (cron sugerido 17 2 * * *).
Monday.com
Workspace Frasa-CAS. Tableros: Contactos, Desarrollos, Unidades (inventario importado), Leads, Oportunidades, Apartado, Ventas, Flujo Escrituras, Saldos a Favor. Los board IDs están en .env.example. Webhook: POST /api/webhooks/monday (responde el challenge de activación).
Board Unidades — columnas de obra/estatus
Alimentadas por api-gateway/scripts/sync-obra-estatus.py desde el Reporte_EstatusVenta.xlsx del cliente (idempotente, --dry-run disponible; ver docstring del script):
% Avance obra,Meses atraso(numbers),Contratista,Clave catastral,No. oficial,Vendedor,Broker(text),Venc. autorización(date).Fecha entrega obra(date): la columna originalFecha entregaya traía datos de habitabilidad, por eso se creó una nueva.- Hitos documentales (checkbox):
Cert. Gas,TO / C4,Régimen inscrito,Lista avalúo. Se encienden cuando la fecha del hito en el Excel ya pasó; el script nunca los apaga. - Nota: en
No. oficial/Clave catastralel Excel del cliente trae fechas programadas (no números oficiales); se cargan como texto ISO tal cual.
Boards operativos nuevos
- Flujo Escrituras: un item por mes/semana/proyecto con
Escrituras(numbers) eIngreso(numbers) del Flujo Calendario del cliente. Idempotencia por nombre único (AGOSTO SEM 3 AL 7 - SOLE). - Saldos a Favor: name
CLIENTE / UNIDAD; columnasDesarrollo(status),Unidad(text),Monto(numbers),Estado(Pendiente/Devuelto),Comentario. Idempotencia por Unidad+Desarrollo.
Las unidades SOLE y MUTUO no existen en el board Unidades: el script las reporta como saltadas (sus vendedor/broker/venc. autorización no se cargan por ahora).
Pendientes conocidos
- Migrar Prisma de SQLite a Postgres 16 (dinero a
Decimal). - Auth JWT, helmet, rate-limit, CORS restringido (hoy: red interna).
- Self-hostear worker/wasm de tesseract.js (OCR sin internet).
- Automatizaciones Monday (round-robin, recordatorios 10 días) y cron de cobranza en el API.