feat: integration API for get data and get meta data

pull/11/head
Firman Ramdhani 2024-07-03 17:03:13 +07:00
parent 85d461c70a
commit fc37e0c502
10 changed files with 223 additions and 15 deletions

View File

@ -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],
}) })

View File

@ -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) {

View File

@ -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],
}) })

View File

@ -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';
} }

View File

@ -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],
}) })

View File

@ -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;
}
} }
} }

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -0,0 +1,4 @@
export function roundingCurrency(value) {
if (!value) return value;
return Number(value).toFixed(2);
}