#!/usr/bin/env node /** * Importa el archivo COBRANZA PREVENTA a PlanPago + Pago. * Lee cada hoja de desarrollo, extrae clientes y sus pagos mensuales. */ import { PrismaClient } from '@prisma/client' import XLSX from 'xlsx' const prisma = new PrismaClient() const toStr = (v) => v == null ? null : String(v).trim() || null const toFloat = (v) => { if (v == null) return null if (typeof v === 'number') return v const n = parseFloat(String(v).replace(/[$,\s]/g, '')) return Number.isFinite(n) ? n : null } const toDate = (v) => { if (v == null) return null if (v instanceof Date) return v const n = Date.parse(String(v).trim()) return isNaN(n) ? null : new Date(n) } const DESARROLLOS = ['ZAFIRO', 'MUTUO', 'SOLE', 'ATELIER', 'ESTANZA', 'SOLANA I', 'SOLANA II', 'UMBRAL', 'DIAGONAL 40', 'SENDA'] const ruta = '/root/COBRANZA PREVENTA 060926.xlsx' console.log(`Leyendo: ${ruta}`) const wb = XLSX.readFile(ruta) let totalPlanes = 0, totalPagos = 0, errores = 0 for (const nombreHoja of DESARROLLOS) { const sheet = wb.Sheets[nombreHoja] if (!sheet) { console.log(` Hoja "${nombreHoja}" no encontrada, saltando`); continue } const rows = XLSX.utils.sheet_to_json(sheet, { header: 1, defval: null }) console.log(`\n ${nombreHoja}: ${rows.length} filas`) // Header row is typically row 2 (index 2), data starts at row 3 (index 3) // Find the header row with 'NOMBRE' or 'CTE' let headerIdx = -1 for (let i = 0; i < Math.min(rows.length, 5); i++) { if (rows[i]?.[2] && String(rows[i][2]).includes('NOMBRE')) { headerIdx = i break } } if (headerIdx === -1) { console.log(` No se encontrĂ³ header en ${nombreHoja}, saltando`) continue } const dataRows = rows.slice(headerIdx + 1) let hojaPlanes = 0, hojaPagos = 0 for (const row of dataRows) { const unidadCodigo = toStr(row[0]) const clienteId = toStr(row[1]) const clienteNombre = toStr(row[2]) if (!clienteNombre || clienteNombre.length < 3) continue const precioVenta = toFloat(row[3]) || 0 const fechaVenta = toDate(row[4]) const tipoVenta = toStr(row[5]) || '' const asesor = toStr(row[6]) || '' const apartadoPagado = toFloat(row[10]) || 0 const enganchePagado = toFloat(row[11]) || 0 const meses = parseInt(String(row[13] || '0')) || 0 const mesInicio = toDate(row[14]) const mensualidad = toFloat(row[16]) || 0 const totalPagado = toFloat(row[58]) || 0 // Create PlanPago try { const plan = await prisma.planPago.create({ data: { ventaRef: clienteId || null, clienteNombre, clienteTelefono: null, unidadCodigo: unidadCodigo || '', proyecto: nombreHoja, fechaInicio: mesInicio || fechaVenta || new Date(), engancheTotal: apartadoPagado + enganchePagado, numPagos: meses || 1, mensualidad, tasaMoraMensual: 0, status: 'ACTIVO', vendedorId: null, }, }) hojaPlanes++ // Create Pago records for each month with a value let numPago = 1 for (let col = 20; col <= 43; col++) { const montoMes = toFloat(row[col]) if (montoMes && montoMes > 0) { // Calculate date for this payment month const fechaMes = new Date(2025, 7 + (col - 20), 1) // Starting from Aug 2025 await prisma.pago.create({ data: { planId: plan.id, numPago, fechaVencimiento: fechaMes, monto: montoMes, montoPagado: 0, // Will be updated if we have payment data }, }) hojaPagos++ numPago++ } } } catch (err) { errores++ if (errores <= 3) console.log(` Error: ${clienteNombre} - ${err.message?.slice(0, 100)}`) } } totalPlanes += hojaPlanes totalPagos += hojaPagos console.log(` ${hojaPlanes} planes, ${hojaPagos} pagos`) } console.log(`\n=== Resumen ===`) console.log(`Planes creados: ${totalPlanes}`) console.log(`Pagos creados: ${totalPagos}`) console.log(`Errores: ${errores}`) await prisma.$disconnect()