feat: integration API for get data and get meta data
parent
85d461c70a
commit
fc37e0c502
|
@ -1,9 +1,15 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ReportBookmarkController } from './report-bookmark.controller';
|
import { ReportBookmarkController } from './report-bookmark.controller';
|
||||||
import { ReportBookmarkService } from './report-bookmark.service';
|
import { ReportBookmarkService } from './report-bookmark.service';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
import { ReportBookmarkModel } from '../shared/models/report-bookmark.model';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([ReportBookmarkModel], CONNECTION_NAME.DEFAULT),
|
||||||
|
],
|
||||||
controllers: [ReportBookmarkController],
|
controllers: [ReportBookmarkController],
|
||||||
providers: [ReportBookmarkService],
|
providers: [ReportBookmarkService],
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,15 +5,45 @@ import {
|
||||||
GetLabelReportBookmarkDto,
|
GetLabelReportBookmarkDto,
|
||||||
GetReportBookmarkDto,
|
GetReportBookmarkDto,
|
||||||
} from '../shared/dto/report-bookmark.get.dto';
|
} from '../shared/dto/report-bookmark.get.dto';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { ReportBookmarkModel } from '../shared/models/report-bookmark.model';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ReportBookmarkService extends BaseReportService {
|
export class ReportBookmarkService extends BaseReportService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(ReportBookmarkModel, CONNECTION_NAME.DEFAULT)
|
||||||
|
private repo: Repository<ReportBookmarkModel>,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
async create(body: CreateReportBookmarkDto) {
|
async create(body: CreateReportBookmarkDto) {
|
||||||
return 'you hit API for create report bookmark';
|
return 'you hit API for create report bookmark';
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAll(query: GetReportBookmarkDto) {
|
async getAll(query: GetReportBookmarkDto) {
|
||||||
return 'you hit API for get all report bookmark';
|
const modelName = ReportBookmarkModel.name;
|
||||||
|
|
||||||
|
const requestor_id = this.userProvider.user.id;
|
||||||
|
const unique_names = query.unique_names;
|
||||||
|
const group_names = query.group_names;
|
||||||
|
|
||||||
|
const qb = this.repo
|
||||||
|
.createQueryBuilder(modelName)
|
||||||
|
.where((query) => {
|
||||||
|
if (unique_names) {
|
||||||
|
query.andWhere(`unique_name IN (:...unique_names)`, { unique_names });
|
||||||
|
}
|
||||||
|
if (group_names) {
|
||||||
|
query.andWhere(`group_name =IN (:...group_names)`, { group_names });
|
||||||
|
}
|
||||||
|
query.andWhere(`requestor_id = :requestor_id`, { requestor_id });
|
||||||
|
})
|
||||||
|
.orderBy(`${modelName}.created_at`, 'DESC');
|
||||||
|
|
||||||
|
return await qb.getMany();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllLabelHistory(query: GetLabelReportBookmarkDto) {
|
async getAllLabelHistory(query: GetLabelReportBookmarkDto) {
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ReportExportController } from './report-export.controller';
|
import { ReportExportController } from './report-export.controller';
|
||||||
import { ReportExportService } from './report-export.service';
|
import { ReportExportService } from './report-export.service';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { ExportReportHistoryModel } from '../shared/models/export-report-history.model';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [
|
||||||
|
TypeOrmModule.forFeature(
|
||||||
|
[ExportReportHistoryModel],
|
||||||
|
CONNECTION_NAME.DEFAULT,
|
||||||
|
),
|
||||||
|
],
|
||||||
controllers: [ReportExportController],
|
controllers: [ReportExportController],
|
||||||
providers: [ReportExportService],
|
providers: [ReportExportService],
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,9 +6,23 @@ import {
|
||||||
GetReportExportFileNameDto,
|
GetReportExportFileNameDto,
|
||||||
GetReportExportProcessingDto,
|
GetReportExportProcessingDto,
|
||||||
} from '../shared/dto/report-export.get.dto';
|
} from '../shared/dto/report-export.get.dto';
|
||||||
|
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { ExportReportHistoryModel } from '../shared/models/export-report-history.model';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ReportExportService extends BaseReportService {
|
export class ReportExportService extends BaseReportService {
|
||||||
|
constructor(
|
||||||
|
@InjectDataSource(CONNECTION_NAME.DEFAULT)
|
||||||
|
private dataSource: DataSource,
|
||||||
|
|
||||||
|
@InjectRepository(ExportReportHistoryModel, CONNECTION_NAME.DEFAULT)
|
||||||
|
private exportHistoryRepo: Repository<ExportReportHistoryModel>,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
async create(body: CreateReportExportDto) {
|
async create(body: CreateReportExportDto) {
|
||||||
return 'you hit API for create report export';
|
return 'you hit API for create report export';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ReportController } from './report.controller';
|
import { ReportController } from './report.controller';
|
||||||
import { ReportService } from './report.service';
|
import { ReportService } from './report.service';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { ExportReportHistoryModel } from '../shared/models/export-report-history.model';
|
||||||
|
import { CONNECTION_NAME } from 'src/core/strings/constants/base.constants';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [
|
||||||
|
TypeOrmModule.forFeature(
|
||||||
|
[ExportReportHistoryModel],
|
||||||
|
CONNECTION_NAME.DEFAULT,
|
||||||
|
),
|
||||||
|
],
|
||||||
controllers: [ReportController],
|
controllers: [ReportController],
|
||||||
providers: [ReportService],
|
providers: [ReportService],
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { BaseReportService } from '../shared/services/base-report.service';
|
import { BaseReportService } from '../shared/services/base-report.service';
|
||||||
import { GetReportConfigDto } from '../shared/dto/report-config.get.dto';
|
import { GetReportConfigDto } from '../shared/dto/report-config.get.dto';
|
||||||
import { GetReportDataDto } from '../shared/dto/report-data.get.dto';
|
import { GetReportDataDto } from '../shared/dto/report-data.get.dto';
|
||||||
import { ReportConfigs } from '../shared/configs';
|
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()
|
@Injectable()
|
||||||
export class ReportService extends BaseReportService {
|
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) {
|
async getReportConfig(query: GetReportConfigDto) {
|
||||||
const { unique_names = [], group_names = [] } = query;
|
const { unique_names = [], group_names = [] } = query;
|
||||||
|
|
||||||
|
@ -23,11 +39,112 @@ export class ReportService extends BaseReportService {
|
||||||
return configs;
|
return configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getReportConfigByUniqueName(unique_name): ReportConfigEntity {
|
||||||
|
return ReportConfigs.find((item) => item.unique_name === unique_name);
|
||||||
|
}
|
||||||
|
|
||||||
async getReportData(body: GetReportDataDto) {
|
async getReportData(body: GetReportDataDto) {
|
||||||
return 'you hit API for get report data';
|
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) {
|
async getReportMeta(body: GetReportDataDto) {
|
||||||
return 'you hit API for get report meta';
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ export default <ReportConfigEntity>{
|
||||||
group_name: REPORT_GROUP.general_report,
|
group_name: REPORT_GROUP.general_report,
|
||||||
unique_name: `${REPORT_GROUP.general_report}__sample`,
|
unique_name: `${REPORT_GROUP.general_report}__sample`,
|
||||||
label: 'Sample General Report ',
|
label: 'Sample General Report ',
|
||||||
table_schema: 'season_types',
|
table_schema: 'season_types main',
|
||||||
main_table_alias: 'main',
|
main_table_alias: 'main',
|
||||||
defaultOrderBy: [],
|
defaultOrderBy: [],
|
||||||
lowLevelOrderBy: [],
|
lowLevelOrderBy: [],
|
||||||
|
@ -22,8 +22,8 @@ export default <ReportConfigEntity>{
|
||||||
format: DATA_FORMAT.DATE_EPOCH,
|
format: DATA_FORMAT.DATE_EPOCH,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
column: 'main__update_at',
|
column: 'main__updated_at',
|
||||||
query: 'main.update_at',
|
query: 'main.updated_at',
|
||||||
label: 'Updated Date',
|
label: 'Updated Date',
|
||||||
type: DATA_TYPE.DIMENSION,
|
type: DATA_TYPE.DIMENSION,
|
||||||
format: DATA_FORMAT.DATE_EPOCH,
|
format: DATA_FORMAT.DATE_EPOCH,
|
||||||
|
|
|
@ -5,7 +5,7 @@ export default <ReportConfigEntity>{
|
||||||
group_name: REPORT_GROUP.tenant_report,
|
group_name: REPORT_GROUP.tenant_report,
|
||||||
unique_name: `${REPORT_GROUP.tenant_report}__sample`,
|
unique_name: `${REPORT_GROUP.tenant_report}__sample`,
|
||||||
label: 'Sample Tenant Report ',
|
label: 'Sample Tenant Report ',
|
||||||
table_schema: 'season_types',
|
table_schema: 'season_types main',
|
||||||
main_table_alias: 'main',
|
main_table_alias: 'main',
|
||||||
defaultOrderBy: [],
|
defaultOrderBy: [],
|
||||||
lowLevelOrderBy: [],
|
lowLevelOrderBy: [],
|
||||||
|
@ -21,8 +21,8 @@ export default <ReportConfigEntity>{
|
||||||
format: DATA_FORMAT.DATE_EPOCH,
|
format: DATA_FORMAT.DATE_EPOCH,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
column: 'main__update_at',
|
column: 'main__updated_at',
|
||||||
query: 'main.update_at',
|
query: 'main.updated_at',
|
||||||
label: 'Updated Date',
|
label: 'Updated Date',
|
||||||
type: DATA_TYPE.DIMENSION,
|
type: DATA_TYPE.DIMENSION,
|
||||||
format: DATA_FORMAT.DATE_EPOCH,
|
format: DATA_FORMAT.DATE_EPOCH,
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsObject, IsString, ValidateIf } from 'class-validator';
|
import { IsObject, IsString, ValidateIf } from 'class-validator';
|
||||||
import { QueryModelEntity } from '../entities/query-model.entity';
|
import { QueryModelEntity } from '../entities/query-model.entity';
|
||||||
|
import { REPORT_GROUP } from '../constant';
|
||||||
|
|
||||||
export class GetReportDataDto {
|
export class GetReportDataDto {
|
||||||
@ApiProperty({ name: 'group_name', required: true })
|
@ApiProperty({
|
||||||
|
name: 'group_name',
|
||||||
|
required: true,
|
||||||
|
default: REPORT_GROUP.general_report,
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
group_name: string;
|
group_name: string;
|
||||||
|
|
||||||
@ApiProperty({ name: 'unique_name', required: true })
|
@ApiProperty({
|
||||||
|
name: 'unique_name',
|
||||||
|
required: true,
|
||||||
|
default: `${REPORT_GROUP.general_report}__sample`,
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
unique_name: string;
|
unique_name: string;
|
||||||
|
|
||||||
|
@ -15,6 +24,17 @@ export class GetReportDataDto {
|
||||||
name: 'query_model',
|
name: 'query_model',
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
|
default: {
|
||||||
|
startRow: 0,
|
||||||
|
endRow: 100,
|
||||||
|
rowGroupCols: [],
|
||||||
|
valueCols: [],
|
||||||
|
pivotCols: [],
|
||||||
|
pivotMode: true,
|
||||||
|
groupKeys: [],
|
||||||
|
filterModel: {},
|
||||||
|
sortModel: [],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@ValidateIf((body) => body.query_model)
|
@ValidateIf((body) => body.query_model)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export function roundingCurrency(value) {
|
||||||
|
if (!value) return value;
|
||||||
|
return Number(value).toFixed(2);
|
||||||
|
}
|
Loading…
Reference in New Issue