import { Injectable, Logger } from '@nestjs/common'; import { BaseReportService } from '../shared/services/base-report.service'; import { GetReportConfigDto } from '../shared/dto/report-config.get.dto'; import { GetReportDataDto } from '../shared/dto/report-data.get.dto'; import { ReportConfigs } from '../shared/configs'; import { InjectDataSource } from '@nestjs/typeorm'; import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants'; import { DataSource } from 'typeorm'; import { ReportConfigEntity } from '../shared/entities/report-config.entity'; import { ReportQueryBuilder } from '../shared/helpers'; import { DATA_FORMAT } from '../shared/constant'; import { roundingCurrency } from '../shared/helpers/rounding-currency'; @Injectable() export class ReportService extends BaseReportService { private readonly logger = new Logger(ReportService.name); constructor( @InjectDataSource(CONNECTION_NAME.DEFAULT) private dataSource: DataSource, ) { super(); } async getReportConfig(query: GetReportConfigDto) { const { unique_names = [], group_names = [] } = query; let configs = ReportConfigs; if (group_names.length > 0) { configs = configs.filter((item) => group_names.includes(item.group_name)); } if (unique_names.length > 0) { configs = configs.filter((item) => unique_names.includes(item.unique_name), ); } return configs; } getReportConfigByUniqueName(unique_name): ReportConfigEntity { return ReportConfigs.find((item) => item.unique_name === unique_name); } async getReportData(body: GetReportDataDto) { try { const queryModel = body.query_model; const reportConfig = this.getReportConfigByUniqueName(body.unique_name); const builder = new ReportQueryBuilder(reportConfig, queryModel); const SQL = builder.getSql(); const queryResult = await this.dataSource.query(SQL); const realData = []; const configColumns = reportConfig.column_configs; for (const item of queryResult) { const realItem = {}; for (const itemKey of Object.keys(item)) { if (itemKey === 'count_child_group') { const realValue = item[itemKey] ?? 0; Object.assign(realItem, { [`${itemKey}`]: Number(realValue) }); } else { const confCol = configColumns.find((c) => c.column === itemKey); const isNumber = confCol.format === DATA_FORMAT.NUMBER; const isCurrency = confCol.format === DATA_FORMAT.CURRENCY; const isMinusCurrency = confCol.format === DATA_FORMAT.MINUS_CURRENCY; const isBoolean = confCol.format === DATA_FORMAT.BOOLEAN; const isPercentage = confCol.format === DATA_FORMAT.PERCENTAGE; const isSetInitNull = isNumber || isCurrency || isMinusCurrency; const isTextUpperCase = confCol.format === DATA_FORMAT.TEXT_UPPERCASE; const isTextLowerCase = confCol.format === DATA_FORMAT.TEXT_LOWERCASE; if (isSetInitNull) { const realValue = item[itemKey] ?? 0; if (isCurrency) { Object.assign(realItem, { [`${itemKey}`]: roundingCurrency(realValue), }); } else if (isMinusCurrency) { Object.assign(realItem, { [`${itemKey}`]: roundingCurrency(realValue) * -1, }); } else { Object.assign(realItem, { [`${itemKey}`]: realValue }); } } else if (isPercentage) { const realValue = item[itemKey] ? `${item[itemKey]}%` : item[itemKey]; Object.assign(realItem, { [`${itemKey}`]: realValue }); } else if (isBoolean) { let realValue = ''; if (item[itemKey] === true || item[itemKey] === 1) realValue = 'Yes'; else if (item[itemKey] === false || item[itemKey] === 0) realValue = 'No'; Object.assign(realItem, { [`${itemKey}`]: realValue }); } else if (isTextUpperCase) { Object.assign(realItem, { [`${itemKey}`]: item[itemKey]?.toUpperCase(), }); } else if (isTextLowerCase) { Object.assign(realItem, { [`${itemKey}`]: item[itemKey]?.toLowerCase(), }); } else { Object.assign(realItem, { [`${itemKey}`]: item[itemKey] }); } } } realData.push(realItem); } return realData; } catch (error) { this.logger.error(error); throw error; } } async getReportMeta(body: GetReportDataDto) { try { const queryModel = body.query_model; const reportConfig = this.getReportConfigByUniqueName(body.unique_name); const builder = new ReportQueryBuilder(reportConfig, queryModel); const SQL_COUNT = builder.getSqlCount(); const queryResult = await this.dataSource.query(SQL_COUNT); const totalRow = parseInt(queryResult[0].count); const startRow = queryModel.startRow; const endRow = queryModel.endRow; const pageSize = endRow - startRow; const meta = { total_row: totalRow, limit: pageSize, offset: startRow, }; return meta; } catch (error) { this.logger.error(error); throw error; } } }