Skip to content
Snippets Groups Projects
structures.service.ts 4.14 KiB
Newer Older
import { HttpService, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Observable } from 'rxjs';
import { AxiosResponse } from 'axios';
import { CreateStructureDto } from './dto/create-structure.dto';
import { Structure, StructureDocument } from './schemas/structure.schema';
import { Logger } from '@nestjs/common';
Hugo SUBTIL's avatar
Hugo SUBTIL committed

@Injectable()
export class StructuresService {
  constructor(
    private readonly httpService: HttpService,
    @InjectModel(Structure.name) private structureModel: Model<StructureDocument>
  ) {}
  public async create(createStructrureDto: CreateStructureDto): Promise<Structure> {
    const createdStructure = new this.structureModel(createStructrureDto);
    return createdStructure.save();
  }

  public async search(searchString: string, filters?: Array<any>): Promise<Structure[]> {
    let query: any;
    if (searchString && filters) {
      query = [...this.parseFilter(filters), { $text: { $search: searchString } }];
    } else if (filters) {
      query = this.parseFilter(filters);
    } else {
      query = [{ $text: { $search: searchString } }];
    }
    return this.structureModel.find({ $or: query }).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) {
          this.getStructurePosition(structure).then((postition) => {
            this.structureModel
              .findOneAndUpdate({ id: structure.id }, { address: postition.address, coord: postition.coord })
              .exec();
          });
        }
        if (structure.coord.length <= 0) {
          this.getStructurePosition(structure).then((postition) => {
            this.structureModel.findOneAndUpdate({ id: postition.id }, { coord: postition.coord }).exec();
          });
        }
      })
    );
    return this.structureModel.find().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.n, structure.voie, structure.commune).subscribe(
        (res) => {
          const address = res.data.features[0];
          structure.address = structure.voie + ' - ' + address.properties.postcode + ' ' + address.properties.city;
          structure.coord = address.geometry.coordinates;
          resolve(structure);
        },
        (err) => {
          Logger.error(`[getCoord] Request error: ${err.config.url}`, err);
        }
      );
    });
  }

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 async countByEquipmentsKey(key: string, displayKey: string): Promise<any> {
    return [{ id: displayKey, count: await this.structureModel.countDocuments({ [key]: true }).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(`[StructureService - getCoord] Request : ${req}`);
    return this.httpService.get(encodeURI(req));
  }