Skip to content

Commit

Permalink
feat: add district name in complaints with only coordinates
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyp3Boy committed Oct 28, 2024
1 parent 3f83bd8 commit 538b3aa
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 30 deletions.
53 changes: 49 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/axios": "^3.1.0",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.0.0",
Expand Down
13 changes: 13 additions & 0 deletions src/complaints/complaints.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ export class ComplaintsController {
}
}

@Get('user/:dni')
async findAllComplaintsFromUser(@Param('dni') dni: string) {
try {
const complaints = await this.complaintsService.findAllComplaintsFromUser(dni);
if (!complaints) {
throw new NotFoundException(`Complaints with DNI ${dni} not found`);
}
return complaints;
} catch (error) {
throw new NotFoundException(error.message);
}
}

@Patch(':id')
async update(@Param('id') id: string, @Body() updateComplaintDto: UpdateComplaintDto) {
try {
Expand Down
6 changes: 4 additions & 2 deletions src/complaints/complaints.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import { ComplaintCategory } from 'src/model/complaint_category.entity';
import { District } from 'src/model/district.entity';
import { ComplaintState } from 'src/model/complaint_state.entity';
import { ComplaintStateService } from './complaints-state.service';
import { GeolocationService } from './geolocation.service';
import { HttpModule } from '@nestjs/axios';

@Module({
imports: [TypeOrmModule.forFeature([Complaint, User, ComplaintCategory, District, ComplaintState])],
imports: [HttpModule, TypeOrmModule.forFeature([Complaint, User, ComplaintCategory, District, ComplaintState])],
controllers: [ComplaintsController],
providers: [ComplaintsService, ComplaintStateService],
providers: [ComplaintsService, ComplaintStateService, GeolocationService],
})
export class ComplaintsModule {}
32 changes: 20 additions & 12 deletions src/complaints/complaints.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import { Complaint } from 'src/model/complaint.entity';
import { Repository } from 'typeorm';
import { User } from 'src/model/user.entity';
import { ComplaintCategory } from 'src/model/complaint_category.entity';
import { District } from 'src/model/district.entity';

import { GeolocationService } from './geolocation.service';
@Injectable()
export class ComplaintsService {
constructor(
Expand All @@ -17,8 +16,7 @@ export class ComplaintsService {
private readonly userRepository: Repository<User>,
@InjectRepository(ComplaintCategory)
private readonly categoryRepository: Repository<ComplaintCategory>,
@InjectRepository(District)
private readonly districtRepository: Repository<District>,
private readonly geolocationService: GeolocationService,
) {}

async findAllComplaints() {
Expand All @@ -34,11 +32,25 @@ export class ComplaintsService {
});
}

async findAllComplaintsFromUser(dni: string): Promise<Complaint[]> {
return await this.complaintRepository.find({
relations: [
'user', // Incluye la relación con el usuario
'category', // Incluye la relación con la categoría de quejas
'district', // Incluye la relación con el distrito
'complaints_image', // Incluye las imágenes de la queja
'comments', // Incluye los comentarios
'complaintState', // Incluye el estado de la queja
],
where: { user: { dni } },
});
}

async create(createComplaintDto: CreateComplaintDto): Promise<Complaint> {
// Convertir latitude y longitude a un string tipo "point" para la base de datos
createComplaintDto.created_at = new Date(createComplaintDto.created_at);
createComplaintDto.updated_at = new Date(createComplaintDto.updated_at);
const { latitude, longitude, userId, categoryId, districtId } = createComplaintDto;
const { latitude, longitude, userId, categoryId } = createComplaintDto;
const formattedUbication = `(${latitude}, ${longitude})`;

const user = await this.userRepository.findOne({ where: { dni: userId } });
Expand All @@ -51,9 +63,9 @@ export class ComplaintsService {
throw new Error(`Category with ID ${categoryId} not found`);
}

const district = await this.districtRepository.findOne({ where: { id: districtId } });
const district = await this.geolocationService.findOrCreateDistrict(latitude, longitude);
if (!district) {
throw new Error(`District with ID ${districtId} not found`);
throw new Error(`District with ID ${district} not found`);
}

// Crear la entidad con las relaciones utilizando objetos parciales
Expand Down Expand Up @@ -84,7 +96,7 @@ export class ComplaintsService {
}

// Extrae la información del DTO
const { latitude, longitude, categoryId, districtId } = updateComplaintDto;
const { latitude, longitude, categoryId } = updateComplaintDto;

// Si hay coordenadas nuevas, conviértalas a formato "point"
if (latitude !== undefined && longitude !== undefined) {
Expand All @@ -98,10 +110,6 @@ export class ComplaintsService {
complaint.category = { id: categoryId } as ComplaintCategory;
}

if (districtId !== undefined) {
complaint.district = { id: districtId } as District;
}

if (updateComplaintDto.description !== undefined) {
complaint.description = updateComplaintDto.description;
}
Expand Down
4 changes: 0 additions & 4 deletions src/complaints/dto/create-complaint.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ export class CreateComplaintDto {
@IsNumber()
categoryId: number;

@IsNotEmpty()
@IsNumber()
districtId: number;

@IsNotEmpty()
@IsDateString()
created_at: Date | string;
Expand Down
4 changes: 0 additions & 4 deletions src/complaints/dto/update-complaint.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,4 @@ export class UpdateComplaintDto {
@IsOptional()
@IsNumber()
categoryId?: number;

@IsOptional()
@IsNumber()
districtId?: number;
}
53 changes: 53 additions & 0 deletions src/complaints/geolocation.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { District } from 'src/model/district.entity';
import { firstValueFrom } from 'rxjs';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class GeolocationService {
constructor(
private readonly httpService: HttpService,
@InjectRepository(District)
private readonly districtRepository: Repository<District>,
) {}

async findOrCreateDistrict(latitude: number, longitude: number): Promise<District> {
// Llamada a la API de Google para obtener la información de ubicación
const response = await firstValueFrom(
this.httpService.get(`https://maps.googleapis.com/maps/api/geocode/json`, {
params: {
latlng: `${latitude},${longitude}`,
key: process.env.GOOGLE_API_KEY,
},
}),
);

const results = response.data.results;
const districtName = this.extractDistrictFromResults(results);

// Verificar si el distrito ya existe en la base de datos
let district = await this.districtRepository.findOne({ where: { name: districtName } });

if (!district) {
// Si el distrito no existe, créalo y guárdalo
district = this.districtRepository.create({ name: districtName });
await this.districtRepository.save(district);
}

return district;
}

private extractDistrictFromResults(results: any[]): string {
// Busca en los resultados un objeto que tenga el tipo 'locality' en su array de types
const districtResult = results.find((result) => result.types.includes('locality') && result.types.includes('political'));

// Si encuentra el distrito, devuelve su nombre completo; de lo contrario, devuelve null
if (districtResult) {
const districtComponent = districtResult.address_components.find((component) => component.types.includes('locality'));
return districtComponent ? districtComponent.long_name : null;
}
return null;
}
}
6 changes: 2 additions & 4 deletions src/model/district.entity.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Entity, OneToMany, PrimaryColumn } from 'typeorm';
import { Complaint } from './complaint.entity';

@Entity({ name: 'district' })
export class District {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'varchar', length: 255 })
@PrimaryColumn({ type: 'varchar', length: 255 })
name: string;

@OneToMany(() => Complaint, (complaint) => complaint.district)
Expand Down

0 comments on commit 538b3aa

Please sign in to comment.