rez_core 2.1.47 → 2.1.49
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 +1 -1
- package/dist/module/filter/entity/saved-filter-detail.entity.d.ts +2 -1
- package/dist/module/filter/entity/saved-filter-detail.entity.js +4 -0
- package/dist/module/filter/entity/saved-filter-detail.entity.js.map +1 -1
- package/dist/module/filter/repository/saved-filter.repository.d.ts +1 -1
- package/dist/module/filter/repository/saved-filter.repository.js +6 -2
- package/dist/module/filter/repository/saved-filter.repository.js.map +1 -1
- package/dist/module/filter/service/filter.service.js +73 -8
- package/dist/module/filter/service/filter.service.js.map +1 -1
- package/dist/module/filter/service/saved-filter.service.d.ts +2 -1
- package/dist/module/filter/service/saved-filter.service.js +28 -5
- package/dist/module/filter/service/saved-filter.service.js.map +1 -1
- package/dist/module/meta/controller/entity.controller.d.ts +5 -0
- package/dist/module/meta/controller/entity.controller.js +29 -0
- package/dist/module/meta/controller/entity.controller.js.map +1 -1
- package/dist/module/meta/service/entity-service-impl.service.d.ts +1 -1
- package/dist/module/meta/service/entity-service-impl.service.js +12 -1
- package/dist/module/meta/service/entity-service-impl.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/filter/entity/saved-filter-detail.entity.ts +6 -3
- package/src/module/filter/repository/saved-filter.repository.ts +8 -3
- package/src/module/filter/service/filter.service.ts +88 -43
- package/src/module/filter/service/saved-filter.service.ts +42 -5
- package/src/module/meta/controller/entity.controller.ts +41 -0
- package/src/module/meta/service/entity-service-impl.service.ts +21 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ENTITYTYPE_SAVEDFILTERDETAIL } from
|
|
2
|
-
import { BaseEntity } from
|
|
3
|
-
import { Column, Entity } from
|
|
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
4
|
|
|
5
5
|
@Entity({ name: 'cr_saved_filter_detail' })
|
|
6
6
|
export class SavedFilterDetail extends BaseEntity {
|
|
@@ -20,4 +20,7 @@ export class SavedFilterDetail extends BaseEntity {
|
|
|
20
20
|
|
|
21
21
|
@Column()
|
|
22
22
|
filter_value: string;
|
|
23
|
+
|
|
24
|
+
@Column({ nullable: true })
|
|
25
|
+
data_type: string;
|
|
23
26
|
}
|
|
@@ -77,7 +77,7 @@ export class SavedFilterRepositoryService {
|
|
|
77
77
|
status: 'ACTIVE',
|
|
78
78
|
},
|
|
79
79
|
order: {
|
|
80
|
-
|
|
80
|
+
created_date: 'DESC',
|
|
81
81
|
},
|
|
82
82
|
});
|
|
83
83
|
|
|
@@ -91,7 +91,7 @@ export class SavedFilterRepositoryService {
|
|
|
91
91
|
{
|
|
92
92
|
filter_attribute: string;
|
|
93
93
|
filter_operator: string;
|
|
94
|
-
filter_value:
|
|
94
|
+
filter_value: any;
|
|
95
95
|
}[]
|
|
96
96
|
> {
|
|
97
97
|
const saveFilterMasterData = await this.savedFilterMasterRepo.findOne({
|
|
@@ -107,7 +107,12 @@ export class SavedFilterRepositoryService {
|
|
|
107
107
|
return filterDetails.map((detail) => ({
|
|
108
108
|
filter_attribute: detail.filter_attribute,
|
|
109
109
|
filter_operator: detail.filter_operator,
|
|
110
|
-
filter_value:
|
|
110
|
+
filter_value:
|
|
111
|
+
detail.data_type === 'multiselect'
|
|
112
|
+
? detail.filter_value?.trim() === ''
|
|
113
|
+
? []
|
|
114
|
+
: detail.filter_value.split(',')
|
|
115
|
+
: detail.filter_value,
|
|
111
116
|
}));
|
|
112
117
|
}
|
|
113
118
|
}
|
|
@@ -121,7 +121,7 @@ export class FilterService {
|
|
|
121
121
|
{} as Record<string, any>,
|
|
122
122
|
);
|
|
123
123
|
|
|
124
|
-
// Get and parse filters
|
|
124
|
+
// Get and parse saved filters
|
|
125
125
|
const savedFilters = await this.getSavedFilters(savedFilterCode);
|
|
126
126
|
const baseFilters = [
|
|
127
127
|
...(quickFilter || []).filter((f) => f.filter_value !== ''),
|
|
@@ -129,8 +129,10 @@ export class FilterService {
|
|
|
129
129
|
...(attributeFilter || []).filter((f) => f.filter_value !== ''),
|
|
130
130
|
];
|
|
131
131
|
|
|
132
|
+
// Build where clauses
|
|
132
133
|
const baseWhere = this.buildWhereClauses(baseFilters, attributeMetaMap);
|
|
133
134
|
|
|
135
|
+
// check level_id and level_type
|
|
134
136
|
if (level_type && level_id) {
|
|
135
137
|
baseWhere.push({
|
|
136
138
|
query: 'e.level_type = :level_type AND e.level_id = :level_id',
|
|
@@ -148,10 +150,11 @@ export class FilterService {
|
|
|
148
150
|
});
|
|
149
151
|
}
|
|
150
152
|
|
|
153
|
+
// layout preference query
|
|
151
154
|
const layoutPreference = await this.dataSource.query(
|
|
152
155
|
`SELECT layout_json
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
FROM cr_layout_preference
|
|
157
|
+
WHERE user_id = ? AND mapped_entity_type = ?`,
|
|
155
158
|
[user_id, entity_type],
|
|
156
159
|
);
|
|
157
160
|
|
|
@@ -191,13 +194,13 @@ export class FilterService {
|
|
|
191
194
|
|
|
192
195
|
// Separate out 'all' tab before sorting
|
|
193
196
|
const allTab = filteredTabs.find(
|
|
194
|
-
(tab) => tab.tab_value
|
|
197
|
+
(tab) => tab.tab_value?.toLowerCase() === 'all',
|
|
195
198
|
);
|
|
196
199
|
filteredTabs = filteredTabs.filter(
|
|
197
|
-
(tab) => tab.tab_value
|
|
200
|
+
(tab) => tab.tab_value?.toLowerCase() !== 'all',
|
|
198
201
|
);
|
|
199
202
|
|
|
200
|
-
//
|
|
203
|
+
// SORTING LOGIC
|
|
201
204
|
if (layout.sorting === 'asc') {
|
|
202
205
|
filteredTabs.sort((a, b) =>
|
|
203
206
|
a.tab_value.toLowerCase().localeCompare(b.tab_value.toLowerCase()),
|
|
@@ -270,7 +273,8 @@ export class FilterService {
|
|
|
270
273
|
{
|
|
271
274
|
filter_attribute: tabs.columnName,
|
|
272
275
|
filter_operator: 'not_equal',
|
|
273
|
-
filter_value: value,
|
|
276
|
+
filter_value: [value],
|
|
277
|
+
skip_id: true,
|
|
274
278
|
},
|
|
275
279
|
tabAttrMeta,
|
|
276
280
|
);
|
|
@@ -285,7 +289,8 @@ export class FilterService {
|
|
|
285
289
|
{
|
|
286
290
|
filter_attribute: tabs.columnName,
|
|
287
291
|
filter_operator: 'equal',
|
|
288
|
-
filter_value: tabs.value,
|
|
292
|
+
filter_value: [tabs.value],
|
|
293
|
+
skip_id: true,
|
|
289
294
|
},
|
|
290
295
|
tabAttrMeta,
|
|
291
296
|
);
|
|
@@ -356,40 +361,31 @@ export class FilterService {
|
|
|
356
361
|
// Get paginated data
|
|
357
362
|
const entity_list = await qb.getRawMany();
|
|
358
363
|
|
|
359
|
-
// const formatDatesInRow = (row: any) => {
|
|
360
|
-
// const formattedRow = { ...row };
|
|
361
|
-
// for (const key of Object.keys(row)) {
|
|
362
|
-
// if (key.endsWith('_date') && row[key]) {
|
|
363
|
-
// formattedRow[key] = moment(row[key]).format('MMM DD, YYYY');
|
|
364
|
-
// }
|
|
365
|
-
// }
|
|
366
|
-
// return formattedRow;
|
|
367
|
-
// };
|
|
368
|
-
|
|
369
364
|
// 1. Extract all date-type attribute keys
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
//
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
//
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
//
|
|
365
|
+
const dateAttributes = Object.entries(attributeMetaMap)
|
|
366
|
+
.filter(([_, attr]) => attr.data_type === 'date')
|
|
367
|
+
.map(([key]) => key);
|
|
368
|
+
|
|
369
|
+
// 2. Format function using moment
|
|
370
|
+
const formatDate = (dateStr: string | null): string | null => {
|
|
371
|
+
if (!dateStr) return '';
|
|
372
|
+
const date = moment(dateStr).format('DD-MM-YYYY'); // converted
|
|
373
|
+
return date;
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// 3. Function to format only those keys in each entity row
|
|
377
|
+
const formatDatesInRow = (row: any): any => {
|
|
378
|
+
const formattedRow = { ...row };
|
|
379
|
+
for (const key of dateAttributes) {
|
|
380
|
+
if (formattedRow[key]) {
|
|
381
|
+
formattedRow[key] = formatDate(formattedRow[key]);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return formattedRow;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// 4. Final transformation
|
|
388
|
+
const formattedEntityList = entity_list.map(formatDatesInRow);
|
|
393
389
|
|
|
394
390
|
// Count query (without pagination)
|
|
395
391
|
const countQb = this.dataSource
|
|
@@ -406,7 +402,7 @@ export class FilterService {
|
|
|
406
402
|
success: true,
|
|
407
403
|
data: {
|
|
408
404
|
entity_tabs: filteredTabs,
|
|
409
|
-
entity_list,
|
|
405
|
+
entity_list: formattedEntityList,
|
|
410
406
|
pagination: {
|
|
411
407
|
total,
|
|
412
408
|
page,
|
|
@@ -466,7 +462,8 @@ export class FilterService {
|
|
|
466
462
|
const op = filter.filter_operator;
|
|
467
463
|
const key = `param_${attr}_${Math.random().toString(36).substring(2, 8)}`;
|
|
468
464
|
|
|
469
|
-
if (meta.data_source_type === 'entity'
|
|
465
|
+
if (meta.data_source_type === 'entity' && !filter.skip_id)
|
|
466
|
+
attr = `${attr}_id`;
|
|
470
467
|
|
|
471
468
|
switch (meta.data_type) {
|
|
472
469
|
case 'text':
|
|
@@ -479,6 +476,10 @@ export class FilterService {
|
|
|
479
476
|
return this.buildMultiSelectCondition(attr, op, val, key);
|
|
480
477
|
case 'multiselect':
|
|
481
478
|
return this.buildMultiSelectCondition(attr, op, val, key);
|
|
479
|
+
case 'checkbox':
|
|
480
|
+
return this.buildMultiSelectCondition(attr, op, val, key);
|
|
481
|
+
case 'radio':
|
|
482
|
+
return this.buildMultiSelectCondition(attr, op, val, key);
|
|
482
483
|
case 'year':
|
|
483
484
|
return this.buildYearCondition(attr, op, val, key);
|
|
484
485
|
default:
|
|
@@ -533,6 +534,15 @@ export class FilterService {
|
|
|
533
534
|
return { query: `e.${attr} > :${key}`, params: { [key]: val } };
|
|
534
535
|
case 'less_than':
|
|
535
536
|
return { query: `e.${attr} < :${key}`, params: { [key]: val } };
|
|
537
|
+
case 'less_than_qual_to':
|
|
538
|
+
return { query: `e.${attr} <= :${key}`, params: { [key]: val } };
|
|
539
|
+
case 'greater_than_qual_to':
|
|
540
|
+
return { query: `e.${attr} >= :${key}`, params: { [key]: val } };
|
|
541
|
+
case 'empty':
|
|
542
|
+
return { query: `e.${attr} IS NULL`, params: {} };
|
|
543
|
+
case 'not_empty':
|
|
544
|
+
return { query: `e.${attr} IS NOT NULL`, params: {} };
|
|
545
|
+
|
|
536
546
|
default:
|
|
537
547
|
throw new BadRequestException(`Unsupported operator for number: ${op}`);
|
|
538
548
|
}
|
|
@@ -561,6 +571,31 @@ export class FilterService {
|
|
|
561
571
|
},
|
|
562
572
|
};
|
|
563
573
|
}
|
|
574
|
+
|
|
575
|
+
case 'today': {
|
|
576
|
+
const today = new Date().toISOString().split('T')[0]; // 'YYYY-MM-DD'
|
|
577
|
+
|
|
578
|
+
return {
|
|
579
|
+
query: `DATE(e.${attr}) = :today`,
|
|
580
|
+
params: {
|
|
581
|
+
today,
|
|
582
|
+
},
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
case 'empty': {
|
|
587
|
+
return {
|
|
588
|
+
query: `e.${attr} IS NULL`,
|
|
589
|
+
params: {},
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
case 'not_empty': {
|
|
594
|
+
return {
|
|
595
|
+
query: `e.${attr} IS NOT NULL`,
|
|
596
|
+
params: {},
|
|
597
|
+
};
|
|
598
|
+
}
|
|
564
599
|
default:
|
|
565
600
|
throw new BadRequestException(`Unsupported operator for date: ${op}`);
|
|
566
601
|
}
|
|
@@ -613,6 +648,16 @@ export class FilterService {
|
|
|
613
648
|
query: `e.${attr} NOT IN (:${key})`,
|
|
614
649
|
params: { [key]: val },
|
|
615
650
|
};
|
|
651
|
+
case 'contains':
|
|
652
|
+
return {
|
|
653
|
+
query: `e.${attr} LIKE :${key}`,
|
|
654
|
+
params: { [key]: `%${val}%` },
|
|
655
|
+
};
|
|
656
|
+
case 'not_contains':
|
|
657
|
+
return {
|
|
658
|
+
query: `e.${attr} NOT LIKE :${key}`,
|
|
659
|
+
params: { [key]: `%${val}%` },
|
|
660
|
+
};
|
|
616
661
|
case 'empty':
|
|
617
662
|
return { query: `e.${attr} IS NULL`, params: {} };
|
|
618
663
|
case 'not_empty':
|
|
@@ -32,6 +32,7 @@ export class SavedFilterService extends EntityServiceImpl {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
entityData.user_id = loggedInUser?.id ?? null;
|
|
35
|
+
|
|
35
36
|
// Save the master record without code
|
|
36
37
|
const savedMaster = await super.createEntity(master, loggedInUser);
|
|
37
38
|
|
|
@@ -45,10 +46,22 @@ export class SavedFilterService extends EntityServiceImpl {
|
|
|
45
46
|
// Save filter details using generated code
|
|
46
47
|
const details = (entityData as any).filterDetails ?? [];
|
|
47
48
|
if (details.length) {
|
|
48
|
-
const prepared = details.map((detail: any) =>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const prepared = details.map((detail: any) => {
|
|
50
|
+
// If detail.filter_value is an array, join it with comma
|
|
51
|
+
if (Array.isArray(detail.filter_value)) {
|
|
52
|
+
return {
|
|
53
|
+
...detail,
|
|
54
|
+
mapped_filter_code: savedMaster.code,
|
|
55
|
+
filter_value: detail.filter_value.join(','),
|
|
56
|
+
data_type: 'multiselect',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Otherwise, just add mapped_filter_code
|
|
60
|
+
return {
|
|
61
|
+
...detail,
|
|
62
|
+
mapped_filter_code: savedMaster.code,
|
|
63
|
+
};
|
|
64
|
+
});
|
|
52
65
|
|
|
53
66
|
await this.savedFilterRepo.saveDetails(prepared);
|
|
54
67
|
}
|
|
@@ -98,11 +111,35 @@ export class SavedFilterService extends EntityServiceImpl {
|
|
|
98
111
|
return updated;
|
|
99
112
|
}
|
|
100
113
|
|
|
114
|
+
async deleteEntity(entityType: string, entityId: number) {
|
|
115
|
+
const entityMaster =
|
|
116
|
+
await this.entityMasterService.getEntityData(entityType);
|
|
117
|
+
|
|
118
|
+
const repoService = this.reflectionHelper.getRepoService(
|
|
119
|
+
entityMaster.entity_data_class,
|
|
120
|
+
);
|
|
121
|
+
if (!repoService) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Repository service not found for entityType: ${entityType}`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const entityData = await repoService.findOne({ where: { id: entityId } });
|
|
128
|
+
|
|
129
|
+
if (!entityData) {
|
|
130
|
+
throw new Error(`Entity not found for entityType: ${entityType}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await this.savedFilterRepo.deleteDetailsByCode(entityData.code);
|
|
134
|
+
|
|
135
|
+
await repoService.delete(entityId);
|
|
136
|
+
}
|
|
137
|
+
|
|
101
138
|
async getDetailsByCode(code: string): Promise<SavedFilterDetail[]> {
|
|
102
139
|
return this.savedFilterRepo.getDetailsByCode(code);
|
|
103
140
|
}
|
|
104
141
|
|
|
105
142
|
async getFilterById(id: number) {
|
|
106
|
-
return this.savedFilterRepo.getFilterById(id);
|
|
143
|
+
return await this.savedFilterRepo.getFilterById(id);
|
|
107
144
|
}
|
|
108
145
|
}
|
|
@@ -144,6 +144,47 @@ export class EntityController {
|
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
@Post('delete/:id')
|
|
148
|
+
@HttpCode(200)
|
|
149
|
+
async delete(
|
|
150
|
+
@Param('id') id: number,
|
|
151
|
+
@Query('entity_type') entityType: string,
|
|
152
|
+
@Req() req: Request & { user: any },
|
|
153
|
+
) {
|
|
154
|
+
const loggedInUser = req.user.userData;
|
|
155
|
+
|
|
156
|
+
if (!entityType) {
|
|
157
|
+
throw new BadRequestException(
|
|
158
|
+
'Query parameter "entity_type" is required',
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const entityMaster =
|
|
163
|
+
await this.entityMasterService.getEntityData(entityType);
|
|
164
|
+
|
|
165
|
+
const entityService =
|
|
166
|
+
await this.reflectionHelper.getBean<EntityServiceImpl>(
|
|
167
|
+
entityMaster.entity_service,
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
if (!entityService) {
|
|
171
|
+
throw new InternalServerErrorException(
|
|
172
|
+
`No service found for entity_type "${entityType}"`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const existingEntity = await entityService.getEntityData(entityType, id);
|
|
177
|
+
if (!existingEntity) {
|
|
178
|
+
throw new NotFoundException(`No entity found for id "${id}"`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await entityService.deleteEntity(entityType, id);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
success: true,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
147
188
|
@Post('getFilteredDataWithTabs/:entity_type')
|
|
148
189
|
async getFilterDataWithTabs(
|
|
149
190
|
@Param('entity_type') entityType: string,
|
|
@@ -94,11 +94,27 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
94
94
|
return repo.save(entityData);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
deleteEntity(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
async deleteEntity(entityType: string, entityId: number) {
|
|
98
|
+
const entityMaster =
|
|
99
|
+
await this.entityMasterService.getEntityData(entityType);
|
|
100
|
+
|
|
101
|
+
const repoService = this.reflectionHelper.getRepoService(
|
|
102
|
+
entityMaster.entity_data_class,
|
|
103
|
+
);
|
|
104
|
+
if (!repoService) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Repository service not found for entityType: ${entityType}`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const entityData = await repoService.findOne({ where: { id: entityId } });
|
|
111
|
+
|
|
112
|
+
if (!entityData) {
|
|
113
|
+
throw new Error(`Entity not found for entityType: ${entityType}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
await repoService.delete(entityId);
|
|
117
|
+
}
|
|
102
118
|
|
|
103
119
|
async findByCode(entityType: string, code: string): Promise<BaseEntity> {
|
|
104
120
|
const entityData = await this.entityMasterService.getEntityData(entityType);
|