rez_core 1.0.78 → 1.0.80
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/meta/controller/entity.controller.d.ts +1 -1
- package/dist/module/meta/controller/entity.controller.js +6 -5
- package/dist/module/meta/controller/entity.controller.js.map +1 -1
- package/dist/module/meta/entity.module.js +3 -0
- package/dist/module/meta/entity.module.js.map +1 -1
- package/dist/module/meta/service/entity-service-impl.service.d.ts +4 -2
- package/dist/module/meta/service/entity-service-impl.service.js +21 -6
- package/dist/module/meta/service/entity-service-impl.service.js.map +1 -1
- package/dist/module/meta/service/entity-validation.service.d.ts +19 -0
- package/dist/module/meta/service/entity-validation.service.js +81 -0
- package/dist/module/meta/service/entity-validation.service.js.map +1 -0
- package/dist/module/meta/service/entity.service.d.ts +1 -1
- package/dist/module/meta/service/media-data.service.d.ts +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/meta/controller/entity.controller.ts +3 -0
- package/src/module/meta/entity.module.ts +3 -0
- package/src/module/meta/service/entity-service-impl.service.ts +35 -15
- package/src/module/meta/service/entity-validation.service.ts +100 -0
- package/src/module/meta/service/entity.service.ts +1 -0
package/package.json
CHANGED
|
@@ -159,15 +159,18 @@ export class EntityController {
|
|
|
159
159
|
@Param('entity_type') entityType: string,
|
|
160
160
|
@Query('list_entity_type') listEntityType: string,
|
|
161
161
|
@Query('display_type') displayType: string,
|
|
162
|
+
@Query('sample_export') sampleExport: boolean,
|
|
162
163
|
@Query() filterCriteria: Record<string, any>,
|
|
163
164
|
@Res() res: Response, // Express Response for file handling
|
|
164
165
|
) {
|
|
165
166
|
try {
|
|
167
|
+
|
|
166
168
|
const filePath = await this.entityService.generateExcelReport(
|
|
167
169
|
entityType,
|
|
168
170
|
filterCriteria,
|
|
169
171
|
listEntityType,
|
|
170
172
|
displayType,
|
|
173
|
+
sampleExport
|
|
171
174
|
);
|
|
172
175
|
|
|
173
176
|
if (!filePath || !fs.existsSync(filePath)) {
|
|
@@ -35,6 +35,7 @@ import { ViewMasterService } from './service/view-master.service';
|
|
|
35
35
|
import { ViewMasterController } from './controller/view-master.controller';
|
|
36
36
|
import { ViewMaterRespository } from './repository/view-master.repository';
|
|
37
37
|
import { MetaController } from './controller/meta.controller';
|
|
38
|
+
import { EntityValidationService } from './service/entity-validation.service';
|
|
38
39
|
|
|
39
40
|
@Module({
|
|
40
41
|
imports: [
|
|
@@ -71,6 +72,7 @@ import { MetaController } from './controller/meta.controller';
|
|
|
71
72
|
SectionMasterService,
|
|
72
73
|
FieldGroupService,
|
|
73
74
|
ViewMaterRespository,
|
|
75
|
+
EntityValidationService,
|
|
74
76
|
{ provide: 'ViewMasterService', useClass: ViewMasterService },
|
|
75
77
|
],
|
|
76
78
|
exports: [
|
|
@@ -79,6 +81,7 @@ import { MetaController } from './controller/meta.controller';
|
|
|
79
81
|
PreferenceService,
|
|
80
82
|
EntityListService,
|
|
81
83
|
EntityTableService,
|
|
84
|
+
EntityValidationService,
|
|
82
85
|
EntityTableColumnService,
|
|
83
86
|
MediaDataService,
|
|
84
87
|
SectionMasterService,
|
|
@@ -16,6 +16,7 @@ import { ExcelsheetData } from '../../../utils/dto/excelsheet-data.dto';
|
|
|
16
16
|
import { EntityTableService } from './entity-table.service';
|
|
17
17
|
import { EntityTableColumnService } from './entity-table-column.service';
|
|
18
18
|
import { ENTITYTYPE_ENTITYMASTER } from '../../../constant/global.constant';
|
|
19
|
+
import { EntityValidationService } from './entity-validation.service';
|
|
19
20
|
|
|
20
21
|
@Injectable()
|
|
21
22
|
export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
@@ -26,12 +27,15 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
26
27
|
@Inject() protected readonly reflectionHelper: ReflectionHelper;
|
|
27
28
|
@Inject() protected readonly entityListService: EntityListService;
|
|
28
29
|
@Inject() protected readonly loggingService: LoggingService;
|
|
30
|
+
@Inject()
|
|
31
|
+
protected readonly entityValidationService: EntityValidationService;
|
|
32
|
+
|
|
29
33
|
|
|
30
34
|
async createEntity(
|
|
31
35
|
entityData: BaseEntity,
|
|
32
36
|
loggedInUser: UserData | null,
|
|
33
37
|
manager?: EntityManager,
|
|
34
|
-
)
|
|
38
|
+
){
|
|
35
39
|
if (!entityData.entity_type) {
|
|
36
40
|
throw new BadRequestException(`EntityType is missing`);
|
|
37
41
|
}
|
|
@@ -39,6 +43,16 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
39
43
|
entityData.entity_type,
|
|
40
44
|
);
|
|
41
45
|
|
|
46
|
+
const validationErrors = await this.entityValidationService.validateEntityData(entityData,entityMaster);
|
|
47
|
+
if (validationErrors.length > 0) {
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
success: false,
|
|
51
|
+
errors: validationErrors,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
const repo = manager
|
|
43
57
|
? manager.getRepository(entityMaster.entity_data_class) // <-- Use transaction-safe repo
|
|
44
58
|
: this.reflectionHelper.getRepoService(entityMaster.entity_data_class);
|
|
@@ -186,6 +200,7 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
186
200
|
filterCriteria: Record<string, any>,
|
|
187
201
|
listEntityType: string,
|
|
188
202
|
displayType: string,
|
|
203
|
+
sampleExport: boolean,
|
|
189
204
|
): Promise<string | null> {
|
|
190
205
|
let fileName: string;
|
|
191
206
|
try {
|
|
@@ -196,6 +211,7 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
196
211
|
filterCriteria,
|
|
197
212
|
listEntityType,
|
|
198
213
|
displayType,
|
|
214
|
+
sampleExport
|
|
199
215
|
);
|
|
200
216
|
|
|
201
217
|
const modifiedDate = new Date().toISOString().replace(/[-T:.Z]/g, '');
|
|
@@ -218,19 +234,20 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
218
234
|
filterCriteria: Record<string, any>,
|
|
219
235
|
listEntityType: string,
|
|
220
236
|
displayType: string,
|
|
237
|
+
sampleExport: boolean,
|
|
221
238
|
) {
|
|
222
|
-
const sheet: ExcelsheetData = {
|
|
223
|
-
sheetName: entityType,
|
|
224
|
-
headers: [],
|
|
225
|
-
rowList: [],
|
|
226
|
-
};
|
|
227
|
-
|
|
228
239
|
const entityTable =
|
|
229
240
|
await this.entityTableService.findByEntityTypeAndListTypeAndDisplayType(
|
|
230
241
|
entityType,
|
|
231
242
|
listEntityType,
|
|
232
243
|
displayType,
|
|
233
244
|
);
|
|
245
|
+
const sheet: ExcelsheetData = {
|
|
246
|
+
sheetName: entityTable?.data_source || 'sheet',
|
|
247
|
+
headers: [],
|
|
248
|
+
rowList: [],
|
|
249
|
+
};
|
|
250
|
+
|
|
234
251
|
if (entityTable) {
|
|
235
252
|
const entityTableColumnList =
|
|
236
253
|
await this.entityTableColumnService.findByParentIdAndParentType(
|
|
@@ -243,14 +260,17 @@ export class EntityServiceImpl implements EntityService<BaseEntity> {
|
|
|
243
260
|
(col) => col.attribute_key,
|
|
244
261
|
);
|
|
245
262
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
263
|
+
let filteredList: any[] = [];
|
|
264
|
+
if(!sampleExport) {
|
|
265
|
+
filteredList = await this.entityListService.getFilteredList(
|
|
266
|
+
entityTable,
|
|
267
|
+
filterCriteria,
|
|
268
|
+
undefined,
|
|
269
|
+
undefined,
|
|
270
|
+
undefined,
|
|
271
|
+
undefined,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
254
274
|
|
|
255
275
|
sheet.rowList = filteredList.map((item) =>
|
|
256
276
|
attributeList.map((attr) =>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { AttributeMasterService } from 'src/module/meta/service/attribute-master.service';
|
|
3
|
+
import { AttributeMaster } from '../entity/attribute-master.entity';
|
|
4
|
+
import { ReflectionHelper } from 'src/utils/service/reflection-helper.service';
|
|
5
|
+
import { DataSource } from 'typeorm';
|
|
6
|
+
|
|
7
|
+
interface ValidationError {
|
|
8
|
+
field: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Injectable()
|
|
13
|
+
export class EntityValidationService {
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly attributeMasterService: AttributeMasterService,
|
|
16
|
+
private readonly reflectionHelper: ReflectionHelper,
|
|
17
|
+
private dataSource: DataSource
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Validates required fields based on attribute metadata.
|
|
22
|
+
*/
|
|
23
|
+
validateRequiredFields(
|
|
24
|
+
entityData: Record<string, any>,
|
|
25
|
+
attributeData: AttributeMaster[],
|
|
26
|
+
): ValidationError[] {
|
|
27
|
+
const errors: ValidationError[] = [];
|
|
28
|
+
|
|
29
|
+
attributeData
|
|
30
|
+
.filter(attr => attr.required)
|
|
31
|
+
.forEach(attr => {
|
|
32
|
+
const value = entityData[attr.attribute_key];
|
|
33
|
+
if (!this.hasValidValue(value)) {
|
|
34
|
+
errors.push({
|
|
35
|
+
field: attr.name,
|
|
36
|
+
message: `Field ${attr.name} is required.`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return errors;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Validates uniqueness of fields based on attribute metadata.
|
|
46
|
+
*/
|
|
47
|
+
async validateUniqueFields(
|
|
48
|
+
entityData: Record<string, any>,
|
|
49
|
+
attributeData: AttributeMaster[],
|
|
50
|
+
entityType: string,
|
|
51
|
+
db_table_name: string
|
|
52
|
+
): Promise<ValidationError[]> {
|
|
53
|
+
const errors: ValidationError[] = [];
|
|
54
|
+
|
|
55
|
+
for (const attr of attributeData.filter(a => a.is_unique)) {
|
|
56
|
+
const value = entityData[attr.attribute_key];
|
|
57
|
+
|
|
58
|
+
if (this.hasValidValue(value)) {
|
|
59
|
+
const existing = await this.dataSource
|
|
60
|
+
.createQueryBuilder()
|
|
61
|
+
.select("*")
|
|
62
|
+
.from(db_table_name, db_table_name)
|
|
63
|
+
.where(`${db_table_name}.${attr.attribute_key} = :value`, { value })
|
|
64
|
+
.limit(1)
|
|
65
|
+
.getRawOne();
|
|
66
|
+
|
|
67
|
+
if (existing) {
|
|
68
|
+
errors.push({
|
|
69
|
+
field: attr.name,
|
|
70
|
+
message: `Field ${attr.name} must be unique. Value ${value} already exists.`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return errors;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validates both required and unique fields for a given entity type.
|
|
81
|
+
*/
|
|
82
|
+
async validateEntityData(
|
|
83
|
+
entityData: Record<string, any>,
|
|
84
|
+
entityMaster
|
|
85
|
+
): Promise<ValidationError[]> {
|
|
86
|
+
const attributes = await this.attributeMasterService.findAttributesByMappedEntityType(entityData.entity_type);
|
|
87
|
+
|
|
88
|
+
const requiredErrors = this.validateRequiredFields(entityData, attributes);
|
|
89
|
+
const uniqueErrors = await this.validateUniqueFields(entityData, attributes, entityData.entity_type,entityMaster.db_table_name);
|
|
90
|
+
|
|
91
|
+
return [...requiredErrors, ...uniqueErrors];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
private hasValidValue(value: any): boolean {
|
|
96
|
+
if (value === null || value === undefined) return false;
|
|
97
|
+
if (typeof value === 'string' && value.trim() === '') return false;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|