Add reporting features with new report engine and bookmark management

- 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.
This commit is contained in:
shancheas
2026-09-01 08:45:52 +07:00
parent 5579cf6566
commit 2955b974d2
43 changed files with 3257 additions and 1 deletions
@@ -0,0 +1,90 @@
import type { DataFormat } from '../constants/data-format';
import type { DataType } from '../constants/data-type';
import type { FilterFieldType } from '../constants/filter-field-type';
import type { FilterType } from '../constants/filter-type';
import type { ReportGroupName } from '../constants/report-group';
export interface ReportColumnConfigEntity {
column: string;
query: string;
label: string;
type: DataType;
format: DataFormat;
dateFormat?: string;
}
export interface FilterConfigEntity {
filterColumn: string;
filterType: FilterType;
fieldType: FilterFieldType;
fieldLabel: string;
hideField?: boolean;
selectDataSourceUrl?: string;
selectCustomOptions?: string[];
selectValueKey?: string;
selectLabelKey?: string;
dateFormat?: string;
}
export interface FilterPeriodConfig {
hidden?: boolean;
}
export interface FilterModelEntry {
type: FilterType;
filter: unknown;
}
export interface ReportConfigEntity {
groupName: ReportGroupName;
uniqueName: string;
privilegeKey: string;
label: string;
tableSchema: string;
mainTableAlias?: string;
columnConfigs: ReportColumnConfigEntity[];
filterConfigs?: FilterConfigEntity[];
filterPeriodConfig?: FilterPeriodConfig;
whereDefaultConditions?: string[];
whereCondition?: (filterModel: Record<string, FilterModelEntry>) => string[];
ignoreFilterKeys?: string[];
customQueryColumn?: (column: string) => string | undefined;
defaultOrderBy?: string[];
lowLevelOrderBy?: string[];
}
export interface ReportConfigPublicEntity extends Omit<
ReportConfigEntity,
'whereCondition' | 'customQueryColumn'
> {}
export interface RowGroupColEntity {
id: string;
displayName: string;
field: string;
}
export interface ValueColEntity {
id: string;
field: string;
aggFunc: string;
}
export interface SortModelEntry {
colId: string;
sort: 'asc' | 'desc';
}
export interface QueryModelEntity {
startRow: number;
endRow: number;
rowGroupCols: RowGroupColEntity[];
valueCols: ValueColEntity[];
pivotCols: unknown[];
pivotMode: boolean;
groupKeys: unknown[];
filterModel: Record<string, FilterModelEntry>;
sortModel: SortModelEntry[];
}
export const COUNT_CHILD_GROUP_COLUMN = 'countChildGroup';