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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "2.0.57",
3
+ "version": "2.0.59",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -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
- const qb = this.dataSource
30
- .getRepository(tableName)
31
- .createQueryBuilder('e')
32
- .select(`e.${column}`, 'tab_value')
33
- .addSelect('COUNT(*)', 'tab_value_count')
34
- .groupBy(`e.${column}`);
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
- whereClauses.forEach((clause) => qb.andWhere(clause.query, clause.params));
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 qb.getRawMany();
55
+ const rows = await this.dataSource.query(rawSQL, values);
39
56
 
40
- const total = rows.reduce((sum, r) => sum + parseInt(r.tab_value_count), 0);
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 || 'UNKNOWN',
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
- await this.entityMasterService.getEntityData(entity_type);
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
- tableName,
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
- // Final query for filtered data
134
- // Final query for filtered data
135
- const qb = this.dataSource.getRepository(tableName).createQueryBuilder('e');
136
- dataWhere.forEach((clause) => qb.andWhere(clause.query, clause.params));
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
- const [entity_list, total] = await qb.getManyAndCount();
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
- const attr = filter.filter_attribute;
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(attr: string, val: any[], key: string) {
317
- if (!Array.isArray(val)) {
318
- throw new BadRequestException(`Expected array for multiselect: ${attr}`);
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 = await this.entityTableRepository.findOne({
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
- private readonly listMasterService: ListMasterService,
17
-
18
- private readonly savedFilterRepoService: SavedFilterRepositoryService,
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(entityType: string, listType: string,userId?: number) {
42
- return await this.getTableMetaData(entityType, listType, DISPLAY_LIST,userId);
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
- entityTableDto.operation_list = {
65
- "text": await this.listMasterService.getDropdownOptions("OPT",{}),
66
- "number": await this.listMasterService.getDropdownOptions("OPN",{}),
67
- "date": await this.listMasterService.getDropdownOptions("OPD",{}),
68
- "select": await this.listMasterService.getDropdownOptions("OPS",{}),
69
- "multiselect": await this.listMasterService.getDropdownOptions("OPM",{})
70
- // Add any other operations you want to include
71
- };
72
- entityTableDto.default_filter= await this.savedFilterRepoService.getDefaultFilterByEntityType(entityTable.list_type);
73
- if(userId){
74
- entityTableDto.saved_filter = await this.savedFilterRepoService.getSavedFiltersByUserIdAndEntityType(userId, entityTable.list_type);
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 userId = req.user.userData.id;
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
- userId,
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
- userId: number,
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
- id: userId,
93
- level_id: currentUserLevelId,
94
- level_type: currentUserLevelType,
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, userId],
97
+ [data.appcode, currentUser.id],
101
98
  );
102
99
 
103
100
  // }