rez_core 2.0.57 → 2.0.59
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/module/filter/controller/filter.controller.d.ts +2 -8
- package/dist/module/filter/service/filter.service.d.ts +2 -8
- package/dist/module/filter/service/filter.service.js +77 -26
- package/dist/module/filter/service/filter.service.js.map +1 -1
- package/dist/module/meta/repository/entity-table.repository.d.ts +1 -0
- package/dist/module/meta/repository/entity-table.repository.js +5 -0
- package/dist/module/meta/repository/entity-table.repository.js.map +1 -1
- package/dist/module/meta/service/entity-table.service.d.ts +1 -0
- package/dist/module/meta/service/entity-table.service.js +21 -7
- package/dist/module/meta/service/entity-table.service.js.map +1 -1
- package/dist/module/user/controller/login.controller.js +2 -5
- package/dist/module/user/controller/login.controller.js.map +1 -1
- package/dist/module/user/service/user-session.service.d.ts +1 -1
- package/dist/module/user/service/user-session.service.js +5 -5
- package/dist/module/user/service/user-session.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/filter/service/filter.service.ts +111 -31
- package/src/module/meta/repository/entity-table.repository.ts +7 -1
- package/src/module/meta/service/entity-table.service.ts +54 -22
- package/src/module/user/controller/login.controller.ts +2 -9
- package/src/module/user/service/user-session.service.ts +5 -8
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { SavedFilterService } from './saved-filter.service';
|
|
|
6
6
|
import { FilterRequestDto } from '../dto/filter-request.dto';
|
|
7
7
|
import { EntityTableService } from 'src/module/meta/service/entity-table.service';
|
|
8
8
|
import { EntityTableColumnService } from 'src/module/meta/service/entity-table-column.service';
|
|
9
|
+
import { get } from 'http';
|
|
9
10
|
|
|
10
11
|
@Injectable()
|
|
11
12
|
export class FilterService {
|
|
@@ -22,28 +23,47 @@ export class FilterService {
|
|
|
22
23
|
private async gettab_value_counts(
|
|
23
24
|
tableName: string,
|
|
24
25
|
column: string | undefined,
|
|
25
|
-
whereClauses: any[],
|
|
26
|
+
whereClauses: { query: string; params: Record<string, any> }[],
|
|
26
27
|
) {
|
|
27
28
|
if (!column) return [];
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
30
|
+
let whereSQL = '';
|
|
31
|
+
const values: any[] = [];
|
|
32
|
+
|
|
33
|
+
// Convert whereClauses to SQL
|
|
34
|
+
if (whereClauses.length > 0) {
|
|
35
|
+
const clauseParts = whereClauses.map((clause) => {
|
|
36
|
+
let parsedQuery = clause.query.replace(/\be\./g, ''); // removes e. prefix
|
|
37
|
+
Object.entries(clause.params).forEach(([key, val]) => {
|
|
38
|
+
parsedQuery = parsedQuery.replace(new RegExp(`:${key}`, 'g'), '?');
|
|
39
|
+
values.push(val);
|
|
40
|
+
});
|
|
41
|
+
return parsedQuery;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
whereSQL = `WHERE ${clauseParts.join(' AND ')}`;
|
|
45
|
+
}
|
|
35
46
|
|
|
36
|
-
|
|
47
|
+
// Construct raw SQL
|
|
48
|
+
const rawSQL = `
|
|
49
|
+
SELECT ${column} AS tab_value, COUNT(*) AS tab_value_count
|
|
50
|
+
FROM ${tableName}
|
|
51
|
+
${whereSQL}
|
|
52
|
+
GROUP BY ${column}
|
|
53
|
+
`;
|
|
37
54
|
|
|
38
|
-
const rows = await
|
|
55
|
+
const rows = await this.dataSource.query(rawSQL, values);
|
|
39
56
|
|
|
40
|
-
const total = rows.reduce(
|
|
57
|
+
const total = rows.reduce(
|
|
58
|
+
(sum, r) => sum + parseInt(r.tab_value_count, 10),
|
|
59
|
+
0,
|
|
60
|
+
);
|
|
41
61
|
|
|
42
62
|
return [
|
|
43
63
|
{ tab_value: 'All', tab_value_count: total },
|
|
44
64
|
...rows.map((r) => ({
|
|
45
|
-
tab_value: r.tab_value
|
|
46
|
-
tab_value_count: parseInt(r.tab_value_count),
|
|
65
|
+
tab_value: r.tab_value ?? 'UNKNOWN',
|
|
66
|
+
tab_value_count: parseInt(r.tab_value_count, 10),
|
|
47
67
|
})),
|
|
48
68
|
];
|
|
49
69
|
}
|
|
@@ -59,9 +79,8 @@ export class FilterService {
|
|
|
59
79
|
} = dto;
|
|
60
80
|
|
|
61
81
|
// Fetch meta
|
|
62
|
-
const entityMeta =
|
|
63
|
-
|
|
64
|
-
const tableName = entityMeta?.db_table_name;
|
|
82
|
+
const entityMeta = await this.entityTableService.getEntityData(entity_type);
|
|
83
|
+
const tableName = entityMeta?.data_source; // data_souce is the table name
|
|
65
84
|
if (!tableName)
|
|
66
85
|
throw new BadRequestException(`Invalid entity_type: ${entity_type}`);
|
|
67
86
|
|
|
@@ -108,7 +127,7 @@ export class FilterService {
|
|
|
108
127
|
|
|
109
128
|
// Build query for tab counts (no tab.value filter here)
|
|
110
129
|
const allTabs = await this.gettab_value_counts(
|
|
111
|
-
|
|
130
|
+
getTableMeta.data_source,
|
|
112
131
|
tabs?.columnName,
|
|
113
132
|
baseWhere,
|
|
114
133
|
);
|
|
@@ -130,10 +149,16 @@ export class FilterService {
|
|
|
130
149
|
}
|
|
131
150
|
}
|
|
132
151
|
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
// Build raw SQL base
|
|
153
|
+
const qb = this.dataSource
|
|
154
|
+
.createQueryBuilder()
|
|
155
|
+
.select('e.*')
|
|
156
|
+
.from(tableName, 'e');
|
|
157
|
+
|
|
158
|
+
// Apply WHERE clauses
|
|
159
|
+
dataWhere.forEach((clause) => {
|
|
160
|
+
qb.andWhere(clause.query, clause.params);
|
|
161
|
+
});
|
|
137
162
|
|
|
138
163
|
// Optional sorting
|
|
139
164
|
if (Array.isArray(sortby)) {
|
|
@@ -150,7 +175,19 @@ export class FilterService {
|
|
|
150
175
|
const size = dto.size && dto.size > 0 ? dto.size : 10;
|
|
151
176
|
qb.skip((page - 1) * size).take(size);
|
|
152
177
|
|
|
153
|
-
|
|
178
|
+
// Get paginated data
|
|
179
|
+
const entity_list = await qb.getRawMany();
|
|
180
|
+
|
|
181
|
+
// Count query (without pagination)
|
|
182
|
+
const countQb = this.dataSource
|
|
183
|
+
.createQueryBuilder()
|
|
184
|
+
.select('COUNT(*)', 'count')
|
|
185
|
+
.from(tableName, 'e');
|
|
186
|
+
dataWhere.forEach((clause) => {
|
|
187
|
+
countQb.andWhere(clause.query, clause.params);
|
|
188
|
+
});
|
|
189
|
+
const countResult = await countQb.getRawOne();
|
|
190
|
+
const total = parseInt(countResult.count, 10);
|
|
154
191
|
|
|
155
192
|
return {
|
|
156
193
|
success: true,
|
|
@@ -191,7 +228,6 @@ export class FilterService {
|
|
|
191
228
|
if (!savedFilter) {
|
|
192
229
|
throw new BadRequestException(`Saved filter not found for code: ${code}`);
|
|
193
230
|
}
|
|
194
|
-
|
|
195
231
|
return savedFilter;
|
|
196
232
|
}
|
|
197
233
|
|
|
@@ -212,11 +248,13 @@ export class FilterService {
|
|
|
212
248
|
): { query: string; params: any } | null {
|
|
213
249
|
if (!meta) return null;
|
|
214
250
|
|
|
215
|
-
|
|
251
|
+
let attr = filter.filter_attribute;
|
|
216
252
|
const val = filter.filter_value;
|
|
217
253
|
const op = filter.filter_operator;
|
|
218
254
|
const key = `param_${attr}_${Math.random().toString(36).substring(2, 8)}`;
|
|
219
255
|
|
|
256
|
+
if (meta.data_source_type === 'entity') attr = `${attr}_id`;
|
|
257
|
+
|
|
220
258
|
switch (meta.data_type) {
|
|
221
259
|
case 'text':
|
|
222
260
|
return this.buildTextCondition(attr, op, val, key);
|
|
@@ -227,7 +265,7 @@ export class FilterService {
|
|
|
227
265
|
case 'select':
|
|
228
266
|
return this.buildSelectCondition(attr, op, val, key);
|
|
229
267
|
case 'multiselect':
|
|
230
|
-
return this.buildMultiSelectCondition(attr, val, key);
|
|
268
|
+
return this.buildMultiSelectCondition(attr, op, val, key);
|
|
231
269
|
default:
|
|
232
270
|
return null;
|
|
233
271
|
}
|
|
@@ -298,6 +336,7 @@ export class FilterService {
|
|
|
298
336
|
}
|
|
299
337
|
}
|
|
300
338
|
|
|
339
|
+
// this can be inproved
|
|
301
340
|
private buildSelectCondition(
|
|
302
341
|
attr: string,
|
|
303
342
|
op: string,
|
|
@@ -308,18 +347,59 @@ export class FilterService {
|
|
|
308
347
|
case 'equal':
|
|
309
348
|
return { query: `e.${attr} = :${key}`, params: { [key]: val } };
|
|
310
349
|
|
|
350
|
+
case 'not_equal':
|
|
351
|
+
return { query: `e.${attr} != :${key}`, params: { [key]: val } };
|
|
352
|
+
|
|
353
|
+
case 'empty':
|
|
354
|
+
return { query: `e.${attr} IS NULL`, params: {} };
|
|
355
|
+
|
|
356
|
+
case 'not_empty':
|
|
357
|
+
return { query: `e.${attr} IS NOT NULL`, params: {} };
|
|
358
|
+
|
|
311
359
|
default:
|
|
312
360
|
throw new BadRequestException(`Unsupported operator for select: ${op}`);
|
|
313
361
|
}
|
|
314
362
|
}
|
|
315
363
|
|
|
316
|
-
private buildMultiSelectCondition(
|
|
317
|
-
|
|
318
|
-
|
|
364
|
+
private buildMultiSelectCondition(
|
|
365
|
+
attr: string,
|
|
366
|
+
op: string,
|
|
367
|
+
val: any,
|
|
368
|
+
key: string,
|
|
369
|
+
) {
|
|
370
|
+
if (Array.isArray(val) && val.length === 0) {
|
|
371
|
+
return { query: '1=1', params: {} };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if ((op === 'equal' || op === 'not_equal') && !Array.isArray(val)) {
|
|
375
|
+
throw new BadRequestException(
|
|
376
|
+
`Value for multi-select must be an array for operator: ${op}`,
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
switch (op) {
|
|
381
|
+
case 'equal':
|
|
382
|
+
return {
|
|
383
|
+
query: `e.${attr} IN (:${key})`,
|
|
384
|
+
params: { [key]: val },
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
case 'not_equal':
|
|
388
|
+
return {
|
|
389
|
+
query: `e.${attr} NOT IN (:${key})`,
|
|
390
|
+
params: { [key]: val },
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
case 'empty':
|
|
394
|
+
return { query: `e.${attr} IS NULL`, params: {} };
|
|
395
|
+
|
|
396
|
+
case 'not_empty':
|
|
397
|
+
return { query: `e.${attr} IS NOT NULL`, params: {} };
|
|
398
|
+
|
|
399
|
+
default:
|
|
400
|
+
throw new BadRequestException(
|
|
401
|
+
`Unsupported operator for multiselect: ${op}`,
|
|
402
|
+
);
|
|
319
403
|
}
|
|
320
|
-
return {
|
|
321
|
-
query: `e.${attr} IN (:...${key})`,
|
|
322
|
-
params: { [key]: val },
|
|
323
|
-
};
|
|
324
404
|
}
|
|
325
405
|
}
|
|
@@ -11,12 +11,18 @@ export class EntityTableRepository {
|
|
|
11
11
|
) {}
|
|
12
12
|
|
|
13
13
|
async findByEntityTypeAndListType(entityType: string, listType: string) {
|
|
14
|
-
const temp =
|
|
14
|
+
const temp = await this.entityTableRepository.findOne({
|
|
15
15
|
where: { mapped_entity_type: entityType, list_type: listType },
|
|
16
16
|
});
|
|
17
17
|
return temp;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
async findByMappedEntityType(mappedEntityType: string) {
|
|
21
|
+
return await this.entityTableRepository.findOne({
|
|
22
|
+
where: { mapped_entity_type: mappedEntityType, display_type: 'LIST' },
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
async findByEntityTypeAndListTypeAndDisplayType(
|
|
21
27
|
entityType: string,
|
|
22
28
|
listType: string,
|
|
@@ -12,11 +12,29 @@ export class EntityTableService {
|
|
|
12
12
|
constructor(
|
|
13
13
|
private entityTableRepository: EntityTableRepository,
|
|
14
14
|
private readonly entityTableColumnRepository: EntityTableColumnRepository,
|
|
15
|
-
@Inject(forwardRef(() => ListMasterService))
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
) {
|
|
15
|
+
@Inject(forwardRef(() => ListMasterService))
|
|
16
|
+
private readonly listMasterService: ListMasterService,
|
|
17
|
+
|
|
18
|
+
private readonly savedFilterRepoService: SavedFilterRepositoryService,
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
async getEntityData(mappedEntityType: string | null) {
|
|
22
|
+
if (mappedEntityType) {
|
|
23
|
+
const tableMaster =
|
|
24
|
+
await this.entityTableRepository.findByMappedEntityType(
|
|
25
|
+
mappedEntityType,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (!tableMaster) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Entity with mappedEntityType "${mappedEntityType}" not found.`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return tableMaster;
|
|
35
|
+
} else {
|
|
36
|
+
throw new Error();
|
|
37
|
+
}
|
|
20
38
|
}
|
|
21
39
|
|
|
22
40
|
async findByEntityTypeAndListType(entityType: string, listType: string) {
|
|
@@ -38,15 +56,24 @@ export class EntityTableService {
|
|
|
38
56
|
);
|
|
39
57
|
}
|
|
40
58
|
|
|
41
|
-
async getTableMetaDataForListing(
|
|
42
|
-
|
|
59
|
+
async getTableMetaDataForListing(
|
|
60
|
+
entityType: string,
|
|
61
|
+
listType: string,
|
|
62
|
+
userId?: number,
|
|
63
|
+
) {
|
|
64
|
+
return await this.getTableMetaData(
|
|
65
|
+
entityType,
|
|
66
|
+
listType,
|
|
67
|
+
DISPLAY_LIST,
|
|
68
|
+
userId,
|
|
69
|
+
);
|
|
43
70
|
}
|
|
44
71
|
|
|
45
72
|
async getTableMetaData(
|
|
46
73
|
entityType: string,
|
|
47
74
|
listType: string,
|
|
48
75
|
displayType: string,
|
|
49
|
-
userId?: number
|
|
76
|
+
userId?: number,
|
|
50
77
|
) {
|
|
51
78
|
let entityTable = await this.findByEntityTypeAndListTypeAndDisplayType(
|
|
52
79
|
entityType,
|
|
@@ -61,22 +88,27 @@ export class EntityTableService {
|
|
|
61
88
|
entityTable.id,
|
|
62
89
|
entityTable.entity_type,
|
|
63
90
|
);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
entityTableDto.operation_list = {
|
|
92
|
+
text: await this.listMasterService.getDropdownOptions('OPT', {}),
|
|
93
|
+
number: await this.listMasterService.getDropdownOptions('OPN', {}),
|
|
94
|
+
date: await this.listMasterService.getDropdownOptions('OPD', {}),
|
|
95
|
+
select: await this.listMasterService.getDropdownOptions('OPS', {}),
|
|
96
|
+
multiselect: await this.listMasterService.getDropdownOptions('OPM', {}),
|
|
97
|
+
// Add any other operations you want to include
|
|
98
|
+
};
|
|
99
|
+
entityTableDto.default_filter =
|
|
100
|
+
await this.savedFilterRepoService.getDefaultFilterByEntityType(
|
|
101
|
+
entityTable.list_type,
|
|
102
|
+
);
|
|
103
|
+
if (userId) {
|
|
104
|
+
entityTableDto.saved_filter =
|
|
105
|
+
await this.savedFilterRepoService.getSavedFiltersByUserIdAndEntityType(
|
|
106
|
+
userId,
|
|
107
|
+
entityTable.list_type,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
76
110
|
}
|
|
77
111
|
|
|
78
|
-
|
|
79
|
-
|
|
80
112
|
return entityTableDto;
|
|
81
113
|
}
|
|
82
114
|
}
|
|
@@ -67,17 +67,10 @@ export class LoginController {
|
|
|
67
67
|
appcode: string;
|
|
68
68
|
},
|
|
69
69
|
): Promise<any> {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
const currentUserLevelType = req.user.userData.level_type;
|
|
73
|
-
const currentUserLevelId = req.user.userData.level_id;
|
|
74
|
-
const currentUserOrganization_id = req.user.userData.organization_id;
|
|
70
|
+
const currentUser = req.user.userData;
|
|
75
71
|
|
|
76
72
|
return await this.userSessionService.switchCurrentLevelService(
|
|
77
|
-
|
|
78
|
-
currentUserLevelType,
|
|
79
|
-
currentUserLevelId,
|
|
80
|
-
currentUserOrganization_id,
|
|
73
|
+
currentUser,
|
|
81
74
|
data,
|
|
82
75
|
);
|
|
83
76
|
}
|
|
@@ -65,10 +65,7 @@ export class UserSessionService {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
async switchCurrentLevelService(
|
|
68
|
-
|
|
69
|
-
currentUserLevelType: string,
|
|
70
|
-
currentUserLevelId: string,
|
|
71
|
-
currentUserOrgId: number,
|
|
68
|
+
currentUser: any,
|
|
72
69
|
data: any,
|
|
73
70
|
): Promise<{ success: boolean; access_token: string; appcode: string }> {
|
|
74
71
|
let payload;
|
|
@@ -89,15 +86,15 @@ export class UserSessionService {
|
|
|
89
86
|
// }
|
|
90
87
|
|
|
91
88
|
payload = {
|
|
92
|
-
|
|
93
|
-
level_id:
|
|
94
|
-
level_type:
|
|
89
|
+
...currentUser,
|
|
90
|
+
level_id: data.level_id,
|
|
91
|
+
level_type: data.level_type,
|
|
95
92
|
appcode: data.appcode,
|
|
96
93
|
};
|
|
97
94
|
|
|
98
95
|
await this.dataSource.query(
|
|
99
96
|
`UPDATE cr_user SET last_app_access = ? WHERE id = ?`,
|
|
100
|
-
[data.appcode,
|
|
97
|
+
[data.appcode, currentUser.id],
|
|
101
98
|
);
|
|
102
99
|
|
|
103
100
|
// }
|