rez_core 3.1.87 → 3.1.89

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": "3.1.87",
3
+ "version": "3.1.89",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -87,12 +87,12 @@ export class IntegrationService {
87
87
  private readonly gmailApiStrategy: GmailApiStrategy,
88
88
  private readonly sendGridApiStrategy: SendGridApiStrategy,
89
89
  private readonly configService: ConfigService,
90
- @Inject('FieldMapperService') private readonly fieldMapperService: FieldMapperService,
90
+ @Inject('FieldMapperService')
91
+ private readonly fieldMapperService: FieldMapperService,
91
92
  private readonly entityService: EntityServiceImpl,
92
93
  @Inject(forwardRef(() => IntegrationQueueService))
93
94
  private readonly queueService?: IntegrationQueueService,
94
- ) {
95
- }
95
+ ) {}
96
96
 
97
97
  private deriveServiceType(
98
98
  integration_type: string,
@@ -104,15 +104,15 @@ export class IntegrationService {
104
104
  }
105
105
 
106
106
  async sendMessage({
107
- levelId,
108
- levelType,
109
- app_code,
110
- to,
111
- message,
112
- mode,
113
- priority = 1,
114
- user_id,
115
- }: SendMessageDto): Promise<IntegrationResult> {
107
+ levelId,
108
+ levelType,
109
+ app_code,
110
+ to,
111
+ message,
112
+ mode,
113
+ priority = 1,
114
+ user_id,
115
+ }: SendMessageDto): Promise<IntegrationResult> {
116
116
  try {
117
117
  // Get active communication configs for the level
118
118
  const configs = await this.getActiveConfigs(
@@ -192,7 +192,9 @@ export class IntegrationService {
192
192
  .where('config.level_id = :levelId', { levelId })
193
193
  .andWhere('config.level_type = :levelType', { levelType })
194
194
  .andWhere('config.app_code = :app_code', { app_code })
195
- .andWhere('config.integration_type = :integration_type', { integration_type })
195
+ .andWhere('config.integration_type = :integration_type', {
196
+ integration_type,
197
+ })
196
198
  .andWhere('config.status = 1')
197
199
  .orderBy('config.is_default', 'DESC')
198
200
  .addOrderBy('config.priority', 'ASC')
@@ -703,7 +705,7 @@ export class IntegrationService {
703
705
  if (configJson?.[field]) {
704
706
  safeConfig[
705
707
  `has${field.charAt(0).toUpperCase() + field.slice(1)}`
706
- ] = true;
708
+ ] = true;
707
709
  }
708
710
  });
709
711
 
@@ -1017,7 +1019,7 @@ export class IntegrationService {
1017
1019
  ...enhancedConfig,
1018
1020
  templateId: externalTemplateId,
1019
1021
  variables,
1020
- richText
1022
+ richText,
1021
1023
  };
1022
1024
 
1023
1025
  // Handle user integration if user_id provided
@@ -1033,11 +1035,7 @@ export class IntegrationService {
1033
1035
  }
1034
1036
  }
1035
1037
 
1036
- const result = await strategy.sendMessage(
1037
- to,
1038
- message,
1039
- finalConfig,
1040
- );
1038
+ const result = await strategy.sendMessage(to, message, finalConfig);
1041
1039
 
1042
1040
  if (result.success) {
1043
1041
  this.logger.log(
@@ -1257,8 +1255,16 @@ export class IntegrationService {
1257
1255
  templateId: number,
1258
1256
  entity_type: any,
1259
1257
  entity_id: any,
1260
- ): Promise<{ variables?: Record<string, any>; externalTemplateId?: string; rich_text?: string }> {
1261
- const commTemplate: any = await this.entityService.getEntityData(COMM_TEMPLATE, templateId, {} as any);
1258
+ ): Promise<{
1259
+ variables?: Record<string, any>;
1260
+ externalTemplateId?: string;
1261
+ rich_text?: string;
1262
+ }> {
1263
+ const commTemplate: any = await this.entityService.getEntityData(
1264
+ COMM_TEMPLATE,
1265
+ templateId,
1266
+ {} as any,
1267
+ );
1262
1268
  if (!commTemplate) {
1263
1269
  return {
1264
1270
  variables: {},
@@ -1270,6 +1276,7 @@ export class IntegrationService {
1270
1276
  if (commTemplate.mapper_id) {
1271
1277
  variables = await this.fieldMapperService.resolveData(
1272
1278
  commTemplate.mapper_id,
1279
+ 'LOOKUP',
1273
1280
  entity_type,
1274
1281
  entity_id,
1275
1282
  {} as any,
@@ -1973,10 +1980,10 @@ export class IntegrationService {
1973
1980
 
1974
1981
  async getIntegrationConfigById(hubId: number): Promise<
1975
1982
  | (IntegrationConfig & {
1976
- config: IntegrationConfig;
1977
- linkedSource?: string;
1978
- configDetails?: any;
1979
- })
1983
+ config: IntegrationConfig;
1984
+ linkedSource?: string;
1985
+ configDetails?: any;
1986
+ })
1980
1987
  | null
1981
1988
  > {
1982
1989
  try {
@@ -2468,7 +2475,8 @@ export class IntegrationService {
2468
2475
  if (!userIntegration) {
2469
2476
  return {
2470
2477
  success: false,
2471
- error: 'User integration mapping not found. Please configure agent details.',
2478
+ error:
2479
+ 'User integration mapping not found. Please configure agent details.',
2472
2480
  };
2473
2481
  }
2474
2482
 
@@ -186,7 +186,7 @@ export class SendGridApiStrategy implements IntegrationStrategy {
186
186
  }
187
187
  }
188
188
 
189
- async getTemplates(apiKey: string): Promise<{
189
+ async getTemplates(config: any): Promise<{
190
190
  success: boolean;
191
191
  data?: Array<{
192
192
  label: string;
@@ -195,7 +195,7 @@ export class SendGridApiStrategy implements IntegrationStrategy {
195
195
  error?: string;
196
196
  }> {
197
197
  try {
198
- if (!apiKey) {
198
+ if (!config.apiKey) {
199
199
  throw new Error('SendGrid API key is required');
200
200
  }
201
201
 
@@ -203,7 +203,7 @@ export class SendGridApiStrategy implements IntegrationStrategy {
203
203
  'https://api.sendgrid.com/v3/templates?generations=dynamic',
204
204
  {
205
205
  headers: {
206
- Authorization: `Bearer ${apiKey}`,
206
+ Authorization: `Bearer ${config.apiKey}`,
207
207
  'Content-Type': 'application/json',
208
208
  },
209
209
  },
@@ -18,18 +18,28 @@ import { FieldMapperDto } from '../dto/field-mapper.dto';
18
18
  @Controller('field-mapper')
19
19
  @UseGuards(JwtAuthGuard)
20
20
  export class FieldMapperController {
21
- constructor(@Inject('FieldMapperService') private readonly fieldMapperService: FieldMapperService) {
22
- }
21
+ constructor(
22
+ @Inject('FieldMapperService')
23
+ private readonly fieldMapperService: FieldMapperService,
24
+ ) {}
23
25
 
24
26
  @Post('resolve')
25
- async resolve(@Req() req: any, @Query('integration_component') integration_component: number,
26
- @Query('entity_type') entity_type: string,
27
- @Query('entity_id') entity_id: number) {
27
+ async resolve(
28
+ @Req() req: any,
29
+ @Query('integration_component') integration_component: number,
30
+ @Query('entity_type') entity_type: string,
31
+ @Query('entity_id') entity_id: number,
32
+ ) {
28
33
  const loggedInUser = req.user.userData;
29
- return this.fieldMapperService.resolveData(integration_component, entity_type, entity_id, loggedInUser);
34
+ return this.fieldMapperService.resolveData(
35
+ integration_component,
36
+ 'LOOKUP',
37
+ entity_type,
38
+ entity_id,
39
+ loggedInUser,
40
+ );
30
41
  }
31
42
 
32
-
33
43
  @Post('bulk')
34
44
  @HttpCode(HttpStatus.OK)
35
45
  async createBulk(@Req() req: any, @Body() dtos: FieldMapperDto[]) {
@@ -53,4 +63,4 @@ export class FieldMapperController {
53
63
  async getLovsByMapperField(@Param('mapperFieldId') mapperFieldId: number) {
54
64
  return this.fieldMapperService.getFieldLovs(mapperFieldId);
55
65
  }
56
- }
66
+ }
@@ -39,7 +39,8 @@ export class FieldMapperService extends EntityServiceImpl {
39
39
  async createFieldMappers(dtos: FieldMapperDto[], loggedInUser: UserData) {
40
40
  let mapperId = dtos[0].mapper_id;
41
41
 
42
- let existingMappers = await this.fieldMapperRepository.findByMapperId(mapperId);
42
+ let existingMappers =
43
+ await this.fieldMapperRepository.findByMapperId(mapperId);
43
44
 
44
45
  for (const mapper of existingMappers) {
45
46
  await this.fieldLovsRepository.deleteByMapperFieldId(mapper.id);
@@ -65,7 +66,14 @@ export class FieldMapperService extends EntityServiceImpl {
65
66
  }
66
67
 
67
68
  async getMapperFields(mapperId: number) {
68
- return await this.fieldMapperRepository.findByMapperId(mapperId);
69
+ let fieldMappers =
70
+ await this.fieldMapperRepository.findByMapperId(mapperId);
71
+ const fieldMapperDtos = fieldMappers as unknown as FieldMapperDto[];
72
+ for (const fieldMapper of fieldMapperDtos) {
73
+ fieldMapper.field_lovs =
74
+ await this.fieldLovsRepository.findByMapperFieldId(fieldMapper.id);
75
+ }
76
+ return fieldMapperDtos;
69
77
  }
70
78
 
71
79
  async getFieldLovs(mapperFieldId: number) {
@@ -74,98 +82,92 @@ export class FieldMapperService extends EntityServiceImpl {
74
82
 
75
83
  async resolveData(
76
84
  mapper_id: number,
85
+ action: 'LOOKUP' | 'LOAD',
77
86
  parent_type: string,
78
87
  parent_id: number,
79
88
  userData: UserData,
89
+ inputJson?: Record<string, any>,
80
90
  ) {
91
+ // Fetch field mappings for this mapper
81
92
  const fieldMappers =
82
- await this.fieldMapperRepository.findByMapperId(
83
- mapper_id,
84
- );
93
+ await this.fieldMapperRepository.findByMapperId(mapper_id);
85
94
 
86
95
  const result: Record<string, any> = {};
87
- const inMemory: Record<string, Record<string, any>> = {};
96
+ const inMemory: Record<string, Record<string, any>> = {}; // cache for entity lookups
88
97
 
89
98
  for (const field of fieldMappers) {
90
- const entityType = field.mapped_entity_type
91
- ? field.mapped_entity_type
92
- : field.mapper_entity_type;
99
+ const entityType = field.mapped_entity_type || field.mapper_entity_type;
93
100
  const filterCode = field.filter_code || 'default';
94
101
 
95
- if (!inMemory[entityType]) {
96
- inMemory[entityType] = {};
97
- }
102
+ // --------------------------
103
+ // CASE 1: LOOKUP (System → External)
104
+ // --------------------------
105
+ if (action === 'LOOKUP') {
106
+ // Build cache (fetch entity data if needed)
107
+ if (!inMemory[entityType]) inMemory[entityType] = {};
98
108
 
99
- // Case 1️⃣ direct mapping (no mapped_entity_type or equal)
100
- if (
101
- !inMemory[entityType][filterCode] &&
102
- field.mapped_entity_type == field.mapper_entity_type
103
- ) {
104
- inMemory[entityType][filterCode] = await super.getResolvedEntityData(
105
- entityType,
106
- parent_id,
107
- userData,
108
- );
109
-
110
- // Case 2️⃣ mapped_entity_type
111
- } else if (
112
- field.mapped_entity_type &&
113
- !inMemory[entityType][filterCode]
114
- ) {
115
- // Step 1: get related target entity ids
116
- const relations = await this.datasource.query(
117
- `SELECT target_entity_id
118
- FROM cr_entity_relation_data
119
- WHERE source_entity_type = ?
120
- AND source_entity_id = ?
121
- AND target_entity_type = ?`,
122
- [
123
- parent_type,
124
- parent_id,
125
- field.mapped_entity_type,
126
- ],
127
- );
128
-
129
- const targetEntityIds = relations.map((r) => r.target_entity_id);
130
-
131
- if (targetEntityIds.length > 0) {
132
- if (filterCode && filterCode !== 'default') {
133
- // Step 2a: filtered fetch with IN clause using applyFilterWrapper
134
- inMemory[entityType][filterCode] = inMemory[entityType][
135
- filterCode
136
- ] = await this.filterService.applyFilterWrapper({
137
- entity_type: entityType,
138
- savedFilterCode: filterCode,
139
- quickFilter: [
140
- {
141
- filter_attribute: 'id',
142
- filter_operator: 'equal',
143
- filter_value: targetEntityIds,
144
- filter_entity_type: entityType,
145
- },
146
- ],
147
- attributeFilter: [],
148
- loggedInUser: userData,
149
- queryParams: {},
150
- });
151
- } else {
152
- // Step 2b: no filter → just pick first related entity
153
- const firstId = targetEntityIds[0];
109
+ if (!inMemory[entityType][filterCode]) {
110
+ if (field.mapped_entity_type === field.mapper_entity_type) {
111
+ // Direct mapping
154
112
  inMemory[entityType][filterCode] =
155
- await super.getResolvedEntityData(entityType, firstId, userData);
113
+ await super.getResolvedEntityData(
114
+ entityType,
115
+ parent_id,
116
+ userData,
117
+ );
118
+ } else {
119
+ // Indirect mapping through relation
120
+ const relations = await this.datasource.query(
121
+ `SELECT target_entity_id
122
+ FROM cr_entity_relation_data
123
+ WHERE source_entity_type = ?
124
+ AND source_entity_id = ?
125
+ AND target_entity_type = ?`,
126
+ [parent_type, parent_id, field.mapped_entity_type],
127
+ );
128
+
129
+ const targetEntityIds = relations.map((r) => r.target_entity_id);
130
+
131
+ if (targetEntityIds.length > 0) {
132
+ if (filterCode && filterCode !== 'default') {
133
+ inMemory[entityType][filterCode] =
134
+ await this.filterService.applyFilterWrapper({
135
+ entity_type: entityType,
136
+ savedFilterCode: filterCode,
137
+ quickFilter: [
138
+ {
139
+ filter_attribute: 'id',
140
+ filter_operator: 'equal',
141
+ filter_value: targetEntityIds,
142
+ filter_entity_type: entityType,
143
+ },
144
+ ],
145
+ attributeFilter: [],
146
+ loggedInUser: userData,
147
+ queryParams: {},
148
+ });
149
+ } else {
150
+ const firstId = targetEntityIds[0];
151
+ inMemory[entityType][filterCode] =
152
+ await super.getResolvedEntityData(
153
+ entityType,
154
+ firstId,
155
+ userData,
156
+ );
157
+ }
158
+ } else {
159
+ inMemory[entityType][filterCode] = null;
160
+ }
156
161
  }
157
- } else {
158
- inMemory[entityType][filterCode] = null;
159
162
  }
160
- }
161
163
 
162
- // Fetch mapped attribute values
163
- const entityData = inMemory[entityType][filterCode];
164
- if (entityData) {
165
- let value = entityData[field.attribute_key];
164
+ // Extract and transform values
165
+ const entityData = inMemory[entityType][filterCode];
166
+ if (entityData) {
167
+ let value = entityData[field.attribute_key];
166
168
 
167
- if (field.is_lov_present) {
168
- if (field.action === 'LOOKUP') {
169
+ // Apply LOV mapping (System → External)
170
+ if (field.is_lov_present) {
169
171
  const fieldLovMapper =
170
172
  await this.fieldLovsRepository.findByMapperFieldIdAndDestinationAttributeValue(
171
173
  field.id,
@@ -174,18 +176,38 @@ export class FieldMapperService extends EntityServiceImpl {
174
176
  if (fieldLovMapper) {
175
177
  value = fieldLovMapper.source_attribute_value;
176
178
  }
177
- } else {
178
- const fieldLovMapper =
179
- await this.fieldLovsRepository.findByMapperFieldIdAndSourceAttributeValue(
180
- field.id,
181
- value,
182
- );
183
- if (fieldLovMapper) {
184
- value = fieldLovMapper.destination_attribute_value;
185
- }
186
179
  }
180
+
181
+ // Add to result
182
+ result[field.source_attribute] = value;
187
183
  }
188
- result[field.source_attribute] = value;
184
+ }
185
+
186
+ // --------------------------
187
+ // CASE 2: LOAD (External → System)
188
+ // --------------------------
189
+ else if (action === 'LOAD' && inputJson) {
190
+ // Ensure nested object exists
191
+ if (!result[field.mapper_entity_type]) {
192
+ result[field.mapper_entity_type] = {};
193
+ }
194
+
195
+ // Read from external payload (third-party)
196
+ let value = inputJson[field.source_attribute];
197
+
198
+ // Apply LOV mapping (External → System)
199
+ if (field.is_lov_present && value !== undefined && value !== null) {
200
+ const fieldLovMapper =
201
+ await this.fieldLovsRepository.findByMapperFieldIdAndSourceAttributeValue(
202
+ field.id,
203
+ value,
204
+ );
205
+ if (fieldLovMapper) {
206
+ value = fieldLovMapper.destination_attribute_value;
207
+ }
208
+ }
209
+
210
+ result[field.mapper_entity_type][field.attribute_key] = value;
189
211
  }
190
212
  }
191
213