Skip to content
Snippets Groups Projects
structures.service.ts 5.41 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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';
    
    Hugo SUBTIL's avatar
    Hugo SUBTIL committed
    
    @Injectable()
    
    export class StructuresService {
    
      constructor(
        private readonly httpService: HttpService,
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
        private readonly userService: UsersService,
    
        @InjectModel(Structure.name) private structureModel: Model<StructureDocument>
      ) {}
    
      public async create(idUser: string, structureDto: structureDto): Promise<Structure> {
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
        const user = await this.userService.findOne(idUser);
    
        if (!user) {
          throw new HttpException('Invalid profile', HttpStatus.NOT_FOUND);
        }
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
        const createdStructure = new this.structureModel(structureDto);
    
        createdStructure.id = (await this.getNumberStructures()) + 1;
        createdStructure.save();
    
        user.structuresLink.push(createdStructure.id);
        user.save();
    
      public async search(searchString: string, filters?: Array<any>): Promise<Structure[]> {
        if (searchString && filters) {
    
    Hugo SUBTIL's avatar
    Hugo SUBTIL committed
          return this.structureModel
            .find({ $and: [...this.parseFilter(filters), { $text: { $search: searchString } }] })
            .exec();
    
    Hugo SUBTIL's avatar
    Hugo SUBTIL committed
          return this.structureModel.find({ $or: this.parseFilter(filters) }).exec();
    
    Hugo SUBTIL's avatar
    Hugo SUBTIL committed
          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> {
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
        const result = await this.structureModel.updateOne({ id: idStructure }, structure); //NOSONAR
    
        if (!result) {
          throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
        }
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
        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);
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
      public async isClaimed(idStructure): Promise<boolean> {
        const users = await this.userService.findAll();
        users.forEach((user) => {
          if (user.structuresLink.includes(idStructure)) {
            return true;
          }
        });
        return false;
      }
    
    
    Hugo SUBTIL's avatar
    Hugo SUBTIL committed
      /**
       * Count every value occurence of a given key
       * @param key structure key
       * @return [{id: 'key', count: 'value'}]
       */
    
      public async countByStructureKey(key: string): Promise<any> {
    
    Hugo SUBTIL's avatar
    Hugo SUBTIL committed
        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> {
    
    Jérémie BRISON's avatar
    Jérémie BRISON committed
        return await this.structureModel.countDocuments(); //NOSONAR