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:
112
apps/api/scripts/reset-demo-asignaciones.ts
Normal file
112
apps/api/scripts/reset-demo-asignaciones.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Script: reset-demo-asignaciones
|
||||
*
|
||||
* Deja el tenant Demo Ventas listo para que el usuario haga manualmente
|
||||
* el flujo de asignación de carteras, obligaciones y tareas (útiles para tutoriales):
|
||||
* - Elimina la subcartera del auxiliar.
|
||||
* - Deja todos los contribuyentes en la cartera principal (sin auxiliar).
|
||||
* - Elimina asignaciones de obligaciones y tareas.
|
||||
* - Elimina la relación auxiliar → supervisor.
|
||||
*
|
||||
* Ejecución:
|
||||
* cd apps/api && npx tsx scripts/reset-demo-asignaciones.ts
|
||||
*/
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { tenantDb } from '../src/config/database.ts';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
const DEMO_RFC = 'DEMO2501019X2';
|
||||
|
||||
async function findUserIdByEmail(email: string): Promise<string | null> {
|
||||
const rows = await prisma.$queryRawUnsafe<{ id: string }[]>(
|
||||
`SELECT id FROM users WHERE email = $1 LIMIT 1`,
|
||||
email,
|
||||
);
|
||||
return rows[0]?.id ?? null;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🔄 Reseteando asignaciones de Demo Ventas para tutoriales...\n');
|
||||
|
||||
const tenants = await prisma.$queryRawUnsafe<{ id: string; database_name: string }[]>(
|
||||
`SELECT id, database_name FROM tenants WHERE rfc = $1 LIMIT 1`,
|
||||
DEMO_RFC,
|
||||
);
|
||||
const tenant = tenants[0];
|
||||
if (!tenant) throw new Error(`Tenant ${DEMO_RFC} no encontrado`);
|
||||
|
||||
const supervisorId = await findUserIdByEmail('supervisor@horuxfin.com');
|
||||
if (!supervisorId) throw new Error('Usuario supervisor no encontrado');
|
||||
|
||||
const auxiliarId = await findUserIdByEmail('auxiliar@horuxfin.com');
|
||||
|
||||
const pool = await tenantDb.getPool(tenant.id, tenant.database_name);
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
|
||||
// Eliminar asignaciones de obligaciones y tareas
|
||||
await client.query('DELETE FROM obligacion_asignaciones');
|
||||
await client.query('DELETE FROM tarea_asignaciones');
|
||||
console.log('✅ Asignaciones de obligaciones y tareas eliminadas');
|
||||
|
||||
// Obtener cartera principal
|
||||
const { rows: [carteraPrincipal] } = await client.query<{ id: string }>(`
|
||||
SELECT id FROM carteras WHERE parent_id IS NULL ORDER BY created_at LIMIT 1
|
||||
`);
|
||||
if (!carteraPrincipal) throw new Error('No existe cartera principal');
|
||||
|
||||
// Eliminar subcarteras (borra también cartera_entidades en cascade si hay FK)
|
||||
await client.query('DELETE FROM cartera_entidades WHERE cartera_id != $1', [carteraPrincipal.id]);
|
||||
await client.query('DELETE FROM carteras WHERE parent_id = $1', [carteraPrincipal.id]);
|
||||
console.log('✅ Subcarteras eliminadas');
|
||||
|
||||
// Limpiar cartera principal: sin auxiliar, supervisor demo
|
||||
await client.query(`
|
||||
UPDATE carteras SET auxiliar_user_id = NULL, supervisor_user_id = $1 WHERE id = $2
|
||||
`, [supervisorId, carteraPrincipal.id]);
|
||||
|
||||
// Agregar todos los contribuyentes a la cartera principal
|
||||
const { rows: contribuyentes } = await client.query<{ entidad_id: string }>(`
|
||||
SELECT entidad_id FROM contribuyentes
|
||||
`);
|
||||
|
||||
for (const c of contribuyentes) {
|
||||
await client.query(`
|
||||
INSERT INTO cartera_entidades (cartera_id, entidad_id)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT DO NOTHING
|
||||
`, [carteraPrincipal.id, c.entidad_id]);
|
||||
}
|
||||
console.log(`✅ ${contribuyentes.length} contribuyentes dejados en Cartera Principal`);
|
||||
|
||||
// Eliminar relación auxiliar → supervisor para que se cree en el tutorial
|
||||
if (auxiliarId) {
|
||||
await client.query('DELETE FROM auxiliar_supervisores WHERE auxiliar_user_id = $1', [auxiliarId]);
|
||||
console.log('✅ Relación auxiliar → supervisor eliminada');
|
||||
}
|
||||
|
||||
await client.query('COMMIT');
|
||||
} catch (err) {
|
||||
await client.query('ROLLBACK');
|
||||
throw err;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
|
||||
console.log('\n🎉 Demo Ventas listo para tutoriales');
|
||||
console.log(' - Cartera Principal con 6 contribuyentes, sin auxiliar');
|
||||
console.log(' - 48 obligaciones y 24 tareas sin asignar');
|
||||
console.log(' - Usuarios: owner, supervisor, auxiliar, cliente');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error('\n❌ Error:', e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
await tenantDb.shutdown();
|
||||
});
|
||||
Reference in New Issue
Block a user