From a5da2624697b82d3f6a6d1ab2585375777fc8fd1 Mon Sep 17 00:00:00 2001 From: miguel Date: Mon, 28 Jul 2025 21:52:03 -0600 Subject: [PATCH 1/3] Add Almacenamiento module, controller, service, and entity for data management --- .../almacenamiento.controller.ts | 23 ++++++++++++++ src/almacenamiento/almacenamiento.module.ts | 31 +++++++++++++++++++ src/almacenamiento/almacenamiento.service.ts | 23 ++++++++++++++ src/app.module.ts | 4 ++- src/entities/almacenamiento.entity.ts | 16 ++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/almacenamiento/almacenamiento.controller.ts create mode 100644 src/almacenamiento/almacenamiento.module.ts create mode 100644 src/almacenamiento/almacenamiento.service.ts create mode 100644 src/entities/almacenamiento.entity.ts diff --git a/src/almacenamiento/almacenamiento.controller.ts b/src/almacenamiento/almacenamiento.controller.ts new file mode 100644 index 0000000..528eb0a --- /dev/null +++ b/src/almacenamiento/almacenamiento.controller.ts @@ -0,0 +1,23 @@ +import { Controller, Post, Get, Body } from '@nestjs/common'; +import { AlmacenamientoService } from './almacenamiento.service'; + +@Controller('almacenamiento') +export class AlmacenamientoController { + constructor(private readonly almacenamientoService: AlmacenamientoService) {} + + @Post() + async create(@Body() body: { email: string; agree: boolean }) { + // Save only if agree is true + if (!body.agree) { + return { message: 'User did not agree', data: body }; + } + const saved = await this.almacenamientoService.create(body.email); + return { message: 'Data saved', data: saved }; + } + + @Get() + async findAll() { + const data = await this.almacenamientoService.findAll(); + return { message: 'GET endpoint reached', data }; + } +} diff --git a/src/almacenamiento/almacenamiento.module.ts b/src/almacenamiento/almacenamiento.module.ts new file mode 100644 index 0000000..af83d13 --- /dev/null +++ b/src/almacenamiento/almacenamiento.module.ts @@ -0,0 +1,31 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Almacenamiento } from '../entities/almacenamiento.entity'; +import { AlmacenamientoService } from './almacenamiento.service'; +import { AlmacenamientoController } from './almacenamiento.controller'; +import { ConfigModule, ConfigService } from '@nestjs/config'; + +@Module({ + imports: [ + TypeOrmModule.forRootAsync({ + name: 'almacenamiento', + imports: [ConfigModule], + inject: [ConfigService], + useFactory: async (configService: ConfigService) => ({ + name: 'almacenamiento', + type: 'mariadb', + host: configService.get('HOST_TYL'), + port: configService.get('PORT_TYL'), + username: configService.get('USUARIO_TYL'), + password: configService.get('CONTRASENA_TYL'), + database: configService.get('DATABASE_TYL'), + entities: [Almacenamiento], + synchronize: false, + }), + }), + TypeOrmModule.forFeature([Almacenamiento], 'almacenamiento'), + ], + providers: [AlmacenamientoService], + controllers: [AlmacenamientoController], +}) +export class AlmacenamientoModule {} diff --git a/src/almacenamiento/almacenamiento.service.ts b/src/almacenamiento/almacenamiento.service.ts new file mode 100644 index 0000000..a5b6718 --- /dev/null +++ b/src/almacenamiento/almacenamiento.service.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Almacenamiento } from '../entities/almacenamiento.entity'; + +@Injectable() +export class AlmacenamientoService { + constructor( + @InjectRepository(Almacenamiento, 'almacenamiento') + private readonly almacenamientoRepository: Repository, + ) {} + + // Example method to create a new record + async create(correo: string): Promise { + const nuevo = this.almacenamientoRepository.create({ correo }); + return this.almacenamientoRepository.save(nuevo); + } + + // Example method to get all records + async findAll(): Promise { + return this.almacenamientoRepository.find(); + } +} diff --git a/src/app.module.ts b/src/app.module.ts index 07d553e..cb4978b 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -52,6 +52,8 @@ import { CarruselModule } from './carrusel/carrusel.module'; import { Carrusel } from './entities/carrusel.entity'; import { ComentariosModule } from './comentarios/comentarios.module'; import { Comentarios } from './comentarios/entity/comentarios.entity'; +import { AlmacenamientoModule } from './almacenamiento/almacenamiento.module'; +import { Almacenamiento } from './entities/almacenamiento.entity'; @Module({ imports: [ @@ -100,7 +102,6 @@ import { Comentarios } from './comentarios/entity/comentarios.entity'; /* No recuerdo porque empece a ponerle fechas */ Comentarios, ], - synchronize: true, }), }), EventosModule, @@ -127,6 +128,7 @@ import { Comentarios } from './comentarios/entity/comentarios.entity'; }), CarruselModule, ComentariosModule, + AlmacenamientoModule, ], controllers: [ AppController, diff --git a/src/entities/almacenamiento.entity.ts b/src/entities/almacenamiento.entity.ts new file mode 100644 index 0000000..c25f994 --- /dev/null +++ b/src/entities/almacenamiento.entity.ts @@ -0,0 +1,16 @@ +import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity('almacenamiento') +export class Almacenamiento { + @PrimaryGeneratedColumn({ type: 'int', name: 'id_almacenamiento' }) + idAlmacenamiento: number; + + @Column('varchar', { name: 'correo', length: 100 }) + correo: string; + + @Column('timestamp', { + name: 'fecha_ampliacion', + default: () => 'CURRENT_TIMESTAMP', + }) + fechaAmpliacion: Date; +} -- 2.43.0 From 5c68472a85abef729dd51c2b8999c19d3a550715 Mon Sep 17 00:00:00 2001 From: santiago Date: Wed, 30 Jul 2025 14:16:14 -0600 Subject: [PATCH 2/3] Agregar funcionalidad para agregar almacenamiento en la base de cedetec de T&L --- .env.example | 13 +++- package-lock.json | 68 +++++++++++++------ package.json | 2 +- .../almacenamiento.controller.ts | 5 +- src/almacenamiento/almacenamiento.module.ts | 5 +- src/almacenamiento/almacenamiento.service.ts | 8 ++- src/app.module.ts | 1 + 7 files changed, 71 insertions(+), 31 deletions(-) diff --git a/.env.example b/.env.example index ce26c2b..543bc3f 100644 --- a/.env.example +++ b/.env.example @@ -12,4 +12,15 @@ DB_NAME_DSC= NODEMAILER_SERVICE= NODEMAILER_USER= -NODEMAILER_PASWORD= \ No newline at end of file +NODEMAILER_PASWORD= + +#132.248.180.82 +#3306 +#usr_tl +#A1m_p@$ +#Betelgeuse_TL_test +HOST_TYL=132.248.180.82 +PORT_TYL=3306 +USUARIO_TYL=usr_tl +CONTRASENA_TYL=A1m_p@$ +DATABASE_TYL=Betelgeuse_TL_test diff --git a/package-lock.json b/package-lock.json index eb25f65..9ca6cb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "exceljs": "^4.3.0", "moment": "^2.29.4", "multer": "^1.4.5-lts.1", - "mysql2": "^3.1.2", + "mysql2": "^3.14.3", "nodemailer": "^6.9.1", "passport": "^0.6.0", "passport-jwt": "^4.0.1", @@ -3188,6 +3188,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/babel-jest": { "version": "29.4.2", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.2.tgz", @@ -7531,6 +7540,21 @@ "yallist": "^3.0.2" } }, + "node_modules/lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/macos-release": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", @@ -7813,15 +7837,17 @@ "dev": true }, "node_modules/mysql2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.1.2.tgz", - "integrity": "sha512-NXz6sUvHSEOKz1jv3koSga7eb2dHrwD/mnPmqbbZzMRvjQcSpb0Eh0ectWyYt1U60CLlEbjoA3XYjjbbReRF5Q==", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz", + "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==", + "license": "MIT", "dependencies": { + "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.6.3", "long": "^5.2.1", - "lru-cache": "^7.14.1", + "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" @@ -7841,14 +7867,6 @@ "node": ">=0.10.0" } }, - "node_modules/mysql2/node_modules/lru-cache": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.1.tgz", - "integrity": "sha512-8/HcIENyQnfUTCDizRu9rrDyG6XG/21M4X7/YEGZeD76ZJilFPAUVb/2zysFf7VVO1LEjCDFyHp8pMMvozIrvg==", - "engines": { - "node": ">=12" - } - }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -13713,6 +13731,11 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, + "aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==" + }, "babel-jest": { "version": "29.4.2", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.2.tgz", @@ -17034,6 +17057,11 @@ "yallist": "^3.0.2" } }, + "lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==" + }, "macos-release": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", @@ -17247,15 +17275,16 @@ "dev": true }, "mysql2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.1.2.tgz", - "integrity": "sha512-NXz6sUvHSEOKz1jv3koSga7eb2dHrwD/mnPmqbbZzMRvjQcSpb0Eh0ectWyYt1U60CLlEbjoA3XYjjbbReRF5Q==", + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz", + "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==", "requires": { + "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.6.3", "long": "^5.2.1", - "lru-cache": "^7.14.1", + "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" @@ -17268,11 +17297,6 @@ "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } - }, - "lru-cache": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.1.tgz", - "integrity": "sha512-8/HcIENyQnfUTCDizRu9rrDyG6XG/21M4X7/YEGZeD76ZJilFPAUVb/2zysFf7VVO1LEjCDFyHp8pMMvozIrvg==" } } }, diff --git a/package.json b/package.json index ceb6d77..1b656df 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "exceljs": "^4.3.0", "moment": "^2.29.4", "multer": "^1.4.5-lts.1", - "mysql2": "^3.1.2", + "mysql2": "^3.14.3", "nodemailer": "^6.9.1", "passport": "^0.6.0", "passport-jwt": "^4.0.1", diff --git a/src/almacenamiento/almacenamiento.controller.ts b/src/almacenamiento/almacenamiento.controller.ts index 528eb0a..fb8682a 100644 --- a/src/almacenamiento/almacenamiento.controller.ts +++ b/src/almacenamiento/almacenamiento.controller.ts @@ -6,12 +6,11 @@ export class AlmacenamientoController { constructor(private readonly almacenamientoService: AlmacenamientoService) {} @Post() - async create(@Body() body: { email: string; agree: boolean }) { - // Save only if agree is true + async create(@Body() body: { correo: string; agree: boolean }) { if (!body.agree) { return { message: 'User did not agree', data: body }; } - const saved = await this.almacenamientoService.create(body.email); + const saved = await this.almacenamientoService.create(body.correo); return { message: 'Data saved', data: saved }; } diff --git a/src/almacenamiento/almacenamiento.module.ts b/src/almacenamiento/almacenamiento.module.ts index af83d13..a557732 100644 --- a/src/almacenamiento/almacenamiento.module.ts +++ b/src/almacenamiento/almacenamiento.module.ts @@ -15,12 +15,13 @@ import { ConfigModule, ConfigService } from '@nestjs/config'; name: 'almacenamiento', type: 'mariadb', host: configService.get('HOST_TYL'), - port: configService.get('PORT_TYL'), + port: Number(configService.get('PORT_TYL')), username: configService.get('USUARIO_TYL'), password: configService.get('CONTRASENA_TYL'), database: configService.get('DATABASE_TYL'), entities: [Almacenamiento], - synchronize: false, + synchronize: true, + ssl: false, // <- importante }), }), TypeOrmModule.forFeature([Almacenamiento], 'almacenamiento'), diff --git a/src/almacenamiento/almacenamiento.service.ts b/src/almacenamiento/almacenamiento.service.ts index a5b6718..39a5e50 100644 --- a/src/almacenamiento/almacenamiento.service.ts +++ b/src/almacenamiento/almacenamiento.service.ts @@ -12,8 +12,12 @@ export class AlmacenamientoService { // Example method to create a new record async create(correo: string): Promise { - const nuevo = this.almacenamientoRepository.create({ correo }); - return this.almacenamientoRepository.save(nuevo); + const existente = await this.almacenamientoRepository.findOneBy({ correo }); + if (existente) { + return existente; // o lanzar un error si prefieres + } + const nuevo = this.almacenamientoRepository.create({ correo }); + return this.almacenamientoRepository.save(nuevo); } // Example method to get all records diff --git a/src/app.module.ts b/src/app.module.ts index cb4978b..ac20313 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -75,6 +75,7 @@ import { Almacenamiento } from './entities/almacenamiento.entity'; username: configService.get('DB_USER'), password: configService.get('DB_PASSWORD'), database: configService.get('DB_NAME'), + synchronize: true, entities: [ Evento, Participante, -- 2.43.0 From d6f28003b3a42b856bd882fa68040a263def65a2 Mon Sep 17 00:00:00 2001 From: miguel Date: Tue, 12 Aug 2025 14:56:34 -0600 Subject: [PATCH 3/3] Implement deleteAllCarrusel method to remove all images and database records from the carrusel --- src/carrusel/carrusel.controller.ts | 5 +++ src/carrusel/carrusel.service.ts | 50 +++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/carrusel/carrusel.controller.ts b/src/carrusel/carrusel.controller.ts index 8ad3d09..d7102ca 100644 --- a/src/carrusel/carrusel.controller.ts +++ b/src/carrusel/carrusel.controller.ts @@ -57,4 +57,9 @@ export class CarruselController { getAllImagenes() { return this.carruselService.getAllImages(); } + + @Delete('deleteAll') + deleteAllCarrusel() { + return this.carruselService.deleteAllCarrusel(); + } } diff --git a/src/carrusel/carrusel.service.ts b/src/carrusel/carrusel.service.ts index 4a6c602..7c4624b 100644 --- a/src/carrusel/carrusel.service.ts +++ b/src/carrusel/carrusel.service.ts @@ -1,10 +1,14 @@ -import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common'; +import { + BadRequestException, + Injectable, + InternalServerErrorException, +} from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Carrusel } from 'src/entities/carrusel.entity'; import { Repository } from 'typeorm'; import { carruselDto } from './dto/carruselDto.dto'; import * as fs from 'fs'; -import { Response } from 'express'; +import * as path from 'path'; @Injectable() export class CarruselService { @@ -74,4 +78,46 @@ export class CarruselService { getAllImages(): Promise { return this.carruselRepository.find(); } + + async deleteAllCarrusel(): Promise<{ message: string }> { + try { + // Obtener todas las imágenes del carrusel + const images = await this.carruselRepository.find(); + + // Eliminar archivos físicos de la carpeta public/carrusel + const carruselDir = './public/carrusel'; + + if (fs.existsSync(carruselDir)) { + // Leer todos los archivos en el directorio + const files = await fs.promises.readdir(carruselDir); + + // Eliminar cada archivo + for (const file of files) { + const filePath = path.join(carruselDir, file); + try { + await fs.promises.unlink(filePath); + console.log(`✅ Archivo eliminado: ${filePath}`); + } catch (fileError) { + console.warn( + `⚠️ No se pudo eliminar el archivo: ${filePath}`, + fileError.message, + ); + } + } + } + + // Eliminar todos los registros de la base de datos + await this.carruselRepository.delete({}); + + return { + message: `Carrusel limpiado exitosamente. Se eliminaron ${images.length} imágenes y registros.`, + }; + } catch (error) { + console.error('❌ Error al limpiar el carrusel:', error); + throw new InternalServerErrorException({ + message: 'Ocurrió un error inesperado al limpiar el carrusel', + error: error.message, + }); + } + } } -- 2.43.0