Muchos cambios
This commit is contained in:
Generated
+42
-6
@@ -23,6 +23,7 @@
|
||||
"blob-stream": "^0.1.3",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"exceljs": "^4.3.0",
|
||||
"moment": "^2.29.4",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
@@ -745,6 +746,17 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
|
||||
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
|
||||
@@ -4212,9 +4224,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
@@ -8919,6 +8934,11 @@
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||
@@ -11784,6 +11804,14 @@
|
||||
"@babel/helper-plugin-utils": "^7.19.0"
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
|
||||
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
|
||||
@@ -14464,9 +14492,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
}
|
||||
},
|
||||
"dayjs": {
|
||||
"version": "1.11.7",
|
||||
@@ -18066,6 +18097,11 @@
|
||||
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"regexp.prototype.flags": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"blob-stream": "^0.1.3",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"exceljs": "^4.3.0",
|
||||
"moment": "^2.29.4",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
|
||||
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 185 KiB |
+1
-4
@@ -46,8 +46,6 @@ import { EmailService } from './email/email.service';
|
||||
import { EmailController } from './email/email.controller';
|
||||
import { EmailModule } from './email/email.module';
|
||||
import { MulterModule } from '@nestjs/platform-express';
|
||||
import { CarouselController } from './carousel/carousel.controller';
|
||||
import { CarouselService } from './carousel/carousel.service';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
import { join } from 'path';
|
||||
import { CarruselModule } from './carrusel/carrusel.module';
|
||||
@@ -128,9 +126,8 @@ import { Carrusel } from './entities/carrusel.entity';
|
||||
AppController,
|
||||
ParticipanteController,
|
||||
InscripcionStatusController,
|
||||
CarouselController,
|
||||
],
|
||||
providers: [AppService, InscripcionStatusService, CarouselService],
|
||||
providers: [AppService, InscripcionStatusService],
|
||||
})
|
||||
export class AppModule {
|
||||
static port: number;
|
||||
|
||||
@@ -54,9 +54,11 @@ export class AuthService {
|
||||
/* console.log(token); */
|
||||
|
||||
const data = {
|
||||
usuario: usuario.nombre,
|
||||
id: usuario.id_miembro,
|
||||
email: usuario.email,
|
||||
user: {
|
||||
usuario: usuario.nombre,
|
||||
id: usuario.id_miembro,
|
||||
email: usuario.email,
|
||||
},
|
||||
token,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Param,
|
||||
Post,
|
||||
Res,
|
||||
UploadedFile,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { Response } from 'express';
|
||||
import * as fs from 'fs';
|
||||
import { diskStorage } from 'multer';
|
||||
import * as path from 'path';
|
||||
|
||||
@Controller('carousel')
|
||||
export class CarouselController {
|
||||
private images: string[] = [];
|
||||
|
||||
@Post('/imagenes')
|
||||
@UseInterceptors(
|
||||
FileInterceptor('file', {
|
||||
storage: diskStorage({
|
||||
destination: './public',
|
||||
filename: function (req, file, cb) {
|
||||
const directory = './public';
|
||||
const filePath = `${directory}/${file.originalname}`;
|
||||
if (fs.existsSync(filePath)) {
|
||||
cb(
|
||||
new BadRequestException(
|
||||
`Ya existe un archivo con el nombre: '${file.originalname}'. Si está seguro de que no es el mismo, cambie el nombre del archivo.`,
|
||||
),
|
||||
null,
|
||||
);
|
||||
} else {
|
||||
cb(null, file.originalname);
|
||||
}
|
||||
},
|
||||
}),
|
||||
fileFilter: function (req, file, cb) {
|
||||
const filetypes = /jpeg|jpg|webp|png/;
|
||||
const extname = filetypes.test(
|
||||
path.extname(file.originalname).toLowerCase(),
|
||||
);
|
||||
const mimetype = filetypes.test(file.mimetype);
|
||||
if (mimetype && extname) {
|
||||
return cb(null, true);
|
||||
}
|
||||
cb(
|
||||
new BadRequestException(
|
||||
'Lo sentimos, para mejorar la calidad de las imagenes en el carousel solo se aceptan imagenes con terminación: .jpeg .jpg .png .webp',
|
||||
),
|
||||
false,
|
||||
);
|
||||
},
|
||||
}),
|
||||
)
|
||||
async addImage(@UploadedFile() file) {
|
||||
return { msg: 'Imagen guardada con exito :)' };
|
||||
}
|
||||
|
||||
@Delete('/imagenes/:nombreArchivo')
|
||||
async deleteImage(@Param('nombreArchivo') nombreArchivo: string) {
|
||||
try {
|
||||
await fs.promises.unlink(`./public/${nombreArchivo}`);
|
||||
return { message: 'Imagen eliminada exitosamente' };
|
||||
} catch (err) {
|
||||
throw new Error('Error al eliminar la imagen');
|
||||
}
|
||||
}
|
||||
|
||||
@Get('/imagenes')
|
||||
async getImages(@Res() res: Response) {
|
||||
// Leer el directorio 'public' para obtener el nombre de todos los archivos
|
||||
|
||||
const fileNames = await fs.promises.readdir('./public');
|
||||
// Generar la URL para cada archivo y agregarla a un arreglo
|
||||
|
||||
// Filtrar solo las imágenes con las terminaciones "jpg", "webp" y "png"
|
||||
const imageNames = fileNames.filter((fileName) =>
|
||||
['.jpg', '.webp', '.png'].includes(path.extname(fileName)),
|
||||
);
|
||||
|
||||
const imageUrls = imageNames.map((imageName) => `public/${imageName}`);
|
||||
// Devolver el arreglo de URLs como respuesta
|
||||
return res.json(imageUrls);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class CarouselService {
|
||||
|
||||
uploadImage(file){
|
||||
/* console.log(file) */
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, Res } from '@nestjs/common';
|
||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, Res, UseGuards } from '@nestjs/common';
|
||||
import { Response } from 'express';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { EventoParticipante } from 'src/evento-participante/evento-participante/eventoParticipante.entity';
|
||||
@@ -7,6 +7,7 @@ import { actualizarEventoDto } from './dto/actualizarEvento.dto';
|
||||
import { crearEventoDto } from './dto/crearEvento.dto';
|
||||
import { Evento } from './evento.entity';
|
||||
import { EventosService } from './eventos.service';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@Controller('eventos')
|
||||
export class EventosController {
|
||||
@@ -23,16 +24,19 @@ export class EventosController {
|
||||
return this.eventoService.getEventosPorId(id)
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Post()
|
||||
postEvento(@Body() nuevoEvento: crearEventoDto){
|
||||
return this.eventoService.postEvento(nuevoEvento)
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Patch(':id')
|
||||
patchEvento(@Param('id', ParseIntPipe)id:number, @Body() actualizacion: actualizarEventoDto){
|
||||
return this.eventoService.updateEvento(id,actualizacion)
|
||||
}
|
||||
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Delete(':id')
|
||||
deleteEvento(@Param('id', ParseIntPipe)id: number){
|
||||
return this.eventoService.deleteEventoParticipante(id)
|
||||
@@ -43,11 +47,13 @@ export class EventosController {
|
||||
return this.eventoService.getCupos(id)
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Get(':id/participante')
|
||||
async getParticipnates(@Param('id', ParseIntPipe)id:number){
|
||||
return this.eventoService.getParticipantes(id)
|
||||
}
|
||||
|
||||
@UseGuards(AuthGuard('jwt'))
|
||||
@Get(':id/exportExcel')
|
||||
async exportarExcel (@Param('id', ParseIntPipe)id:number ,@Res() res: Response){
|
||||
this.eventoService.exportarParticipantes(id, res)
|
||||
|
||||
@@ -23,7 +23,7 @@ export class EventosService {
|
||||
return this.eventoRepository.find();
|
||||
}
|
||||
|
||||
getEventosPorId(id: number) {
|
||||
public getEventosPorId(id: number) {
|
||||
return this.eventoRepository.findOne({
|
||||
where: {
|
||||
id_evento: id,
|
||||
|
||||
Reference in New Issue
Block a user