Newer
Older
import { HttpException, HttpService, Injectable, HttpStatus } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Observable } from 'rxjs';
import { AxiosResponse } from 'axios';
import { Structure, StructureDocument } from './schemas/structure.schema';
import { Logger } from '@nestjs/common';
import { structureDto } from './dto/structure.dto';
import { UsersService } from '../users/users.service';
export class StructuresService {
constructor(
private readonly httpService: HttpService,
@InjectModel(Structure.name) private structureModel: Model<StructureDocument>
) {}
public async create(idUser: string, structureDto: structureDto): Promise<Structure> {
const user = await this.userService.findOne(idUser);
if (!user) {
throw new HttpException('Invalid profile', HttpStatus.NOT_FOUND);
}
const createdStructure = new this.structureModel(structureDto);
createdStructure.id = (await this.getNumberStructures()) + 1;
createdStructure.save();
user.structuresLink.push(createdStructure.id);
user.save();
return createdStructure;
public async search(searchString: string, filters?: Array<any>): Promise<Structure[]> {
if (searchString && filters) {
return this.structureModel
.find({ $and: [...this.parseFilter(filters), { $text: { $search: searchString } }] })
.exec();
} else if (filters) {
return this.structureModel.find({ $or: this.parseFilter(filters) }).exec();
return this.structureModel.find({ $or: [{ $text: { $search: searchString } }] }).exec();
/**
* Parse filter value from string to boolean
* @param filters
*/
private parseFilter(filters: Array<any>): Array<any> {
return filters.map((filter) => {
const key = Object.keys(filter)[0];
if (filter[key] === 'True') {
return { [key]: true };
} else {
return filter;
}
});
}
public async findAll(): Promise<Structure[]> {
const structures = await this.structureModel.find().exec();
// Update structures coord and address before sending them
await Promise.all(
structures.map((structure: Structure) => {
// If structre has no address, add it
if (!structure.address) {
return this.getStructurePosition(structure).then((postition) => {
this.structureModel
.findOneAndUpdate({ id: structure.id }, { address: postition.address, coord: postition.coord })
.exec();
});
}
if (structure.coord.length <= 0) {
return new Promise((resolve) => {
this.getStructurePosition(structure).then((postition) => {
this.structureModel
.findOneAndUpdate({ id: postition.id }, { coord: postition.coord })
.exec()
.then(() => {
resolve('');
});
});
});
}
})
);
return this.structureModel.find().exec();
}
public async update(idStructure: number, structure: structureDto): Promise<Structure> {
const result = await this.structureModel.updateOne({ id: idStructure }, structure); //NOSONAR
if (!result) {
throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
}
return this.structureModel.findOne({ id: idStructure }).exec();
}
public findOne(idParam: number): Promise<Structure> {
return this.structureModel.findOne({ id: idParam }).exec();
}
/**
* Get structures positions and add marker corresponding to those positons on the map
*/
private getStructurePosition(structure: Structure): Promise<Structure> {
return new Promise((resolve) => {
this.getCoord(structure.address.numero, structure.address.street, structure.address.commune).subscribe(
(res) => {
const address = res.data.features[0];
structure.coord = address.geometry.coordinates;
resolve(structure);
},
(err) => {
Logger.error(`Request error: ${err.config.url}`, 'StructureService');
Logger.error(err);
}
);
});
}
public async isClaimed(idStructure): Promise<boolean> {
const users = await this.userService.findAll();
users.forEach((user) => {
if (user.structuresLink.includes(idStructure)) {
return true;
}
});
return false;
}
/**
* Count every value occurence of a given key
* @param key structure key
* @return [{id: 'key', count: 'value'}]
*/
public async countByStructureKey(key: string): Promise<any> {
const uniqueElements = await this.structureModel.distinct(key).exec();
return await Promise.all(
uniqueElements.map(async (value) => {
return {
id: value,
count: await this.structureModel.countDocuments({ [key]: { $elemMatch: { $eq: value } } }).exec(),
};
})
);
}
public getCoord(numero: string, address: string, zipcode: string): Observable<AxiosResponse<any>> {
const req =
'https://download.data.grandlyon.com/geocoding/photon/api' + '?q=' + numero + ' ' + address + ' ' + zipcode;
Logger.log(`Request : ${req}`, 'StructureService - getCoord');
return this.httpService.get(encodeURI(req));
}
public async getNumberStructures(): Promise<number> {
return await this.structureModel.countDocuments(); //NOSONAR
}