import { HttpException, HttpStatus, Inject, Injectable, Logger, forwardRef } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Between, FindOptionsWhere, ILike, In, IsNull, LessThan, MoreThan, Not, Repository } from 'typeorm';
import { LinkedDistributorsChartBody, LinkedDistributorsChartQuery } from '../dto/linked-distributors-chart.dto';
import { LinkedDistributorsChart } from '../entities/linked-distributors-chart.entity';
import { OrganizationChart } from '../entities/organization-chart.entity';
import { OrganizationChartService } from '../organization-chart/organization-chart.services';
import { excelToJson } from 'src/util/excelToJson';
import { ClientService } from 'src/client/client.service';
import { SharedService } from 'src/provider/shared-api/shared.services';
import * as ExcelJS from 'exceljs';
import { SalesForceService } from '../sales-force/sales-force.services';
@Injectable()
export class LinkedDistributorsChartService {
private readonly logger = new Logger(LinkedDistributorsChartService.name);
constructor(
@InjectRepository(LinkedDistributorsChart)
private readonly linkedDistributorsChartRepository: Repository<LinkedDistributorsChart>,
@InjectRepository(OrganizationChart)
private readonly organizationChartRepository: Repository<OrganizationChart>,
private organizationChartService: OrganizationChartService,
private clientService: ClientService,
private sharedService: SharedService,
@Inject(forwardRef(() => SalesForceService))
private readonly salesForceService: SalesForceService,
) { }
async createlinkedDistributorsChart(body: LinkedDistributorsChartBody, organizationChartId: number) {
if (body.level !== 1) {
throw new HttpException('you_can_only_link_a_distributor_to_level_1', HttpStatus.FAILED_DEPENDENCY)
}
const linkedDistributorsChartFind = await this.linkedDistributorsChartRepository.findOneBy({ organizationChartId, clientId: body.clientId, distributorId: body.distributorId })
if (linkedDistributorsChartFind) {
throw new HttpException('duplicate_linked_distribuitor_client_level', HttpStatus.CONFLICT)
}
const linkedDistributorsChart = new LinkedDistributorsChart()
linkedDistributorsChart.organizationChartId = organizationChartId;
linkedDistributorsChart.clientId = body.clientId;
linkedDistributorsChart.clientDistributorId = body.clientDistributorId;
linkedDistributorsChart.distributorId = body.distributorId;
linkedDistributorsChart.nameDistributor = body.nameDistributor;
linkedDistributorsChart.level = body.level;
const organizationChart = await this.organizationChartRepository.findOneBy({
id: organizationChartId,
});
// const linkedDistributorsChartPreviuos = new LinkedDistributorsChart()
// linkedDistributorsChartPreviuos.organizationChartId = organizationChart.previousId;
// linkedDistributorsChartPreviuos.clientId = body.clientId;
// linkedDistributorsChartPreviuos.clientDistributorId = body.clientDistributorId;
// linkedDistributorsChartPreviuos.distributorId = body.distributorId;
// linkedDistributorsChartPreviuos.nameDistributor = body.nameDistributor;
// linkedDistributorsChartPreviuos.level = body.level;
// await this.linkedDistributorsChartRepository.save(linkedDistributorsChartPreviuos);
await this.linkedDistributorsChartRepository.save(linkedDistributorsChart);
return { linkedDistributorsChart };
}
async putlinkedDistributorsChart(body: LinkedDistributorsChartBody, organizationChartId: number, id: number) {
if (body.level !== 1) {
throw new HttpException('you_can_only_link_a_distributor_to_level_1', HttpStatus.FAILED_DEPENDENCY)
}
const linkedDistributorsChart = await this.linkedDistributorsChartRepository.findOne({
where: {
id,
organizationChartId
}
});
// linkedDistributorsChart.organizationChartId = body.organizationChartId;
// linkedDistributorsChart.clientId = body.clientId;
linkedDistributorsChart.clientDistributorId = body.clientDistributorId;
linkedDistributorsChart.distributorId = body.distributorId;
linkedDistributorsChart.nameDistributor = body.nameDistributor;
linkedDistributorsChart.level = body.level;
return await this.linkedDistributorsChartRepository.save(linkedDistributorsChart)
}
async getlinkedDistributorsChart(query: LinkedDistributorsChartQuery, organizationChartId: number) {
const take = query.pageRows || 10;
const page = query.pageNumber || 1;
const skip = (page - 1) * take;
let where: FindOptionsWhere<LinkedDistributorsChart> = {
organizationChartId,
distributorId: query.distributorId,
clientDistributorId: query.clientDistributorId,
nameDistributor: ILike(`%${query.nameDistributor || ''}%`),
level: query.level,
}
const [recordset, count] = await this.linkedDistributorsChartRepository.findAndCount({ where, skip, take });
return { recordset, count }
}
async deletelinkedDistributorsChart(organizationChartId: number, id: number) {
const linkedDistributorsChart = await this.linkedDistributorsChartRepository.findOneBy({
id,
organizationChartId
});
const organizationChart = await this.organizationChartRepository.findOneBy({
id: organizationChartId,
});
const { salesForceId } = organizationChart;
const organizationChartIds: number[] = await this.organizationChartService.getOrganizationChartDescendants(salesForceId, organizationChartId)
// let previousId = organizationChartId;
return await this.linkedDistributorsChartRepository.softDelete({
distributorId: linkedDistributorsChart.distributorId,
organizationChartId: In(organizationChartIds)
});
}
async deletelinkedDistributorsChartAll(organizationChartId: number) {
const linkedDistributorsChart = await this.linkedDistributorsChartRepository.delete({
organizationChartId,
});
return { count: linkedDistributorsChart.affected };
}
async getlinkedDistributorsChartId(id: number, organizationChartId: number) {
return await this.linkedDistributorsChartRepository.findOneBy({ id, organizationChartId });
}
async getIdDistributorsSalesForce(salesForceId) {
const ids = await this.organizationChartService.getIdsOrganizationChart(salesForceId);
const linkedDistributorsChart = await this.linkedDistributorsChartRepository.findBy({ organizationChartId: In(ids) });
const distributorsIDs = linkedDistributorsChart.map(item => item.distributorId);
let distributors = distributorsIDs.filter((value, index, self) => {
return self.indexOf(value) === index;
});
return distributors;
}
async uploadFile(file: Express.Multer.File,
organizationChartId: number,
token: string = undefined,
) {
let arrayError = [];
const organizationChart = await this.organizationChartRepository.findOne({
where: {
id: organizationChartId,
},
relations: ['salesForce'],
});
const client = await this.clientService.findClientByMtrixCode({ mtrixCode: organizationChart.salesForce.cdMtrix, clientType: 'F' });
const parceriaFornecedor = await this.sharedService.getFornecedorParceria(organizationChart.salesForce.cdMtrix, token)
if (!organizationChart) {
throw new HttpException('organization_chart_id_not_found', 404);
}
if (organizationChart.level !== 1) {
throw new HttpException('organization_chart_id_not_level_1', 404);
}
const data: any[] = await excelToJson<any>(file.buffer);
const distributorIds = data.map((item, index) => {
const cdIntermediario = item[`CD_INTERMEDIARIO`];
const intermediario = parceriaFornecedor.content.findIndex(intermediario => intermediario.cdIntermediario === +cdIntermediario);
if (intermediario === -1) {
arrayError.push({
row: index + 2,
item: [+item[`CD_INTERMEDIARIO`]],
msg: ['verify_partnership']
})
// throw new HttpException('bulk_registration.errors.verify_partnership', 501 )
}
return cdIntermediario;
});
const linkedDistributorsCharts = await this.linkedDistributorsChartRepository.find({
where: {
distributorId: In(distributorIds),
clientId: client.id,
organizationChart: {
deleteDate: IsNull(),
salesForce: {
deleteDate: IsNull(),
}
}
}
, relations: ['organizationChart', 'organizationChart.salesForce']
});
const queryRunner = this.organizationChartRepository.manager.connection.createQueryRunner();
try {
await queryRunner.startTransaction();
let linkedDistributorsChartsNew: LinkedDistributorsChart[] = [];
data.forEach((item, index) => {
const distributor = parceriaFornecedor.content.find(intermediario => intermediario.cdIntermediario === +item[`CD_INTERMEDIARIO`]);
if (distributor) {
const linkedDistributorsDuplication = linkedDistributorsCharts.find(elem => elem.distributorId === distributor.cdIntermediario && organizationChart.salesForce.id === elem.organizationChart.salesForce?.id);
if (linkedDistributorsDuplication) {
const indexRow = arrayError.findIndex(item => item.row === (index + 2))
if (indexRow !== -1) {
arrayError[indexRow].msg.push('organization_chart_id_exists_linked')
}
else {
arrayError.push({
row: index + 2,
item: [+item[`CD_INTERMEDIARIO`]],
msg: ['organization_chart_id_exists_linked']
})
}
// throw new HttpException('bulk_registration.errors.organization_chart_id_exists_linked', 404);
}
const linkedDistributorsChart = new LinkedDistributorsChart()
linkedDistributorsChart.organizationChartId = organizationChart.id;
linkedDistributorsChart.clientId = client.id;
linkedDistributorsChart.distributorId = distributor.cdIntermediario;
linkedDistributorsChart.nameDistributor = distributor.nmIntermediario;
linkedDistributorsChart.level = organizationChart.level;
linkedDistributorsChartsNew.push(linkedDistributorsChart);
}
})
if (arrayError.length > 0)
throw new HttpException(arrayError, 415);
if (linkedDistributorsChartsNew.length && arrayError.length === 0) {
await queryRunner.manager.save(LinkedDistributorsChart, linkedDistributorsChartsNew);
await queryRunner.commitTransaction();
}
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
}
async getLinkDistributorsHeaders() {
const headers = ['CD_INTERMEDIARIO'];
const wch = [{ width: 20 }];
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('DISTRIBUTORS');
worksheet.columns = wch.map(width => ({ width: width.width }));
worksheet.addRow(headers);
worksheet.getRow(1).font = { bold: true };
const buffer = await workbook.xlsx.writeBuffer();
return ['DISTRIBUTORS', buffer];
}
async getLinkDistributors(query, removeUser = false) {
const { pageNumber, pageRows, name, distributorId, clientId, salesForceId } = query
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 skip = (+pageNumber - 1) * +pageRows;
const queryBuilder = this.linkedDistributorsChartRepository.createQueryBuilder('ldc')
// innerJoinAndSelect('ldc.organizationChart', 'organizationChart');
let organizationChartStr = 'ldc.organizationChart';
salesForce.salesForceLevelConfig.map(item => {
queryBuilder.leftJoinAndSelect(organizationChartStr, `${item.description}`)
organizationChartStr = `${item.description}.previusOrganizationChart`;
})
queryBuilder.leftJoinAndSelect(`${salesForce.salesForceLevelConfig[0].description}.salesForce`, 'salesForce')
// leftJoinAndSelect('organizationChart.previusOrganizationChart','previusOrganizationChart');
queryBuilder.where(`${salesForce.salesForceLevelConfig[0].description}.name ilike :name`, { name: `%${name || ''}%` });
if (distributorId)
queryBuilder.andWhere(`ldc.distributorId = :distributorId`, { distributorId });
if (salesForceId)
queryBuilder.andWhere(`${salesForce.salesForceLevelConfig[0].description}.salesForceId = :salesForceId`, { salesForceId: +salesForceId });
// queryBuilder.select(['ldc_organization_chart_id'])
if (pageNumber && pageRows) {
queryBuilder
.skip(skip)
.take(+pageRows);
}
const [recordset, count] = await queryBuilder.getManyAndCount();
if (recordset.length) {
const recordsetFormated = recordset.map(item => {
let organizationChartStr = {};
let oc = item.organizationChart;
salesForce.salesForceLevelConfig.map((elem, index) => {
organizationChartStr[`nameNivel${index + 1}`] = oc.name;
organizationChartStr[`isSensitiveNivel${index + 1}`] = oc.isSensitive;
organizationChartStr[`emailNivel${index + 1}`] = oc.email;
if (!removeUser)
organizationChartStr[`userNameNivel${index + 1}`] = oc.userName;
oc = oc.previusOrganizationChart;
})
return {
id: item.id,
distributorId: item.distributorId,
nameDistributor: item.nameDistributor,
nameSalesForce: salesForce.nameSalesForce,
...organizationChartStr
}
})
return { recordset: { salesForce, linkedDistributorsChart: recordsetFormated, client }, count }
}
// const organizationChartIds = recordset.map(item => item.organizationChart);
return { recordset: { salesForce, linkedDistributorsChart: [], client }, count: 0 }
}
async getLinkDistributorsExcel(query) {
const { recordset } = await this.getLinkDistributors(query, true);
let namePropertiesLevel = recordset.salesForce.salesForceLevelConfig.map(elem => elem.description);
let headers = [];
namePropertiesLevel.reverse().forEach(item => {
headers = [item.toUpperCase(), `${item.toUpperCase()} PV`, `${item.toUpperCase()} EMAIL`, ...headers]
})
let formatLinkedDistributorsChart = recordset.linkedDistributorsChart.map(item => {
let organization = [];
delete item.distributorId;
delete item.id;
Object.keys(item).forEach(e => {
if (typeof item[e] === 'boolean') {
item[e] = item[e] === true ? 'S' : 'N';
}
organization.push(item[e]);
});
return organization;
});
headers = ['DISTRIBUIDOR', 'FORCA DE VENDAS', ...headers];
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('DISTRIBUTORS');
worksheet.addRow(headers);
worksheet.columns.forEach(function (column, i) {
column.width = 25;
});
formatLinkedDistributorsChart.forEach(rowData => {
worksheet.addRow(rowData);
});
worksheet.getRow(1).font = { bold: true };
const buffer = await workbook.xlsx.writeBuffer();
return [recordset?.client?.client?.name || 'DISTRIBUTORS', buffer];
}
}