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