feat: integration export report
parent
ed66b88dd0
commit
f9c36582e1
|
@ -43,6 +43,7 @@
|
||||||
"elastic-apm-node": "^4.5.4",
|
"elastic-apm-node": "^4.5.4",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"googleapis": "^140.0.0",
|
"googleapis": "^140.0.0",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"nano": "^10.1.3",
|
"nano": "^10.1.3",
|
||||||
"pg": "^8.11.5",
|
"pg": "^8.11.5",
|
||||||
"plop": "^4.0.1",
|
"plop": "^4.0.1",
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import { Injectable, Logger, Scope } from '@nestjs/common';
|
import {
|
||||||
|
Injectable,
|
||||||
|
Logger,
|
||||||
|
NotFoundException,
|
||||||
|
Scope,
|
||||||
|
UnprocessableEntityException,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { BaseReportService } from '../shared/services/base-report.service';
|
import { BaseReportService } from '../shared/services/base-report.service';
|
||||||
import { CreateReportExportDto } from '../shared/dto/report-export.create.dto';
|
import { CreateReportExportDto } from '../shared/dto/report-export.create.dto';
|
||||||
import {
|
import {
|
||||||
|
@ -19,6 +25,8 @@ import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as ExcelJS from 'exceljs';
|
import * as ExcelJS from 'exceljs';
|
||||||
import { roundingCurrency } from '../shared/helpers';
|
import { roundingCurrency } from '../shared/helpers';
|
||||||
|
import { createPaginationMeta } from 'src/core/response/domain/utils/pagination-meta.helper';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
@Injectable({ scope: Scope.REQUEST })
|
@Injectable({ scope: Scope.REQUEST })
|
||||||
export class ReportExportService extends BaseReportService {
|
export class ReportExportService extends BaseReportService {
|
||||||
|
@ -97,7 +105,7 @@ export class ReportExportService extends BaseReportService {
|
||||||
group_name: config.group_name,
|
group_name: config.group_name,
|
||||||
unique_name: config.unique_name,
|
unique_name: config.unique_name,
|
||||||
label: config.label,
|
label: config.label,
|
||||||
file_name: fileName,
|
file_name: fName,
|
||||||
file_url: null,
|
file_url: null,
|
||||||
total_data: totalRow,
|
total_data: totalRow,
|
||||||
processing_data: 0,
|
processing_data: 0,
|
||||||
|
@ -304,18 +312,152 @@ export class ReportExportService extends BaseReportService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAll(query: GetReportExportDto) {
|
async getAll(query: GetReportExportDto) {
|
||||||
return 'you hit API for get all report export';
|
const modelName = ExportReportHistoryModel.name;
|
||||||
|
|
||||||
|
const page = query.page;
|
||||||
|
const limit = query.limit;
|
||||||
|
|
||||||
|
const creator_id = this.getUser().id;
|
||||||
|
const group_names = query.group_names;
|
||||||
|
const unique_names = query.unique_names;
|
||||||
|
const statuses = query.statuses;
|
||||||
|
|
||||||
|
const qb = this.exportHistoryRepo
|
||||||
|
.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 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statuses) {
|
||||||
|
query.andWhere(`status IN (:...statuses)`, { statuses });
|
||||||
|
}
|
||||||
|
|
||||||
|
query.andWhere(`creator_id = :creator_id`, { creator_id });
|
||||||
|
})
|
||||||
|
.orderBy(`${modelName}.created_at`, 'DESC');
|
||||||
|
|
||||||
|
const [data, total] = await qb
|
||||||
|
.take(+limit)
|
||||||
|
.skip(+limit * +page - +limit)
|
||||||
|
.getManyAndCount();
|
||||||
|
|
||||||
|
const meta = createPaginationMeta(page, limit, data.length, total);
|
||||||
|
|
||||||
|
return { data, meta };
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string) {
|
async delete(id: string) {
|
||||||
return 'you hit API for delete report export';
|
const findData = await this.exportHistoryRepo.findOneBy({ id });
|
||||||
|
if (findData && findData?.file_url) {
|
||||||
|
try {
|
||||||
|
const directory = './uploads/report-data/';
|
||||||
|
const filePath = path.join(directory, findData.file_url);
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
await this.exportHistoryRepo.delete(id);
|
||||||
|
this.logger.warn(
|
||||||
|
`Successfully deleted the ${findData.file_url} file`,
|
||||||
|
);
|
||||||
|
return { success: true, message: 'File deleted successfully' };
|
||||||
|
} else {
|
||||||
|
throw new NotFoundException('File not found');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new UnprocessableEntityException('File could not be deleted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new UnprocessableEntityException();
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateFailedData(group_names, unique_names) {
|
||||||
|
const creator_id = this.getUser().id;
|
||||||
|
const aMinutesAgo = moment().subtract(5, 'minutes').valueOf();
|
||||||
|
|
||||||
|
await this.exportHistoryRepo
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update(ExportReportHistoryModel)
|
||||||
|
.set({
|
||||||
|
status: REPORT_HISTORY_STATUS.FAILED,
|
||||||
|
updated_at: moment().valueOf(),
|
||||||
|
})
|
||||||
|
.where((query) => {
|
||||||
|
if (group_names) {
|
||||||
|
query.andWhere(`group_name IN (:...group_names)`, { group_names });
|
||||||
|
}
|
||||||
|
if (unique_names) {
|
||||||
|
query.andWhere(`unique_name IN (:...unique_names)`, { unique_names });
|
||||||
|
}
|
||||||
|
query.andWhere(`status = :status`, {
|
||||||
|
status: REPORT_HISTORY_STATUS.PROCESSING,
|
||||||
|
});
|
||||||
|
query.andWhere(`updated_at < :aMinutesAgo`, { aMinutesAgo });
|
||||||
|
query.andWhere(`creator_id = :creator_id`, { creator_id });
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllProcessing(query: GetReportExportProcessingDto) {
|
async getAllProcessing(query: GetReportExportProcessingDto) {
|
||||||
return 'you hit API for get all processing report export';
|
const creator_id = this.getUser().id;
|
||||||
|
const modelName = ExportReportHistoryModel.name;
|
||||||
|
|
||||||
|
const group_names = query.group_names;
|
||||||
|
const unique_names = query.unique_names;
|
||||||
|
|
||||||
|
await this.updateFailedData(group_names, unique_names);
|
||||||
|
const aMinutesAgo = moment().subtract(100, 'seconds').valueOf();
|
||||||
|
|
||||||
|
const qb = this.exportHistoryRepo
|
||||||
|
.createQueryBuilder(modelName)
|
||||||
|
.where((query) => {
|
||||||
|
if (group_names) {
|
||||||
|
query.andWhere(`unique_name IN (:...unique_names)`, { unique_names });
|
||||||
|
}
|
||||||
|
if (unique_names) {
|
||||||
|
query.andWhere(`group_name IN (:...group_names)`, { group_names });
|
||||||
|
}
|
||||||
|
|
||||||
|
query.andWhere(`status IN (:...status)`, {
|
||||||
|
status: ['processing', 'failed', 'done'],
|
||||||
|
});
|
||||||
|
query.andWhere(`updated_at > :aMinutesAgo`, { aMinutesAgo });
|
||||||
|
query.andWhere(`creator_id = :creator_id`, { creator_id });
|
||||||
|
})
|
||||||
|
.orderBy(`${modelName}.created_at`, 'DESC');
|
||||||
|
|
||||||
|
const data = await qb.getMany();
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: data,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getListHistoryFileName(query: GetReportExportFileNameDto) {
|
async getListHistoryFileName(query: GetReportExportFileNameDto) {
|
||||||
return 'you hit API for get all file name report export';
|
const modelName = ExportReportHistoryModel.name;
|
||||||
|
|
||||||
|
const creator_id = this.getUser().id;
|
||||||
|
const unique_names = query.unique_names;
|
||||||
|
const group_names = query.group_names;
|
||||||
|
|
||||||
|
const qb = this.exportHistoryRepo
|
||||||
|
.createQueryBuilder(modelName)
|
||||||
|
.select(`${modelName}.file_name`)
|
||||||
|
.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(`creator_id = :creator_id`, { creator_id });
|
||||||
|
})
|
||||||
|
.distinct(true);
|
||||||
|
|
||||||
|
const newData = await qb.getRawMany();
|
||||||
|
return newData.map((el) => el.ExportReportHistoryModel_file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,12 +46,6 @@ export class GetReportExportProcessingDto {
|
||||||
return Array.isArray(body.value) ? body.value : [body.value];
|
return Array.isArray(body.value) ? body.value : [body.value];
|
||||||
})
|
})
|
||||||
unique_names?: string[];
|
unique_names?: string[];
|
||||||
|
|
||||||
@ApiProperty({ type: ['string'], required: false })
|
|
||||||
@Transform((body) => {
|
|
||||||
return Array.isArray(body.value) ? body.value : [body.value];
|
|
||||||
})
|
|
||||||
statuses?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetReportExportFileNameDto {
|
export class GetReportExportFileNameDto {
|
||||||
|
|
|
@ -5174,6 +5174,11 @@ module-details-from-path@^1.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
|
resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
|
||||||
integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==
|
integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==
|
||||||
|
|
||||||
|
moment@^2.30.1:
|
||||||
|
version "2.30.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
|
||||||
|
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
|
||||||
|
|
||||||
monitor-event-loop-delay@^1.0.0:
|
monitor-event-loop-delay@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/monitor-event-loop-delay/-/monitor-event-loop-delay-1.0.0.tgz#b5ab78165a3bb93f2b275c50d01430c7f155d1f7"
|
resolved "https://registry.yarnpkg.com/monitor-event-loop-delay/-/monitor-event-loop-delay-1.0.0.tgz#b5ab78165a3bb93f2b275c50d01430c7f155d1f7"
|
||||||
|
|
Loading…
Reference in New Issue