24 KiB
Marketplace de Extensiones - Guía de Desarrollo
Versión: 1.0 Fecha: 2025-11-17 SDK Version: 1.0.0 Modelo: SaaS Multi-tenant B2B
📋 Resumen Ejecutivo
El Marketplace de Extensiones permite a constructoras (tenants), partners y desarrolladores externos crear funcionalidad custom sin modificar el core del sistema. Las extensiones se desarrollan usando el SDK oficial y se distribuyen a través del marketplace centralizado.
Tipos de desarrolladores:
- Equipo interno: Extensiones oficiales (integraciones, reportes)
- Partners certificados: Módulos verticales especializados
- Clientes enterprise: Extensiones privadas para uso interno
- Comunidad: Extensiones públicas open-source
🎯 Tipos de Extensiones
1. Integraciones (Connectors)
Conectores a sistemas externos:
Ejemplos:
- SAP S/4HANA Connector
- CONTPAQi Connector
- WhatsApp Business API
- QuickBooks Online
- Slack Notifications
- Microsoft Teams
- Google Workspace
- Zoom Meetings
Características:
- Autenticación OAuth 2.0
- Webhooks bidireccionales
- Retry logic y error handling
- Rate limiting inteligente
- Logs de sincronización
Pricing típico: $0-$199/mes
2. Reportes Custom
Plantillas de reportes especializados:
Ejemplos:
- Reporte INFONAVIT EVC (formato oficial 2025)
- Reporte para licitaciones CFE
- Reporte de cumplimiento NOM-031-STPS
- Dashboard ejecutivo C-level
- Reporte de rentabilidad por proyecto
- Análisis de variaciones de presupuesto
Características:
- Exportación a PDF, Excel, CSV
- Scheduling automático (diario, semanal, mensual)
- Email delivery
- Plantillas con branding de la constructora
- Cálculos complejos pre-configurados
Pricing típico: $29-$99 (one-time) o $10-$50/mes
3. Módulos Verticales
Funcionalidad específica por tipo de constructora:
Ejemplos:
- Módulo de Obra Civil Pesada (puentes, carreteras)
- Módulo de Edificación Alta (rascacielos, oficinas)
- Módulo de Obra Industrial (plantas, fábricas)
- Módulo de Infraestructura (aeropuertos, estaciones)
- Módulo de Restauración (edificios históricos)
Características:
- Catálogos especializados (actividades, riesgos, EPP)
- Workflows específicos
- Reportes regulatorios verticales
- Integraciones con herramientas especializadas
Pricing típico: $199-$599/mes
4. Workflows Custom
Flujos de aprobación personalizados:
Ejemplos:
- Workflow de estimaciones 5 niveles (Resident → Super → Director → Finance → Cliente)
- Workflow de compras con 3 cotizaciones obligatorias
- Workflow de cambios de alcance con firma digital
- Workflow de liberación de pagos a subcontratistas
Características:
- Aprobaciones paralelas o secuenciales
- Escalamiento automático por tiempo
- Notificaciones por múltiples canales
- Firma digital integrada
- Audit trail completo
Pricing típico: $49-$199/mes
5. Dashboards Temáticos
Dashboards especializados:
Ejemplos:
- Dashboard Financiero (CFO)
- Dashboard de Producción (Gerente de Obra)
- Dashboard de Calidad (QA Manager)
- Dashboard de HSE (Safety Manager)
- Dashboard de Compras (Procurement)
Características:
- Widgets personalizables
- Drill-down interactivo
- Alertas en tiempo real
- Exportación programada
- Mobile responsive
Pricing típico: $29-$99/mes
6. Templates
Plantillas de documentos y procesos:
Ejemplos:
- Contratos tipo (obra, subcontrato, arrendamiento)
- Formatos oficiales (permisos, licencias)
- Checklists de calidad por actividad
- Procedimientos de seguridad
- Minutas de junta
Características:
- Merge de datos del sistema
- Variables dinámicas
- Versionado de templates
- Firma digital
- Multi-idioma
Pricing típico: $9-$49 (one-time)
🛠️ SDK de Desarrollo
Instalación
npm install @erp-construccion/extension-sdk
Estructura de una Extensión
// mi-extension/
// ├── package.json
// ├── extension.config.ts
// ├── src/
// │ ├── index.ts // Entry point
// │ ├── hooks/ // Event hooks
// │ ├── components/ // UI components (React)
// │ ├── services/ // Business logic
// │ └── utils/ // Utilities
// └── tests/
// package.json
{
"name": "@mi-empresa/extension-whatsapp",
"version": "1.0.0",
"description": "Notificaciones por WhatsApp",
"main": "dist/index.js",
"dependencies": {
"@erp-construccion/extension-sdk": "^1.0.0"
},
"extensionMetadata": {
"displayName": "WhatsApp Notifier",
"category": "integrations",
"pricing": {
"type": "free"
},
"permissions": [
"notifications.send",
"users.read"
]
}
}
Configuración de Extensión
// extension.config.ts
import { ExtensionConfig } from '@erp-construccion/extension-sdk';
export default {
id: 'whatsapp-notifier',
name: 'WhatsApp Notifier',
version: '1.0.0',
author: {
name: 'Mi Empresa',
email: 'soporte@mi-empresa.com',
website: 'https://mi-empresa.com'
},
description: 'Envía notificaciones automáticas por WhatsApp',
icon: 'https://cdn.mi-empresa.com/whatsapp-icon.png',
// Compatibilidad
minPlatformVersion: '2.0.0',
maxPlatformVersion: '3.0.0',
// Pricing
pricing: {
type: 'free', // 'free' | 'one_time' | 'subscription'
amount: 0,
currency: 'USD',
trial: false
},
// Permisos requeridos
permissions: [
'notifications.send',
'users.read',
'projects.read'
],
// Configuración
settings: [
{
key: 'whatsapp_api_key',
type: 'string',
required: true,
secure: true,
label: 'WhatsApp API Key',
description: 'API key de WhatsApp Business'
},
{
key: 'default_template',
type: 'select',
options: ['template1', 'template2'],
default: 'template1',
label: 'Plantilla por defecto'
}
]
} as ExtensionConfig;
📚 API del SDK
1. Hooks (Eventos)
import { Extension, Hook } from '@erp-construccion/extension-sdk';
@Extension({
id: 'whatsapp-notifier',
name: 'WhatsApp Notifier'
})
export class WhatsAppNotifierExtension {
// Hook: Cuando se crea una estimación
@Hook('estimations.created')
async onEstimationCreated(estimation: Estimation) {
const constructora = this.context.constructora;
const users = await this.api.users.findByRole('finance');
for (const user of users) {
if (user.phone && user.notificationsEnabled) {
await this.sendWhatsApp(user.phone, {
template: 'estimation_created',
params: {
estimationNumber: estimation.number,
amount: estimation.amount,
project: estimation.project.name
}
});
}
}
}
// Hook: Cuando se aprueba un presupuesto
@Hook('budgets.approved')
async onBudgetApproved(budget: Budget) {
// Lógica custom
}
// Hook: Cuando un proyecto excede presupuesto
@Hook('projects.budget_exceeded')
async onBudgetExceeded(project: Project, overrun: number) {
// Alertar al director de proyecto
const director = await this.api.users.findById(project.directorId);
await this.sendWhatsApp(director.phone, {
template: 'budget_alert',
params: {
projectName: project.name,
overrunPercentage: (overrun * 100).toFixed(2)
}
});
}
}
Hooks disponibles:
// Proyectos
'projects.created'
'projects.updated'
'projects.deleted'
'projects.budget_exceeded'
'projects.milestone_reached'
// Presupuestos
'budgets.created'
'budgets.approved'
'budgets.rejected'
// Compras
'purchases.order_created'
'purchases.order_approved'
'purchases.goods_received'
// Estimaciones
'estimations.created'
'estimations.approved'
'estimations.paid'
// Control de Obra
'progress.updated'
'progress.milestone_completed'
// RRHH
'employees.hired'
'employees.terminated'
'attendance.checked_in'
'attendance.anomaly_detected'
// HSE
'incidents.registered'
'incidents.investigated'
'risks.predicted' // IA
'patterns.detected' // IA
// Calidad
'defects.reported'
'defects.resolved'
// Finanzas
'accounting.entry_created'
'payments.made'
'invoices.received'
// General
'notifications.sent'
'reports.generated'
2. API de Datos
// Acceso a datos de la constructora
import { API } from '@erp-construccion/extension-sdk';
export class MiExtension {
async getMiData() {
const api = this.context.api;
// Proyectos
const projects = await api.projects.findAll({
status: 'active',
limit: 10
});
// Presupuestos
const budget = await api.budgets.findById('budget-123');
// Usuarios
const users = await api.users.findByRole('engineer');
// Custom queries
const result = await api.query(`
SELECT p.name, SUM(b.amount) as total
FROM projects p
JOIN budgets b ON b.project_id = p.id
WHERE p.status = 'active'
GROUP BY p.id
`);
return result;
}
// Crear datos
async createProject() {
const project = await this.context.api.projects.create({
name: 'Nuevo Proyecto',
code: 'PRJ-2025-001',
startDate: '2025-01-01',
endDate: '2025-12-31'
});
return project;
}
// Actualizar datos
async updateProject(id: string) {
const project = await this.context.api.projects.update(id, {
status: 'completed'
});
return project;
}
}
3. UI Components (React)
import { Component, MenuItem } from '@erp-construccion/extension-sdk';
import { useState } from 'react';
// Agregar ítem al menú lateral
@MenuItem({
section: 'settings',
label: 'Configurar WhatsApp',
icon: 'whatsapp',
route: '/settings/whatsapp'
})
export function WhatsAppSettingsPage() {
const [apiKey, setApiKey] = useState('');
const handleSave = async () => {
await context.settings.save({ whatsapp_api_key: apiKey });
};
return (
<div>
<h1>Configuración de WhatsApp</h1>
<input
type="text"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
placeholder="API Key"
/>
<button onClick={handleSave}>Guardar</button>
</div>
);
}
// Agregar widget al dashboard
@Component({
type: 'dashboard-widget',
title: 'Notificaciones WhatsApp Enviadas',
defaultSize: { w: 2, h: 1 }
})
export function WhatsAppStatsWidget() {
const [stats, setStats] = useState({ sent: 0, delivered: 0, failed: 0 });
useEffect(() => {
// Cargar estadísticas
const loadStats = async () => {
const data = await context.api.custom('/whatsapp/stats');
setStats(data);
};
loadStats();
}, []);
return (
<div className="widget">
<h3>WhatsApp Stats (Últimos 7 días)</h3>
<div>Enviados: {stats.sent}</div>
<div>Entregados: {stats.delivered}</div>
<div>Fallidos: {stats.failed}</div>
</div>
);
}
// Agregar botón en página de estimaciones
@Component({
type: 'action-button',
page: 'estimations.detail',
label: 'Enviar por WhatsApp',
icon: 'send'
})
export function SendEstimationButton({ estimation }: { estimation: Estimation }) {
const handleSend = async () => {
// Enviar estimación por WhatsApp
await sendEstimationViaWhatsApp(estimation);
};
return <button onClick={handleSend}>Enviar por WhatsApp</button>;
}
4. Servicios y Utilidades
import { Service, injectable } from '@erp-construccion/extension-sdk';
@Service()
export class WhatsAppService {
async sendMessage(phone: string, message: string) {
const apiKey = await this.context.settings.get('whatsapp_api_key');
const response = await fetch('https://api.whatsapp.com/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
to: phone,
message: message
})
});
if (!response.ok) {
throw new Error('Failed to send WhatsApp message');
}
// Registrar en audit log
await this.context.audit.log({
action: 'whatsapp.message_sent',
details: { phone, message }
});
return response.json();
}
async sendTemplate(phone: string, templateId: string, params: any) {
// Implementación de template
}
}
5. Storage (Persistencia)
// Cada extensión tiene su propio almacenamiento aislado por constructora
import { Storage } from '@erp-construccion/extension-sdk';
export class MiExtension {
async guardarConfig() {
// Guardar en storage de la extensión
await this.context.storage.set('mi_config', {
apiKey: 'xxx',
enabled: true,
lastSync: new Date()
});
}
async cargarConfig() {
const config = await this.context.storage.get('mi_config');
return config;
}
async eliminarConfig() {
await this.context.storage.delete('mi_config');
}
// Storage de archivos
async subirArchivo(file: File) {
const url = await this.context.storage.uploadFile(file, {
folder: 'whatsapp-attachments',
maxSize: 10 * 1024 * 1024, // 10 MB
allowedTypes: ['image/png', 'image/jpeg', 'application/pdf']
});
return url;
}
}
6. Notificaciones
import { Notifications } from '@erp-construccion/extension-sdk';
export class MiExtension {
async enviarNotificacion() {
// Notificación in-app
await this.context.notifications.send({
userId: 'user-123',
title: 'Estimación Aprobada',
message: 'La estimación #EST-2025-001 ha sido aprobada',
type: 'success',
link: '/estimations/EST-2025-001'
});
// Email
await this.context.notifications.sendEmail({
to: 'user@example.com',
subject: 'Estimación Aprobada',
template: 'estimation_approved',
data: {
estimationNumber: 'EST-2025-001',
amount: '$250,000 USD'
}
});
// SMS
await this.context.notifications.sendSMS({
phone: '+52 442 123 4567',
message: 'Estimación EST-2025-001 aprobada por $250,000 USD'
});
}
}
7. Scheduled Jobs (Tareas Programadas)
import { Job, Schedule } from '@erp-construccion/extension-sdk';
@Job()
export class SyncJob {
// Ejecutar cada hora
@Schedule('0 * * * *')
async syncData() {
console.log('Sincronizando datos con sistema externo...');
// Obtener datos pendientes
const pending = await this.context.storage.get('pending_sync');
// Sincronizar
for (const item of pending) {
await this.syncItem(item);
}
// Limpiar
await this.context.storage.delete('pending_sync');
}
// Ejecutar diariamente a las 2 AM
@Schedule('0 2 * * *')
async dailyReport() {
// Generar reporte diario
const report = await this.generateReport();
// Enviar por email
await this.context.notifications.sendEmail({
to: 'admin@company.com',
subject: 'Reporte Diario WhatsApp',
body: report
});
}
private async syncItem(item: any) {
// Implementación
}
private async generateReport() {
// Implementación
return 'Reporte...';
}
}
📦 Publicación en el Marketplace
1. Desarrollo Local
# Clonar template
git clone https://github.com/erp-construccion/extension-template
cd extension-template
# Instalar dependencias
npm install
# Desarrollo en modo watch
npm run dev
# Testing
npm test
# Build para producción
npm run build
2. Testing en Constructora de Prueba
# Subir extensión a constructora de prueba
npm run deploy --constructora=my-test-constructora
# Ver logs en tiempo real
npm run logs --constructora=my-test-constructora
3. Validación y Certificación
Checklist de validación:
- ✅ Todos los tests pasan (coverage ≥80%)
- ✅ Sin vulnerabilidades de seguridad (npm audit)
- ✅ Documentación completa (README.md)
- ✅ Screenshots/demo video
- ✅ Pricing definido
- ✅ Soporte definido (email, docs, SLA)
- ✅ Compatible con versiones de plataforma
- ✅ No usa APIs privadas/no documentadas
- ✅ Maneja errores gracefully
- ✅ Logs apropiados (no spam)
- ✅ Performance aceptable (no bloquea UI)
Revisión del equipo:
- Seguridad: Audit de código (SAST/DAST)
- Compliance: Verificación de licencias
- UX: Revisión de interfaz
- Performance: Load testing
4. Publicar al Marketplace
# Login con credenciales de desarrollador
npm run marketplace:login
# Publicar (primera vez)
npm run marketplace:publish
# Actualizar versión existente
npm run marketplace:publish --version=1.1.0 --changelog="Bug fixes"
Formulario de publicación:
name: "WhatsApp Notifier"
description: "Envía notificaciones automáticas por WhatsApp Business API"
category: "integrations"
version: "1.0.0"
author: "Mi Empresa"
support_email: "soporte@mi-empresa.com"
support_url: "https://docs.mi-empresa.com/whatsapp"
documentation_url: "https://docs.mi-empresa.com/whatsapp"
privacy_policy_url: "https://mi-empresa.com/privacy"
terms_url: "https://mi-empresa.com/terms"
pricing:
type: "free"
screenshots:
- url: "https://cdn.mi-empresa.com/screenshot1.png"
caption: "Dashboard principal"
- url: "https://cdn.mi-empresa.com/screenshot2.png"
caption: "Configuración"
demo_video: "https://youtube.com/watch?v=xxx"
keywords:
- whatsapp
- notifications
- messaging
compatible_plans:
- professional
- enterprise
permissions:
- notifications.send
- users.read
changelog: |
## v1.0.0 (2025-11-17)
- Initial release
- WhatsApp Business API integration
- Templates for estimations and budgets
💰 Modelos de Monetización
1. Gratis
pricing: {
type: 'free'
}
Casos de uso:
- Extensiones open-source
- Marketing (lead generation)
- Complemento de servicio principal
2. Pago Único
pricing: {
type: 'one_time',
amount: 49,
currency: 'USD'
}
Casos de uso:
- Templates
- Reportes estáticos
- Herramientas simples
3. Suscripción Mensual
pricing: {
type: 'subscription',
amount: 99,
currency: 'USD',
interval: 'month',
trial: {
enabled: true,
days: 14
}
}
Casos de uso:
- Integraciones
- Módulos con mantenimiento
- Servicios externos (APIs)
4. Basado en Uso
pricing: {
type: 'usage_based',
base: 29, // Base mensual
tiers: [
{ upTo: 1000, pricePerUnit: 0.05 }, // $0.05 por notificación
{ upTo: 10000, pricePerUnit: 0.03 },
{ upTo: null, pricePerUnit: 0.01 } // Ilimitado a $0.01
],
unit: 'notification'
}
Casos de uso:
- SMS/WhatsApp
- APIs externas con costo
- Servicios de IA/ML
5. Freemium
pricing: {
type: 'freemium',
free: {
limits: {
notifications: 100, // 100 notificaciones/mes gratis
users: 5
}
},
pro: {
amount: 49,
currency: 'USD',
interval: 'month',
limits: {
notifications: 10000,
users: null // Ilimitado
}
}
}
🔒 Seguridad de Extensiones
Sandboxing
Las extensiones corren en un entorno aislado:
// Restricciones automáticas:
- No pueden acceder directamente a la base de datos
- Solo pueden usar APIs expuestas por el SDK
- No pueden ejecutar código nativo
- Timeouts automáticos (30s por request)
- Rate limiting por constructora
- Memory limits (512 MB por extensión)
Permisos Granulares
permissions: [
'projects.read', // Leer proyectos
'projects.write', // Crear/editar proyectos
'budgets.read',
'users.read',
'notifications.send',
'files.upload',
'webhooks.create'
]
La constructora debe aprobar los permisos al instalar la extensión.
Audit Logging
Todas las acciones de extensiones se registran:
await this.context.audit.log({
action: 'extension.data_accessed',
extension: 'whatsapp-notifier',
resource: 'projects',
resourceId: 'proj-123',
details: { action: 'read' }
});
📊 Analytics para Desarrolladores
Dashboard de métricas de tu extensión:
┌─────────────────────────────────────────────────┐
│ WhatsApp Notifier - Analytics │
├─────────────────────────────────────────────────┤
│ │
│ 📊 Instalaciones │
│ Total: 234 tenants │
│ Activos: 198 (84.6%) │
│ Trial: 28 (12%) │
│ Cancelados: 8 (3.4%) │
│ │
│ 💰 Revenue (MRR) │
│ $0 (extensión gratuita) │
│ │
│ ⭐ Ratings │
│ Promedio: 4.7/5.0 (89 reviews) │
│ │
│ 📈 Uso │
│ Notificaciones enviadas (30 días): 45,678 │
│ Promedio por tenant: 230/mes │
│ │
│ 🐛 Errores (últimos 7 días) │
│ Total: 12 (0.026% error rate) │
│ Por tipo: │
│ - API timeout: 8 │
│ - Invalid phone: 3 │
│ - Rate limit: 1 │
│ │
└─────────────────────────────────────────────────┘
🎯 Casos de Éxito
Ejemplo 1: SAP Connector (Partner Oficial)
Desarrollador: SAP Integration Partners Tipo: Integración Pricing: $99/mes Instalaciones: 45 tenants enterprise MRR: $4,455
Descripción: Conecta el ERP de construcción con SAP S/4HANA para sincronizar pólizas contables, cuentas por pagar/cobrar y datos maestros.
Features:
- Sincronización bidireccional automática
- Mapping personalizable de cuentas
- Logs de sincronización
- Soporte 24/7
Ejemplo 2: Reporte INFONAVIT (Comunidad)
Desarrollador: Juan Pérez (independiente) Tipo: Reporte custom Pricing: $49 (one-time) Ventas: 127 instalaciones Revenue total: $6,223
Descripción: Genera el reporte oficial de INFONAVIT en formato EVC actualizado 2025, con todos los campos requeridos pre-llenados desde los datos del sistema.
Ejemplo 3: Módulo Obra Civil (Partner Certificado)
Desarrollador: CivilTech Solutions Tipo: Módulo vertical Pricing: $299/mes Instalaciones: 12 tenants MRR: $3,588
Descripción: Módulo especializado para constructoras de obra civil pesada (puentes, carreteras, presas) con funcionalidad específica de control de acarreos, laboratorio de suelos, y reportes para SCT.
🚀 Roadmap del SDK
Q1 2026:
- ✅ SDK v2.0 con TypeScript full support
- ✅ Webhooks mejorados (retry exponential backoff)
- ✅ GraphQL API (además de REST)
Q2 2026:
- 📋 Mobile SDK (React Native components)
- 📋 Extension templates (quickstart)
- 📋 CLI tool mejorado
Q3 2026:
- 📋 Serverless functions (AWS Lambda integration)
- 📋 Real-time data subscriptions (WebSockets)
- 📋 AI/ML integration (TensorFlow.js)
📚 Recursos
Documentación:
Comunidad:
Soporte:
- Email: developers@erp-construccion.com
- Office Hours: Viernes 10am-12pm PST (Zoom)
Generado: 2025-11-17 SDK Versión: 1.0.0 Modelo: SaaS Multi-tenant Marketplace