From 3350b1bc2881b1e75197055fd5959dcde4daccae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:28:13 -0600 Subject: [PATCH 01/30] agregando dtos para categories --- .../src/category/dto/create-category-req.dto.ts | 8 ++++++++ backend/src/category/dto/create-category.dto.ts | 7 +++++++ backend/src/category/dto/update-category.dto.ts | 4 ++++ backend/src/category/entities/category.entity.ts | 14 ++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 backend/src/category/dto/create-category-req.dto.ts create mode 100644 backend/src/category/dto/create-category.dto.ts create mode 100644 backend/src/category/dto/update-category.dto.ts create mode 100644 backend/src/category/entities/category.entity.ts diff --git a/backend/src/category/dto/create-category-req.dto.ts b/backend/src/category/dto/create-category-req.dto.ts new file mode 100644 index 00000000..3f1e6b18 --- /dev/null +++ b/backend/src/category/dto/create-category-req.dto.ts @@ -0,0 +1,8 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateCategoryReqDto { + @ApiProperty() + nameES: string; + @ApiProperty() + nameEN: string; +} diff --git a/backend/src/category/dto/create-category.dto.ts b/backend/src/category/dto/create-category.dto.ts new file mode 100644 index 00000000..eab17f0d --- /dev/null +++ b/backend/src/category/dto/create-category.dto.ts @@ -0,0 +1,7 @@ +import { LANGUAGES } from 'src/shared/enum/languages.enum'; + +export class CreateCategoryDto { + idCategory?: number; + language: LANGUAGES; + name: string; +} diff --git a/backend/src/category/dto/update-category.dto.ts b/backend/src/category/dto/update-category.dto.ts new file mode 100644 index 00000000..d713b9b9 --- /dev/null +++ b/backend/src/category/dto/update-category.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateCategoryDto } from './create-category.dto'; + +export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {} diff --git a/backend/src/category/entities/category.entity.ts b/backend/src/category/entities/category.entity.ts new file mode 100644 index 00000000..1eaed7c7 --- /dev/null +++ b/backend/src/category/entities/category.entity.ts @@ -0,0 +1,14 @@ +import { LANGUAGES } from 'src/shared/enum/languages.enum'; +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity() +export class Category { + @PrimaryGeneratedColumn() + idCategory: number; + + @Column({ nullable: false, primary: true, type: 'enum', enum: LANGUAGES }) + language: LANGUAGES; + + @Column({ nullable: false }) + name: string; +} -- GitLab From 2a54fab181f9495e2613e988b5f491bde608d3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:28:31 -0600 Subject: [PATCH 02/30] agregando controlador para category --- backend/src/category/category.controller.ts | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 backend/src/category/category.controller.ts diff --git a/backend/src/category/category.controller.ts b/backend/src/category/category.controller.ts new file mode 100644 index 00000000..c5395cfc --- /dev/null +++ b/backend/src/category/category.controller.ts @@ -0,0 +1,43 @@ +import { Controller, Get, Post, Body, Param, Delete, UseGuards } from '@nestjs/common'; +import { CategoryService } from './category.service'; +import { AuthAdminGuard } from 'src/auth/admin/authAdmin.guard'; +import { Roles } from 'src/auth/role.decorator'; +import { SUPERADMIN_ROLES } from 'src/shared/enum/admin-role.enum'; +import { ApiBearerAuth, ApiBody, ApiTags } from '@nestjs/swagger'; +import { CreateCategoryReqDto } from './dto/create-category-req.dto'; +import { LANGUAGES } from 'src/shared/enum/languages.enum'; + +@Controller('category') +@ApiTags('Category') +export class CategoryController { + constructor(private readonly categoryService: CategoryService) {} + + @UseGuards(AuthAdminGuard) + @Roles(SUPERADMIN_ROLES) + @ApiBearerAuth('jwt') + @ApiBody({ type: CreateCategoryReqDto }) + @Post() + create(@Body() createCategoryDto: CreateCategoryReqDto) { + this.categoryService.create(createCategoryDto); + return { message: 'Category created successfully' }; + } + + @Get(':lang') + findAll(@Param('lang') lang: LANGUAGES) { + return this.categoryService.findAll(lang); + } + + // @Patch(':id') + // update(@Param('id') id: string, @Body() updateCategoryDto: UpdateCategoryDto) { + // return this.categoryService.update(+id, updateCategoryDto); + // } + + @UseGuards(AuthAdminGuard) + @Roles(SUPERADMIN_ROLES) + @ApiBearerAuth('jwt') + @Delete(':id') + remove(@Param('id') id: string) { + this.categoryService.remove(+id); + return { message: 'Category deleted successfully' }; + } +} -- GitLab From c60bffaf4df5c8ffc74f0ec8177cea6040dfad7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:28:49 -0600 Subject: [PATCH 03/30] agregando servicio para category --- backend/src/category/category.service.ts | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 backend/src/category/category.service.ts diff --git a/backend/src/category/category.service.ts b/backend/src/category/category.service.ts new file mode 100644 index 00000000..7531340d --- /dev/null +++ b/backend/src/category/category.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@nestjs/common'; +import { CreateCategoryDto } from './dto/create-category.dto'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Category } from './entities/category.entity'; +import { LANGUAGES } from 'src/shared/enum/languages.enum'; +import { CreateCategoryReqDto } from './dto/create-category-req.dto'; + +@Injectable() +export class CategoryService { + constructor(@InjectRepository(Category) private categoryRepository) {} + + async create(createCategoryDto: CreateCategoryReqDto): Promise { + const categoriyEN: CreateCategoryDto = { + name: createCategoryDto.nameEN, + language: LANGUAGES.EN, + }; + + const insertedId: number = (await this.categoryRepository.insert(categoriyEN)).raw.insertId; + + await this.categoryRepository.insert({ + idCategory: insertedId, + name: createCategoryDto.nameES, + language: LANGUAGES.ES, + }); + } + + async findAll(lang: string) { + return await this.categoryRepository.find({ where: { language: lang }, select: ['idCategory', 'name'] }); + } + + // update(id: number, updateCategoryDto: UpdateCategoryDto) { + // return `This action updates a #${id} category`; + // } + + async remove(idCategory: number) { + await this.categoryRepository.delete({ idCategory }); + } +} -- GitLab From e00cd30f8443c9f8c1e9eb8d3f2a758612984463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:28:58 -0600 Subject: [PATCH 04/30] agregando modulo para category --- backend/src/category/category.module.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 backend/src/category/category.module.ts diff --git a/backend/src/category/category.module.ts b/backend/src/category/category.module.ts new file mode 100644 index 00000000..21397c56 --- /dev/null +++ b/backend/src/category/category.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { CategoryService } from './category.service'; +import { CategoryController } from './category.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Category } from './entities/category.entity'; +import { AuthAdminService } from 'src/auth/admin/authAdmin.service'; +import { JwtService } from '@nestjs/jwt'; +import { EncryptionService } from 'src/auth/encryption/encryption.service'; +import { AdminService } from 'src/admin/admin.service'; +import { Admin } from 'src/admin/entities/admin.entity'; +import { Town } from 'src/town/entities/town.entity'; + +@Module({ + controllers: [CategoryController], + providers: [CategoryService, AuthAdminService, JwtService, EncryptionService, AdminService], + imports: [TypeOrmModule.forFeature([Category, Admin, Town])], +}) +export class CategoryModule {} -- GitLab From e59b7e265711803d8522d02cace5b77525834ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:29:14 -0600 Subject: [PATCH 05/30] agregando categorias por defecto --- .../database-seeder/database-seeder.module.ts | 4 +++ .../database-seeder.service.ts | 33 ++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/backend/src/database-seeder/database-seeder.module.ts b/backend/src/database-seeder/database-seeder.module.ts index 80f8867d..f9c5fb36 100644 --- a/backend/src/database-seeder/database-seeder.module.ts +++ b/backend/src/database-seeder/database-seeder.module.ts @@ -19,6 +19,8 @@ import { PointOfInterest } from 'src/pointOfInterest/entities/PointOfInterest.en import { AvailableDate } from 'src/place/entities/available-date.entity'; import { PlaceTraduction } from 'src/place/entities/place-traduction.entity'; import { PointOfInterestTraduction } from 'src/pointOfInterest/entities/PointOfInterestTraduction.entity'; +import { CategoryService } from 'src/category/category.service'; +import { Category } from 'src/category/entities/category.entity'; @Module({ providers: [ @@ -31,6 +33,7 @@ import { PointOfInterestTraduction } from 'src/pointOfInterest/entities/PointOfI TownService, PointOfInterestService, PlaceService, + CategoryService, ], imports: [ TypeOrmModule.forFeature([ @@ -44,6 +47,7 @@ import { PointOfInterestTraduction } from 'src/pointOfInterest/entities/PointOfI AvailableDate, PlaceTraduction, PointOfInterestTraduction, + Category, ]), ], }) diff --git a/backend/src/database-seeder/database-seeder.service.ts b/backend/src/database-seeder/database-seeder.service.ts index 6e678340..324262c7 100644 --- a/backend/src/database-seeder/database-seeder.service.ts +++ b/backend/src/database-seeder/database-seeder.service.ts @@ -10,8 +10,8 @@ import { UserStatus } from 'src/shared/enum/user-status.enum'; import { AuthAdminService } from 'src/auth/admin/authAdmin.service'; import { TownService } from 'src/town/town.service'; import { CreateTownDto } from 'src/town/dto/create-town.dto'; -import { PointOfInterestService } from 'src/pointOfInterest/PointOfInterest.service'; -import { PlaceService } from 'src/place/place.service'; +import { LANGUAGES } from 'src/shared/enum/languages.enum'; +import { Category } from 'src/category/entities/category.entity'; @Injectable() export class DatabaseSeederService implements OnModuleInit { @@ -20,8 +20,7 @@ export class DatabaseSeederService implements OnModuleInit { private readonly stateService: StateService, private readonly authAdminService: AuthAdminService, private readonly townService: TownService, - private readonly activityService: PointOfInterestService, - private readonly placeService: PlaceService, + @InjectRepository(Category) private categoryRepo: Repository, ) {} async insertStates() { @@ -93,9 +92,35 @@ export class DatabaseSeederService implements OnModuleInit { await this.townService.create(town); } + async insertCategories() { + const categoriesES = [ + { idCategory: 1, language: LANGUAGES.ES, name: 'Arquitectura' }, + { idCategory: 2, language: LANGUAGES.ES, name: 'Comida' }, + ]; + const categoriesEN = [ + { idCategory: 1, language: LANGUAGES.EN, name: 'Architecture' }, + { idCategory: 2, language: LANGUAGES.EN, name: 'Food' }, + ]; + for (let i = 0; i < categoriesES.length; i++) { + await this.categoryRepo.upsert( + [{ idCategory: categoriesES[i].idCategory, language: LANGUAGES.ES, name: categoriesES[i].name }], + { + conflictPaths: ['idCategory', 'language'], + }, + ); + await this.categoryRepo.upsert( + [{ idCategory: categoriesES[i].idCategory, language: LANGUAGES.EN, name: categoriesEN[i].name }], + { + conflictPaths: ['idCategory', 'language'], + }, + ); + } + } + async onModuleInit() { await this.insertStates(); await this.insertSuperAdmin(); await this.insertTowns(); + await this.insertCategories(); } } -- GitLab From 786dcd051a360f7b2ecfbc7decd8d2a600434e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:29:39 -0600 Subject: [PATCH 06/30] corrigiendo error en admin service --- backend/src/admin/admin.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/admin/admin.service.ts b/backend/src/admin/admin.service.ts index 793c06a5..2435742e 100644 --- a/backend/src/admin/admin.service.ts +++ b/backend/src/admin/admin.service.ts @@ -12,7 +12,7 @@ export class AdminService { @InjectRepository(Town) private townRepository: Repository, ) {} async create(createAdminDto: CreateAdminDto) { - const town = await this.townRepository.findOneByOrFail({ townId: createAdminDto.idTown }); + const town = await this.townRepository.findOneBy({ townId: createAdminDto.idTown }); await this.adminRepository.insert({ ...createAdminDto, idTown: town }); } -- GitLab From 315880d27ed7aff6a4e22bb6aeff1b8977656ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:30:02 -0600 Subject: [PATCH 07/30] quitando el logger de typeorm en la consola --- backend/src/app.module.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 85d00ffe..6567c8b2 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -17,8 +17,6 @@ import { join } from 'path'; import { Town } from './town/entities/town.entity'; import { TownModule } from './town/town.module'; import { TownTraduction } from './town/entities/town-traduction.entity'; -import { APP_GUARD } from '@nestjs/core'; -import { AuthAdminGuard } from './auth/admin/authAdmin.guard'; import { PlaceModule } from './place/place.module'; import { Place } from './place/entities/place.entity'; import { PointOfInterestModule } from './pointOfInterest/PointOfInterest.module'; @@ -26,6 +24,8 @@ import { PointOfInterest } from './pointOfInterest/entities/PointOfInterest.enti import { AvailableDate } from './place/entities/available-date.entity'; import { PointOfInterestTraduction } from './pointOfInterest/entities/PointOfInterestTraduction.entity'; import { PlaceTraduction } from './place/entities/place-traduction.entity'; +import { CategoryModule } from './category/category.module'; +import { Category } from './category/entities/category.entity'; @Module({ imports: [ @@ -47,9 +47,10 @@ import { PlaceTraduction } from './place/entities/place-traduction.entity'; AvailableDate, PointOfInterestTraduction, PlaceTraduction, + Category, ], synchronize: DbConstants.DB_SYNC, - logging: true, + logging: false, }), AuthAdminModule, AdminModule, @@ -63,6 +64,7 @@ import { PlaceTraduction } from './place/entities/place-traduction.entity'; rootPath: join(__dirname, '..', 'static'), }), PointOfInterestModule, + CategoryModule, ], controllers: [AppController], providers: [AppService, DatabaseSeederModule], -- GitLab From dcdbb2330e10361c73b7a66b588049970ff29276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:19:31 -0600 Subject: [PATCH 08/30] instalando paquete class-transformer y class-validator --- backend/package-lock.json | 41 +++++++++++++++++++++++++++++++++------ backend/package.json | 2 ++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index ff7ea91d..30e373bf 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -19,8 +19,9 @@ "@nestjs/swagger": "^7.3.0", "@nestjs/typeorm": "^10.0.2", "bcrypt": "^5.1.1", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", "dotenv": "^16.4.5", - "ip": "^2.0.1", "mysql2": "^3.9.2", "network": "^0.7.0", "reflect-metadata": "^0.2.0", @@ -2709,6 +2710,11 @@ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" }, + "node_modules/@types/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -3872,6 +3878,21 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "node_modules/class-validator": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", + "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", + "dependencies": { + "@types/validator": "^13.11.8", + "libphonenumber-js": "^1.10.53", + "validator": "^13.9.0" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -6082,11 +6103,6 @@ "node": ">= 0.10" } }, - "node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -7169,6 +7185,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.11.4", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.4.tgz", + "integrity": "sha512-F/R50HQuWWYcmU/esP5jrH5LiWYaN7DpN0a/99U8+mnGGtnx8kmRE+649dQh3v+CowXXZc8vpkf5AmYkO0AQ7Q==" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -10066,6 +10087,14 @@ "node": ">=10.12.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/backend/package.json b/backend/package.json index 541598de..4b33bcab 100644 --- a/backend/package.json +++ b/backend/package.json @@ -30,6 +30,8 @@ "@nestjs/swagger": "^7.3.0", "@nestjs/typeorm": "^10.0.2", "bcrypt": "^5.1.1", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", "dotenv": "^16.4.5", "mysql2": "^3.9.2", "network": "^0.7.0", -- GitLab From 9535c082b7ce35626ccb9b512f338201114b4cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:36:30 -0600 Subject: [PATCH 09/30] corrigiendo bug al insertar los admins por defecto --- backend/src/database-seeder/database-seeder.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/database-seeder/database-seeder.service.ts b/backend/src/database-seeder/database-seeder.service.ts index 324262c7..522177fc 100644 --- a/backend/src/database-seeder/database-seeder.service.ts +++ b/backend/src/database-seeder/database-seeder.service.ts @@ -119,8 +119,8 @@ export class DatabaseSeederService implements OnModuleInit { async onModuleInit() { await this.insertStates(); - await this.insertSuperAdmin(); await this.insertTowns(); + await this.insertSuperAdmin(); await this.insertCategories(); } } -- GitLab From 0ff6032ce8492c3c69194b72f4d97f93284817a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:37:48 -0600 Subject: [PATCH 10/30] corrigiendo atributo de entidad category --- backend/src/category/entities/category.entity.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/src/category/entities/category.entity.ts b/backend/src/category/entities/category.entity.ts index 1eaed7c7..3236e8a2 100644 --- a/backend/src/category/entities/category.entity.ts +++ b/backend/src/category/entities/category.entity.ts @@ -1,13 +1,12 @@ -import { LANGUAGES } from 'src/shared/enum/languages.enum'; -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class Category { @PrimaryGeneratedColumn() idCategory: number; - @Column({ nullable: false, primary: true, type: 'enum', enum: LANGUAGES }) - language: LANGUAGES; + @PrimaryColumn({ nullable: false, primary: true }) + language: string; @Column({ nullable: false }) name: string; -- GitLab From 645f63a714c3b5da6e2614211408360baa79995c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:38:26 -0600 Subject: [PATCH 11/30] agregando cateoryService como export --- backend/src/category/category.module.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/category/category.module.ts b/backend/src/category/category.module.ts index 21397c56..403cc887 100644 --- a/backend/src/category/category.module.ts +++ b/backend/src/category/category.module.ts @@ -14,5 +14,6 @@ import { Town } from 'src/town/entities/town.entity'; controllers: [CategoryController], providers: [CategoryService, AuthAdminService, JwtService, EncryptionService, AdminService], imports: [TypeOrmModule.forFeature([Category, Admin, Town])], + exports: [CategoryService], }) export class CategoryModule {} -- GitLab From 005d8adf177fc18255f47a85ebaa908dc0e4d09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:40:55 -0600 Subject: [PATCH 12/30] agregando findOne cateogory --- backend/src/category/category.service.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/category/category.service.ts b/backend/src/category/category.service.ts index 7531340d..c4f75479 100644 --- a/backend/src/category/category.service.ts +++ b/backend/src/category/category.service.ts @@ -28,11 +28,11 @@ export class CategoryService { return await this.categoryRepository.find({ where: { language: lang }, select: ['idCategory', 'name'] }); } - // update(id: number, updateCategoryDto: UpdateCategoryDto) { - // return `This action updates a #${id} category`; - // } - async remove(idCategory: number) { await this.categoryRepository.delete({ idCategory }); } + + async findOne(idCategory: number): Promise { + return await this.categoryRepository.findOne({ where: { idCategory } }); + } } -- GitLab From fb7873906eb15868ce3113ef058aae8f9049c2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:42:39 -0600 Subject: [PATCH 13/30] agregando relacion many to many de place y categories --- backend/src/place/entities/place.entity.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/backend/src/place/entities/place.entity.ts b/backend/src/place/entities/place.entity.ts index 35869609..00412dcc 100644 --- a/backend/src/place/entities/place.entity.ts +++ b/backend/src/place/entities/place.entity.ts @@ -1,8 +1,19 @@ import { PointOfInterest } from 'src/pointOfInterest/entities/PointOfInterest.entity'; import { Available } from 'src/pointOfInterest/enum/available.enum'; import { Town } from 'src/town/entities/town.entity'; -import { Column, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { + Column, + Entity, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + PrimaryGeneratedColumn, +} from 'typeorm'; import { AvailableDate } from './available-date.entity'; +import { Category } from 'src/category/entities/category.entity'; +import { PlaceTraduction } from './place-traduction.entity'; @Entity() export class Place { @@ -11,7 +22,7 @@ export class Place { @JoinColumn({ name: 'idTown' }) @ManyToOne(() => Town, (town) => town.townId, { nullable: false }) - idTown: Town; + town: Town; @OneToMany(() => PointOfInterest, (point) => point.idPoint) points: PointOfInterest[]; @@ -19,6 +30,13 @@ export class Place { @OneToMany(() => AvailableDate, (available) => available.idPlace) availableDates: AvailableDate[]; + @ManyToMany(() => Category) + @JoinTable() + categories: Category[]; + + @OneToMany(() => PlaceTraduction, (placeTraduction) => placeTraduction.idPlace) + placeTraduction: PlaceTraduction[]; + @Column() available: Available; -- GitLab From 73022204232624ae3976158bfd14710fdc77c92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:43:02 -0600 Subject: [PATCH 14/30] cambiando tipo de datos entidad place-trad --- backend/src/place/entities/place-traduction.entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/place/entities/place-traduction.entity.ts b/backend/src/place/entities/place-traduction.entity.ts index 3c29b7de..5804fa47 100644 --- a/backend/src/place/entities/place-traduction.entity.ts +++ b/backend/src/place/entities/place-traduction.entity.ts @@ -9,7 +9,7 @@ export class PlaceTraduction { @PrimaryColumn({ name: 'idPlace', type: Number }) @ManyToOne(() => Place, (place) => place.availableDates, { nullable: false }) - idPlace: Place; + idPlace: number; @Column() description: string; -- GitLab From 2e5714421ff51160db3aee94a01f461004101159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:43:34 -0600 Subject: [PATCH 15/30] corrigiendo relacion town con place --- backend/src/town/entities/town.entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/town/entities/town.entity.ts b/backend/src/town/entities/town.entity.ts index 4b6a569f..83fff7fa 100644 --- a/backend/src/town/entities/town.entity.ts +++ b/backend/src/town/entities/town.entity.ts @@ -9,7 +9,7 @@ export class Town { @ManyToOne(() => State, (state) => state.stateId, { nullable: false, eager: true }) state: State; - @OneToMany(() => Place, (place) => place.idTown) + @OneToMany(() => Place, (place) => place.town) places: Place[]; @Column() -- GitLab From 5584b5ba3e0cfe4adcd5e5140f7eb3209f445136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:44:29 -0600 Subject: [PATCH 16/30] agregando propiedades al dto para obtener un place --- backend/src/place/dto/get-place.dto.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/backend/src/place/dto/get-place.dto.ts b/backend/src/place/dto/get-place.dto.ts index 4625b1c5..ae110d55 100644 --- a/backend/src/place/dto/get-place.dto.ts +++ b/backend/src/place/dto/get-place.dto.ts @@ -1,17 +1,30 @@ -import { Available } from 'src/pointOfInterest/enum/available.enum'; -import { Place } from '../entities/place.entity'; +import { ApiProperty } from '@nestjs/swagger'; export class GetPlaceDto { + @ApiProperty() idTown: number; - idPlace: Place; - available: Available; + @ApiProperty() + idPlace: number; + @ApiProperty() name: string; + @ApiProperty() description: string; + @ApiProperty() + available: string; + @ApiProperty() imageName: string; + @ApiProperty() latitude: number; + @ApiProperty() longitude: number; + @ApiProperty() openAt: number; + @ApiProperty() closeAt: number; + @ApiProperty() startDate: Date; + @ApiProperty() endDate: Date; + @ApiProperty() + categories: any[]; } -- GitLab From 2fd6fb3718532987bfdca67a85c2a2707c192b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:45:06 -0600 Subject: [PATCH 17/30] agregando pipes para la validacion de datos --- backend/src/main.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/main.ts b/backend/src/main.ts index 733878db..08ac9ed6 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -2,9 +2,15 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { ServerConstants } from './constants/server.contants'; +import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { const app = await NestFactory.create(AppModule); + app.useGlobalPipes( + new ValidationPipe({ + transform: true, + }), + ); const config = new DocumentBuilder() .setTitle('Pueblos Magicos API') .setVersion('1.0') -- GitLab From 7b6a7f126e51b3981e233d072fee50a9b1a4d1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:45:48 -0600 Subject: [PATCH 18/30] agregando relacion many-to-many de user y category --- backend/src/user/entities/user.entity.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/user/entities/user.entity.ts b/backend/src/user/entities/user.entity.ts index 01e24044..43698b21 100644 --- a/backend/src/user/entities/user.entity.ts +++ b/backend/src/user/entities/user.entity.ts @@ -1,4 +1,5 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; +import { Category } from 'src/category/entities/category.entity'; +import { Entity, Column, PrimaryGeneratedColumn, ManyToMany, JoinTable } from 'typeorm'; @Entity() export class User { @@ -10,6 +11,10 @@ export class User { }) email: string; + @JoinTable() + @ManyToMany(() => Category) + preferedCategories: Category[]; + @Column() name: string; -- GitLab From 8803cc79124505579cfcdacb10a588b1d2631bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:47:26 -0600 Subject: [PATCH 19/30] cambiando tipo de dato para create-date.dto --- backend/src/place/dto/create-date.dto.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/place/dto/create-date.dto.ts b/backend/src/place/dto/create-date.dto.ts index a311bb99..7a127a24 100644 --- a/backend/src/place/dto/create-date.dto.ts +++ b/backend/src/place/dto/create-date.dto.ts @@ -1,4 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; +import { Place } from '../entities/place.entity'; export class CreateDateDto { @ApiProperty() @@ -7,5 +8,5 @@ export class CreateDateDto { @ApiProperty() endDate: Date; - idPlace: number; + idPlace: Place; } -- GitLab From 62c90166d0d3133fef75c4ab0edd64d32b14738f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:47:52 -0600 Subject: [PATCH 20/30] agregando categoriesId al dto para agregar un Place --- backend/src/place/dto/create-place-date.dto.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/place/dto/create-place-date.dto.ts b/backend/src/place/dto/create-place-date.dto.ts index 7e3adcc5..a8162052 100644 --- a/backend/src/place/dto/create-place-date.dto.ts +++ b/backend/src/place/dto/create-place-date.dto.ts @@ -1,5 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Available } from 'src/pointOfInterest/enum/available.enum'; +import { Transform } from 'class-transformer'; +import { IsArray } from 'class-validator'; export class CreatePlaceDateTradDto { @ApiProperty({ enum: Available, enumName: 'Available' }) @@ -11,6 +13,11 @@ export class CreatePlaceDateTradDto { @ApiProperty() name: string; + @ApiProperty({ type: String, description: 'Comma-separated list of category IDs', example: '1,2,3' }) + @IsArray({}) + @Transform(({ value }) => value.split(',').map(Number)) + categoriesId: number[]; + @ApiProperty() descriptionES: string; @ApiProperty() -- GitLab From fe54d8dcf866f23d9c35426af132d94ca2a02b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:48:24 -0600 Subject: [PATCH 21/30] agregando categories[ ] a CreatePlaceDto --- backend/src/place/dto/create-place.dto.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/place/dto/create-place.dto.ts b/backend/src/place/dto/create-place.dto.ts index b37e0f41..63fd9330 100644 --- a/backend/src/place/dto/create-place.dto.ts +++ b/backend/src/place/dto/create-place.dto.ts @@ -1,3 +1,4 @@ +import { Category } from 'src/category/entities/category.entity'; import { Available } from 'src/pointOfInterest/enum/available.enum'; import { Town } from 'src/town/entities/town.entity'; @@ -5,9 +6,10 @@ export class CreatePlaceDto { available: Available; name: string; imageName: string; - idTown: Town; + town: Town; latitude: number; longitude: number; openAt: number; closeAt: number; + categories: Category[]; } -- GitLab From 69a13eb35bda27a70c6d4582130faa57323f83a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:48:57 -0600 Subject: [PATCH 22/30] agregando dto para actualizar relacion user-category --- backend/src/user/dto/update-preferedCategories.dto.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 backend/src/user/dto/update-preferedCategories.dto.ts diff --git a/backend/src/user/dto/update-preferedCategories.dto.ts b/backend/src/user/dto/update-preferedCategories.dto.ts new file mode 100644 index 00000000..b13aeae8 --- /dev/null +++ b/backend/src/user/dto/update-preferedCategories.dto.ts @@ -0,0 +1,10 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; +import { IsArray } from 'class-validator'; + +export class UpdatePreferedCategoriesDto { + @ApiProperty({ type: String, description: 'Comma-separated list of category IDs', example: '1,2,3' }) + @IsArray() + @Transform(({ value }) => value.split(',').map(Number)) + idCategories: number[]; +} -- GitLab From d15dcbb0e810c8b341ca1fc194a5d2daa7acc063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:49:25 -0600 Subject: [PATCH 23/30] agregando imports y providers a authUser --- backend/src/auth/user/authUser.module.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/auth/user/authUser.module.ts b/backend/src/auth/user/authUser.module.ts index 22ac1b09..60fb0b10 100644 --- a/backend/src/auth/user/authUser.module.ts +++ b/backend/src/auth/user/authUser.module.ts @@ -6,9 +6,11 @@ import { AuthUserController } from './authUsercontroller'; import { UserService } from 'src/user/user.service'; import { User } from 'src/user/entities/user.entity'; import { AuthUserService } from './authUserservice'; +import { Category } from 'src/category/entities/category.entity'; +import { CategoryService } from 'src/category/category.service'; @Module({ controllers: [AuthUserController], - providers: [UserService, JwtService, EncryptionService, AuthUserService], - imports: [TypeOrmModule.forFeature([User])], + providers: [UserService, JwtService, EncryptionService, AuthUserService, CategoryService], + imports: [TypeOrmModule.forFeature([User, Category])], }) export class AuthUserModule {} -- GitLab From b190e8c93692993265849d0b267ab9d0719c6c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:49:42 -0600 Subject: [PATCH 24/30] agregando imports y providers a user.module --- backend/src/user/user.module.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/src/user/user.module.ts b/backend/src/user/user.module.ts index 8a4003a1..03b2f9d6 100644 --- a/backend/src/user/user.module.ts +++ b/backend/src/user/user.module.ts @@ -3,10 +3,15 @@ import { UserService } from './user.service'; import { UserController } from './user.controller'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './entities/user.entity'; +import { CategoryService } from 'src/category/category.service'; +import { Category } from 'src/category/entities/category.entity'; +import { AuthUserService } from 'src/auth/user/authUserservice'; +import { JwtService } from '@nestjs/jwt'; +import { EncryptionService } from 'src/auth/encryption/encryption.service'; @Module({ controllers: [UserController], - providers: [UserService], - imports: [TypeOrmModule.forFeature([User])], + providers: [UserService, CategoryService, AuthUserService, JwtService, EncryptionService], + imports: [TypeOrmModule.forFeature([User, Category])], }) export class UserModule {} -- GitLab From 6abfbd8e2c2942878ed27482995cb27b4d2b4dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:50:13 -0600 Subject: [PATCH 25/30] agregando metodo para actualizar preferencias de usuarios --- backend/src/user/user.service.ts | 43 ++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index e22805e2..63b2c3cc 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -1,15 +1,21 @@ -import { Injectable } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from './entities/user.entity'; import { Repository } from 'typeorm'; import { CreateUserDto } from './dto/create-user.dto'; +import { Category } from 'src/category/entities/category.entity'; +import { CategoryService } from 'src/category/category.service'; +import { LANGUAGES } from 'src/shared/enum/languages.enum'; @Injectable() /** * Service responsible for handling user-related operations. */ export class UserService { - constructor(@InjectRepository(User) private userRepository: Repository) {} + constructor( + @InjectRepository(User) private userRepository: Repository, + private categoryService: CategoryService, + ) {} async findOne(email: string) { return await this.userRepository.findOneBy({ email }); @@ -28,4 +34,37 @@ export class UserService { async updatePassword(email: string, password: string) { await this.userRepository.update({ email }, { password }); } + + async updatePreferedCategories(email: string, idCategories: number[]) { + const user = await this.userRepository.findOneBy({ email }); + const categories: Category[] = []; + for (const idCategory of idCategories) { + const categoryEN: Category = await this.categoryService.findOne(idCategory); + if (!categoryEN) throw new BadRequestException('Category not found'); + categoryEN.language = LANGUAGES.EN; + const categoryES: Category = { + ...categoryEN, + language: LANGUAGES.ES, + }; + categories.push(categoryEN); + categories.push(categoryES); + } + user.preferedCategories = categories; + await this.userRepository.save(user); + } + + async getPreferedCategories(email: string, language: LANGUAGES): Promise { + const user: any = await this.userRepository.findOne({ + relations: { + preferedCategories: true, + }, + where: { + email, + preferedCategories: { + language, + }, + }, + }); + return user?.preferedCategories || []; + } } -- GitLab From fb6faead241c5fa55b05d5d1b113dd90831a2f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:51:04 -0600 Subject: [PATCH 26/30] agregando categories en las queries de Place --- backend/src/place/place.service.ts | 160 ++++++++++++++++------------- 1 file changed, 87 insertions(+), 73 deletions(-) diff --git a/backend/src/place/place.service.ts b/backend/src/place/place.service.ts index 214c40d0..e0f8d592 100644 --- a/backend/src/place/place.service.ts +++ b/backend/src/place/place.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Injectable } from '@nestjs/common'; +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { CreatePlaceDateTradDto } from './dto/create-place-date.dto'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { Place } from './entities/place.entity'; @@ -13,6 +13,7 @@ import { GetPlaceDto } from './dto/get-place.dto'; import { ServerConstants } from 'src/constants/server.contants'; import { Available } from 'src/pointOfInterest/enum/available.enum'; import { UpdatePlaceReqDto } from './dto/update-place.req.dto'; +import { Category } from 'src/category/entities/category.entity'; @Injectable() export class PlaceService { @@ -26,35 +27,46 @@ export class PlaceService { async create(createPlaceDto: CreatePlaceDateTradDto) { const town: Town = await this.townRepository.findOneBy({ townId: createPlaceDto.idTown }); + const categories: Category[] = []; + for (const categoryId of createPlaceDto.categoriesId) { + const categoryEN: Category = await this.dataSource + .getRepository(Category) + .findOneByOrFail({ idCategory: categoryId }); + categoryEN.language = LANGUAGES.EN; + const categoryES: Category = { ...categoryEN, language: LANGUAGES.ES }; + categories.push(categoryEN); + categories.push(categoryES); + } const createPlace: CreatePlaceDto = { available: createPlaceDto.available, closeAt: createPlaceDto.closeAt, latitude: createPlaceDto.latitude, longitude: createPlaceDto.longitude, - idTown: town, + town: town, name: createPlaceDto.name, openAt: createPlaceDto.openAt, imageName: createPlaceDto.image.filename, + categories: categories, }; if (!town) { throw new BadRequestException('Town not found'); } - const insertedId = (await this.placeRepository.insert({ ...createPlace })).raw.insertId; + const insertedPlace = await this.placeRepository.save({ ...createPlace }); const createDate: CreateDateDto = { endDate: createPlaceDto.endDate, startDate: createPlaceDto.startDate, - idPlace: insertedId, + idPlace: insertedPlace, }; const createTradEn: PlaceTraduction = { language: LANGUAGES.EN, - idPlace: insertedId, + idPlace: insertedPlace.idPlace, description: createPlaceDto.descriptionEN, }; const createTradEs: PlaceTraduction = { language: LANGUAGES.ES, - idPlace: insertedId, + idPlace: insertedPlace.idPlace, description: createPlaceDto.descriptionES, }; @@ -62,48 +74,37 @@ export class PlaceService { await this.placeTraductionRepository.insert(createTradEs); await this.placeTraductionRepository.insert(createTradEn); if (createPlaceDto.available === Available.CUSTOM) { - await this.availableDateRepository.insert({ ...createDate, idPlace: insertedId }); + await this.availableDateRepository.insert({ ...createDate, idPlace: insertedPlace }); } } async findAllByTown(idTown: number, lang: LANGUAGES) { - const res: GetPlaceDto[] = await this.dataSource - .getRepository(PlaceTraduction) - .createQueryBuilder('placeTrad') - .leftJoin('placeTrad.idPlace', 'place') - .leftJoin('place.availableDates', 'availableDate') - .select([ - 'place.idPlace AS idPlace', - 'place.name AS name', - 'place.imageName AS imageName', - 'placeTrad.language AS language', - 'placeTrad.description AS description', - 'place.openAt AS openAt', - 'place.closeAt AS closeAt', - 'availableDate.startDate AS startDate', - 'availableDate.endDate AS endDate', - 'place.available AS available', - 'place.idTown AS idTown', - 'place.latitude AS latitude', - 'place.longitude AS longitude', - ]) + const res: any[] = await this.dataSource + .getRepository(Place) + .createQueryBuilder('place') + .leftJoinAndSelect('place.availableDates', 'availableDate') + .leftJoinAndSelect('place.categories', 'category') + .leftJoinAndSelect('place.placeTraduction', 'placeTrad') + .leftJoinAndSelect('place.town', 'town') .where('place.idTown = :idTown', { idTown: idTown }) .andWhere('placeTrad.language = :language', { language: lang }) - .getRawMany(); - const places: GetPlaceDto[] = res.map((place) => { + .andWhere('category.language = :language', { language: lang }) + .getMany(); + const places: GetPlaceDto[] = res.map((place): GetPlaceDto => { return { - idTown: place.idTown, + idTown: place.town.townId, idPlace: place.idPlace, available: place.available, - description: place.description, latitude: place.latitude, longitude: place.longitude, imageName: `${ServerConstants.HOST}/places/${place.imageName}`, name: place.name, openAt: place.openAt, closeAt: place.closeAt, - startDate: place.startDate, - endDate: place.endDate, + startDate: place.availableDates[0]?.startDate || null, + endDate: place.availableDates[0]?.endDate || null, + categories: place.categories, + description: place.placeTraduction[0].description, }; }); return places; @@ -114,60 +115,71 @@ export class PlaceService { } async findOneAndTradAndAvailable(idPlace: number, lang: LANGUAGES) { - const place: GetPlaceDto = await this.dataSource - .getRepository(PlaceTraduction) - .createQueryBuilder('placeTrad') - .leftJoin('placeTrad.idPlace', 'place') - .leftJoin('place.availableDates', 'availableDate') - .select([ - 'place.idPlace AS idPlace', - 'place.name AS name', - 'place.imageName AS imageName', - 'placeTrad.language AS language', - 'placeTrad.description AS description', - 'place.latitude AS latitude', - 'place.longitude AS longitude', - 'place.openAt AS openAt', - 'place.closeAt AS closeAt', - 'availableDate.startDate AS startDate', - 'availableDate.endDate AS endDate', - 'place.idTown AS idTown', - 'place.available AS available', - ]) - .where('place.idPlace = :idPlace', { idPlace: idPlace }) + const place: any = await this.dataSource + .getRepository(Place) + .createQueryBuilder('place') + .leftJoinAndSelect('place.availableDates', 'availableDate') + .leftJoinAndSelect('place.categories', 'category') + .leftJoinAndSelect('place.placeTraduction', 'placeTrad') + .leftJoinAndSelect('place.town', 'town') + .where('place.idPlace = :idPlace', { idPlace }) .andWhere('placeTrad.language = :language', { language: lang }) - .getRawOne(); - - return { - idTown: place.idTown, + .andWhere('category.language = :language', { language: lang }) + .getOne(); + const res: GetPlaceDto = { + idTown: place.town.townId, idPlace: place.idPlace, available: place.available, - description: place.description, latitude: place.latitude, longitude: place.longitude, imageName: `${ServerConstants.HOST}/places/${place.imageName}`, name: place.name, openAt: place.openAt, closeAt: place.closeAt, - startDate: place.startDate, - endDate: place.endDate, + startDate: place.availableDates[0]?.startDate, + endDate: place.availableDates[0]?.endDate, + categories: place.categories, + description: place.placeTraduction[0].description, }; + return res; } async update(idPlace: number, updatePlaceReqDto: UpdatePlaceReqDto) { - const place: Place = await this.placeRepository.findOneBy({ idPlace }); - const createPlaceDto: CreatePlaceDto = { - available: updatePlaceReqDto.available, - closeAt: updatePlaceReqDto.closeAt, - latitude: updatePlaceReqDto.latitude, - longitude: updatePlaceReqDto.longitude, - name: updatePlaceReqDto.name, - openAt: updatePlaceReqDto.openAt, - imageName: updatePlaceReqDto.image.filename, - idTown: place.idTown, - }; + const place: Place = await this.placeRepository.findOne({ + where: { idPlace }, + relations: ['categories'], + }); + + if (!place) { + throw new NotFoundException('Place not found'); + } + + // Update place properties + place.available = updatePlaceReqDto.available; + place.closeAt = updatePlaceReqDto.closeAt; + place.latitude = updatePlaceReqDto.latitude; + place.longitude = updatePlaceReqDto.longitude; + place.name = updatePlaceReqDto.name; + place.openAt = updatePlaceReqDto.openAt; + place.imageName = updatePlaceReqDto.image.filename; + + // Update categories + const categories: Category[] = []; + for (const categoryId of updatePlaceReqDto.categoriesId) { + const categoryEN: Category = await this.dataSource + .getRepository(Category) + .findOneByOrFail({ idCategory: categoryId }); + categoryEN.language = LANGUAGES.EN; + const categoryES: Category = { ...categoryEN, language: LANGUAGES.ES }; + categories.push(categoryEN); + categories.push(categoryES); + } + place.categories = categories; + + // Save the updated place + await this.placeRepository.save(place); - await this.placeRepository.update({ idPlace }, createPlaceDto); + // Update PlaceTraduction for EN await this.placeTraductionRepository .createQueryBuilder() .update(PlaceTraduction) @@ -175,6 +187,7 @@ export class PlaceService { .where('idPlace = :idPlace AND language = :language', { idPlace, language: LANGUAGES.EN }) .execute(); + // Update PlaceTraduction for ES await this.placeTraductionRepository .createQueryBuilder() .update(PlaceTraduction) @@ -182,6 +195,7 @@ export class PlaceService { .where('idPlace = :idPlace AND language = :language', { idPlace, language: LANGUAGES.ES }) .execute(); + // Update available date if necessary if (updatePlaceReqDto.available === Available.CUSTOM) { await this.availableDateRepository.update( { idPlace: place }, -- GitLab From 6fc657cb536b7e65fbca6437277fbbd4e34521e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:51:43 -0600 Subject: [PATCH 27/30] agregando validacion del Town, solo para admins --- backend/src/admin/admin.service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/admin/admin.service.ts b/backend/src/admin/admin.service.ts index 2435742e..65c9a377 100644 --- a/backend/src/admin/admin.service.ts +++ b/backend/src/admin/admin.service.ts @@ -4,6 +4,7 @@ import { Admin } from './entities/admin.entity'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { Town } from 'src/town/entities/town.entity'; +import { ADMIN_ROLE } from 'src/shared/enum/admin-role.enum'; @Injectable() export class AdminService { @@ -12,7 +13,10 @@ export class AdminService { @InjectRepository(Town) private townRepository: Repository, ) {} async create(createAdminDto: CreateAdminDto) { - const town = await this.townRepository.findOneBy({ townId: createAdminDto.idTown }); + let town: Town = null; + if (createAdminDto.role == ADMIN_ROLE.ADMIN) { + town = await this.townRepository.findOneByOrFail({ townId: createAdminDto.idTown }); + } await this.adminRepository.insert({ ...createAdminDto, idTown: town }); } -- GitLab From b5ee99bd140fde7382cd798e7885fea7da4d8d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:52:11 -0600 Subject: [PATCH 28/30] agregando endpoint para actualizar y obtener categorias de usuario --- backend/src/user/user.controller.ts | 38 ++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/backend/src/user/user.controller.ts b/backend/src/user/user.controller.ts index b95b2314..34e7c6d0 100644 --- a/backend/src/user/user.controller.ts +++ b/backend/src/user/user.controller.ts @@ -1,7 +1,43 @@ -import { Controller } from '@nestjs/common'; +import { Body, Controller, Get, Param, Patch, Req, UseGuards } from '@nestjs/common'; import { UserService } from './user.service'; +import { UpdatePreferedCategoriesDto } from './dto/update-preferedCategories.dto'; +import { CustomUserRequest } from 'src/auth/user/interface/customUserReq'; +import { ApiBearerAuth, ApiBody, ApiParam, ApiTags } from '@nestjs/swagger'; +import { AuthUserGuard } from 'src/auth/user/authUser.guard'; +import { LANGUAGES } from 'src/shared/enum/languages.enum'; @Controller('user') +@ApiTags('User') export class UserController { constructor(private readonly userService: UserService) {} + + @Patch('update-prefered-categories') + @ApiBearerAuth('jwt') + @ApiBody({ type: UpdatePreferedCategoriesDto }) + @UseGuards(AuthUserGuard) + async updatePreferedCategories( + @Body() updatePreferedCategoriesDto: UpdatePreferedCategoriesDto, + @Req() req: CustomUserRequest, + ) { + try { + const { email } = req.user; + await this.userService.updatePreferedCategories(email, updatePreferedCategoriesDto.idCategories); + return { message: 'Prefered categories updated successfully' }; + } catch (error) { + throw error; + } + } + + @Get('prefered-categories:lang') + @ApiBearerAuth('jwt') + @ApiParam({ name: 'lang', type: String }) + @UseGuards(AuthUserGuard) + async getPreferedCategories(@Req() req: CustomUserRequest, @Param('lang') lang: string) { + try { + const { email } = req.user; + return await this.userService.getPreferedCategories(email, lang as LANGUAGES); + } catch (error) { + throw error; + } + } } -- GitLab From 30be624d66c8abe81f5ab12a76dab304a8ec5534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:54:03 -0600 Subject: [PATCH 29/30] agregando mensaje de confirmacion al crear un Place --- backend/src/place/place.controller.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/src/place/place.controller.ts b/backend/src/place/place.controller.ts index 4e26dcfb..b98b3ae8 100644 --- a/backend/src/place/place.controller.ts +++ b/backend/src/place/place.controller.ts @@ -14,7 +14,7 @@ import { } from '@nestjs/common'; import { PlaceService } from './place.service'; import { CreatePlaceDateTradDto } from './dto/create-place-date.dto'; -import { ApiBearerAuth, ApiBody, ApiConsumes, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiBody, ApiConsumes, ApiParam, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger'; import { Roles } from 'src/auth/role.decorator'; import { ALL_ROLES } from 'src/shared/enum/admin-role.enum'; import { fileInterceptor } from 'src/shared/interceptors/file-save.interceptor'; @@ -23,6 +23,7 @@ import { LANGUAGES } from 'src/shared/enum/languages.enum'; import { CustomAdminRequest } from 'src/auth/admin/interface/customAdminReq'; import { UpdatePlaceReqDto } from './dto/update-place.req.dto'; import { AuthAdminGuard } from 'src/auth/admin/authAdmin.guard'; +import { GetPlaceDto } from './dto/get-place.dto'; @Controller('place') @ApiTags('Place') @@ -31,6 +32,7 @@ export class PlaceController { @ApiBody({ type: CreatePlaceDateTradDto }) @ApiConsumes('multipart/form-data') + @ApiResponse({ type: GetPlaceDto, status: 201, description: 'Created' }) @UseGuards(AuthAdminGuard) @Roles([ALL_ROLES.ADMIN]) @ApiBearerAuth('jwt') @@ -46,7 +48,8 @@ export class PlaceController { throw new UnauthorizedException('This is not your assigned town'); } createPlaceDto.image = file; - return await this.placeService.create(createPlaceDto); + await this.placeService.create(createPlaceDto); + return { message: 'Place created successfully' }; } catch (e) { throw e; } @@ -83,13 +86,12 @@ export class PlaceController { @Req() req: CustomAdminRequest, ) { try { - const place = await this.placeService.findOne(idPlace); - console.log({ place }); if (req.admin.idTown.townId != updatePlaceReqDto.idTown) { throw new UnauthorizedException('This is not your assigned town'); } updatePlaceReqDto.image = file; - return await this.placeService.update(idPlace, updatePlaceReqDto); + await this.placeService.update(idPlace, updatePlaceReqDto); + return { message: 'Place updated successfully' }; } catch (e) { throw e; } -- GitLab From 7eabcd48128198c3b06dbd909a750f20512a3859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:04:16 -0600 Subject: [PATCH 30/30] corrigiendo docs --- backend/src/user/dto/update-preferedCategories.dto.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/backend/src/user/dto/update-preferedCategories.dto.ts b/backend/src/user/dto/update-preferedCategories.dto.ts index b13aeae8..290f3ddc 100644 --- a/backend/src/user/dto/update-preferedCategories.dto.ts +++ b/backend/src/user/dto/update-preferedCategories.dto.ts @@ -1,10 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; -import { IsArray } from 'class-validator'; export class UpdatePreferedCategoriesDto { - @ApiProperty({ type: String, description: 'Comma-separated list of category IDs', example: '1,2,3' }) - @IsArray() - @Transform(({ value }) => value.split(',').map(Number)) + @ApiProperty({ isArray: true, type: Number, example: [1, 2] }) idCategories: number[]; } -- GitLab