faloker/purify

View on GitHub
api/src/reports/reports.service.ts

Summary

Maintainability
A
0 mins
Test Coverage
D
64%
import {
  Injectable,
  NotFoundException,
  BadRequestException,
  NotAcceptableException,
} from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { find, forOwn, isObject } from 'lodash';
import { Template } from 'src/templates/interfaces/template.interface';
import { Unit } from 'src/units/interfaces/unit.interface';
import { Issue } from 'src/issues/interfaces/issue.interface';
import { Report, ReportType } from './interfaces/report.interface';
import { xmlToJson } from 'src/utils/converter';
import { TemplatesService } from 'src/templates/templates.service';

@Injectable()
export class ReportsService {
  constructor(
    @InjectModel('Template') private readonly templateModel: Model<Template>,
    @InjectModel('Unit') private readonly unitModel: Model<Unit>,
    @InjectModel('Issue') private readonly issueModel: Model<Issue>,
    @InjectModel('Report') private readonly reportModel: Model<Report>,
    private readonly templatesService: TemplatesService
  ) {}

  async saveFileReport(file: any, unit: Unit, templateName = '') {
    if (!file) {
      throw new BadRequestException('Nothing to save, file was not provided');
    }

    const fileName: string = file.originalname;
    const rawData: any = file.buffer.toString('utf8');

    let data = null;

    if (fileName.indexOf('.json') > -1) {
      data = JSON.parse(rawData);
    } else if (fileName.indexOf('.xml') > -1) {
      data = xmlToJson(rawData);
    } else {
      throw new NotAcceptableException('Unsupported format');
    }

    return this.saveReport(ReportType.FILE, data, unit, templateName);
  }

  async saveOneshot(body: any, unit: Unit, templateName = '') {
    if (!Object.keys(body).length) {
      throw new BadRequestException('Request body is not valid JSON');
    } else if (Array.isArray(body)) {
      throw new BadRequestException(
        'Request body should be a single JSON object'
      );
    }

    return this.saveReport(ReportType.ONESHOT, body, unit, templateName);
  }

  async deleteOne(reportId: string) {
    await this.issueModel.deleteMany({ report: reportId });
    await this.reportModel.deleteOne({ _id: reportId });
  }

  async getReports(unitId: string) {
    return this.reportModel
      .find({ unit: unitId }, '-content')
      .lean()
      .populate('template', 'name');
  }

  async getContent(reportId: string) {
    const report = await this.reportModel.findOne({ _id: reportId }).lean();
    if (!report) {
      throw new NotFoundException('No such report');
    }

    if (report.type === 'oneshot') {
      return JSON.parse(report.content);
    }

    const result = {};

    function recur(obj, path) {
      if (Array.isArray(obj) && Object.keys(obj).length) {
        const len = Math.max(...obj.map((o) => Object.keys(o).length), 0);
        result[path] = find(obj, (k) => Object.keys(k).length === len);
      }
      forOwn(obj, (value, key) => {
        if (Array.isArray(value) && Object.keys(value).length) {
          if (isObject(value[0])) {
            const len = Math.max(...value.map((o) => Object.keys(o).length), 0);
            result[`${path}.${key}[0]`] = find(
              value,
              (k) => Object.keys(k).length === len
            );
          }
        } else if (isObject(value)) {
          recur(value, `${path}.${key}`);
        }
      });
    }

    recur(JSON.parse(report.content), 'root');
    return result;
  }

  async saveReport(type: ReportType, data: any, unit: Unit, templateName = '') {
    const report = await new this.reportModel({
      unit: unit._id,
      project: unit.project,
      type: type,
      content: JSON.stringify(data),
    }).save();

    if (templateName !== '') {
      await this.templatesService.apply(report._id, templateName);
    }

    return this.reportModel.findOne({ _id: report._id }, '-content').lean();
  }

  async findOne(reportId: string) {
    return this.reportModel.findOne({ _id: reportId }, '-content').lean();
  }
}