rez_core 1.0.85 → 1.0.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constant/global.constant.d.ts +2 -0
- package/dist/constant/global.constant.js +3 -1
- package/dist/constant/global.constant.js.map +1 -1
- package/dist/core.module.js +3 -0
- package/dist/core.module.js.map +1 -1
- package/dist/module/filter/controller/filter.controller.d.ts +19 -0
- package/dist/module/filter/controller/filter.controller.js +46 -0
- package/dist/module/filter/controller/filter.controller.js.map +1 -0
- package/dist/module/filter/dto/filter-request.dto.d.ts +22 -0
- package/dist/module/filter/dto/filter-request.dto.js +3 -0
- package/dist/module/filter/dto/filter-request.dto.js.map +1 -0
- package/dist/module/filter/entity/saved-filter-detail.entity.d.ts +8 -0
- package/dist/module/filter/entity/saved-filter-detail.entity.js +43 -0
- package/dist/module/filter/entity/saved-filter-detail.entity.js.map +1 -0
- package/dist/module/filter/entity/saved-filter-master.entity.d.ts +5 -0
- package/dist/module/filter/entity/saved-filter-master.entity.js +31 -0
- package/dist/module/filter/entity/saved-filter-master.entity.js.map +1 -0
- package/dist/module/filter/filter.module.d.ts +2 -0
- package/dist/module/filter/filter.module.js +34 -0
- package/dist/module/filter/filter.module.js.map +1 -0
- package/dist/module/filter/repository/saved-filter.repository.d.ts +13 -0
- package/dist/module/filter/repository/saved-filter.repository.js +62 -0
- package/dist/module/filter/repository/saved-filter.repository.js.map +1 -0
- package/dist/module/filter/service/filter.service.d.ts +34 -0
- package/dist/module/filter/service/filter.service.js +210 -0
- package/dist/module/filter/service/filter.service.js.map +1 -0
- package/dist/module/filter/service/saved-filter.service.d.ts +12 -0
- package/dist/module/filter/service/saved-filter.service.js +73 -0
- package/dist/module/filter/service/saved-filter.service.js.map +1 -0
- package/dist/module/meta/entity.module.js +1 -0
- package/dist/module/meta/entity.module.js.map +1 -1
- package/dist/module/meta/service/entity-list.service.js +1 -0
- package/dist/module/meta/service/entity-list.service.js.map +1 -1
- package/dist/module/meta/service/media-data.service.d.ts +1 -1
- package/dist/module/meta/service/media-data.service.js +1 -1
- package/dist/module/meta/service/media-data.service.js.map +1 -1
- package/dist/resources/properties.yaml.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/constant/global.constant.ts +2 -0
- package/src/core.module.ts +4 -2
- package/src/module/filter/controller/filter.controller.ts +28 -0
- package/src/module/filter/dto/filter-request.dto.ts +24 -0
- package/src/module/filter/entity/saved-filter-detail.entity.ts +23 -0
- package/src/module/filter/entity/saved-filter-master.entity.ts +14 -0
- package/src/module/filter/filter.module.ts +21 -0
- package/src/module/filter/repository/saved-filter.repository.ts +54 -0
- package/src/module/filter/service/filter.service.ts +260 -0
- package/src/module/filter/service/saved-filter.service.ts +101 -0
- package/src/module/meta/entity.module.ts +1 -0
- package/src/module/meta/service/entity-list.service.ts +6 -0
- package/src/module/meta/service/media-data.service.ts +1 -1
- package/src/resources/dev.properties.yaml +2 -2
- package/src/resources/properties.yaml.ts +1 -1
package/package.json
CHANGED
|
@@ -12,6 +12,8 @@ export const ENTITYTYPE_LISTMASTERITEMS = 'LMI';
|
|
|
12
12
|
export const ENTITYTYPE_SECTIONMASTER = 'SEC';
|
|
13
13
|
export const ENTITYTYPE_FIELDMASTER = 'FLD';
|
|
14
14
|
export const ENTITYTYPE_USRROLMAP = 'URM';
|
|
15
|
+
export const ENTITYTYPE_SAVEDFILTERMASTER = 'SFM';
|
|
16
|
+
export const ENTITYTYPE_SAVEDFILTERDETAIL = 'SFD';
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
export const STORAGETYPE_SINGLEJSON = 'singlejson';
|
package/src/core.module.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { ModuleModule } from './module/module/module.module';
|
|
|
8
8
|
import { NotificationModule } from './module/notification/notification.module';
|
|
9
9
|
import { LayoutModule } from './module/layout/layout.module';
|
|
10
10
|
import { ListMasterModule } from './module/listmaster/listmaster.module';
|
|
11
|
+
import { FilterModule } from './module/filter/filter.module';
|
|
11
12
|
|
|
12
13
|
@Global()
|
|
13
14
|
@Module({})
|
|
@@ -21,7 +22,7 @@ export class CoreModule {
|
|
|
21
22
|
module: CoreModule,
|
|
22
23
|
imports: [
|
|
23
24
|
ConfigModule.forRoot({ isGlobal: true }),
|
|
24
|
-
dbModule,
|
|
25
|
+
dbModule,
|
|
25
26
|
EntityModule,
|
|
26
27
|
EnterpriseModule,
|
|
27
28
|
UtilsModule,
|
|
@@ -30,6 +31,7 @@ export class CoreModule {
|
|
|
30
31
|
NotificationModule,
|
|
31
32
|
LayoutModule,
|
|
32
33
|
ListMasterModule,
|
|
34
|
+
FilterModule
|
|
33
35
|
],
|
|
34
36
|
exports: [
|
|
35
37
|
ConfigModule,
|
|
@@ -42,7 +44,7 @@ export class CoreModule {
|
|
|
42
44
|
NotificationModule,
|
|
43
45
|
LayoutModule,
|
|
44
46
|
ListMasterModule,
|
|
45
|
-
|
|
47
|
+
FilterModule
|
|
46
48
|
],
|
|
47
49
|
};
|
|
48
50
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Controller, Post, Body } from '@nestjs/common';
|
|
2
|
+
import { FilterService } from '../service/filter.service';
|
|
3
|
+
|
|
4
|
+
@Controller('filter')
|
|
5
|
+
export class FilterController {
|
|
6
|
+
constructor(private readonly filterService: FilterService) {}
|
|
7
|
+
|
|
8
|
+
@Post()
|
|
9
|
+
async applyFilter(@Body() body: any) {
|
|
10
|
+
const {
|
|
11
|
+
entity_type,
|
|
12
|
+
quickFilter,
|
|
13
|
+
savedFilterCode,
|
|
14
|
+
attributeFilter,
|
|
15
|
+
tabs,
|
|
16
|
+
sortby,
|
|
17
|
+
} = body;
|
|
18
|
+
|
|
19
|
+
return this.filterService.applyFilter({
|
|
20
|
+
entity_type,
|
|
21
|
+
quickFilter,
|
|
22
|
+
savedFilterCode,
|
|
23
|
+
attributeFilter,
|
|
24
|
+
tabs,
|
|
25
|
+
sortby,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/module/filter/dto/filter-request.dto.ts
|
|
2
|
+
export interface FilterCondition {
|
|
3
|
+
filter_attribute: string;
|
|
4
|
+
filter_operator: string;
|
|
5
|
+
filter_value?: string | number | boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface TabsConfig {
|
|
9
|
+
columnName: string;
|
|
10
|
+
value: string;
|
|
11
|
+
sortBy?: 'ASC' | 'DSC';
|
|
12
|
+
}
|
|
13
|
+
export interface SortConfig {
|
|
14
|
+
sortColum: string;
|
|
15
|
+
sortType: 'ASC' | 'DSC';
|
|
16
|
+
}
|
|
17
|
+
export interface FilterRequestDto {
|
|
18
|
+
entity_type: string;
|
|
19
|
+
quickFilter?: FilterCondition[];
|
|
20
|
+
savedFilterCode?: string;
|
|
21
|
+
attributeFilter?: FilterCondition[];
|
|
22
|
+
sortby?: SortConfig[];
|
|
23
|
+
tabs?: TabsConfig;
|
|
24
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ENTITYTYPE_SAVEDFILTERDETAIL } from "src/constant/global.constant";
|
|
2
|
+
import { BaseEntity } from "src/module/meta/entity/base-entity.entity";
|
|
3
|
+
import { Column, Entity } from "typeorm";
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'cr_saved_filter_detail' })
|
|
6
|
+
export class SavedFilterDetail extends BaseEntity {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.entity_type = ENTITYTYPE_SAVEDFILTERDETAIL;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Column()
|
|
13
|
+
mapped_filter_code: string; // This links to SavedFilterMaster.code (no relation, manual)
|
|
14
|
+
|
|
15
|
+
@Column()
|
|
16
|
+
filter_attribute: string;
|
|
17
|
+
|
|
18
|
+
@Column()
|
|
19
|
+
filter_operator: string;
|
|
20
|
+
|
|
21
|
+
@Column()
|
|
22
|
+
filter_value: string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ENTITYTYPE_SAVEDFILTERMASTER } from "src/constant/global.constant";
|
|
2
|
+
import { BaseEntity } from "src/module/meta/entity/base-entity.entity";
|
|
3
|
+
import { Column, Entity } from "typeorm";
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'cr_saved_filter_master' })
|
|
6
|
+
export class SavedFilterMaster extends BaseEntity {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.entity_type = ENTITYTYPE_SAVEDFILTERMASTER;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Column({ length: 50, type: 'varchar', nullable: true })
|
|
13
|
+
app_code: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
3
|
+
import { SavedFilterService } from './service/saved-filter.service';
|
|
4
|
+
import { SavedFilterDetail } from './entity/saved-filter-detail.entity';
|
|
5
|
+
import { SavedFilterMaster } from './entity/saved-filter-master.entity';
|
|
6
|
+
import { SavedFilterRepositoryService } from './repository/saved-filter.repository';
|
|
7
|
+
import { EntityModule } from '../meta/entity.module';
|
|
8
|
+
import { FilterService } from './service/filter.service';
|
|
9
|
+
import { FilterController } from './controller/filter.controller';
|
|
10
|
+
|
|
11
|
+
@Module({
|
|
12
|
+
imports: [TypeOrmModule.forFeature([SavedFilterDetail,SavedFilterMaster]),EntityModule],
|
|
13
|
+
controllers: [FilterController],
|
|
14
|
+
providers: [
|
|
15
|
+
{ provide: 'SavedFilterService', useClass: SavedFilterService },
|
|
16
|
+
SavedFilterRepositoryService,
|
|
17
|
+
FilterService
|
|
18
|
+
],
|
|
19
|
+
exports: ['SavedFilterService', SavedFilterRepositoryService],
|
|
20
|
+
})
|
|
21
|
+
export class FilterModule {}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { InjectRepository } from '@nestjs/typeorm';
|
|
3
|
+
import { Repository, Not } from 'typeorm';
|
|
4
|
+
import { SavedFilterMaster } from '../entity/saved-filter-master.entity';
|
|
5
|
+
import { SavedFilterDetail } from '../entity/saved-filter-detail.entity';
|
|
6
|
+
|
|
7
|
+
@Injectable()
|
|
8
|
+
export class SavedFilterRepositoryService {
|
|
9
|
+
constructor(
|
|
10
|
+
@InjectRepository(SavedFilterMaster)
|
|
11
|
+
private readonly savedFilterMasterRepo: Repository<SavedFilterMaster>,
|
|
12
|
+
@InjectRepository(SavedFilterDetail)
|
|
13
|
+
private readonly savedFilterDetailRepo: Repository<SavedFilterDetail>,
|
|
14
|
+
) {}
|
|
15
|
+
|
|
16
|
+
async isFilterNameExists(
|
|
17
|
+
name: string,
|
|
18
|
+
orgId: number,
|
|
19
|
+
entId: number,
|
|
20
|
+
excludeId?: number,
|
|
21
|
+
): Promise<boolean> {
|
|
22
|
+
const where: any = {
|
|
23
|
+
name,
|
|
24
|
+
organization_id: orgId,
|
|
25
|
+
enterprise_id: entId,
|
|
26
|
+
};
|
|
27
|
+
if (excludeId) {
|
|
28
|
+
where.id = Not(excludeId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const existing = await this.savedFilterMasterRepo.findOne({ where });
|
|
32
|
+
return !!existing;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async getDetailsByCode(code: string): Promise<SavedFilterDetail[]> {
|
|
36
|
+
return this.savedFilterDetailRepo.find({
|
|
37
|
+
where: { mapped_filter_code: code },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async deleteDetailsByCode(code: string): Promise<void> {
|
|
42
|
+
await this.savedFilterDetailRepo.delete({ mapped_filter_code: code });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async saveDetails(details: Partial<SavedFilterDetail>[]): Promise<void> {
|
|
46
|
+
const entities = this.savedFilterDetailRepo.create(details);
|
|
47
|
+
await this.savedFilterDetailRepo.save(entities);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async updateCode(id: number, code: string): Promise<void> {
|
|
51
|
+
await this.savedFilterMasterRepo.update(id, { code });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { Injectable, BadRequestException, Inject } from '@nestjs/common';
|
|
2
|
+
import { AttributeMasterService } from 'src/module/meta/service/attribute-master.service';
|
|
3
|
+
import { EntityMasterService } from 'src/module/meta/service/entity-master.service';
|
|
4
|
+
import { DataSource } from 'typeorm';
|
|
5
|
+
import { SavedFilterService } from './saved-filter.service';
|
|
6
|
+
import { FilterRequestDto } from '../dto/filter-request.dto';
|
|
7
|
+
|
|
8
|
+
@Injectable()
|
|
9
|
+
export class FilterService {
|
|
10
|
+
constructor(
|
|
11
|
+
private dataSource: DataSource,
|
|
12
|
+
private readonly entityMasterService: EntityMasterService,
|
|
13
|
+
private readonly attributeMasterService: AttributeMasterService,
|
|
14
|
+
@Inject('SavedFilterService')
|
|
15
|
+
private readonly savedFilterService: SavedFilterService,
|
|
16
|
+
) {}
|
|
17
|
+
|
|
18
|
+
private async getTabCounts(
|
|
19
|
+
tableName: string,
|
|
20
|
+
column: string | undefined,
|
|
21
|
+
whereClauses: any[],
|
|
22
|
+
) {
|
|
23
|
+
if (!column) return [];
|
|
24
|
+
|
|
25
|
+
const qb = this.dataSource
|
|
26
|
+
.getRepository(tableName)
|
|
27
|
+
.createQueryBuilder('e')
|
|
28
|
+
.select(`e.${column}`, 'tabName')
|
|
29
|
+
.addSelect('COUNT(*)', 'tabCount')
|
|
30
|
+
.groupBy(`e.${column}`);
|
|
31
|
+
|
|
32
|
+
whereClauses.forEach((clause) => qb.andWhere(clause.query, clause.params));
|
|
33
|
+
|
|
34
|
+
const rows = await qb.getRawMany();
|
|
35
|
+
|
|
36
|
+
const total = rows.reduce((sum, r) => sum + parseInt(r.tabCount), 0);
|
|
37
|
+
|
|
38
|
+
return [
|
|
39
|
+
{ tabName: 'All', tabCount: total },
|
|
40
|
+
...rows.map((r) => ({
|
|
41
|
+
tabName: r.tabName || 'UNKNOWN',
|
|
42
|
+
tabCount: parseInt(r.tabCount),
|
|
43
|
+
})),
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async applyFilter(dto: FilterRequestDto) {
|
|
48
|
+
const {
|
|
49
|
+
entity_type,
|
|
50
|
+
quickFilter,
|
|
51
|
+
savedFilterCode,
|
|
52
|
+
attributeFilter,
|
|
53
|
+
tabs,
|
|
54
|
+
sortby,
|
|
55
|
+
} = dto;
|
|
56
|
+
|
|
57
|
+
// Fetch meta
|
|
58
|
+
const entityMeta =
|
|
59
|
+
await this.entityMasterService.getEntityData(entity_type);
|
|
60
|
+
const tableName = entityMeta?.db_table_name;
|
|
61
|
+
if (!tableName)
|
|
62
|
+
throw new BadRequestException(`Invalid entity_type: ${entity_type}`);
|
|
63
|
+
|
|
64
|
+
const attributeMeta =
|
|
65
|
+
await this.attributeMasterService.findAttributesByMappedEntityType(
|
|
66
|
+
entity_type,
|
|
67
|
+
);
|
|
68
|
+
const attributeMetaMap = attributeMeta.reduce(
|
|
69
|
+
(acc, attr) => {
|
|
70
|
+
acc[attr.attribute_key] = attr;
|
|
71
|
+
return acc;
|
|
72
|
+
},
|
|
73
|
+
{} as Record<string, any>,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Get and parse filters
|
|
77
|
+
const savedFilters = await this.getSavedFilters(savedFilterCode);
|
|
78
|
+
const baseFilters = [
|
|
79
|
+
...(quickFilter || []),
|
|
80
|
+
...savedFilters,
|
|
81
|
+
...(attributeFilter || []),
|
|
82
|
+
];
|
|
83
|
+
const baseWhere = this.buildWhereClauses(baseFilters, attributeMetaMap);
|
|
84
|
+
|
|
85
|
+
// Build query for tab counts (no tab.value filter here)
|
|
86
|
+
const allTabs = await this.getTabCounts(
|
|
87
|
+
tableName,
|
|
88
|
+
tabs?.columnName,
|
|
89
|
+
baseWhere,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// Add tab.value filter only if present
|
|
93
|
+
const dataWhere = [...baseWhere];
|
|
94
|
+
if (tabs?.columnName && tabs?.value) {
|
|
95
|
+
const tabAttrMeta = attributeMetaMap[tabs.columnName];
|
|
96
|
+
const tabCondition = this.buildCondition(
|
|
97
|
+
{
|
|
98
|
+
filter_attribute: tabs.columnName,
|
|
99
|
+
filter_operator: 'equal',
|
|
100
|
+
filter_value: tabs.value,
|
|
101
|
+
},
|
|
102
|
+
tabAttrMeta,
|
|
103
|
+
);
|
|
104
|
+
if (tabCondition) {
|
|
105
|
+
dataWhere.push(tabCondition);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Final query for filtered data
|
|
110
|
+
const qb = this.dataSource.getRepository(tableName).createQueryBuilder('e');
|
|
111
|
+
dataWhere.forEach((clause) => qb.andWhere(clause.query, clause.params));
|
|
112
|
+
|
|
113
|
+
// Optional sorting
|
|
114
|
+
if (Array.isArray(sortby)) {
|
|
115
|
+
sortby.forEach(({ sortColum, sortType }) => {
|
|
116
|
+
qb.addOrderBy(
|
|
117
|
+
`e.${sortColum}`,
|
|
118
|
+
sortType.toUpperCase() === 'DSC' ? 'DESC' : 'ASC',
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const entity_list = await qb.getMany();
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
data: {
|
|
128
|
+
entity_tabs: allTabs,
|
|
129
|
+
entity_list,
|
|
130
|
+
pagination: [], // add pagination later if needed
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private parseFilters(raw: any, isSingle = false): any[] {
|
|
136
|
+
if (!raw) return [];
|
|
137
|
+
|
|
138
|
+
if (typeof raw === 'string') {
|
|
139
|
+
try {
|
|
140
|
+
const parsed = JSON.parse(raw);
|
|
141
|
+
return isSingle ? [parsed] : parsed;
|
|
142
|
+
} catch {
|
|
143
|
+
throw new BadRequestException('Invalid JSON in filter input');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return isSingle ? [raw] : Array.isArray(raw) ? raw : [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private async getSavedFilters(code?: string): Promise<any[]> {
|
|
151
|
+
if (!code) return [];
|
|
152
|
+
|
|
153
|
+
const savedFilter = await this.savedFilterService.getDetailsByCode(code);
|
|
154
|
+
if (!savedFilter) {
|
|
155
|
+
throw new BadRequestException(`Saved filter not found for code: ${code}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log(savedFilter);
|
|
159
|
+
return savedFilter;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private buildWhereClauses(
|
|
163
|
+
filters: any[],
|
|
164
|
+
attributeMeta: Record<string, any>,
|
|
165
|
+
) {
|
|
166
|
+
return filters
|
|
167
|
+
.map((f) => this.buildCondition(f, attributeMeta[f.filter_attribute]))
|
|
168
|
+
.filter(
|
|
169
|
+
(clause): clause is { query: string; params: any } => clause !== null,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private buildCondition(
|
|
174
|
+
filter: any,
|
|
175
|
+
meta: any,
|
|
176
|
+
): { query: string; params: any } | null {
|
|
177
|
+
if (!meta) return null;
|
|
178
|
+
|
|
179
|
+
const attr = filter.filter_attribute;
|
|
180
|
+
const val = filter.filter_value;
|
|
181
|
+
const op = filter.filter_operator;
|
|
182
|
+
const key = `param_${attr}_${Math.random().toString(36).substring(2, 8)}`;
|
|
183
|
+
|
|
184
|
+
switch (meta.db_datatype) {
|
|
185
|
+
case 'varchar':
|
|
186
|
+
return this.buildTextCondition(attr, op, val, key);
|
|
187
|
+
case 'number':
|
|
188
|
+
return this.buildNumberCondition(attr, op, val, key);
|
|
189
|
+
case 'date':
|
|
190
|
+
return this.buildDateCondition(attr, op, val, key);
|
|
191
|
+
default:
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private buildTextCondition(attr: string, op: string, val: any, key: string) {
|
|
197
|
+
switch (op) {
|
|
198
|
+
case 'contains':
|
|
199
|
+
return {
|
|
200
|
+
query: `LOWER(e.${attr}) LIKE :${key}`,
|
|
201
|
+
params: { [key]: `%${val.toLowerCase()}%` },
|
|
202
|
+
};
|
|
203
|
+
case 'equal':
|
|
204
|
+
return {
|
|
205
|
+
query: `e.${attr} = :${key}`,
|
|
206
|
+
params: { [key]: val },
|
|
207
|
+
};
|
|
208
|
+
case 'not_equal':
|
|
209
|
+
return {
|
|
210
|
+
query: `e.${attr} != :${key}`,
|
|
211
|
+
params: { [key]: val },
|
|
212
|
+
};
|
|
213
|
+
case 'empty':
|
|
214
|
+
return {
|
|
215
|
+
query: `e.${attr} IS NULL`,
|
|
216
|
+
params: {},
|
|
217
|
+
};
|
|
218
|
+
case 'not_empty':
|
|
219
|
+
return {
|
|
220
|
+
query: `e.${attr} IS NOT NULL`,
|
|
221
|
+
params: {},
|
|
222
|
+
};
|
|
223
|
+
default:
|
|
224
|
+
throw new BadRequestException(`Unsupported operator for text: ${op}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private buildNumberCondition(
|
|
229
|
+
attr: string,
|
|
230
|
+
op: string,
|
|
231
|
+
val: any,
|
|
232
|
+
key: string,
|
|
233
|
+
) {
|
|
234
|
+
switch (op) {
|
|
235
|
+
case 'equal':
|
|
236
|
+
return { query: `e.${attr} = :${key}`, params: { [key]: val } };
|
|
237
|
+
case 'not_equal':
|
|
238
|
+
return { query: `e.${attr} != :${key}`, params: { [key]: val } };
|
|
239
|
+
case 'greater_than':
|
|
240
|
+
return { query: `e.${attr} > :${key}`, params: { [key]: val } };
|
|
241
|
+
case 'less_than':
|
|
242
|
+
return { query: `e.${attr} < :${key}`, params: { [key]: val } };
|
|
243
|
+
default:
|
|
244
|
+
throw new BadRequestException(`Unsupported operator for number: ${op}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private buildDateCondition(attr: string, op: string, val: any, key: string) {
|
|
249
|
+
switch (op) {
|
|
250
|
+
case 'equal':
|
|
251
|
+
return { query: `e.${attr} = :${key}`, params: { [key]: val } };
|
|
252
|
+
case 'before':
|
|
253
|
+
return { query: `e.${attr} < :${key}`, params: { [key]: val } };
|
|
254
|
+
case 'after':
|
|
255
|
+
return { query: `e.${attr} > :${key}`, params: { [key]: val } };
|
|
256
|
+
default:
|
|
257
|
+
throw new BadRequestException(`Unsupported operator for date: ${op}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { BadRequestException, Injectable } from '@nestjs/common';
|
|
2
|
+
import { EntityServiceImpl } from '../../meta/service/entity-service-impl.service';
|
|
3
|
+
import { BaseEntity } from '../../meta/entity/base-entity.entity';
|
|
4
|
+
import { UserData } from '../../user/entity/user.entity';
|
|
5
|
+
import { SavedFilterMaster } from '../entity/saved-filter-master.entity';
|
|
6
|
+
import { SavedFilterDetail } from '../entity/saved-filter-detail.entity';
|
|
7
|
+
import { ENTITYTYPE_SAVEDFILTERMASTER } from 'src/constant/global.constant';
|
|
8
|
+
import { SavedFilterRepositoryService } from '../repository/saved-filter.repository';
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class SavedFilterService extends EntityServiceImpl {
|
|
12
|
+
constructor(private readonly savedFilterRepo: SavedFilterRepositoryService) {
|
|
13
|
+
super();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async createEntity(
|
|
17
|
+
entityData: BaseEntity,
|
|
18
|
+
loggedInUser: UserData | null,
|
|
19
|
+
): Promise<BaseEntity> {
|
|
20
|
+
const master = entityData as SavedFilterMaster;
|
|
21
|
+
|
|
22
|
+
const exists = await this.savedFilterRepo.isFilterNameExists(
|
|
23
|
+
master.name,
|
|
24
|
+
master.organization_id,
|
|
25
|
+
master.enterprise_id,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (exists) {
|
|
29
|
+
throw new BadRequestException('Saved filter name already exists.');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Save the master record without code
|
|
33
|
+
const savedMaster = await super.createEntity(master, loggedInUser);
|
|
34
|
+
|
|
35
|
+
// Generate the code like SFM00001 using the saved ID
|
|
36
|
+
const code = `SFM${savedMaster.id.toString().padStart(5, '0')}`;
|
|
37
|
+
|
|
38
|
+
// Update the code
|
|
39
|
+
savedMaster.code = code;
|
|
40
|
+
await this.savedFilterRepo.updateCode(savedMaster.id, code);
|
|
41
|
+
|
|
42
|
+
// Save filter details using generated code
|
|
43
|
+
const details = (entityData as any).filterDetails ?? [];
|
|
44
|
+
if (details.length) {
|
|
45
|
+
const prepared = details.map((detail: any) => ({
|
|
46
|
+
...detail,
|
|
47
|
+
mapped_filter_code: savedMaster.code,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
await this.savedFilterRepo.saveDetails(prepared);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return savedMaster;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async updateEntity(
|
|
57
|
+
entityData: BaseEntity,
|
|
58
|
+
loggedInUser: UserData | null,
|
|
59
|
+
): Promise<BaseEntity> {
|
|
60
|
+
const master = entityData as SavedFilterMaster;
|
|
61
|
+
|
|
62
|
+
const existing = await this.getEntityData(
|
|
63
|
+
ENTITYTYPE_SAVEDFILTERMASTER,
|
|
64
|
+
master.id,
|
|
65
|
+
);
|
|
66
|
+
if (!existing) {
|
|
67
|
+
throw new BadRequestException('Saved filter not found.');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const nameExists = await this.savedFilterRepo.isFilterNameExists(
|
|
71
|
+
master.name,
|
|
72
|
+
master.organization_id,
|
|
73
|
+
master.enterprise_id,
|
|
74
|
+
master.id,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (nameExists) {
|
|
78
|
+
throw new BadRequestException('Saved filter name already exists.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { filterDetails, ...persistableData } = master as any;
|
|
82
|
+
const updated = await super.updateEntity(persistableData, loggedInUser);
|
|
83
|
+
|
|
84
|
+
if (filterDetails?.length) {
|
|
85
|
+
await this.savedFilterRepo.deleteDetailsByCode(updated.code);
|
|
86
|
+
|
|
87
|
+
const prepared = filterDetails.map((detail: any) => ({
|
|
88
|
+
...detail,
|
|
89
|
+
mapped_filter_code: updated.code,
|
|
90
|
+
}));
|
|
91
|
+
|
|
92
|
+
await this.savedFilterRepo.saveDetails(prepared);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return updated;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async getDetailsByCode(code: string): Promise<SavedFilterDetail[]> {
|
|
99
|
+
return this.savedFilterRepo.getDetailsByCode(code);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -87,6 +87,7 @@ import { EntityValidationService } from './service/entity-validation.service';
|
|
|
87
87
|
SectionMasterService,
|
|
88
88
|
FieldGroupService,
|
|
89
89
|
'ViewMasterService',
|
|
90
|
+
AttributeMasterService
|
|
90
91
|
],
|
|
91
92
|
controllers: [EntityController, MasterController, MediaController, ViewMasterController, MetaController],
|
|
92
93
|
})
|
|
@@ -87,18 +87,24 @@ export class EntityListService {
|
|
|
87
87
|
query += whereClause.query;
|
|
88
88
|
}
|
|
89
89
|
query += ' GROUP BY ' + entityTable.tab_column;
|
|
90
|
+
|
|
90
91
|
let tabs = await this.entityManager.query(query, whereClause.argumentList);
|
|
92
|
+
|
|
91
93
|
let all = 0;
|
|
92
94
|
for (const i in tabs) {
|
|
93
95
|
let tab = tabs[i] as EntityTab;
|
|
96
|
+
tab.tab_value = String(tab.tab_value).toUpperCase(); // Capitalize tab_value
|
|
94
97
|
all += parseInt(String(tab.tab_value_count));
|
|
95
98
|
}
|
|
99
|
+
|
|
96
100
|
let entityTab = new EntityTab();
|
|
97
101
|
entityTab.tab_value = 'ALL';
|
|
98
102
|
entityTab.tab_value_count = all;
|
|
99
103
|
tabs.push(entityTab);
|
|
104
|
+
|
|
100
105
|
return tabs.reverse();
|
|
101
106
|
}
|
|
107
|
+
|
|
102
108
|
|
|
103
109
|
private getQuery(source: string, groupByColumn: string | null) {
|
|
104
110
|
if (groupByColumn) {
|
|
@@ -124,7 +124,7 @@ export class MediaDataService extends EntityServiceImpl {
|
|
|
124
124
|
Key: mediaData.media_url,
|
|
125
125
|
Expires: 60 * 5, // URL valid for 5 mins
|
|
126
126
|
});
|
|
127
|
-
return {signedUrl,
|
|
127
|
+
return {signedUrl,name: mediaData.file_name,id:mediaData.id};
|
|
128
128
|
} catch (error) {
|
|
129
129
|
console.error('Error generating signed URL for media:', error);
|
|
130
130
|
throw new Error('Failed to generate signed URL');
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# DB_HOST: "13.234.25.234"
|
|
2
|
-
DB_HOST: "
|
|
2
|
+
DB_HOST: "13.234.25.234"
|
|
3
3
|
DB_PORT: "3306"
|
|
4
4
|
DB_USER: "root"
|
|
5
|
-
DB_PASS: "
|
|
5
|
+
DB_PASS: "Rezolut@123"
|
|
6
6
|
DB_NAME: "core"
|
|
7
7
|
MASTER_KEY: "0QZ2eRJv5oVILYnyBlC+FbSGVQiWKReh"
|
|
8
8
|
MASTER_IV: "heuUQf5uPVtkotrFAOKUVw=="
|