chore: catálogo obligaciones, cierre automático, fixes SAT y facturación
- Catálogo de obligaciones fiscales expandido a 30 entradas con campo requierePago. - Soporte de frecuencia cuatrimestral en obligaciones y declaraciones. - Automatización de cierre de obligaciones fiscales desde Documentos › Declaraciones. - Nuevas tablas obligacion_evidencias, obligacion_periodos estados y declaracion_obligaciones. - Nuevo servicio obligacion-evidencias.service.ts y endpoints REST. - Refactor de declaraciones.service.ts para vincular obligaciones y crear evidencias. - Notificaciones por email para evidencias de obligaciones. - Adjuntar PDFs en correo de declaración subida. - Fix drill-down de CFDIs: carga completa al visualizar. - Fix sincronización SAT: tipos P/N, UUID case-insensitive, no reutilizar requestId. - Fix suscripciones pending en /configuracion/planes-despacho. - Fix sugerencias de Clave Producto SAT: importar catálogo y robustecer autocomplete. - Quitar toggle manual de completado en Configuración › Obligaciones fiscales › Tareas. - Scripts de soporte para Demo Ventas y utilerías (change-user-email, resend-welcome, import-clave-prod-serv). - Documentación de cambios en docs/CAMBIOS-2026-05-04.md.
This commit is contained in:
67
apps/api/scripts/resend-welcome.ts
Normal file
67
apps/api/scripts/resend-welcome.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Script: resend-welcome
|
||||
*
|
||||
* Genera una nueva contraseña temporal para el usuario y reenvía el correo
|
||||
* de bienvenida. Útil cuando el envío anterior falló o se perdió.
|
||||
*
|
||||
* Ejecución:
|
||||
* cd apps/api && npx tsx scripts/resend-welcome.ts
|
||||
*/
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import { randomBytes } from 'crypto';
|
||||
import { emailService } from '../src/services/email/email.service.js';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const EMAIL = 'miguel.corona@corpcyl.com';
|
||||
|
||||
function generateTempPassword(length = 12): string {
|
||||
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789';
|
||||
let result = '';
|
||||
const bytes = randomBytes(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += chars[bytes[i] % chars.length];
|
||||
}
|
||||
return result + '!';
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const user = await prisma.user.findUnique({ where: { email: EMAIL } });
|
||||
if (!user) {
|
||||
console.error(`❌ No existe un usuario con el correo ${EMAIL}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const tempPassword = generateTempPassword();
|
||||
const passwordHash = await bcrypt.hash(tempPassword, 12);
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: {
|
||||
passwordHash,
|
||||
tokenVersion: { increment: 1 },
|
||||
},
|
||||
});
|
||||
|
||||
console.log('⏳ Enviando correo de bienvenida a', EMAIL, '...');
|
||||
await emailService.sendWelcome(EMAIL, {
|
||||
nombre: user.nombre,
|
||||
email: EMAIL,
|
||||
tempPassword,
|
||||
});
|
||||
|
||||
console.log('✅ Correo de bienvenida enviado');
|
||||
console.log(' Nombre:', user.nombre);
|
||||
console.log(' Email:', EMAIL);
|
||||
console.log(' Contraseña temporal:', tempPassword);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('\n❌ Error enviando correo:', e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user