Muchos cambios
This commit is contained in:
Binary file not shown.
@@ -8,6 +8,7 @@ import {
|
||||
Post,
|
||||
Res,
|
||||
UploadedFile,
|
||||
UseGuards,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
@@ -15,27 +16,36 @@ import { EmailDto } from './dto/emailDto.dto';
|
||||
import { EmailService } from './email.service';
|
||||
import { Response } from 'express';
|
||||
import * as xlsx from 'xlsx';
|
||||
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@Controller('email')
|
||||
export class EmailController {
|
||||
constructor(private readonly emailService: EmailService) {}
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Post('/evento/:id')
|
||||
async sendEmail(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() emailDto: EmailDto,
|
||||
@Res() res,
|
||||
): Promise<any> {
|
||||
return this.emailService.sendEmail(id, emailDto);
|
||||
return this.emailService.sendEmail(id, emailDto, res);
|
||||
}
|
||||
|
||||
@Post('constancias')
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Post('constancias/:id')
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
async sendConstancias(@UploadedFile() file, @Body('nombreEvento') nombreEvento: string,) {
|
||||
if(!file) {
|
||||
throw new HttpException("No se ha cargado ningun archivo", HttpStatus.BAD_REQUEST)
|
||||
async sendConstancias(
|
||||
@UploadedFile() file,
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Res() res,
|
||||
) {
|
||||
if (!file) {
|
||||
throw new HttpException(
|
||||
'No se ha cargado ningun archivo',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
/* console.log(file) */
|
||||
return this.emailService.sendConstancias(file, nombreEvento);
|
||||
return this.emailService.sendConstancias(file, id, res);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@ import { EventosModule } from 'src/eventos/eventos.module';
|
||||
import { Participante } from 'src/participante/participante.entity';
|
||||
import { EmailController } from './email.controller';
|
||||
import { EmailService } from './email.service';
|
||||
import { EventosService } from 'src/eventos/eventos.service';
|
||||
import { EventoParticipante } from 'src/evento-participante/evento-participante/eventoParticipante.entity';
|
||||
import { Evento } from 'src/eventos/evento.entity';
|
||||
|
||||
@Module({
|
||||
imports:[TypeOrmModule.forFeature([Participante])],
|
||||
imports:[TypeOrmModule.forFeature([Participante, EventoParticipante, Evento])],
|
||||
controllers:[EmailController],
|
||||
providers:[EmailService]
|
||||
providers:[EmailService, EventosService]
|
||||
})
|
||||
export class EmailModule {}
|
||||
|
||||
+103
-43
@@ -1,4 +1,11 @@
|
||||
import { HttpException, HttpStatus, Inject, Injectable, Res, UploadedFile } from '@nestjs/common';
|
||||
import {
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Injectable,
|
||||
Res,
|
||||
UploadedFile,
|
||||
} from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import * as nodemailer from 'nodemailer';
|
||||
@@ -13,6 +20,8 @@ import * as pdfFonts from 'pdfmake/build/vfs_fonts';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
|
||||
import { Response } from 'express';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
@Injectable()
|
||||
export class EmailService {
|
||||
@@ -22,6 +31,7 @@ export class EmailService {
|
||||
@InjectRepository(Participante)
|
||||
private participanteRepository: Repository<Participante>,
|
||||
private configService: ConfigService,
|
||||
private readonly eventoService: EventosService,
|
||||
) {
|
||||
this.transporter = nodemailer.createTransport({
|
||||
service: this.configService.get('NODEMAILER_SERVICE'),
|
||||
@@ -32,7 +42,7 @@ export class EmailService {
|
||||
});
|
||||
}
|
||||
|
||||
async sendEmail(id: number, message: EmailDto) {
|
||||
async sendEmail(id: number, message: EmailDto, res: Response) {
|
||||
const participantes = await this.getEmailDeParticipantes(id);
|
||||
participantes.map((res) => {
|
||||
const emailDestinatario = res.email;
|
||||
@@ -41,8 +51,8 @@ export class EmailService {
|
||||
subject: message.subject,
|
||||
text: message.text,
|
||||
});
|
||||
/*console.log("Email enviado a: ", res)*/
|
||||
});
|
||||
return res.status(201).json({ message: 'Correos enviados con exito' });
|
||||
}
|
||||
|
||||
async getEmailDeParticipantes(idEvento: number) {
|
||||
@@ -57,63 +67,113 @@ export class EmailService {
|
||||
return participantes;
|
||||
}
|
||||
|
||||
async sendConstancias(file, nombreEvento) {
|
||||
/* console.log(file) */
|
||||
async sendConstancias(file, id_evento, res: Response) {
|
||||
//traemos la info del evento
|
||||
const evento = await this.eventoService.getEventosPorId(id_evento);
|
||||
|
||||
const workbook = xlsx.read(file.buffer);
|
||||
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
const data = xlsx.utils.sheet_to_json(worksheet);
|
||||
|
||||
for (const row of data as Row[]) {
|
||||
const pdfDoc = await PDFDocument.create();
|
||||
const page = pdfDoc.addPage();
|
||||
page.setSize(792, 612);
|
||||
// Carga el PDF pre-diseñado
|
||||
const existingPdfBytes = fs.readFileSync('src/email/DisenoConstancia.pdf');
|
||||
|
||||
const font = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
||||
const fontSize = 30;
|
||||
const text = 'Constancia de asistencia';
|
||||
const textWidth = font.widthOfTextAtSize(text, fontSize);
|
||||
const textHeight = font.heightAtSize(fontSize);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const row = data[i] as Row;
|
||||
|
||||
page.drawText(text, {
|
||||
x: (page.getWidth() - textWidth) / 2,
|
||||
y: (page.getHeight() - textHeight) / 2,
|
||||
if(row.Email == undefined){
|
||||
return res.status(400).json({ message: `El correo del renglon ${ i + 2} puede estar vacio o ser undefined`, solucion: `Seleccione el renglon donde ocurre el problema y borre todo lo de este renglon, Aunque parezca que el renglon esta vacio puede que haya un espacio en algun campo y esto genera que el sistema haga la lectura de este renglon`});
|
||||
}
|
||||
|
||||
// Carga el PDF pre-diseñado en un documento PDF editable
|
||||
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
||||
|
||||
const pagina = pdfDoc.getPages();
|
||||
const primeraPagina = pagina[0];
|
||||
|
||||
// Obtén el ancho y alto de la página
|
||||
const { width, height } = primeraPagina.getSize();
|
||||
|
||||
// Obtén la fuente del texto
|
||||
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
||||
|
||||
// Configura el tamaño del texto
|
||||
const fontSize = 26;
|
||||
|
||||
const nombreParticipante = `${row['Apellido Paterno']} ${row['Apellido Materno']} ${row.Nombre}`;
|
||||
|
||||
// Calcula la anchura del texto del nombre del participante
|
||||
const textWidth = font.widthOfTextAtSize(nombreParticipante, fontSize);
|
||||
|
||||
const centerX = (width - textWidth) / 2;
|
||||
const centerY = (height - fontSize) / 2;
|
||||
|
||||
// Dibuja el texto centrado en la página
|
||||
primeraPagina.drawText(nombreParticipante, {
|
||||
x: centerX,
|
||||
y: centerY + 70,
|
||||
size: fontSize,
|
||||
font: font,
|
||||
color: rgb(0/255, 0/255, 0/255),
|
||||
color: rgb(0, 0, 0),
|
||||
});
|
||||
|
||||
const { width, height } = page.getSize();
|
||||
page.drawText(
|
||||
`Se le otorga la constancia por su asistencia al evento: ${nombreEvento}`,
|
||||
{
|
||||
x: 50,
|
||||
y: height - 50,
|
||||
size: 12,
|
||||
font: await pdfDoc.embedFont('Helvetica'),
|
||||
},
|
||||
);
|
||||
page.drawText(
|
||||
`A ${row['Apellido Paterno']} ${row['Apellido Materno']} ${row.Nombre}`,
|
||||
{
|
||||
x: 50,
|
||||
y: height - 80,
|
||||
size: 12,
|
||||
font: await pdfDoc.embedFont('Helvetica'),
|
||||
},
|
||||
);
|
||||
const nombreCurso = `${evento.nombre}`;
|
||||
|
||||
// Calcula la anchura del texto del nombre del evento
|
||||
const nombreCursoWidth = font.widthOfTextAtSize(nombreCurso, fontSize);
|
||||
|
||||
const centerXNombreCurso = (width - nombreCursoWidth) / 2;
|
||||
const centerYNombreCurso = (height - fontSize) / 2;
|
||||
|
||||
primeraPagina.drawText(nombreCurso, {
|
||||
x: centerXNombreCurso,
|
||||
y: centerYNombreCurso - 17,
|
||||
size: fontSize,
|
||||
color: rgb(0, 0, 0),
|
||||
});
|
||||
|
||||
const fechaCurso = `del ${this.formatoFecha(
|
||||
evento.fecha_inicio,
|
||||
)} al ${this.formatoFecha(evento.fecha_fin)}`;
|
||||
|
||||
// Calcula la anchura del texto del nombre del participante
|
||||
const fechaCursoWidth = font.widthOfTextAtSize(fechaCurso, 20);
|
||||
|
||||
const centerXFechaCurso = (width - fechaCursoWidth) / 2;
|
||||
const centerYFechaCurso = (height - 20) / 2;
|
||||
|
||||
primeraPagina.drawText(fechaCurso, {
|
||||
x: centerXFechaCurso,
|
||||
y: centerYFechaCurso - 55,
|
||||
size: 20,
|
||||
color: rgb(0, 0, 0),
|
||||
});
|
||||
|
||||
// Guarda el PDF modificado en forma de bytes
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
|
||||
// Crea el objeto de adjunto con el nombre y contenido del PDF
|
||||
const attachment = {
|
||||
filename: `Constancia ${nombreEvento} - ${row.Nombre}_${row['Apellido Paterno']}.pdf`,
|
||||
filename: `Constancia ${evento.nombre} - ${row.Nombre}_${row['Apellido Paterno']}.pdf`,
|
||||
content: pdfBytes,
|
||||
};
|
||||
/* const blob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(blob); */
|
||||
|
||||
// Crea el objeto Blob y la URL para el PDF
|
||||
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
|
||||
// Envía el correo electrónico con la constancia adjunta
|
||||
this.transporter.sendMail({
|
||||
to: row.Email,
|
||||
subject: `Constancia de asistencia a "${nombreEvento}"`,
|
||||
text: `¡Un saludo ${row.Nombre}! Aquí está tu constancia de asistencia por el evento "${nombreEvento}". Agradecemos tu asistencia y constancia, esperamos seguir viéndote en eventos futuros.`,
|
||||
subject: `Constancia de asistencia a "${evento.nombre}"`,
|
||||
text: `¡Un saludo ${row.Nombre}! Aquí está tu constancia de asistencia por el evento "${evento.nombre}". Agradecemos tu asistencia y constancia, esperamos seguir viéndote en eventos futuros.`,
|
||||
attachments: [attachment],
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({ message: 'Constancias enviadas con éxito' });
|
||||
}
|
||||
|
||||
formatoFecha(fecha: Date) {
|
||||
const fechaLimpia = format(fecha, 'dd/MM/yyyy');
|
||||
return fechaLimpia;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user