File

src/sales-force/organization-chart/organization-chart.services.ts

Index

Properties
Methods

Constructor

constructor(organizationChartRepository: Repository<OrganizationChart>, salesForceService: SalesForceService, clientService: ClientService, sharedService: SharedService)
Parameters :
Name Type Optional
organizationChartRepository Repository<OrganizationChart> No
salesForceService SalesForceService No
clientService ClientService No
sharedService SharedService No

Methods

buildRelations
buildRelations(n: number)
Parameters :
Name Type Optional
n number No
Returns : string[]
buildTree
buildTree(data: OrganizationChart[])
Parameters :
Name Type Optional
data OrganizationChart[] No
Returns : {}
buildTreeDescendents
buildTreeDescendents(data: OrganizationChart[])
Parameters :
Name Type Optional
data OrganizationChart[] No
Returns : any
Async createOrganizationChart
createOrganizationChart(body: OrganizationChartBody, clientId: number, authorization: string)
Parameters :
Name Type Optional
body OrganizationChartBody No
clientId number No
authorization string No
Returns : unknown
Async createOrganizationChartExcel
createOrganizationChartExcel(salesForceId, clientId, type)
Parameters :
Name Optional
salesForceId No
clientId No
type No
Returns : unknown
Async createOrganizationChartInitSalesForce
createOrganizationChartInitSalesForce(salesForceId: number, clientId: number)
Parameters :
Name Type Optional
salesForceId number No
clientId number No
Returns : unknown
Async deleteOrganizationChart
deleteOrganizationChart(id: number, clientId: number)
Parameters :
Name Type Optional
id number No
clientId number No
Returns : unknown
Async excelReportOrganizationCharts
excelReportOrganizationCharts(clientId: any, salesForceId: number, query: OrganizationChartExcelQuery)
Parameters :
Name Type Optional
clientId any No
salesForceId number No
query OrganizationChartExcelQuery No
Returns : unknown
getDescendantsIds
getDescendantsIds(nodeId, roots)
Parameters :
Name Optional
nodeId No
roots No
Returns : {}
Async getIdsOrganizationChart
getIdsOrganizationChart(salesForceId)
Parameters :
Name Optional
salesForceId No
Returns : unknown
Async getOrganizationChart
getOrganizationChart(clientId: any, salesForceId: number, query: OrganizationChartTableQuery)
Parameters :
Name Type Optional
clientId any No
salesForceId number No
query OrganizationChartTableQuery No
Returns : unknown
Async getOrganizationChartDescendants
getOrganizationChartDescendants(salesForceId: number, id)
Parameters :
Name Type Optional
salesForceId number No
id No
Returns : unknown
Async getOrganizationChartDistributor
getOrganizationChartDistributor(clientId: any, salesForceId: number, query: OrganizationChartTableQuery)
Parameters :
Name Type Optional
clientId any No
salesForceId number No
query OrganizationChartTableQuery No
Returns : unknown
Async getOrganizationChartId
getOrganizationChartId(id: number, clientId: number)
Parameters :
Name Type Optional
id number No
clientId number No
Returns : unknown
Async getOrganizationChartTree
getOrganizationChartTree(clientId: any, salesForceId: number)
Parameters :
Name Type Optional
clientId any No
salesForceId number No
Returns : unknown
Async putOrganizationChart
putOrganizationChart(body: OrganizationChartUpdate, clientId: number, id: number)
Parameters :
Name Type Optional
body OrganizationChartUpdate No
clientId number No
id number No
Returns : unknown
Async uploadFile
uploadFile(file: Express.Multer.File, clientId: number, salesForceId: number, token)
Parameters :
Name Type Optional
file Express.Multer.File No
clientId number No
salesForceId number No
token No
Returns : any
Async uploadFileType
uploadFileType(file: Express.Multer.File, clientId: number, salesForceId: number, type: string, token: string)
Parameters :
Name Type Optional
file Express.Multer.File No
clientId number No
salesForceId number No
type string No
token string No
Returns : any
validateExcel
validateExcel(data, salesForce, fornecedorParceriaAll, type)
Parameters :
Name Optional Default value
data No
salesForce No
fornecedorParceriaAll No
type No undefined
Returns : { arrayError: {}; arrayValue: {}; }

Properties

Private logger
Default value : new Logger(OrganizationChartService.name)
import { HttpException, HttpStatus, Inject, Injectable, Logger, forwardRef } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ILike, Repository } from 'typeorm';
import { OrganizationChartBody, OrganizationChartExcelQuery, OrganizationChartTableQuery, OrganizationChartUpdate, TreeNode } from '../dto/organization-chart.dto';
import { OrganizationChart } from '../entities/organization-chart.entity';
import { ClientService } from 'src/client/client.service';
import { SalesForceService } from '../sales-force/sales-force.services';
import { excelToJson } from 'src/util/excelToJson';
import { LinkedDistributorsChart } from '../entities/linked-distributors-chart.entity';
import { SharedService } from 'src/provider/shared-api/shared.services';
import { SalesForce } from '../entities/sales-force.entity';
import * as ExcelJS from 'exceljs';

@Injectable()
export class OrganizationChartService {
  private logger = new Logger(OrganizationChartService.name)
  constructor(
    @InjectRepository(OrganizationChart)
    private readonly organizationChartRepository: Repository<OrganizationChart>,
    @Inject(forwardRef(() => SalesForceService))
    private readonly salesForceService: SalesForceService,
    private readonly clientService: ClientService,
    private readonly sharedService: SharedService,

  ) { }

  async getIdsOrganizationChart(salesForceId) {
    const organizationCharts = await this.organizationChartRepository.findBy({ salesForceId })
    const idOrganizationCharts = organizationCharts.map(item => item.id);

    return idOrganizationCharts
  }

  async createOrganizationChart(body: OrganizationChartBody, clientId: number, authorization: string) {
    const organizationChart = new OrganizationChart();
    organizationChart.accessUserCode = body.accessUserCode;
    organizationChart.internalCode = body.internalCode;
    organizationChart.level = body.level;
    organizationChart.previousId = body.previousId;
    organizationChart.name = body.name;
    organizationChart.color = body.color;
    organizationChart.userName = body.userName;
    organizationChart.salesForceId = body.salesforceId;
    organizationChart.isSensitive = body.isSensitive;
    organizationChart.email = body.email;
    if (body.isSensitive && !body.email) {
      throw new HttpException('email_is_required', HttpStatus.BAD_REQUEST);
    }
    const regexEmail = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    if (body.email && !regexEmail.test(body.email)) {
      throw new HttpException('email_invalid', HttpStatus.BAD_REQUEST)
    }

    const salesforceLevel = await this.clientService.getClientIdSalesForceLevel(clientId);
    if (!salesforceLevel?.client) {
      throw new HttpException('client_id_not_found', 404);
    }
    const salesForce = await this.salesForceService.getSalesForceId(body.salesforceId, +salesforceLevel.client.mtrixCode);

    if (!salesForce) {
      throw new HttpException('sales_force_not_found_to_client', 404);
    }
    if (body.level === salesForce.countLevel && !!body.previousId) {
      throw new HttpException("previous_id_invalid_there_cant_be_a_previus_id", 504);
    }
    else if (salesForce.countLevel > body.level && !body.previousId) {
      throw new HttpException('previous_id_invalid_there_has_to_be_a_previus_id', 504);
    }

    if (body.previousId) {
      const organizationChartPrevius = await this.organizationChartRepository.findOneBy({ id: body.previousId })

      if (organizationChartPrevius && (body.level + 1 !== organizationChartPrevius.level)) {
        throw new HttpException('previousId_invalid_the_level_of_the_previous_node_has_to_be_higher_only_one_level', 504);
      }
    }

    if (salesforceLevel.countSalesForceLevel < body.level) {
      throw new HttpException('salesforceLevel_invalid_client_has_different_configuration_of_the_data_provided', 504);
    }
    salesForce.canImportExcel = false;
    await this.salesForceService.updateSalesForce(salesForce);
    return this.organizationChartRepository.save(organizationChart)
  }

  async createOrganizationChartInitSalesForce(salesForceId: number, clientId: number) {
    let organizationChartArray: OrganizationChart[] = [];
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);

    for (let i = client.countSalesForceLevel; i > 0; i--) {
      const organizationChart = new OrganizationChart();
      // organizationChart.previousId = ;
      organizationChart.name = 'NC';
      organizationChart.level = i
      organizationChart.salesForceId = salesForceId;
      organizationChartArray.push(organizationChart);

    }
    let previousId = undefined;
    let organizationChartArraySave: OrganizationChart[] = [];
    for await (let organizationChartItem of organizationChartArray) {
      organizationChartItem.previousId = previousId;
      await this.organizationChartRepository.save(organizationChartItem);
      previousId = organizationChartItem.id;
      organizationChartArraySave.push(organizationChartItem);
    }
    return organizationChartArraySave;
    // return this.organizationChartRepository.save(organizationChart);
  }

  async putOrganizationChart(body: OrganizationChartUpdate, clientId: number, id: number) {
    const salesforceLevel = await this.clientService.getClientIdSalesForceLevel(clientId);
    if (!salesforceLevel?.client) {
      throw new HttpException('client_id_not_found', 404);
    }
    const organizationChart = await this.organizationChartRepository.findOneBy({ id })
    organizationChart.accessUserCode = body.accessUserCode;
    organizationChart.internalCode = body.internalCode;
    organizationChart.name = body.name;
    organizationChart.color = body.color;
    organizationChart.userName = body.userName;
    organizationChart.isSensitive = body.isSensitive;
    organizationChart.email = body.email;
    if (body.isSensitive && !body.email) {
      throw new HttpException('email_is_required', HttpStatus.BAD_REQUEST);
    }
    const regexEmail = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    if (body.email && !regexEmail.test(body.email)) {
      throw new HttpException('email_invalid', HttpStatus.BAD_REQUEST)
    }
    const salesForce = await this.salesForceService.getSalesForceId(organizationChart.salesForceId, +salesforceLevel.client.mtrixCode);

    if (!salesForce) {
      throw new HttpException('sales_force_not_found_to_client', 404);
    }

    salesForce.canImportExcel = false;
    await this.salesForceService.updateSalesForce(salesForce);
    return this.organizationChartRepository.save(organizationChart)
  }
  buildRelations(n: number): string[] {
    if (n <= 0) {
      return [];
    }

    const relation = n === 1 ? 'previusOrganizationChart' : `previusOrganizationChart`;
    const parentRelation = this.buildRelations(n - 1);

    return parentRelation.length > 0
      ? [`${relation}.${parentRelation[0]}`, ...parentRelation]
      : [relation];
  }

  async getOrganizationChart(clientId: any, salesForceId: number, query: OrganizationChartTableQuery) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (!salesForce) {
      throw new HttpException('sales_force_not_found_to_client', HttpStatus.FAILED_DEPENDENCY);
    }
    const take = query.pageRows || 10;
    const page = query.pageNumber || 1;
    const skip = (page - 1) * take;

    const relations = this.buildRelations(salesForce.countLevel).reverse();
    const [organizationCharts, count] = await this.organizationChartRepository.findAndCount({
      where: {
        salesForceId,
        name: ILike(`%${query.name || ''}%`),
        linkedDistributorsChart: {
          distributorId: query.distributorId || undefined,
        },
        level: 1,
      },
      relations,
      order: { id: 'ASC' },
      skip, take
    });
    let namePropertiesLevel = salesForce.salesForceLevelConfig.map(elem => elem.description);
    let headers = [];
    let wch = [];
    namePropertiesLevel.forEach(item => {
      wch = [...wch, { wch: 20 }, { wch: 20 }, { wch: 20 }];
      headers = [item.toUpperCase(), `${item.toUpperCase()} PV`, `${item.toUpperCase()} USERNAME`, `${item.toUpperCase()} EMAIL`, `${item.toUpperCase()} COLOR`, ...headers]
    })
    headers = ['ID', 'SALES FORCE', ...headers]
    const formatTableOrganizationCharts = organizationCharts.map(item => {

      let organization = {
        id: item.id,
        nameSalesForce: salesForce.nameSalesForce,
        name: item.name,
        isSensitive: item.isSensitive,
        userName: item.userName,
        email: item.email,
        color: item.color,
      }
      let count = salesForce.countLevel;
      let previusOrganizationChart = item.previusOrganizationChart
      for (let i = 2; i <= count; i++) {
        if (i < count && !previusOrganizationChart) {
          organization[`nameNivel${i}`] = 'NC';
          organization[`isSensitiveNivel${i}`] = false;
          organization[`userNameNivel${i}`] = '';
          organization[`emailNivel${i}`] = '';
          organization[`colorNivel${i}`] = '';
          throw new HttpException(`not_invalid_sales_force_level_verify_configuration`, HttpStatus.FAILED_DEPENDENCY)
        }
        else {
          organization[`nameNivel${i}`] = previusOrganizationChart.name;
          organization[`isSensitiveNivel${i}`] = previusOrganizationChart.isSensitive;
          organization[`userNameNivel${i}`] = previusOrganizationChart.userName;
          organization[`emailNivel${i}`] = previusOrganizationChart.email;
          organization[`colorNivel${i}`] = previusOrganizationChart.color;
          previusOrganizationChart = previusOrganizationChart?.previusOrganizationChart;
        }
      }
      return organization;
    })

    return {
      recordset: {
        salesForce, headers, organizationCharts:
          formatTableOrganizationCharts
      },
      count
    };
  }

  async getOrganizationChartDistributor(clientId: any, salesForceId: number, query: OrganizationChartTableQuery) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (!salesForce) {
      throw new HttpException('sales_force_not_found_to_client', HttpStatus.FAILED_DEPENDENCY);
    }
    const take = query.pageRows || 10;
    const page = query.pageNumber || 1;
    const skip = (page - 1) * take;

    const queryBuilder = this.organizationChartRepository.createQueryBuilder('oc');
    queryBuilder.leftJoinAndSelect('oc.linkedDistributorsChart', 'linkedDistributorsChart');

    queryBuilder
      .skip(skip)
      .take(+page);
    const [organizationCharts, count] = await queryBuilder.getManyAndCount();

    let namePropertiesLevel = salesForce.salesForceLevelConfig.map(elem => elem.description);
    let headers = [];
    let wch = [];
    namePropertiesLevel.forEach(item => {
      wch = [...wch, { wch: 20 }, { wch: 20 }, { wch: 20 }];
      headers = [item.toUpperCase(), `${item.toUpperCase()} PV`, `${item.toUpperCase()} USERNAME`, `${item.toUpperCase()} EMAIL`, `${item.toUpperCase()} COLOR`, ...headers]
    })
    headers = ['ID', 'SALES FORCE', ...headers]

    return {
      recordset: {
        salesForce, headers, organizationCharts
      },
      count
    };
  }

  async excelReportOrganizationCharts(clientId: any, salesForceId: number, query: OrganizationChartExcelQuery) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (!salesForce) {
      throw new HttpException('sales_force_not_found_to_client', HttpStatus.FAILED_DEPENDENCY);
    }
    const relations = this.buildRelations(salesForce.countLevel).reverse();
    const [organizationCharts, count] = await this.organizationChartRepository.findAndCount({
      where: {
        salesForceId,
        name: ILike(`%${query.name || ''}%`),
        linkedDistributorsChart: {
          distributorId: query.distributorId || undefined,
        },
        level: 1,
      },
      relations,
      order: { id: 'ASC' },
    });

    let namePropertiesLevel = salesForce.salesForceLevelConfig.map(elem => elem.description).reverse();
    let headers = [];

    namePropertiesLevel.forEach(item => {
      headers = [`${item.toUpperCase()}`, `${item.toUpperCase()} PV`, `${item.toUpperCase()} EMAIL`, ...headers]
    })
    headers = ['SALES FORCE', ...headers]

    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet(salesForce.id.toString());
    worksheet.addRow(headers);
    worksheet.columns.forEach(function (column, i) {
      column.width = 25;
    });

    organizationCharts.forEach(item => {
      let rowData = [
        salesForce.nameSalesForce,
        item.name,
        item.isSensitive ? 'S' : 'N',
        item.email,
      ];
      let previusOrganizationChart = item.previusOrganizationChart;
      for (let i = 2; i <= salesForce.countLevel; i++) {
        rowData = [...rowData, previusOrganizationChart?.name, previusOrganizationChart?.isSensitive ? 'S' : 'N', previusOrganizationChart?.email];
        previusOrganizationChart = previusOrganizationChart?.previusOrganizationChart;
      }
      worksheet.addRow(rowData);
    });

    // Formatting headers
    worksheet.getRow(1).font = { bold: true };

    // Generate buffer
    const buffer = await workbook.xlsx.writeBuffer();
    return [client.client.name, buffer];
  }

  async getOrganizationChartTree(clientId: any, salesForceId: number) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (!salesForce) {
      throw new HttpException('sales_force_not_found_to_client', HttpStatus.FAILED_DEPENDENCY);
    }
    const organizationCharts = await this.organizationChartRepository.find({ where: { salesForceId }, order: { id: 'ASC' } });
    const tree = this.buildTree(organizationCharts);

    return { salesForce, tree };
  }

  async getOrganizationChartDescendants(salesForceId: number, id) {
    const organizationCharts = await this.organizationChartRepository.find({ where: { salesForceId }, order: { id: 'ASC' } });
    const tree = this.buildTreeDescendents(organizationCharts);
    const descendants = this.getDescendantsIds(id, tree);
    return descendants;
  }

  async createOrganizationChartExcel(salesForceId, clientId, type) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (salesForce.published) {
      throw new HttpException('sales_force_published', HttpStatus.BAD_REQUEST);
    }
    if (!client?.client) {
      throw new HttpException('client_id_not_found', HttpStatus.BAD_REQUEST);
    }
    if (!salesForce) {
      throw new HttpException('sales_force_id_not_found', HttpStatus.BAD_REQUEST);
    }

    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet(salesForce.id.toString());

    let namePropertiesLevel = salesForce.salesForceLevelConfig.map(elem => elem.description);
    let headers = [];
    let firstRow = [];
    let secondRow = [];
    let INTERMEDIARIO = '';
    let ID = undefined
    if (type === 'cnpjMtrix') {
      INTERMEDIARIO = 'CNPJ';
      ID =  10000000000000
    }
    else if (type === 'cdMtrix') {
      INTERMEDIARIO = 'CD_INTERMEDIARIO';
      ID =  0
    }
    namePropertiesLevel.forEach(item => {
      headers.push(item.toUpperCase(), `${item.toUpperCase()} PV`, `${item.toUpperCase()} EMAIL`);
      firstRow.push(`${item.toUpperCase()} NC -S`, `S`, `[email protected]`);
      secondRow.push(`${item.toUpperCase()} NC -N`, `N`, ``);
    });
    if (INTERMEDIARIO) {
      headers.push(INTERMEDIARIO);
      firstRow.push(`${ID}`);
      secondRow.push(`${ID+1}`)
    }
    worksheet.addRow(headers);
    worksheet.addRow(firstRow);
    worksheet.addRow(secondRow);
    worksheet.getRow(1).font = { bold: true };
    worksheet.columns.forEach(column => {
      column.width = 25;
    });

    const buffer = await workbook.xlsx.writeBuffer();
    return [client.client.name, buffer]; // Return name and buffer
  }

  validateExcel(data, salesForce, fornecedorParceriaAll, type = undefined) {
    let arrayValue = [];
    let arrayError = [];
    data.forEach((item, numberRow) => {
      let namePropertiesLevel = salesForce.salesForceLevelConfig.map(elem => elem.description.toUpperCase());
      let itemError = [];
      let msgError = [];
      let INTERMEDIARIO = '';
      if (type === 'cnpjMtrix') {
        INTERMEDIARIO = 'CNPJ'
      }
      else if (type === 'cdMtrix') {
        INTERMEDIARIO = 'CD_INTERMEDIARIO'
      }
      else if (!type) {
        INTERMEDIARIO = 'INTERMEDIARIO'
      }

      const distributorParceria = fornecedorParceriaAll.content.find(intermediario =>
        intermediario.cnpjIntermediario === item[INTERMEDIARIO] ||
        intermediario.cdIntermediario === +item[INTERMEDIARIO]);
      namePropertiesLevel.forEach((level, index) => {
        let hash = '';
        namePropertiesLevel.forEach((itemP) => {
          hash = `${hash ? hash + '🤝' : ''}${item[itemP]}`;
        });
        const existItemChart = arrayValue.findIndex(elem => {
          const nodesItem = hash.split('🤝').reverse();;
          nodesItem.splice(namePropertiesLevel.length - (index + 1), nodesItem.length - (namePropertiesLevel.length - (index + 1)));
          const nodesItemjoin = nodesItem.join('🤝');
          const nodesElem = elem.hash.split('🤝').reverse();
          nodesElem.splice(namePropertiesLevel.length - (index + 1), nodesElem.length - (namePropertiesLevel.length - (index + 1)));
          const nodesElemjoin = nodesElem.join('🤝');
          if (elem.NAME_CHART === item[`${level.toUpperCase()}`] &&
            (elem.LEVEL === index + 1) &&
            elem.PREVIUS_NAME_CHART === item[`${namePropertiesLevel[index + 1]}`.toUpperCase()] &&
            nodesItemjoin === nodesElemjoin
          )
            return elem
        })
        if (existItemChart === -1 && !!item[`${level.toUpperCase()}`]) {

          const row = {
            LEVEL: index + 1,
            NAME_CHART: item[`${level}`],
            IS_SENSITIVE: item[`${level} PV`],
            EMAIL: item[`${level} EMAIL`],
            PREVIUS_NAME_CHART: item[`${namePropertiesLevel[index + 1]}`],
            DISTRIBUTORS: index === 0 && item[INTERMEDIARIO] ? [distributorParceria?.cdIntermediario] : [],
            hash,
          };
          arrayValue.push(row);
          if (!row.NAME_CHART) {
            msgError.push('name_chart_required');
            itemError.push(level);
          }
          if (row.IS_SENSITIVE === 'S' && !row.EMAIL) {
            msgError.push('email_is_required_to_lgpd');
            itemError.push(`${level} EMAIL`);
          }
          if (row.IS_SENSITIVE === 'N' && row.EMAIL) {
            msgError.push('email_should_not_be_filled_in');
            itemError.push(`${level} EMAIL`);
          }
          const regexEmail = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
          if (row.EMAIL && !regexEmail.test(row.EMAIL)) {
            msgError.push('email_invalid');
            itemError.push(`${level} EMAIL`);
          }

          if (index === 0 && item[INTERMEDIARIO] && !distributorParceria?.cdIntermediario) {
            msgError.push('distributor_not_found_partnership');
            itemError.push(level);
          }
        }
        else if (index === 0) {
          if (item[INTERMEDIARIO] && !distributorParceria?.cdIntermediario) {
            msgError.push('distributor_not_found');
            itemError.push(level);
          }
          if (!item[`${level.toUpperCase()}`]) {
            msgError.push('name_chart_required');
            itemError.push(level);
          }
          else
            if (item[INTERMEDIARIO])
              arrayValue[existItemChart].DISTRIBUTORS.push(item[INTERMEDIARIO]);
        }
        else if (!item[`${level.toUpperCase()}`]) {
          msgError.push('previus_name_chart_required');
          itemError.push(level);
        }
      })
      if (msgError.length) {
        arrayError.push({
          row: numberRow + 2,
          item: itemError,
          msg: msgError
        })
      }
    })

    return { arrayError, arrayValue }
  }
  async uploadFileType(file: Express.Multer.File,
    clientId: number,
    salesForceId: number,
    type: string,
    token: string
  ) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (salesForce.published) {
      throw new HttpException('sales_force_published', HttpStatus.BAD_REQUEST);
    }
    if (!client?.client) {
      throw new HttpException('client_id_not_found', HttpStatus.BAD_REQUEST);
    }
    if (!salesForce) {
      throw new HttpException('sales_force_id_not_found', HttpStatus.BAD_REQUEST);
    }
    if (!salesForce.canImportExcel) {
      throw new HttpException('sales_force_not_import', HttpStatus.BAD_REQUEST);
    }
    const data: any[] = await excelToJson<any>(file.buffer);
    const arrayLevel = [];
    const arrayDescriptionLevel = [];
    for (let i = salesForce.countLevel; i > 0; i--) {
      arrayLevel.push(i);
    }
    salesForce.salesForceLevelConfig.forEach(itemLevel => {
      arrayDescriptionLevel.push(itemLevel.description)
    })
    const fornecedorParceriaAll = await this.sharedService.getFornecedorParceria(+client.client.mtrixCode, token);

    const { arrayValue, arrayError } = this.validateExcel(data, salesForce, fornecedorParceriaAll, type)
    if (arrayError.length) {
      throw new HttpException(arrayError, 415);
    }
    const queryRunner = this.organizationChartRepository.manager.connection.createQueryRunner();
    try {
      await queryRunner.startTransaction();
      await queryRunner.manager.softDelete(OrganizationChart, { name: 'NC', salesForceId: salesForce.id });
      let organizationChartPrevius: OrganizationChart[] = []
      let linkedDistributorsChartArray: LinkedDistributorsChart[] = []
      for await (let organizationLevel of arrayLevel) {
        const organizationChartsExcel = arrayValue.filter(item => +item.LEVEL === organizationLevel);
        const organizationCharts = organizationChartsExcel.map(item => {
          const previous = organizationChartPrevius.find(elem => {
            const structurePrevius = elem.hash.split('🤝').reverse();
            structurePrevius.splice(structurePrevius.length - (item.LEVEL + 1), structurePrevius.length - (structurePrevius.length - (item.LEVEL + 1)));
            const structurePreviusString = structurePrevius.join('🤝');
            const strutuctOc = item.hash.split('🤝').reverse();
            strutuctOc.splice(strutuctOc.length - (item.LEVEL + 1), strutuctOc.length - (strutuctOc.length - (item.LEVEL + 1)));
            const strutuctOcString = strutuctOc.join('🤝');
            if (
              item.PREVIUS_NAME_CHART === elem.name &&
              elem.level === +item.LEVEL + 1 &&
              structurePreviusString === strutuctOcString)
              return elem;
          })
          const organizationChart = new OrganizationChart();
          organizationChart.name = item.NAME_CHART;
          organizationChart.accessUserCode = item.ACCESS_USER_CODE
          organizationChart.internalCode = item.INTERNAL_CODE;
          organizationChart.level = +item.LEVEL;
          organizationChart.isSensitive = item.IS_SENSITIVE === 'S' ? true : false;
          organizationChart.email = item.EMAIL;
          organizationChart.hash = item.hash;
          if (+item.LEVEL < salesForce.countLevel && !previous?.id) {
            throw new HttpException('invalid_worksheet', HttpStatus.BAD_REQUEST)
          }
          if (organizationChart.isSensitive && !organizationChart.email) {
            throw new HttpException('email_is_required_to_lgpd', HttpStatus.BAD_REQUEST);
          }
          const regexEmail = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
          if (organizationChart.email && !regexEmail.test(organizationChart.email)) {
            throw new HttpException('email_invalid', HttpStatus.BAD_REQUEST)
          }
          organizationChart.previousId = previous?.id;
          organizationChart.userName = item.USER_NAME;
          organizationChart.salesForceId = salesForce.id;
          organizationChart.linkedDistributorsChart = [];
          item.DISTRIBUTORS?.forEach(distID => {
            const linkedDistributorsChart = new LinkedDistributorsChart();
            const distributorParceria = fornecedorParceriaAll.content.find(intermediario =>
              intermediario.cnpjIntermediario === distID ||
              intermediario.cdIntermediario === +distID)
            if (distID) {
              linkedDistributorsChart.distributorId = distributorParceria?.cdIntermediario || distID;
              linkedDistributorsChart.nameDistributor = distributorParceria?.nmIntermediario || 'Não encontrado';
              linkedDistributorsChart.clientId = client.client.id;
              linkedDistributorsChart.level = +item.LEVEL;
              organizationChart.linkedDistributorsChart.push(linkedDistributorsChart);
            }
          })
          return organizationChart;
        })
        organizationChartPrevius = await queryRunner.manager.save(OrganizationChart, organizationCharts);
        if (organizationLevel === 1) {
          organizationCharts.forEach(organizationToLink => {
            organizationToLink.linkedDistributorsChart.forEach(link => {
              link.organizationChartId = organizationToLink.id;
              linkedDistributorsChartArray.push(link);
            })
          })
        }
      }
      if (linkedDistributorsChartArray.length)
        await queryRunner.manager.save(LinkedDistributorsChart, linkedDistributorsChartArray);

      salesForce.canImportExcel = false;
      await queryRunner.manager.save(SalesForce, salesForce);
      await queryRunner.commitTransaction();
    } catch (error) {
      this.logger.error(`uploadFileType.catch, ${clientId}, ${salesForceId}, ${type}`);
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }

  async uploadFile(file: Express.Multer.File,
    clientId: number,
    salesForceId: number,
    token
  ) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);
    const salesForce = await this.salesForceService.getSalesForceId(salesForceId, +client.client.mtrixCode);
    if (salesForce.published) {
      throw new HttpException('sales_force_published', HttpStatus.BAD_REQUEST);
    }
    if (!client?.client) {
      throw new HttpException('client_id_not_found', HttpStatus.BAD_REQUEST);
    }
    if (!salesForce) {
      throw new HttpException('sales_force_id_not_found', HttpStatus.BAD_REQUEST);
    }
    if (!salesForce.canImportExcel) {
      throw new HttpException('sales_force_not_import', HttpStatus.BAD_REQUEST);
    }
    const data: any[] = await excelToJson<any>(file.buffer);
    const arrayLevel = [];
    const arrayDescriptionLevel = [];
    for (let i = salesForce.countLevel; i > 0; i--) {
      arrayLevel.push(i);
    }
    salesForce.salesForceLevelConfig.forEach(itemLevel => {
      arrayDescriptionLevel.push(itemLevel.description)
    })
    const fornecedorParceriaAll = await this.sharedService.getFornecedorParceria(+client.client.mtrixCode, token);

    const { arrayValue, arrayError } = await this.validateExcel(data, salesForce, fornecedorParceriaAll)
    if (arrayError.length) {
      throw new HttpException(arrayError, 415);
    }
    const queryRunner = this.organizationChartRepository.manager.connection.createQueryRunner();
    try {
      await queryRunner.startTransaction();
      await queryRunner.manager.softDelete(OrganizationChart, { name: 'NC', salesForceId: salesForce.id });
      let organizationChartPrevius: OrganizationChart[] = []
      let linkedDistributorsChartArray: LinkedDistributorsChart[] = []
      for await (let organizationLevel of arrayLevel) {
        const organizationChartsExcel = arrayValue.filter(item => +item.LEVEL === organizationLevel);
        const organizationCharts = organizationChartsExcel.map(item => {
          const previous = organizationChartPrevius.find(elem => {
            const structurePrevius = elem.hash.split('🤝').reverse();
            structurePrevius.splice(structurePrevius.length - (item.LEVEL + 1), structurePrevius.length - (structurePrevius.length - (item.LEVEL + 1)));
            const structurePreviusString = structurePrevius.join('🤝');
            const strutuctOc = item.hash.split('🤝').reverse();
            strutuctOc.splice(strutuctOc.length - (item.LEVEL + 1), strutuctOc.length - (strutuctOc.length - (item.LEVEL + 1)));
            const strutuctOcString = strutuctOc.join('🤝');
            if (
              item.PREVIUS_NAME_CHART === elem.name &&
              elem.level === +item.LEVEL + 1 &&
              structurePreviusString === strutuctOcString)
              return elem;
          })
          const organizationChart = new OrganizationChart();
          organizationChart.name = item.NAME_CHART;
          organizationChart.accessUserCode = item.ACCESS_USER_CODE
          organizationChart.internalCode = item.INTERNAL_CODE;
          organizationChart.level = +item.LEVEL;
          organizationChart.isSensitive = item.IS_SENSITIVE === 'S' ? true : false;
          organizationChart.email = item.EMAIL;
          organizationChart.hash = item.hash;
          if (+item.LEVEL < salesForce.countLevel && !previous?.id) {
            throw new HttpException('invalid_worksheet', HttpStatus.BAD_REQUEST)
          }
          if (organizationChart.isSensitive && !organizationChart.email) {
            throw new HttpException('email_is_required_to_lgpd', HttpStatus.BAD_REQUEST);
          }
          const regexEmail = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
          if (organizationChart.email && !regexEmail.test(organizationChart.email)) {
            throw new HttpException('email_invalid', HttpStatus.BAD_REQUEST)
          }
          organizationChart.previousId = previous?.id;
          organizationChart.userName = item.USER_NAME;
          organizationChart.salesForceId = salesForce.id;
          organizationChart.linkedDistributorsChart = [];
          item.DISTRIBUTORS?.forEach(distID => {
            const linkedDistributorsChart = new LinkedDistributorsChart();
            const distributorParceria = fornecedorParceriaAll.content.find(intermediario =>
              intermediario.cnpjIntermediario === distID ||
              intermediario.cdIntermediario === +distID)
            if (distID) {
              linkedDistributorsChart.distributorId = distributorParceria?.cdIntermediario || distID;
              linkedDistributorsChart.nameDistributor = distributorParceria?.nmIntermediario || 'Não encontrado';
              linkedDistributorsChart.clientId = client.client.id;
              linkedDistributorsChart.level = +item.LEVEL;
              organizationChart.linkedDistributorsChart.push(linkedDistributorsChart);
            }
          })
          return organizationChart;
        })
        organizationChartPrevius = await queryRunner.manager.save(OrganizationChart, organizationCharts);
        if (organizationLevel === 1) {
          organizationCharts.forEach(organizationToLink => {
            organizationToLink.linkedDistributorsChart.forEach(link => {
              link.organizationChartId = organizationToLink.id;
              linkedDistributorsChartArray.push(link);
            })
          })
        }
      }
      if (linkedDistributorsChartArray.length)
        await queryRunner.manager.save(LinkedDistributorsChart, linkedDistributorsChartArray);

      salesForce.canImportExcel = false;
      await queryRunner.manager.save(SalesForce, salesForce);
      await queryRunner.commitTransaction();
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }


  async deleteOrganizationChart(id: number, clientId: number) {
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);

    if (client.client) {
      const crildren = await this.organizationChartRepository.findBy({ previousId: id });
      if (crildren.length > 0) {
        throw new HttpException('unable_to_delete_node_with_bottom_link', 404);
      }

      return await this.organizationChartRepository.softDelete({ id });
    }
    throw new HttpException('client_id_not_found', 404);
  }

  async getOrganizationChartId(id: number, clientId: number) {
    // return  await this.salesForceRepository.findOneBy({ id, supplierId });
    const client = await this.clientService.getClientIdSalesForceLevel(clientId);

    if (client?.client) {
      return await this.organizationChartRepository.findOneBy({ id });
    }
    throw new HttpException('client_id_not_found', 404);
  }

  buildTree(data: OrganizationChart[]) {
    const idToNodeMap = new Map();
    for (const item of data) {
      const { id, previousId } = item;
      let node = new TreeNode();
      node = { ...item, children: [] }
      idToNodeMap.set(id, node);

      if (previousId !== null && idToNodeMap.has(previousId)) {
        idToNodeMap.get(previousId).children.push(node);
      }
    }
    const roots = [];
    for (const node of idToNodeMap.values()) {
      if (!node.previousId || !idToNodeMap.has(node.previousId)) {
        roots.push(node);
      }
    }
    return roots;
  }

  buildTreeDescendents(data: OrganizationChart[]) {
    const idToNodeMap = new Map();
    for (const item of data) {
      const { id, previousId } = item;
      let node = new TreeNode();
      node = { ...item, children: [] }
      idToNodeMap.set(id, node);

      if (previousId !== null && idToNodeMap.has(previousId)) {
        idToNodeMap.get(previousId).children.push(node);
      }
    }
    return idToNodeMap;
  }
  getDescendantsIds(nodeId, roots) {
    const descendants = [];
    const dfs = (node) => {
      descendants.push(node.id);
      for (const child of node.children) {
        dfs(child);
      }
    };
    const startNode = roots.get(nodeId);
    if (startNode) {
      dfs(startNode);
    }
    return descendants;
  }

}

results matching ""

    No results matching ""