rez_core 2.2.108 → 2.2.110

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.
Files changed (58) hide show
  1. package/dist/app.module.js +2 -0
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/constant/global.constant.d.ts +2 -0
  4. package/dist/constant/global.constant.js +3 -1
  5. package/dist/constant/global.constant.js.map +1 -1
  6. package/dist/module/ics/controller/ics.controller.d.ts +8 -0
  7. package/dist/module/ics/controller/ics.controller.js +45 -0
  8. package/dist/module/ics/controller/ics.controller.js.map +1 -0
  9. package/dist/module/ics/dto/ics.dto.d.ts +17 -0
  10. package/dist/module/ics/dto/ics.dto.js +73 -0
  11. package/dist/module/ics/dto/ics.dto.js.map +1 -0
  12. package/dist/module/ics/ics.module.d.ts +2 -0
  13. package/dist/module/ics/ics.module.js +26 -0
  14. package/dist/module/ics/ics.module.js.map +1 -0
  15. package/dist/module/ics/service/ics.service.d.ts +5 -0
  16. package/dist/module/ics/service/ics.service.js +55 -0
  17. package/dist/module/ics/service/ics.service.js.map +1 -0
  18. package/dist/module/meta/controller/entity-dynamic.controller.js +3 -3
  19. package/dist/module/meta/controller/entity-dynamic.controller.js.map +1 -1
  20. package/dist/module/meta/controller/entity-relation.controller.d.ts +6 -0
  21. package/dist/module/meta/controller/entity-relation.controller.js +43 -0
  22. package/dist/module/meta/controller/entity-relation.controller.js.map +1 -0
  23. package/dist/module/meta/entity/entity-relation-data.entity.d.ts +10 -0
  24. package/dist/module/meta/entity/entity-relation-data.entity.js +51 -0
  25. package/dist/module/meta/entity/entity-relation-data.entity.js.map +1 -0
  26. package/dist/module/meta/entity/entity-relation.entity.d.ts +10 -0
  27. package/dist/module/meta/entity/entity-relation.entity.js +51 -0
  28. package/dist/module/meta/entity/entity-relation.entity.js.map +1 -0
  29. package/dist/module/meta/entity.module.js +16 -3
  30. package/dist/module/meta/entity.module.js.map +1 -1
  31. package/dist/module/meta/service/entity-dynamic.service.d.ts +5 -0
  32. package/dist/module/meta/service/entity-dynamic.service.js +195 -5
  33. package/dist/module/meta/service/entity-dynamic.service.js.map +1 -1
  34. package/dist/module/meta/service/entity-realation-data.service.d.ts +4 -0
  35. package/dist/module/meta/service/entity-realation-data.service.js +25 -0
  36. package/dist/module/meta/service/entity-realation-data.service.js.map +1 -0
  37. package/dist/module/meta/service/entity-relation.service.d.ts +7 -0
  38. package/dist/module/meta/service/entity-relation.service.js +31 -0
  39. package/dist/module/meta/service/entity-relation.service.js.map +1 -0
  40. package/dist/module/meta/service/resolver.service.js +2 -2
  41. package/dist/module/meta/service/resolver.service.js.map +1 -1
  42. package/dist/tsconfig.build.tsbuildinfo +1 -1
  43. package/package.json +2 -1
  44. package/src/app.module.ts +2 -0
  45. package/src/constant/global.constant.ts +2 -0
  46. package/src/module/ics/controller/ics.controller.ts +21 -0
  47. package/src/module/ics/dto/ics.dto.ts +55 -0
  48. package/src/module/ics/ics.module.ts +13 -0
  49. package/src/module/ics/service/ics.service.ts +48 -0
  50. package/src/module/meta/controller/entity-dynamic.controller.ts +94 -78
  51. package/src/module/meta/controller/entity-relation.controller.ts +31 -0
  52. package/src/module/meta/entity/entity-relation-data.entity.ts +29 -0
  53. package/src/module/meta/entity/entity-relation.entity.ts +29 -0
  54. package/src/module/meta/entity.module.ts +17 -4
  55. package/src/module/meta/service/entity-dynamic.service.ts +417 -21
  56. package/src/module/meta/service/entity-realation-data.service.ts +9 -0
  57. package/src/module/meta/service/entity-relation.service.ts +22 -0
  58. package/src/module/meta/service/resolver.service.ts +2 -2
@@ -6,11 +6,18 @@ export class EntityDynamicService {
6
6
  constructor(private readonly dataSource: DataSource) {}
7
7
 
8
8
  // -----------------------------
9
- async createEntity(entityType: string, data: Record<string, any>, loggedInUser: any): Promise<any> {
9
+ async createEntity(
10
+ entityType: string,
11
+ data: Record<string, any>,
12
+ loggedInUser: any,
13
+ ): Promise<any> {
10
14
  const organizationId = loggedInUser.organization_id;
11
15
 
12
- const tableName = await this.getTableName(entityType);
13
- const validAttributes = await this.getAttributeCodes(entityType, organizationId);
16
+ const tableName = await this.getTableName(entityType, organizationId);
17
+ const validAttributes = await this.getAttributeCodes(
18
+ entityType,
19
+ organizationId,
20
+ );
14
21
 
15
22
  const columns: string[] = [];
16
23
  const values: any[] = [];
@@ -28,45 +35,412 @@ export class EntityDynamicService {
28
35
  return result;
29
36
  }
30
37
 
38
+ // ----------------------------- get entity with relations
39
+
40
+ async createEntityWithRelation(
41
+ entityType: string,
42
+ data: Record<string, any>,
43
+ loggedInUser: any,
44
+ ): Promise<any> {
45
+ const organizationId = loggedInUser.organization_id;
46
+
47
+ const getRelation = await this.dataSource.query(
48
+ `SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
49
+ [organizationId, entityType],
50
+ );
51
+
52
+ const { mappedEntities, ...mainData } = data;
53
+
54
+ // create main entity
55
+ const createdEntityData = await this.createEntity(
56
+ entityType,
57
+ mainData,
58
+ loggedInUser,
59
+ );
60
+ const mainID = createdEntityData.insertId || createdEntityData.id;
61
+
62
+ // Process related entities
63
+ const relationResults: any[] = [];
64
+
65
+ if (mappedEntities && getRelation.length > 0) {
66
+ for (const relation of getRelation) {
67
+ const targetEntityType = relation.target_entity_type;
68
+ const relationType = relation.relation_type;
69
+ const relationId = relation.relation_id;
70
+
71
+ // Check if we have data for this target entity type
72
+ if (mappedEntities[targetEntityType]) {
73
+ const entityData = mappedEntities[targetEntityType];
74
+
75
+ // resolve from list_master_items
76
+ const relationTypeResult = await this.dataSource.query(
77
+ `SELECT * FROM cr_list_master_items WHERE organization_id = ? AND id = ?`,
78
+ [organizationId, relationId],
79
+ );
80
+
81
+ if (
82
+ relationTypeResult[0]?.value == 'ONE_TO_MANY' ||
83
+ relationTypeResult[0]?.value == 'MANY_TO_ONE'
84
+ ) {
85
+ // Expect array of objects
86
+ if (Array.isArray(entityData)) {
87
+ for (const item of entityData) {
88
+ // Add foreign key reference to main entity
89
+ const itemWithRef = {
90
+ ...item,
91
+ entity_type: targetEntityType,
92
+ };
93
+
94
+ const createdRelatedEntity = await this.createEntity(
95
+ targetEntityType,
96
+ itemWithRef,
97
+ loggedInUser,
98
+ );
99
+
100
+ // SAVE ENTRY IN cr_entity_relation_data
101
+
102
+ await this.dataSource.query(
103
+ `INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
104
+ [
105
+ mainID,
106
+ entityType,
107
+ createdRelatedEntity.insertId,
108
+ targetEntityType,
109
+ relationType,
110
+ ],
111
+ );
112
+ }
113
+ } else {
114
+ throw new Error(
115
+ `Expected array for ONE_TO_MANY relationship with ${targetEntityType}`,
116
+ );
117
+ }
118
+ } else if (
119
+ relationTypeResult[0]?.value == 'ONE_TO_ONE' ||
120
+ relationTypeResult[0]?.value == 'MANY_TO_ONE'
121
+ ) {
122
+ // Expect single object
123
+ if (!Array.isArray(entityData)) {
124
+ // Add foreign key reference to main entity
125
+ const entityWithRef = {
126
+ ...entityData,
127
+ entity_type: targetEntityType,
128
+ };
129
+
130
+ const createdRelatedEntity = await this.createEntity(
131
+ targetEntityType,
132
+ entityWithRef,
133
+ loggedInUser,
134
+ );
135
+
136
+ // SAVE ENTRY IN cr_entity_relation_data
137
+ await this.dataSource.query(
138
+ `INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
139
+ [
140
+ mainID,
141
+ entityType,
142
+ createdRelatedEntity.insertId,
143
+ targetEntityType,
144
+ relationType,
145
+ ],
146
+ );
147
+ } else {
148
+ throw new Error(
149
+ `Expected single object for ONE_TO_ONE relationship with ${targetEntityType}`,
150
+ );
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ return {
158
+ mainEntity: {
159
+ id: mainID,
160
+ entityType: entityType,
161
+ data: createdEntityData,
162
+ },
163
+ relatedEntities: relationResults,
164
+ };
165
+ }
166
+
167
+ // ----------------------------- get entity with relations
168
+ async getEntityWithRelation(
169
+ entityType: string,
170
+ id: number | string,
171
+ loggedInUser: any,
172
+ ): Promise<any> {
173
+ const mainEntity = await this.getEntity(entityType, id, loggedInUser);
174
+
175
+ const relatedEntities = await this.dataSource.query(
176
+ `SELECT * FROM cr_entity_relation_data WHERE source_entity_id = ? AND target_entity_type IN (
177
+ SELECT target_entity_type FROM cr_entity_relation WHERE source_entity_type = ?)`,
178
+ [id, entityType],
179
+ );
180
+
181
+ // Format response to match create entity structure
182
+ const response: any = {
183
+ entity_type: entityType,
184
+ ...mainEntity,
185
+ };
186
+
187
+ if (relatedEntities.length > 0) {
188
+ response.mappedEntities = await this.formatMappedEntities(
189
+ relatedEntities,
190
+ loggedInUser,
191
+ );
192
+ }
193
+
194
+ return response;
195
+ }
196
+
197
+ async formatMappedEntities(
198
+ relatedEntities: any[],
199
+ loggedInUser: any,
200
+ ): Promise<any> {
201
+ const mappedEntities: any = {};
202
+
203
+ for (const relation of relatedEntities) {
204
+ const targetEntityType = relation.target_entity_type;
205
+ const targetEntityId = relation.target_entity_id;
206
+ const relationType = relation.relation_type;
207
+
208
+ // Get the actual entity data
209
+ const entityData = await this.getEntity(
210
+ targetEntityType,
211
+ targetEntityId,
212
+ loggedInUser,
213
+ );
214
+
215
+ if (!mappedEntities[targetEntityType]) {
216
+ // Initialize based on relation type
217
+ if (relationType === 'ONE_TO_MANY') {
218
+ mappedEntities[targetEntityType] = [];
219
+ } else if (
220
+ relationType === 'ONE_TO_ONE' ||
221
+ relationType === 'MANY_TO_ONE'
222
+ ) {
223
+ mappedEntities[targetEntityType] = null;
224
+ }
225
+ }
226
+
227
+ if (relationType === 'ONE_TO_MANY') {
228
+ mappedEntities[targetEntityType].push(entityData);
229
+ } else if (
230
+ relationType === 'ONE_TO_ONE' ||
231
+ relationType === 'MANY_TO_ONE'
232
+ ) {
233
+ mappedEntities[targetEntityType] = entityData;
234
+ }
235
+ }
236
+
237
+ return mappedEntities;
238
+ }
239
+
240
+ // ----------------------------- update with relations
241
+
242
+ async updateEntityWithRelations(
243
+ entityType: string,
244
+ id: number | string,
245
+ data: Record<string, any>,
246
+ loggedInUser: any,
247
+ ): Promise<any> {
248
+ const organizationId = loggedInUser.organization_id;
249
+
250
+ const { mappedEntities, ...mainData } = data;
251
+
252
+ // Update the main entity (excluding mappedEntities)
253
+ await this.updateEntity(entityType, id, mainData, loggedInUser);
254
+
255
+ // Handle related entities if mappedEntities is provided
256
+ if (mappedEntities) {
257
+ // Get existing relations
258
+ const existingRelations = await this.dataSource.query(
259
+ `SELECT * FROM cr_entity_relation_data WHERE source_entity_type = ? AND source_entity_id = ?`,
260
+ [entityType, id],
261
+ );
262
+
263
+ // Get relation definitions
264
+ const getRelationDefs = await this.dataSource.query(
265
+ `SELECT * FROM cr_entity_relation WHERE organization_id = ? AND source_entity_type = ?`,
266
+ [organizationId, entityType],
267
+ );
268
+
269
+ // Process each target entity type in mappedEntities
270
+ for (const [targetEntityType, entityData] of Object.entries(
271
+ mappedEntities,
272
+ )) {
273
+ const relationDef = getRelationDefs.find(
274
+ (r) => r.target_entity_type === targetEntityType,
275
+ );
276
+
277
+ if (!relationDef) {
278
+ console.warn(
279
+ `No relation definition found for ${entityType} -> ${targetEntityType}`,
280
+ );
281
+ continue;
282
+ }
283
+
284
+ const relationType = relationDef.relation_type;
285
+ const existingRelationsForType = existingRelations.filter(
286
+ (r) => r.target_entity_type === targetEntityType,
287
+ );
288
+
289
+ if (relationType === 'ONE_TO_MANY') {
290
+ // Handle array of entities
291
+ if (Array.isArray(entityData)) {
292
+ // Delete existing relations for this type
293
+
294
+ for (const existingRel of existingRelationsForType) {
295
+ await this.dataSource.query(
296
+ `DELETE FROM cr_entity_relation_data WHERE id = ?`,
297
+ [existingRel.id],
298
+ );
299
+ }
300
+
301
+ // Create new relations
302
+ for (const item of entityData) {
303
+ let targetEntityId;
304
+
305
+ if (item.id) {
306
+ // Update existing entity
307
+ await this.updateEntity(
308
+ targetEntityType,
309
+ item.id,
310
+ item,
311
+ loggedInUser,
312
+ );
313
+ targetEntityId = item.id;
314
+ } else {
315
+ // Create new entity
316
+ const createdEntity = await this.createEntity(
317
+ targetEntityType,
318
+ item,
319
+ loggedInUser,
320
+ );
321
+ targetEntityId = createdEntity.insertId || createdEntity.id;
322
+ }
323
+
324
+ // Create relation entry
325
+ await this.dataSource.query(
326
+ `INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
327
+ [
328
+ id,
329
+ entityType,
330
+ targetEntityId,
331
+ targetEntityType,
332
+ relationType,
333
+ ],
334
+ );
335
+ }
336
+ } else {
337
+ throw new Error(
338
+ `Expected array for ONE_TO_MANY relationship with ${targetEntityType}`,
339
+ );
340
+ }
341
+ } else if (
342
+ relationType === 'ONE_TO_ONE' ||
343
+ relationType === 'MANY_TO_ONE'
344
+ ) {
345
+ // Handle single entity
346
+ if (!Array.isArray(entityData)) {
347
+ const singleEntityData = entityData as Record<string, any>;
348
+ let targetEntityId;
349
+
350
+ if (singleEntityData.id) {
351
+ // Update existing entity
352
+ await this.updateEntity(
353
+ targetEntityType,
354
+ singleEntityData.id,
355
+ singleEntityData,
356
+ loggedInUser,
357
+ );
358
+ targetEntityId = singleEntityData.id;
359
+ } else {
360
+ // Create new entity
361
+ const createdEntity = await this.createEntity(
362
+ targetEntityType,
363
+ singleEntityData,
364
+ loggedInUser,
365
+ );
366
+ targetEntityId = createdEntity.insertId || createdEntity.id;
367
+
368
+ // Create relation entry if it doesn't exist
369
+ const existingRel = existingRelationsForType[0];
370
+ if (!existingRel) {
371
+ await this.dataSource.query(
372
+ `INSERT INTO cr_entity_relation_data (source_entity_id, source_entity_type, target_entity_id, target_entity_type, relation_type) VALUES (?, ?, ?, ?, ?)`,
373
+ [
374
+ id,
375
+ entityType,
376
+ targetEntityId,
377
+ targetEntityType,
378
+ relationType,
379
+ ],
380
+ );
381
+ }
382
+ }
383
+ } else {
384
+ throw new Error(
385
+ `Expected single object for ONE_TO_ONE relationship with ${targetEntityType}`,
386
+ );
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ return { success: true };
393
+ }
394
+
31
395
  // -----------------------------
32
396
  async updateEntity(
33
397
  entityType: string,
34
398
  id: number | string,
35
399
  data: Record<string, any>,
36
- loggedInUser: any
400
+ loggedInUser: any,
37
401
  ): Promise<any> {
38
402
  const organizationId = loggedInUser.organization_id;
39
-
40
- const tableName = await this.getTableName(entityType);
41
- const validAttributes = await this.getAttributeCodes(entityType, organizationId);
42
-
403
+
404
+ const tableName = await this.getTableName(entityType, organizationId);
405
+ const validAttributes = await this.getAttributeCodes(
406
+ entityType,
407
+ organizationId,
408
+ );
409
+
43
410
  const updates: string[] = [];
44
411
  const values: any[] = [];
45
-
412
+
46
413
  for (const key of Object.keys(data)) {
47
414
  if (validAttributes.includes(key)) {
48
415
  updates.push(`\`${key}\` = ?`);
49
416
  values.push(data[key]);
50
417
  }
51
418
  }
52
-
419
+
53
420
  if (updates.length === 0) {
54
421
  throw new Error('No valid attributes to update.');
55
422
  }
56
-
423
+
57
424
  const updateQuery = `UPDATE \`${tableName}\` SET ${updates.join(', ')} WHERE id = ?`;
58
425
  values.push(id); // Add id for WHERE clause
59
-
426
+
60
427
  const result = await this.dataSource.query(updateQuery, values);
61
428
  return result;
62
429
  }
63
430
 
64
431
  // -----------------------------
65
- async getEntity(entityType: string, id: number | string, loggedInUser: any): Promise<any> {
432
+ async getEntity(
433
+ entityType: string,
434
+ id: number | string,
435
+ loggedInUser: any,
436
+ ): Promise<any> {
66
437
  const organizationId = loggedInUser.organization_id;
67
438
 
68
- const tableName = await this.getTableName(entityType);
69
- const validAttributes = await this.getAttributeCodes(entityType, organizationId);
439
+ const tableName = await this.getTableName(entityType, organizationId);
440
+ const validAttributes = await this.getAttributeCodes(
441
+ entityType,
442
+ organizationId,
443
+ );
70
444
 
71
445
  const columns = validAttributes.map((attr) => `\`${attr}\``).join(', ');
72
446
  const selectQuery = `SELECT ${columns} FROM \`${tableName}\` WHERE id = ?`;
@@ -76,10 +450,13 @@ export class EntityDynamicService {
76
450
  }
77
451
 
78
452
  // -----------------------------
79
- private async getTableName(entityType: string): Promise<string> {
453
+ private async getTableName(
454
+ entityType: string,
455
+ organizationId: string,
456
+ ): Promise<string> {
80
457
  const result = await this.dataSource.query(
81
- `SELECT db_table_name FROM cr_entity_master WHERE mapped_entity_type = ?`,
82
- [entityType]
458
+ `SELECT db_table_name FROM cr_entity_master WHERE organization_id = ? AND mapped_entity_type = ?`,
459
+ [organizationId, entityType],
83
460
  );
84
461
 
85
462
  if (!result.length) {
@@ -89,16 +466,35 @@ export class EntityDynamicService {
89
466
  return result[0].db_table_name;
90
467
  }
91
468
 
92
- private async getAttributeCodes(entityType: string, organizationId: string): Promise<string[]> {
469
+ private async getAttributeCodes(
470
+ entityType: string,
471
+ organizationId: string,
472
+ ): Promise<string[]> {
93
473
  const result = await this.dataSource.query(
94
474
  `SELECT attribute_key FROM cr_attribute_master WHERE mapped_entity_type = ? AND organization_id = ?`,
95
- [entityType, organizationId]
475
+ [entityType, organizationId],
96
476
  );
97
477
 
98
478
  if (!result.length) {
99
- console.log(`No attributes found for entity '${entityType}' and org '${organizationId}'`);
479
+ console.log(
480
+ `No attributes found for entity '${entityType}' and org '${organizationId}'`,
481
+ );
100
482
  }
101
483
 
102
484
  return result.map((row) => row.attribute_key);
103
485
  }
486
+
487
+ private async deleteEntity(
488
+ entityType: string,
489
+ id: number | string,
490
+ loggedInUser: any,
491
+ ): Promise<any> {
492
+ const organizationId = loggedInUser.organization_id;
493
+
494
+ const tableName = await this.getTableName(entityType, organizationId);
495
+
496
+ const deleteQuery = `DELETE FROM \`${tableName}\` WHERE id = ?`;
497
+ const result = await this.dataSource.query(deleteQuery, [id]);
498
+ return result;
499
+ }
104
500
  }
@@ -0,0 +1,9 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { EntityServiceImpl } from './entity-service-impl.service';
3
+
4
+ @Injectable()
5
+ export class EntityRelationDataService extends EntityServiceImpl {
6
+ constructor() {
7
+ super();
8
+ }
9
+ }
@@ -0,0 +1,22 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { EntityServiceImpl } from './entity-service-impl.service';
3
+ import { DataSource } from 'typeorm';
4
+
5
+ @Injectable()
6
+ export class EntityRelationService extends EntityServiceImpl {
7
+ constructor(private readonly dataSource: DataSource) {
8
+ super();
9
+ }
10
+
11
+ async getEntityRelations(
12
+ entityType: string,
13
+ loggedInUser: any,
14
+ ): Promise<any> {
15
+ const relations = await this.dataSource.query(
16
+ `SELECT name as label , target_entity_type as value FROM cr_entity_relation WHERE source_entity_type = ? AND organization_id = ?`,
17
+ [entityType, loggedInUser.organization_id],
18
+ );
19
+
20
+ return relations;
21
+ }
22
+ }
@@ -61,14 +61,14 @@ export class ResolverService {
61
61
  } else {
62
62
  if (tableName == 'cr_organization') {
63
63
  const [item] = await this.dataSource.query(
64
- `SELECT * FROM ${tableName} WHERE code = ?`,
64
+ `SELECT * FROM ${tableName} WHERE id = ?`,
65
65
  [codeValue],
66
66
  );
67
67
  resolvedEntityData[field] =
68
68
  item?.[attr.data_source_attribute] ?? codeValue;
69
69
  } else {
70
70
  const [item] = await this.dataSource.query(
71
- `SELECT * FROM ${tableName} WHERE code = ? AND organization_id = ?`,
71
+ `SELECT * FROM ${tableName} WHERE id = ? AND organization_id = ?`,
72
72
  [codeValue, loggedInUser.organization_id],
73
73
  );
74
74
  resolvedEntityData[field] =