- Introduced a comprehensive report engine for generating and managing reports, including sales and logistics reports. - Added new API endpoints for retrieving report configurations, data, and metadata, ensuring secure access with privilege checks. - Implemented a report bookmarks system to allow users to save and manage report filters and configurations. - Created database migrations for the `report_bookmarks` table and updated the schema to support new report functionalities. - Developed services and controllers for handling report queries and bookmarks, including CRUD operations for bookmarks. - Enhanced API documentation to reflect the new reporting features and endpoints. - Added unit and integration tests to validate the new functionalities and ensure data integrity across report operations.
135 lines
3.6 KiB
TypeScript
135 lines
3.6 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Injectable,
|
|
NotFoundException,
|
|
} from '@nestjs/common';
|
|
import { toListPage } from '../../../common/http/response';
|
|
import type { PaginationResponse } from '../../../common/http/response';
|
|
import {
|
|
REPORT_BOOKMARK_TYPE,
|
|
type ReportBookmarkType,
|
|
} from '../shared/constants/bookmark-type';
|
|
import { findReportConfig } from '../shared/configs';
|
|
import {
|
|
ReportBookmarksRepository,
|
|
type ReportBookmark,
|
|
} from './report-bookmarks.repository';
|
|
|
|
export type ListReportBookmarksQuery = {
|
|
groupName?: string;
|
|
uniqueName?: string;
|
|
type?: ReportBookmarkType;
|
|
label?: string;
|
|
page?: number;
|
|
limit?: number;
|
|
offset?: number;
|
|
};
|
|
|
|
export type CreateReportBookmarkInput = {
|
|
groupName: string;
|
|
uniqueName: string;
|
|
label: string;
|
|
type: ReportBookmarkType;
|
|
applied?: boolean;
|
|
configuration: unknown;
|
|
};
|
|
|
|
@Injectable()
|
|
export class ReportBookmarksService {
|
|
constructor(private readonly repository: ReportBookmarksRepository) {}
|
|
|
|
async list(
|
|
ownerId: string,
|
|
query: ListReportBookmarksQuery,
|
|
): Promise<PaginationResponse<ReturnType<ReportBookmarksService['toDto']>>> {
|
|
const page = toListPage(query);
|
|
const { data, total } = await this.repository.list(ownerId, {
|
|
groupName: query.groupName,
|
|
uniqueName: query.uniqueName,
|
|
type: query.type,
|
|
label: query.label,
|
|
limit: page.limit,
|
|
offset: page.offset,
|
|
});
|
|
return { data: data.map((item) => this.toDto(item)), total };
|
|
}
|
|
|
|
async labelHistory(ownerId: string, label?: string): Promise<string[]> {
|
|
return this.repository.labelHistory(ownerId, label);
|
|
}
|
|
|
|
async findApplied(
|
|
ownerId: string,
|
|
groupName?: string,
|
|
uniqueName?: string,
|
|
type?: ReportBookmarkType,
|
|
) {
|
|
if (!groupName || !uniqueName || !type) {
|
|
throw new BadRequestException(
|
|
'groupName, uniqueName, and type are required',
|
|
);
|
|
}
|
|
const bookmark = await this.repository.findApplied(
|
|
ownerId,
|
|
groupName,
|
|
uniqueName,
|
|
type,
|
|
);
|
|
return bookmark ? this.toDto(bookmark) : null;
|
|
}
|
|
|
|
async create(ownerId: string, input: CreateReportBookmarkInput) {
|
|
this.assertValidBookmarkInput(input);
|
|
const bookmark = await this.repository.create(ownerId, {
|
|
groupName: input.groupName,
|
|
uniqueName: input.uniqueName,
|
|
label: input.label,
|
|
type: input.type,
|
|
applied: input.applied ?? false,
|
|
configuration: input.configuration,
|
|
});
|
|
return this.toDto(bookmark);
|
|
}
|
|
|
|
async apply(ownerId: string, id: string) {
|
|
const bookmark = await this.repository.apply(ownerId, id);
|
|
return this.toDto(bookmark);
|
|
}
|
|
|
|
async unapply(ownerId: string, id: string) {
|
|
const bookmark = await this.repository.unapply(ownerId, id);
|
|
return this.toDto(bookmark);
|
|
}
|
|
|
|
async delete(ownerId: string, id: string): Promise<void> {
|
|
await this.repository.delete(ownerId, id);
|
|
}
|
|
|
|
private assertValidBookmarkInput(input: CreateReportBookmarkInput) {
|
|
if (!findReportConfig(input.groupName, input.uniqueName)) {
|
|
throw new NotFoundException('Report not found');
|
|
}
|
|
if (
|
|
input.type !== REPORT_BOOKMARK_TYPE.FILTER_TABLE &&
|
|
input.type !== REPORT_BOOKMARK_TYPE.TABLE_CONFIG
|
|
) {
|
|
throw new BadRequestException('Invalid bookmark type');
|
|
}
|
|
}
|
|
|
|
private toDto(bookmark: ReportBookmark) {
|
|
return {
|
|
id: bookmark.id,
|
|
groupName: bookmark.groupName,
|
|
uniqueName: bookmark.uniqueName,
|
|
label: bookmark.label,
|
|
type: bookmark.type,
|
|
applied: bookmark.applied,
|
|
configuration: bookmark.configuration,
|
|
status: bookmark.status,
|
|
createdAt: bookmark.createdAt,
|
|
updatedAt: bookmark.updatedAt,
|
|
};
|
|
}
|
|
}
|