rez_core 4.0.242 → 4.0.243

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.242",
3
+ "version": "4.0.243",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -12,7 +12,7 @@ export class EntityJSONService extends EntityServiceImpl {
12
12
  constructor(
13
13
  private readonly dataSource: DataSource,
14
14
  private readonly filterService: FilterService,
15
- private readonly loggerService: LoggingService, // <-- inject logging service
15
+ private readonly loggerService: LoggingService,
16
16
  ) {
17
17
  super();
18
18
  }
@@ -23,27 +23,18 @@ export class EntityJSONService extends EntityServiceImpl {
23
23
  flag?: 'flat_json' | 'dropdown' | 'all',
24
24
  ) {
25
25
  const orgId = loggedInUser.organization_id;
26
- await this.loggerService.log(
27
- 'info',
28
- 'EntityJSONService',
29
- 'getAttributeForFlatJSON',
30
- `Loading attributes for entity: ${entityType}, org: ${orgId}`,
31
- );
26
+
27
+ await this.loggerService.log('info', 'EntityJSONService', 'getAttributeForFlatJSON', `Loading attributes for entity: ${entityType}, org: ${orgId}`);
32
28
 
33
29
  const mainAttributes = await this.dataSource
34
30
  .getRepository(AttributeMaster)
35
31
  .createQueryBuilder('attr')
36
- .select(['attr.id', 'attr.name', 'attr.flat_json_key','attr.attribute_key'])
32
+ .select(['attr.id', 'attr.name', 'attr.flat_json_key', 'attr.attribute_key'])
37
33
  .where('attr.mapped_entity_type = :entityType', { entityType })
38
34
  .andWhere('attr.organization_id = :orgId', { orgId })
39
35
  .getMany();
40
36
 
41
- await this.loggerService.log(
42
- 'debug',
43
- 'EntityJSONService',
44
- 'getAttributeForFlatJSON',
45
- `Loaded ${mainAttributes.length} main attributes`,
46
- );
37
+ await this.loggerService.log('debug', 'EntityJSONService', 'getAttributeForFlatJSON', `Loaded ${mainAttributes.length} main attributes`);
47
38
 
48
39
  const relatedEntityTypes = await this.dataSource
49
40
  .getRepository(EntityRelation)
@@ -51,44 +42,24 @@ export class EntityJSONService extends EntityServiceImpl {
51
42
  .select(['rel.target_entity_type'])
52
43
  .where('rel.source_entity_type = :entityType', { entityType })
53
44
  .andWhere('rel.organization_id = :orgId', { orgId })
54
- .andWhere('rel.relation_type = :relationType', {
55
- relationType: 'ONE_TO_ONE',
56
- })
45
+ .andWhere('rel.relation_type = :relationType', { relationType: 'ONE_TO_ONE' })
57
46
  .getRawMany();
58
47
 
59
- const relatedTypesList = relatedEntityTypes.map(
60
- (x) => x.rel_target_entity_type,
61
- );
62
- await this.loggerService.log(
63
- 'debug',
64
- 'EntityJSONService',
65
- 'getAttributeForFlatJSON',
66
- `Found ${relatedTypesList.length} ONE-TO-ONE related entity types`,
67
- );
48
+ const relatedTypesList = relatedEntityTypes.map(x => x.rel_target_entity_type);
49
+
50
+ await this.loggerService.log('debug', 'EntityJSONService', 'getAttributeForFlatJSON', `Found ${relatedTypesList.length} ONE-TO-ONE related entity types`);
68
51
 
69
52
  const relatedAttributes = relatedTypesList.length
70
53
  ? await this.dataSource
71
54
  .getRepository(AttributeMaster)
72
55
  .createQueryBuilder('attr')
73
- .select([
74
- 'attr.id',
75
- 'attr.name',
76
- 'attr.flat_json_key',
77
- 'attr.mapped_entity_type',
78
- 'attr.attribute_key',
79
- ])
80
- .where('attr.mapped_entity_type IN (:...types)', {
81
- types: relatedTypesList,
82
- })
56
+ .select(['attr.id', 'attr.name', 'attr.flat_json_key', 'attr.mapped_entity_type', 'attr.attribute_key'])
57
+ .where('attr.mapped_entity_type IN (:...types)', { types: relatedTypesList })
83
58
  .andWhere('attr.organization_id = :orgId', { orgId })
84
59
  .getMany()
85
60
  : [];
86
- await this.loggerService.log(
87
- 'debug',
88
- 'EntityJSONService',
89
- 'getAttributeForFlatJSON',
90
- `Loaded ${relatedAttributes.length} related attributes`,
91
- );
61
+
62
+ await this.loggerService.log('debug', 'EntityJSONService', 'getAttributeForFlatJSON', `Loaded ${relatedAttributes.length} related attributes`);
92
63
 
93
64
  const linkedAttributes = await this.dataSource
94
65
  .getRepository(LinkedAttributes)
@@ -100,110 +71,66 @@ export class EntityJSONService extends EntityServiceImpl {
100
71
  )
101
72
  .select([
102
73
  'fla.applicable_entity_type AS applicable_entity_type',
103
- 'fla.applicable_attribute_key AS applicable_attribute_key', // SOURCE KEY (middle_name)
104
- 'fla.attribute_key AS target_attribute_key', // TARGET KEY (father_middle_name)
74
+ 'fla.applicable_attribute_key AS applicable_attribute_key',
75
+ 'fla.attribute_key AS target_attribute_key',
105
76
  'fla.saved_filter_code AS saved_filter_code',
106
77
  'attr.name AS name',
107
- 'attr.id AS id'
108
- ])
78
+ 'attr.id AS id',
79
+ ])
109
80
  .where('attr.organization_id = :orgId', { orgId })
110
81
  .getRawMany();
111
- await this.loggerService.log(
112
- 'debug',
113
- 'EntityJSONService',
114
- 'getAttributeForFlatJSON',
115
- `Loaded ${linkedAttributes.length} linked attributes`,
116
- );
82
+
83
+ await this.loggerService.log('debug', 'EntityJSONService', 'getAttributeForFlatJSON', `Loaded ${linkedAttributes.length} linked attributes`);
117
84
 
118
85
  if (flag === 'flat_json' || flag === 'all') {
119
86
  const result: Record<string, null> = {};
120
- mainAttributes.forEach((attr) => {
121
- if (attr.flat_json_key) result[attr.flat_json_key] = null;
122
- });
123
- relatedAttributes.forEach((attr) => {
124
- if (attr.flat_json_key) result[attr.flat_json_key] = null;
125
- });
126
- linkedAttributes.forEach((link) => {
127
- // Use target_attribute_key instead of applicable_attribute_key
128
- if (link.target_attribute_key) result[link.target_attribute_key] = null;
129
- });
130
-
131
- if(flag === 'all') {
132
- return {
133
- flat_json: result,
134
- attributes: { mainAttributes, relatedAttributes, linkedAttributes }
135
- };
87
+ mainAttributes.forEach(attr => { if (attr.flat_json_key) result[attr.flat_json_key] = null; });
88
+ relatedAttributes.forEach(attr => { if (attr.flat_json_key) result[attr.flat_json_key] = null; });
89
+ linkedAttributes.forEach(link => { if (link.target_attribute_key) result[link.target_attribute_key] = null; });
90
+
91
+ if (flag === 'all') {
92
+ return { flat_json: result, attributes: { mainAttributes, relatedAttributes, linkedAttributes } };
136
93
  }
137
-
94
+
138
95
  return result;
139
96
  }
140
-
141
97
 
142
98
  const dropdown: any[] = [];
143
- dropdown.push(
144
- ...mainAttributes.map((a) => ({ label: a.name, value: a.flat_json_key })),
145
- );
146
- dropdown.push(
147
- ...relatedAttributes.map((a) => ({
148
- label: a.name,
149
- value: a.flat_json_key,
150
- })),
151
- );
99
+ dropdown.push(...mainAttributes.map(a => ({ label: a.name, value: a.flat_json_key })));
100
+ dropdown.push(...relatedAttributes.map(a => ({ label: a.name, value: a.flat_json_key })));
152
101
  if (linkedAttributes.length > 0) {
153
- dropdown.push({
154
- ...linkedAttributes.map((a) => ({
155
- label: a.name,
156
- value: a.attribute_key,
157
- })),
158
- });
102
+ dropdown.push(...linkedAttributes.map(a => ({ label: a.name, value: a.attribute_key })));
159
103
  }
104
+
160
105
  return dropdown;
161
106
  }
162
107
 
163
108
  async updateEntityJSON(entityType: string, entityId: number, loggedInUser) {
164
- await this.loggerService.log(
165
- 'info',
166
- 'EntityJSONService',
167
- 'updateEntityJSON',
168
- `Building flat JSON for entity: ${entityType}#${entityId}`,
169
- );
170
-
171
- // 1. Load flat JSON template + attributes
109
+ await this.loggerService.log('info', 'EntityJSONService', 'updateEntityJSON', `Building flat JSON for entity: ${entityType}#${entityId}`);
110
+
172
111
  const response = await this.getAttributeForFlatJSON(entityType, loggedInUser, 'all');
173
-
174
- // ---- Structural validation ----
112
+
175
113
  if (!response || !('flat_json' in response) || !('attributes' in response) || !response.attributes) {
176
- await this.loggerService.log(
177
- 'error',
178
- 'EntityJSONService',
179
- 'updateEntityJSON',
180
- `getAttributeForFlatJSON() did not return expected structure`,
181
- );
114
+ await this.loggerService.log('error', 'EntityJSONService', 'updateEntityJSON', `getAttributeForFlatJSON() did not return expected structure`);
182
115
  return null;
183
116
  }
184
-
117
+
185
118
  const { flat_json: flatJson, attributes } = response;
186
119
  if (!flatJson) return null;
187
-
188
- // ---- Strong safety fix ----
120
+
189
121
  const safeAttributes = {
190
122
  mainAttributes: attributes.mainAttributes || [],
191
123
  relatedAttributes: attributes.relatedAttributes || [],
192
124
  linkedAttributes: attributes.linkedAttributes || [],
193
125
  };
194
-
195
- // 2. Build attribute_key → flat_json_key map
126
+
196
127
  const attrMap: Record<string, string> = {};
197
128
  const allAttrs = [...safeAttributes.mainAttributes, ...safeAttributes.relatedAttributes];
198
- allAttrs.forEach(attr => {
199
- if (attr.attribute_key) attrMap[attr.attribute_key] = attr.flat_json_key || attr.attribute_key;
200
- });
201
-
202
- // 3. Merge main entity data
129
+ allAttrs.forEach(attr => { if (attr.attribute_key) attrMap[attr.attribute_key] = attr.flat_json_key || attr.attribute_key; });
130
+
203
131
  const mainData = await this.getResolvedEntityData(entityType, entityId, loggedInUser);
204
132
  this.mergeEntityDataIntoFlatJson(flatJson, mainData, attrMap);
205
-
206
- // 4. Merge ONE-TO-ONE related entities
133
+
207
134
  const relations = await this.dataSource
208
135
  .getRepository('frm_entity_relation_data')
209
136
  .createQueryBuilder('erd')
@@ -212,77 +139,60 @@ export class EntityJSONService extends EntityServiceImpl {
212
139
  .andWhere('erd.source_entity_id = :entityId', { entityId })
213
140
  .andWhere('erd.relation_type = :rt', { rt: 'ONE_TO_ONE' })
214
141
  .getRawMany();
215
-
142
+
216
143
  for (const rel of relations) {
217
144
  const relatedData = await this.getResolvedEntityData(rel.target_entity_type, rel.target_entity_id, loggedInUser);
218
145
  this.mergeEntityDataIntoFlatJson(flatJson, relatedData, attrMap);
219
146
  }
220
-
221
- // 5. Merge linked attributes using saved filters
222
- // 5. Merge linked attributes using saved filters
223
- for (const linkAttr of safeAttributes.linkedAttributes) {
224
-
225
-
226
- const childEntityType = linkAttr.applicable_entity_type; // was undefined
227
- const sourceKey = linkAttr.applicable_attribute_key; // already correct
228
- const targetKey = linkAttr.target_attribute_key; // was undefined
229
- // final JSON key = father_middle_name
230
-
231
- if (!childEntityType || !sourceKey || !targetKey) continue;
232
-
233
- // value must be taken from applicable_attribute_key
234
- const mappingValue = mainData?.[sourceKey] ?? null;
235
-
236
- const value = await this.applyLinkedFilterUsingSavedFilter(
237
- childEntityType,
238
- linkAttr.saved_filter_code,
239
- sourceKey,
240
- mappingValue,
241
- targetKey, // IMPORTANT → write to father_middle_name
242
- loggedInUser,
243
- entityId
244
- );
245
147
 
246
- if (value !== null && value !== undefined) {
247
- const flatKey = targetKey; // do NOT use childAttributeKey
248
- flatJson[flatKey] = value;
249
- }
250
- }
148
+ for (const linkAttr of safeAttributes.linkedAttributes) {
149
+ const childEntityType = linkAttr.applicable_entity_type;
150
+ const sourceKey = linkAttr.applicable_attribute_key;
151
+ const targetKey = linkAttr.target_attribute_key;
152
+
153
+ if (!childEntityType || !sourceKey || !targetKey) continue;
154
+
155
+ const mappingValue = mainData?.[sourceKey] ?? null;
251
156
 
157
+ const value = await this.applyLinkedFilterUsingSavedFilter(
158
+ childEntityType,
159
+ linkAttr.saved_filter_code,
160
+ sourceKey,
161
+ mappingValue,
162
+ targetKey,
163
+ loggedInUser,
164
+ entityId,
165
+ );
252
166
 
253
- // 6. Save JSON
167
+ if (value !== null && value !== undefined) {
168
+ flatJson[targetKey] = value;
169
+ }
170
+ }
171
+
172
+ await this.loggerService.log('info', 'EntityJSONService', 'updateEntityJSON', `Saving flat JSON for entity: ${entityType}#${entityId}`);
254
173
  await this.dataSource.query(
255
174
  `INSERT INTO frm_entity_json (entity_type, entity_id, json_data, created_by)
256
- VALUES (?, ?, ?, ?)
257
- ON DUPLICATE KEY UPDATE json_data = VALUES(json_data), updated_by = VALUES(created_by)`,
175
+ VALUES (?, ?, ?, ?)
176
+ ON DUPLICATE KEY UPDATE json_data = VALUES(json_data), updated_by = VALUES(created_by)`,
258
177
  [entityType, entityId, JSON.stringify(flatJson), loggedInUser.id],
259
178
  );
260
-
179
+
261
180
  return flatJson;
262
181
  }
263
-
264
-
265
- // Helper: Merge entity data using attribute_key → flat_json_key mapping
266
- private mergeEntityDataIntoFlatJson(
267
- flatJson: Record<string, any>,
268
- entityData: any | any[], // accept both object or array
269
- attrMap: Record<string, string>,
270
- ) {
182
+
183
+ private mergeEntityDataIntoFlatJson(flatJson: Record<string, any>, entityData: any | any[], attrMap: Record<string, string>) {
271
184
  const records = Array.isArray(entityData) ? entityData : [entityData];
272
-
185
+
273
186
  for (const record of records) {
274
187
  if (!record || typeof record !== 'object') continue;
275
-
276
188
  for (const key of Object.keys(record)) {
277
- const flatKey = attrMap[key] || key; // map to flat_json_key if exists
189
+ const flatKey = attrMap[key] || key;
278
190
  if (flatJson.hasOwnProperty(flatKey)) {
279
191
  flatJson[flatKey] = record[key];
280
192
  }
281
193
  }
282
194
  }
283
195
  }
284
-
285
-
286
196
 
287
197
  private async applyLinkedFilterUsingSavedFilter(
288
198
  childEntityType: string,
@@ -293,11 +203,7 @@ const targetKey = linkAttr.target_attribute_key; // was undefined
293
203
  loggedInUser,
294
204
  entity_id
295
205
  ) {
296
- if (
297
- !savedFilterCode &&
298
- (mappingValue === null || mappingValue === undefined)
299
- )
300
- return null;
206
+ if (!savedFilterCode && (mappingValue === null || mappingValue === undefined)) return null;
301
207
 
302
208
  const dto: any = {
303
209
  entity_type: childEntityType,
@@ -307,31 +213,18 @@ const targetKey = linkAttr.target_attribute_key; // was undefined
307
213
  size: 1,
308
214
  };
309
215
 
310
- if (
311
- mappingValue !== null &&
312
- mappingValue !== undefined &&
313
- mappingValue !== ''
314
- ) {
216
+ if (mappingValue !== null && mappingValue !== undefined && mappingValue !== '') {
315
217
  dto.quickFilter = [
316
- {
317
- filter_attribute: childFilterAttribute,
318
- filter_operator: 'equal',
319
- filter_value: mappingValue,
320
- },
218
+ { filter_attribute: childFilterAttribute, filter_operator: 'equal', filter_value: mappingValue },
321
219
  ];
322
220
  }
323
221
 
324
222
  dto.quickFilter = [
325
- {
326
- filter_attribute: 'parent_id',
327
- filter_operator: 'equal',
328
- filter_value: [entity_id],
329
- },
223
+ { filter_attribute: 'parent_id', filter_operator: 'equal', filter_value: [entity_id] },
330
224
  ];
331
225
 
332
226
  const result = await this.filterService.applyFilter(dto);
333
227
  const rows = result?.data?.entity_list || [];
334
228
  return rows.length ? (rows[0][childFilterAttribute] ?? null) : null;
335
-
336
229
  }
337
230
  }