rez_core 3.1.61 → 3.1.63

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 (23) hide show
  1. package/dist/module/filter/repository/saved-filter.repository.d.ts +2 -0
  2. package/dist/module/filter/repository/saved-filter.repository.js +2 -1
  3. package/dist/module/filter/repository/saved-filter.repository.js.map +1 -1
  4. package/dist/module/integration/controller/integration.controller.js +1 -1
  5. package/dist/module/integration/controller/integration.controller.js.map +1 -1
  6. package/dist/module/integration/service/integration.service.js +9 -17
  7. package/dist/module/integration/service/integration.service.js.map +1 -1
  8. package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.d.ts +1 -1
  9. package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.js +15 -8
  10. package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.js.map +1 -1
  11. package/dist/module/integration/strategies/telephone/tubelight-voice.strategy.d.ts +7 -0
  12. package/dist/module/integration/strategies/telephone/tubelight-voice.strategy.js +51 -0
  13. package/dist/module/integration/strategies/telephone/tubelight-voice.strategy.js.map +1 -1
  14. package/dist/module/mapper/service/field-mapper.service.js +1 -1
  15. package/dist/module/mapper/service/field-mapper.service.js.map +1 -1
  16. package/dist/tsconfig.build.tsbuildinfo +1 -1
  17. package/package.json +1 -1
  18. package/src/module/filter/repository/saved-filter.repository.ts +3 -2
  19. package/src/module/integration/controller/integration.controller.ts +1 -1
  20. package/src/module/integration/service/integration.service.ts +15 -28
  21. package/src/module/integration/strategies/telephone/ozonetel-voice.strategy.ts +18 -10
  22. package/src/module/integration/strategies/telephone/tubelight-voice.strategy.ts +80 -0
  23. package/src/module/mapper/service/field-mapper.service.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "3.1.61",
3
+ "version": "3.1.63",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -74,7 +74,7 @@ export class SavedFilterRepositoryService {
74
74
 
75
75
  async getDefaultFilterByEntityType(
76
76
  entityType: string,
77
- ): Promise<{ label: string; value: number } | null> {
77
+ ): Promise<{ label: string; value: number ,code: string} | null> {
78
78
  const filter = await this.savedFilterMasterRepo.findOne({
79
79
  where: {
80
80
  mapped_entity_type: entityType,
@@ -82,7 +82,7 @@ export class SavedFilterRepositoryService {
82
82
  },
83
83
  });
84
84
 
85
- return filter ? { label: filter.name, value: filter.id } : null;
85
+ return filter ? { label: filter.name, value: filter.id , code: filter.code} : null;
86
86
  }
87
87
 
88
88
  async getSavedFiltersByUserIdAndEntityType(
@@ -103,6 +103,7 @@ export class SavedFilterRepositoryService {
103
103
  return filters.map((filter) => ({
104
104
  label: filter.name,
105
105
  value: filter.id,
106
+ code: filter.code,
106
107
  }));
107
108
  }
108
109
 
@@ -413,7 +413,7 @@ export class IntegrationController {
413
413
  }
414
414
  }
415
415
 
416
- @Post('user-integration/:id')
416
+ @Post('user-integration/delete/:id')
417
417
  @HttpCode(HttpStatus.OK)
418
418
  async deleteUserIntegration(@Param('id', ParseIntPipe) id: number) {
419
419
  try {
@@ -1279,7 +1279,7 @@ export class IntegrationService {
1279
1279
  if (!commTemplate.template_id) {
1280
1280
  let richText = commTemplate.rich_text;
1281
1281
 
1282
- richText.replace(/\{\{(\w+)\}\}/g, (match, key) => {
1282
+ richText = richText.replace(/\{\{(\w+)\}\}/g, (match, key) => {
1283
1283
  const value = variables[key];
1284
1284
  return value !== undefined ? String(value) : match;
1285
1285
  });
@@ -2370,7 +2370,7 @@ export class IntegrationService {
2370
2370
 
2371
2371
  /**
2372
2372
  * Check agent status for TELEPHONE integration
2373
- * Currently supports: Ozonetel
2373
+ * Works with any provider that implements checkAgentStatus method
2374
2374
  */
2375
2375
  async checkAgentStatus(
2376
2376
  levelId: number,
@@ -2431,37 +2431,24 @@ export class IntegrationService {
2431
2431
  );
2432
2432
  }
2433
2433
 
2434
- // Check if strategy is Ozonetel (currently only Ozonetel supports status check)
2435
- if (config.integration_provider.toLowerCase() === 'ozonetel') {
2436
- const ozonetelStrategy = strategy as any;
2437
-
2438
- // Generate token
2439
- const token = await ozonetelStrategy.generateToken(mergedConfig);
2440
- if (!token) {
2441
- return {
2442
- success: false,
2443
- error: 'Failed to authenticate with telephone provider',
2444
- };
2445
- }
2446
-
2447
- // Check agent status
2448
- const statusResult = await ozonetelStrategy.checkAgentStatus(
2449
- mergedConfig,
2450
- token,
2451
- );
2452
-
2434
+ // Check if strategy supports agent status check
2435
+ if (typeof (strategy as any).checkAgentStatus !== 'function') {
2453
2436
  return {
2454
- success: true,
2455
- isReady: statusResult.isReady,
2456
- state: statusResult.state,
2457
- error: statusResult.error,
2437
+ success: false,
2438
+ error: `Agent status check not supported for provider: ${config.integration_provider}`,
2458
2439
  };
2459
2440
  }
2460
2441
 
2461
- // For other providers, return not supported
2442
+ // Check agent status
2443
+ const statusResult = await (strategy as any).checkAgentStatus(
2444
+ mergedConfig,
2445
+ );
2446
+
2462
2447
  return {
2463
- success: false,
2464
- error: `Agent status check not supported for provider: ${config.integration_provider}`,
2448
+ success: true,
2449
+ isReady: statusResult.isReady,
2450
+ state: statusResult.state,
2451
+ error: statusResult.error,
2465
2452
  };
2466
2453
  } catch (error) {
2467
2454
  this.logger.error(
@@ -50,27 +50,27 @@ export class OzonetelVoiceStrategy implements IntegrationStrategy {
50
50
  }
51
51
 
52
52
  try {
53
- // First, get JWT token
54
- const token = await this.generateToken(config);
55
- if (!token) {
53
+ // Check agent status before making the call
54
+ const agentStatus = await this.checkAgentStatus(config);
55
+ if (!agentStatus.isReady) {
56
56
  return {
57
57
  success: false,
58
58
  provider: 'ozonetel',
59
59
  service: 'THIRD_PARTY',
60
- error: 'Failed to generate Ozonetel authentication token',
60
+ error: agentStatus.error ||
61
+ `Agent is not ready. Current state: ${agentStatus.state || 'Unknown'}. Please login to your agent dashboard.`,
61
62
  timestamp: new Date(),
62
63
  };
63
64
  }
64
65
 
65
- // Check agent status before making the call
66
- const agentStatus = await this.checkAgentStatus(config, token);
67
- if (!agentStatus.isReady) {
66
+ // Get JWT token for manual dial
67
+ const token = await this.generateToken(config);
68
+ if (!token) {
68
69
  return {
69
70
  success: false,
70
71
  provider: 'ozonetel',
71
72
  service: 'THIRD_PARTY',
72
- error: agentStatus.error ||
73
- `Agent is not ready. Current state: ${agentStatus.state || 'Unknown'}. Please login to your agent dashboard.`,
73
+ error: 'Failed to generate Ozonetel authentication token',
74
74
  timestamp: new Date(),
75
75
  };
76
76
  }
@@ -149,9 +149,17 @@ export class OzonetelVoiceStrategy implements IntegrationStrategy {
149
149
 
150
150
  async checkAgentStatus(
151
151
  config: OzonetelVoiceConfig,
152
- token: string,
153
152
  ): Promise<{ isReady: boolean; state?: string; error?: string }> {
154
153
  try {
154
+ // Generate token first
155
+ const token = await this.generateToken(config);
156
+ if (!token) {
157
+ return {
158
+ isReady: false,
159
+ error: 'Failed to authenticate with Ozonetel',
160
+ };
161
+ }
162
+
155
163
  const url = `${this.baseUrl}/ca_apis/AgentDetails`;
156
164
 
157
165
  const response = await axios.post<AgentDetailsResponse>(
@@ -10,6 +10,7 @@ interface TubelightVoiceConfig {
10
10
  userName: string;
11
11
  password: string;
12
12
  tenantId: string;
13
+ accessKey?: string; // For agent status check
13
14
  agentLoginUrl?: string;
14
15
  // Agent phone number from config JSON
15
16
  agentPhoneNumber?: string;
@@ -123,7 +124,86 @@ export class TubelightVoiceStrategy implements IntegrationStrategy {
123
124
  }
124
125
  }
125
126
 
127
+ async checkAgentStatus(
128
+ config: TubelightVoiceConfig,
129
+ ): Promise<{ isReady: boolean; state?: string; error?: string }> {
130
+ try {
131
+ if (!config.accessKey) {
132
+ return {
133
+ isReady: false,
134
+ error: 'Access key is required for agent status check',
135
+ };
136
+ }
137
+
138
+ if (!config.external_user_id) {
139
+ return {
140
+ isReady: false,
141
+ error: 'Agent email (external_user_id) is required',
142
+ };
143
+ }
144
+
145
+ const url = `https://dashboard.hellotubelight.com/tenant/v1/user/sso/agent/user/state/${config.external_user_id}`;
146
+
147
+ const response = await axios.post(
148
+ url,
149
+ {},
150
+ {
151
+ headers: {
152
+ 'accept': '*/*',
153
+ 'X-TENANT-ID': config.tenantId,
154
+ 'access-key': config.accessKey,
155
+ },
156
+ },
157
+ );
158
+
159
+ // Parse the response to determine agent status
160
+ const data = response.data;
161
+ const state = data?.state || data?.status;
162
+
163
+ // Determine if agent is ready based on the state
164
+ // Adjust this logic based on actual Tubelight API response format
165
+ const isReady = state?.toUpperCase() === 'READY' ||
166
+ state?.toUpperCase() === 'AVAILABLE' ||
167
+ state?.toUpperCase() === 'IDLE';
168
+
169
+ return {
170
+ isReady,
171
+ state: state,
172
+ };
173
+ } catch (error) {
174
+ console.error('Failed to check Tubelight agent status:', error);
175
+ return {
176
+ isReady: false,
177
+ error: axios.isAxiosError(error)
178
+ ? error.response?.data?.message || error.message
179
+ : 'Unknown error checking agent status',
180
+ };
181
+ }
182
+ }
183
+
126
184
  validateConfig(config: Partial<TubelightVoiceConfig>): boolean {
127
185
  return !!(config && config.userName && config.password && config.tenantId);
128
186
  }
187
+
188
+ /**
189
+ * Create configuration with user agent data merged with admin credentials
190
+ */
191
+ createUserSpecificConfig(
192
+ baseConfig: Pick<
193
+ TubelightVoiceConfig,
194
+ 'userName' | 'password' | 'tenantId' | 'accessKey' | 'agentLoginUrl' | 'agentPhoneNumber'
195
+ >,
196
+ externalUserId?: string,
197
+ ): TubelightVoiceConfig {
198
+ if (!externalUserId) {
199
+ throw new Error(
200
+ 'External user ID (agent email) is required for Tubelight voice calls',
201
+ );
202
+ }
203
+
204
+ return {
205
+ ...baseConfig,
206
+ external_user_id: externalUserId,
207
+ };
208
+ }
129
209
  }
@@ -39,7 +39,7 @@ export class FieldMapperService extends EntityServiceImpl {
39
39
  async createFieldMappers(dtos: FieldMapperDto[], loggedInUser: UserData) {
40
40
  let result: BaseEntity[] = [];
41
41
  for (const dto of dtos) {
42
- const fieldMapper = await super.createEntity(dto, loggedInUser);
42
+ const fieldMapper = await this.createEntity(dto, loggedInUser);
43
43
  result.push(fieldMapper);
44
44
  }
45
45
  return result;