rez_core 4.0.188 → 4.0.190

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": "4.0.188",
3
+ "version": "4.0.190",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -3,9 +3,11 @@ import { EntityModule } from '../meta/entity.module';
3
3
  import { TypeOrmModule } from '@nestjs/typeorm';
4
4
  import { EntityJSONService } from './service/entity_json.service';
5
5
  import { EntityJSONController } from './controller/entity_json.controller';
6
+ import { FilterModule } from '../filter/filter.module';
7
+ import { UtilsModule } from 'src/utils/utils.module';
6
8
 
7
9
  @Module({
8
- imports: [EntityModule, TypeOrmModule.forFeature([])],
10
+ imports: [EntityModule, TypeOrmModule.forFeature([]),FilterModule,UtilsModule],
9
11
  controllers: [EntityJSONController],
10
12
  providers: [EntityJSONService],
11
13
  exports: [],
@@ -1,12 +1,18 @@
1
1
  import { Injectable } from '@nestjs/common';
2
+ import { FilterService } from 'src/module/filter/service/filter.service';
2
3
  import { AttributeMaster } from 'src/module/meta/entity/attribute-master.entity';
3
4
  import { EntityRelation } from 'src/module/meta/entity/entity-relation.entity';
4
5
  import { EntityServiceImpl } from 'src/module/meta/service/entity-service-impl.service';
6
+ import { LoggingService } from 'src/utils/service/loggingUtil.service';
5
7
  import { DataSource } from 'typeorm';
6
8
 
7
9
  @Injectable()
8
10
  export class EntityJSONService extends EntityServiceImpl {
9
- constructor(private readonly dataSource: DataSource) {
11
+ constructor(
12
+ private readonly dataSource: DataSource,
13
+ private readonly filterService: FilterService,
14
+ private readonly loggerService: LoggingService, // <-- inject logging service
15
+ ) {
10
16
  super();
11
17
  }
12
18
 
@@ -16,10 +22,13 @@ export class EntityJSONService extends EntityServiceImpl {
16
22
  flag?: 'flat_json' | 'dropdown',
17
23
  ) {
18
24
  const orgId = loggedInUser.organization_id;
25
+ await this.loggerService.log(
26
+ 'info',
27
+ 'EntityJSONService',
28
+ 'getAttributeForFlatJSON',
29
+ `Loading attributes for entity: ${entityType}, org: ${orgId}`,
30
+ );
19
31
 
20
- // --------------------------------------------
21
- // 1. Load Main Entity Attributes
22
- // --------------------------------------------
23
32
  const mainAttributes = await this.dataSource
24
33
  .getRepository(AttributeMaster)
25
34
  .createQueryBuilder('attr')
@@ -28,47 +37,46 @@ export class EntityJSONService extends EntityServiceImpl {
28
37
  .andWhere('attr.organization_id = :orgId', { orgId })
29
38
  .getMany();
30
39
 
31
- // --------------------------------------------
32
- // 2. Load Related Entity Types Once
33
- // --------------------------------------------
40
+ await this.loggerService.log(
41
+ 'debug',
42
+ 'EntityJSONService',
43
+ 'getAttributeForFlatJSON',
44
+ `Loaded ${mainAttributes.length} main attributes`,
45
+ );
46
+
34
47
  const relatedEntityTypes = await this.dataSource
35
48
  .getRepository(EntityRelation)
36
49
  .createQueryBuilder('rel')
37
50
  .select(['rel.target_entity_type'])
38
51
  .where('rel.source_entity_type = :entityType', { entityType })
39
52
  .andWhere('rel.organization_id = :orgId', { orgId })
40
- .andWhere('rel.relation_type = :relationType', {
41
- relationType: 'ONE_TO_ONE',
42
- })
53
+ .andWhere('rel.relation_type = :relationType', { relationType: 'ONE_TO_ONE' })
43
54
  .getRawMany();
44
55
 
45
- const relatedTypesList = relatedEntityTypes.map(
46
- (x) => x.rel_target_entity_type,
56
+ const relatedTypesList = relatedEntityTypes.map(x => x.rel_target_entity_type);
57
+ await this.loggerService.log(
58
+ 'debug',
59
+ 'EntityJSONService',
60
+ 'getAttributeForFlatJSON',
61
+ `Found ${relatedTypesList.length} ONE-TO-ONE related entity types`,
47
62
  );
48
63
 
49
- // --------------------------------------------
50
- // 3. Fetch All Related Attributes
51
- // --------------------------------------------
52
64
  const relatedAttributes = relatedTypesList.length
53
65
  ? await this.dataSource
54
66
  .getRepository(AttributeMaster)
55
67
  .createQueryBuilder('attr')
56
- .select([
57
- 'attr.id',
58
- 'attr.name',
59
- 'attr.attribute_key',
60
- 'attr.mapped_entity_type',
61
- ])
62
- .where('attr.mapped_entity_type IN (:...types)', {
63
- types: relatedTypesList,
64
- })
68
+ .select(['attr.id', 'attr.name', 'attr.attribute_key', 'attr.mapped_entity_type'])
69
+ .where('attr.mapped_entity_type IN (:...types)', { types: relatedTypesList })
65
70
  .andWhere('attr.organization_id = :orgId', { orgId })
66
71
  .getMany()
67
72
  : [];
73
+ await this.loggerService.log(
74
+ 'debug',
75
+ 'EntityJSONService',
76
+ 'getAttributeForFlatJSON',
77
+ `Loaded ${relatedAttributes.length} related attributes`,
78
+ );
68
79
 
69
- // --------------------------------------------
70
- // 4. Fetch Linked Attributes
71
- // --------------------------------------------
72
80
  const linkedAttributes = await this.dataSource
73
81
  .getRepository('frm_linked_attribute')
74
82
  .createQueryBuilder('fla')
@@ -85,78 +93,173 @@ export class EntityJSONService extends EntityServiceImpl {
85
93
  ])
86
94
  .where('attr.organization_id = :orgId', { orgId })
87
95
  .getRawMany();
88
-
89
- // ------------------------------------------------------------------
90
- // --------------- RETURN FORMAT BASED ON FLAG ------------------
91
- // ------------------------------------------------------------------
92
-
93
- // ============================================================
94
- // MODE 1: flat_json -> return objects grouped by entity_type
95
- // ============================================================
96
+ await this.loggerService.log(
97
+ 'debug',
98
+ 'EntityJSONService',
99
+ 'getAttributeForFlatJSON',
100
+ `Loaded ${linkedAttributes.length} linked attributes`,
101
+ );
96
102
 
97
103
  if (flag === 'flat_json') {
98
104
  const result: Record<string, null> = {};
105
+ mainAttributes.forEach(attr => { if (attr.attribute_key) result[attr.attribute_key] = null; });
106
+ relatedAttributes.forEach(attr => { if (attr.attribute_key) result[attr.attribute_key] = null; });
107
+ linkedAttributes.forEach(link => { if (link.applicable_attribute_key) result[link.applicable_attribute_key] = null; });
108
+ return result;
109
+ }
99
110
 
100
- // MAIN ENTITY ATTRIBUTES
101
- mainAttributes.forEach((attr) => {
102
- if (attr.attribute_key) {
103
- result[attr.attribute_key] = null;
104
- }
105
- });
106
-
107
- // RELATED ENTITY TYPES
108
- for (const type of relatedTypesList) {
109
- const attrs = relatedAttributes.filter(
110
- (a) => a.mapped_entity_type === type,
111
- );
112
-
113
- attrs.forEach((attr) => {
114
- if (attr.attribute_key) {
115
- result[attr.attribute_key] = null;
116
- }
117
- });
118
- }
111
+ const dropdown: any[] = [];
112
+ dropdown.push(...mainAttributes.map(a => ({ label: a.name, value: a.attribute_key })));
113
+ dropdown.push(...relatedAttributes.map(a => ({ label: a.name, value: a.attribute_key })));
114
+ dropdown.push({
115
+ linked_attributes: linkedAttributes.map(a => ({ label: a.attr_name, value: a.attr_attribute_key })),
116
+ });
117
+ return dropdown;
118
+ }
119
119
 
120
- // LINKED ATTRIBUTES
121
- linkedAttributes.forEach((link) => {
122
- if (link.applicable_attribute_key) {
123
- result[link.applicable_attribute_key] = null;
124
- }
125
- });
120
+ async updateEntityJSON(
121
+ entityType: string,
122
+ entityId: number,
123
+ loggedInUser,
124
+ ) {
125
+ await this.loggerService.log(
126
+ 'info',
127
+ 'EntityJSONService',
128
+ 'updateEntityJSON',
129
+ `Building flat JSON for entity: ${entityType}#${entityId}`,
130
+ );
126
131
 
127
- return result;
132
+ const flatJson = await this.getAttributeForFlatJSON(entityType, loggedInUser, 'flat_json');
133
+ if (!flatJson) {
134
+ await this.loggerService.log(
135
+ 'error',
136
+ 'EntityJSONService',
137
+ 'updateEntityJSON',
138
+ `Flat JSON template not found for entity: ${entityType}`,
139
+ );
140
+ throw new Error(`Flat JSON template not found for ${entityType}`);
128
141
  }
129
142
 
130
- // ============================================================
131
- // MODE 2: dropdown -> return label/value format
132
- // ============================================================
143
+ const mainData = await this.getResolvedEntityData(entityType, entityId, loggedInUser);
144
+ this.mergeIntoFlatJson(flatJson, mainData);
145
+ await this.loggerService.log(
146
+ 'debug',
147
+ 'EntityJSONService',
148
+ 'updateEntityJSON',
149
+ 'Merged main entity data into flat JSON',
150
+ );
151
+
152
+ const relations = await this.dataSource
153
+ .getRepository('frm_entity_relation_data')
154
+ .createQueryBuilder('erd')
155
+ .select(['erd.target_entity_id AS target_entity_id', 'erd.target_entity_type AS target_entity_type'])
156
+ .where('erd.source_entity_type = :entityType', { entityType })
157
+ .andWhere('erd.source_entity_id = :entityId', { entityId })
158
+ .andWhere('erd.relation_type = :rt', { rt: 'ONE_TO_ONE' })
159
+ .getRawMany();
160
+ await this.loggerService.log(
161
+ 'debug',
162
+ 'EntityJSONService',
163
+ 'updateEntityJSON',
164
+ `Found ${relations.length} ONE-TO-ONE relations`,
165
+ );
133
166
 
134
- const dropdown: any[] = [];
167
+ for (const rel of relations) {
168
+ const related = await this.getResolvedEntityData(rel.target_entity_type, rel.target_entity_id, loggedInUser);
169
+ this.mergeIntoFlatJson(flatJson, related);
170
+ await this.loggerService.log(
171
+ 'debug',
172
+ 'EntityJSONService',
173
+ 'updateEntityJSON',
174
+ `Merged related entity ${rel.target_entity_type}#${rel.target_entity_id}`,
175
+ );
176
+ }
135
177
 
136
- // main entity
137
- dropdown.push(
138
- ...mainAttributes.map((a) => ({
139
- label: a.name,
140
- value: a.attribute_key,
141
- })),
178
+ const linkedAttrs = await this.dataSource
179
+ .getRepository('frm_linked_attributes_table')
180
+ .createQueryBuilder('la')
181
+ .where('la.entity_type = :entityType', { entityType })
182
+ .getMany();
183
+ await this.loggerService.log(
184
+ 'debug',
185
+ 'EntityJSONService',
186
+ 'updateEntityJSON',
187
+ `Found ${linkedAttrs.length} linked attributes`,
142
188
  );
143
189
 
144
- // related entities
145
- dropdown.push(
146
- ...relatedAttributes.map((a) => ({
147
- label: a.name,
148
- value: a.attribute_key,
149
- })),
190
+ for (const la of linkedAttrs) {
191
+ const mappingValue = flatJson[la.mapping_attribute];
192
+ const result = await this.applyLinkedFilterUsingSavedFilter(
193
+ la.child_entity_type,
194
+ la.saved_filter_code,
195
+ la.filter_attribute,
196
+ mappingValue,
197
+ la.target_attribute,
198
+ loggedInUser
199
+ );
200
+ flatJson[la.target_attribute] = result;
201
+ await this.loggerService.log(
202
+ 'debug',
203
+ 'EntityJSONService',
204
+ 'updateEntityJSON',
205
+ `Linked attribute ${la.target_attribute} set from child entity ${la.child_entity_type}`,
206
+ );
207
+ }
208
+
209
+ await this.dataSource.query(
210
+ `INSERT INTO frm_entity_json (entity_type, entity_id, json_data, created_by)
211
+ VALUES (?, ?, ?, ?)
212
+ ON DUPLICATE KEY UPDATE json_data = VALUES(json_data), updated_by = VALUES(created_by)`,
213
+ [entityType, entityId, JSON.stringify(flatJson), loggedInUser.id]
214
+ );
215
+ await this.loggerService.log(
216
+ 'info',
217
+ 'EntityJSONService',
218
+ 'updateEntityJSON',
219
+ `Flat JSON saved for entity: ${entityType}#${entityId}`,
150
220
  );
151
221
 
152
- // linked attributes
153
- dropdown.push({
154
- linked_attributes: linkedAttributes.map((a) => ({
155
- label: a.attr_name,
156
- value: a.attr_attribute_key,
157
- })),
158
- });
222
+ return flatJson;
223
+ }
159
224
 
160
- return dropdown;
225
+ private mergeIntoFlatJson(flatJson, entityData) {
226
+ for (const key of Object.keys(entityData)) {
227
+ if (flatJson.hasOwnProperty(key)) {
228
+ flatJson[key] = entityData[key];
229
+ }
230
+ }
231
+ }
232
+
233
+ private async applyLinkedFilterUsingSavedFilter(
234
+ childEntityType: string,
235
+ savedFilterCode: string,
236
+ childFilterAttribute: string,
237
+ mappingValue: any,
238
+ targetAttribute: string,
239
+ loggedInUser,
240
+ ) {
241
+ if (!savedFilterCode && (mappingValue === null || mappingValue === undefined)) return null;
242
+
243
+ const dto: any = {
244
+ entity_type: childEntityType,
245
+ loggedInUser,
246
+ savedFilterCode,
247
+ page: 1,
248
+ size: 1,
249
+ };
250
+
251
+ if (mappingValue !== null && mappingValue !== undefined && mappingValue !== '') {
252
+ dto.quickFilter = [
253
+ {
254
+ filter_attribute: childFilterAttribute,
255
+ filter_operator: 'equal',
256
+ filter_value: mappingValue,
257
+ }
258
+ ];
259
+ }
260
+
261
+ const result = await this.filterService.applyFilter(dto);
262
+ const rows = result?.data?.entity_list || [];
263
+ return rows.length ? rows[0][targetAttribute] ?? null : null;
161
264
  }
162
265
  }
@@ -24,8 +24,8 @@ import { WorkflowScheduleModule } from '../workflow-schedule/workflow-schedule.m
24
24
  ]),
25
25
  FilterModule,
26
26
  forwardRef(() => EntityModule),
27
- DiscoveryModule,
28
- WorkflowScheduleModule
27
+ forwardRef(() => WorkflowScheduleModule),
28
+ DiscoveryModule, // 👈 enables provider scanning
29
29
  ],
30
30
  providers: [
31
31
  WorkflowAutomationEngineService,