- Backend NestJS con módulos de autenticación, inventario, créditos - Frontend React con dashboard y componentes UI - Base de datos PostgreSQL con migraciones - Tests E2E configurados - Configuración de Docker y deployment Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.8 KiB
5.8 KiB
INT-004: Integracion Firebase FCM
id: INT-004 type: Integration status: Pendiente version: "1.0.0" created_date: 2026-01-10 updated_date: 2026-01-10 simco_version: "4.0.0"
Metadata
| Campo | Valor |
|---|---|
| ID | INT-004 |
| Servicio | Firebase Cloud Messaging |
| Proposito | Notificaciones push |
| Criticidad | P1 |
| Estado | Pendiente |
1. Descripcion
Integracion con Firebase Cloud Messaging (FCM) para enviar notificaciones push a los usuarios sobre resultados de inventario, pagos y otros eventos.
2. Informacion del Servicio
| Campo | Valor |
|---|---|
| Proveedor | Google Firebase |
| Documentacion | https://firebase.google.com/docs/cloud-messaging |
| Consola | https://console.firebase.google.com |
| SDK | firebase-admin (node), @react-native-firebase/messaging |
3. Configuracion
Variables de Entorno
FIREBASE_PROJECT_ID=miinventario-xxx
FIREBASE_CLIENT_EMAIL=firebase-adminsdk@...
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n..."
Instalacion Backend
npm install firebase-admin
Instalacion Mobile
npm install @react-native-firebase/app @react-native-firebase/messaging
4. Tipos de Notificaciones
| Tipo | Evento | Prioridad |
|---|---|---|
| INVENTORY_READY | Inventario procesado | Alta |
| PAYMENT_CONFIRMED | Pago confirmado | Alta |
| PAYMENT_PENDING | Voucher por vencer | Media |
| REFERRAL_ACTIVATED | Referido activado | Media |
| LOW_CREDITS | Creditos bajos | Baja |
| PROMO_ACTIVE | Promocion activa | Baja |
5. Implementacion Backend
Inicializacion
import * as admin from 'firebase-admin';
@Module({})
export class FirebaseModule {
static forRoot(): DynamicModule {
admin.initializeApp({
credential: admin.credential.cert({
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
}),
});
return {
module: FirebaseModule,
global: true,
};
}
}
Servicio de Notificaciones
@Injectable()
export class NotificationsService {
async sendToUser(
userId: string,
notification: { title: string; body: string; data?: Record<string, string> }
) {
const user = await this.usersService.findOne(userId);
if (!user.fcmToken) return;
await admin.messaging().send({
token: user.fcmToken,
notification: {
title: notification.title,
body: notification.body,
},
data: notification.data,
android: {
priority: 'high',
notification: {
channelId: 'default',
sound: 'default',
},
},
apns: {
payload: {
aps: {
sound: 'default',
badge: 1,
},
},
},
});
}
async sendToTopic(
topic: string,
notification: { title: string; body: string }
) {
await admin.messaging().sendToTopic(topic, {
notification,
});
}
}
6. Implementacion Mobile
Configuracion
// App.tsx
import messaging from '@react-native-firebase/messaging';
const requestPermission = async () => {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
const token = await messaging().getToken();
await api.updateFcmToken(token);
}
};
Handlers
// Foreground
messaging().onMessage(async remoteMessage => {
// Mostrar notificacion in-app
showLocalNotification(remoteMessage);
});
// Background/Quit
messaging().setBackgroundMessageHandler(async remoteMessage => {
// Procesar datos
console.log('Background message:', remoteMessage);
});
// Tap en notificacion
messaging().onNotificationOpenedApp(remoteMessage => {
// Navegar a pantalla
navigateToScreen(remoteMessage.data.screen);
});
7. Modelo de Datos
Tabla: notification_tokens
CREATE TABLE notification_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
token VARCHAR(255) NOT NULL,
platform VARCHAR(20), -- 'ios', 'android'
device_info JSONB,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
Tabla: notification_logs
CREATE TABLE notification_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
type VARCHAR(50),
title VARCHAR(255),
body TEXT,
data JSONB,
sent_at TIMESTAMP DEFAULT NOW(),
delivered_at TIMESTAMP,
opened_at TIMESTAMP
);
8. Templates de Notificacion
const NOTIFICATION_TEMPLATES = {
INVENTORY_READY: {
title: 'Inventario listo',
body: 'Tu inventario de {{storeName}} esta listo. {{totalItems}} productos detectados.',
},
PAYMENT_CONFIRMED: {
title: 'Pago confirmado',
body: 'Tu pago de ${{amount}} MXN fue confirmado. +{{credits}} creditos.',
},
REFERRAL_ACTIVATED: {
title: 'Referido activado',
body: '{{referredName}} activo su cuenta. +{{reward}} creditos.',
},
};
9. Testing
Enviar Notificacion de Prueba
# Usando Firebase CLI
firebase messaging:send \
--token "device_token" \
--notification-title "Test" \
--notification-body "This is a test"
Simulador iOS
FCM no funciona en simulador iOS. Usar dispositivo fisico o Expo Go.
10. Referencias
- Firebase FCM Docs
- React Native Firebase
- MII-005 - Notificacion de resultado
Ultima Actualizacion: 2026-01-10