From cc8a31319a5f7dcb0bb6baebeeaf6fe9082c2b93 Mon Sep 17 00:00:00 2001 From: evenegas Date: Fri, 28 Feb 2025 14:44:40 -0600 Subject: [PATCH] =?UTF-8?q?Se=20agreg=C3=B3=20el=20m=C3=B3dulo=20para=20ma?= =?UTF-8?q?ndar=20emails=20masivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 103 +++++++++++++++++++++++++- package.json | 4 +- src/app.module.ts | 7 +- src/excel/excel.controller.ts | 14 ++++ src/excel/excel.module.ts | 11 +++ src/excel/excel.service.ts | 36 +++++++++ src/excel_Usuarios/usuarios_fake.xlsx | Bin 0 -> 22638 bytes src/mail/mail.controller.ts | 21 +++++- src/mail/mail.module.ts | 2 + src/mail/mail.service.ts | 2 + votaciones | 29 ++++++++ 11 files changed, 225 insertions(+), 4 deletions(-) create mode 100644 src/excel/excel.controller.ts create mode 100644 src/excel/excel.module.ts create mode 100644 src/excel/excel.service.ts create mode 100644 src/excel_Usuarios/usuarios_fake.xlsx create mode 100644 votaciones diff --git a/package-lock.json b/package-lock.json index 6aa72ab..07d8eae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,12 @@ "@nestjs/swagger": "^11.0.5", "csv-parser": "^3.2.0", "dotenv": "^16.4.7", + "fs": "^0.0.1-security", "multer": "^1.4.5-lts.1", "nodemailer": "^6.10.0", "reflect-metadata": "^0.2.2", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "xlsx": "^0.18.5" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", @@ -3653,6 +3655,14 @@ "node": ">=0.4.0" } }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4347,6 +4357,18 @@ } ] }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4542,6 +4564,14 @@ "node": ">= 0.12.0" } }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", @@ -4731,6 +4761,17 @@ } } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -5997,6 +6038,14 @@ "node": ">= 0.6" } }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", @@ -6005,6 +6054,11 @@ "node": ">= 0.8" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -9157,6 +9211,17 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -10423,6 +10488,22 @@ "node": ">= 8" } }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -10530,6 +10611,26 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 06a9e8a..08cbb51 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,12 @@ "@nestjs/swagger": "^11.0.5", "csv-parser": "^3.2.0", "dotenv": "^16.4.7", + "fs": "^0.0.1-security", "multer": "^1.4.5-lts.1", "nodemailer": "^6.10.0", "reflect-metadata": "^0.2.2", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "xlsx": "^0.18.5" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", diff --git a/src/app.module.ts b/src/app.module.ts index 455467a..89cfbb1 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -2,8 +2,13 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { MailModule } from './mail/mail.module'; +import {ExcelModule} from './excel/excel.module' @Module({ - imports: [MailModule], + imports: [ + MailModule, + ExcelModule, + + ], controllers: [AppController], providers: [AppService], }) diff --git a/src/excel/excel.controller.ts b/src/excel/excel.controller.ts new file mode 100644 index 0000000..182d6b1 --- /dev/null +++ b/src/excel/excel.controller.ts @@ -0,0 +1,14 @@ +import { Controller, Get } from '@nestjs/common'; +import { ExcelService } from './excel.service'; + +@Controller('excel') +export class ExcelController { + constructor(private readonly excelService: ExcelService) {} + + @Get('read-emails') + async getEmails() { + const filePath = './src/excel_Usuarios/usuarios_fake.xlsx'; + const emails = this.excelService.readEmailsFromExcel(filePath); + return { emails }; + } +} diff --git a/src/excel/excel.module.ts b/src/excel/excel.module.ts new file mode 100644 index 0000000..8522693 --- /dev/null +++ b/src/excel/excel.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { ExcelService } from './excel.service'; +import { ExcelController } from './excel.controller'; + + +@Module({ + providers: [ExcelService], // Servicio que maneja la lectura de Excel + controllers: [ExcelController], // Controlador con los endpoints + exports: [ExcelService], // Exportarlo si se usa en otros módulos +}) +export class ExcelModule {} diff --git a/src/excel/excel.service.ts b/src/excel/excel.service.ts new file mode 100644 index 0000000..949a88d --- /dev/null +++ b/src/excel/excel.service.ts @@ -0,0 +1,36 @@ +import * as fs from 'fs'; +import * as XLSX from 'xlsx'; +import { Injectable } from '@nestjs/common'; + + + +@Injectable() +export class ExcelService { + readEmailsFromExcel(filePath: string): string[] { + console.log(` Verificando archivo en: ${filePath}`); + + if (!fs.existsSync(filePath)) { + console.error(' Archivo Excel NO encontrado'); + throw new Error('Archivo Excel no encontrado'); + } else { + console.log('Archivo Excel encontrado'); + } + + const workbook = XLSX.readFile(filePath); + const sheetName = workbook.SheetNames[0]; + const sheet = workbook.Sheets[sheetName]; + + const jsonData = XLSX.utils.sheet_to_json(sheet); + + console.log(`Datos extraídos:`, jsonData); + + // Extraer correos de la columna "Correo" + const emails = jsonData + .map((row: any) => row['Correo']) + .filter(email => email); + + console.log(` Correos extraídos:`, emails); + + return emails; + } +} diff --git a/src/excel_Usuarios/usuarios_fake.xlsx b/src/excel_Usuarios/usuarios_fake.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..420b7d19583b41af5b8f1f7dd9fff158144f1954 GIT binary patch literal 22638 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 bty}*^c