rez_core 2.2.190 → 2.2.191
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/communication/communication.module.js +4 -1
- package/dist/module/communication/communication.module.js.map +1 -1
- package/dist/module/communication/controller/calender-event.controller.d.ts +31 -0
- package/dist/module/communication/controller/calender-event.controller.js +51 -0
- package/dist/module/communication/controller/calender-event.controller.js.map +1 -0
- package/dist/module/communication/controller/communication.controller.d.ts +8 -1
- package/dist/module/communication/controller/communication.controller.js +27 -0
- package/dist/module/communication/controller/communication.controller.js.map +1 -1
- package/dist/module/communication/dto/create-config.dto.d.ts +40 -0
- package/dist/module/communication/dto/create-config.dto.js +24 -1
- package/dist/module/communication/dto/create-config.dto.js.map +1 -1
- package/dist/module/communication/factories/whatsapp.factory.d.ts +3 -1
- package/dist/module/communication/factories/whatsapp.factory.js +13 -3
- package/dist/module/communication/factories/whatsapp.factory.js.map +1 -1
- package/dist/module/communication/service/calendar-event.service.d.ts +32 -0
- package/dist/module/communication/service/calendar-event.service.js +115 -0
- package/dist/module/communication/service/calendar-event.service.js.map +1 -0
- package/dist/module/communication/service/communication.service.d.ts +8 -0
- package/dist/module/communication/service/communication.service.js +56 -1
- package/dist/module/communication/service/communication.service.js.map +1 -1
- package/dist/module/communication/strategies/whatsapp/whatsapp-cloud.strategy.d.ts +15 -0
- package/dist/module/communication/strategies/whatsapp/whatsapp-cloud.strategy.js +233 -16
- package/dist/module/communication/strategies/whatsapp/whatsapp-cloud.strategy.js.map +1 -1
- package/dist/module/workflow/service/task.service.js +0 -1
- package/dist/module/workflow/service/task.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/communication/communication.module.ts +5 -1
- package/src/module/communication/controller/calender-event.controller.ts +31 -0
- package/src/module/communication/controller/communication.controller.ts +29 -0
- package/src/module/communication/dto/create-config.dto.ts +71 -0
- package/src/module/communication/factories/whatsapp.factory.ts +13 -2
- package/src/module/communication/service/calendar-event.service.ts +123 -0
- package/src/module/communication/service/communication.service.ts +91 -2
- package/src/module/communication/strategies/whatsapp/whatsapp-cloud.strategy.ts +373 -19
- package/src/module/workflow/service/task.service.ts +1 -1
package/package.json
CHANGED
|
@@ -38,10 +38,12 @@ import { SmsFactory } from './factories/sms.factory';
|
|
|
38
38
|
import { WhatsAppFactory } from './factories/whatsapp.factory';
|
|
39
39
|
import { TelephoneFactory } from './factories/telephone.factory';
|
|
40
40
|
import { CommunicationFactory } from './factories/communication.factory';
|
|
41
|
+
import { GoogleController } from './controller/calender-event.controller';
|
|
42
|
+
import { GoogleService } from './service/calendar-event.service';
|
|
41
43
|
|
|
42
44
|
@Module({
|
|
43
45
|
imports: [TypeOrmModule.forFeature([CommunicationConfig, CommunicationHub])],
|
|
44
|
-
controllers: [CommunicationController],
|
|
46
|
+
controllers: [CommunicationController, GoogleController],
|
|
45
47
|
providers: [
|
|
46
48
|
// Main Services
|
|
47
49
|
CommunicationService,
|
|
@@ -75,6 +77,8 @@ import { CommunicationFactory } from './factories/communication.factory';
|
|
|
75
77
|
WhatsAppFactory,
|
|
76
78
|
TelephoneFactory,
|
|
77
79
|
CommunicationFactory,
|
|
80
|
+
|
|
81
|
+
GoogleService,
|
|
78
82
|
],
|
|
79
83
|
exports: [
|
|
80
84
|
CommunicationService,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/google/google.controller.ts
|
|
2
|
+
import { Body, Controller, Param, Patch, Post } from '@nestjs/common';
|
|
3
|
+
import { GoogleService } from '../service/calendar-event.service';
|
|
4
|
+
|
|
5
|
+
@Controller('google/calendar')
|
|
6
|
+
export class GoogleController {
|
|
7
|
+
constructor(private readonly googleService: GoogleService) {}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create calendar event
|
|
11
|
+
*/
|
|
12
|
+
@Post('create')
|
|
13
|
+
async createEvent(
|
|
14
|
+
@Body('googleCred') googleCred: any,
|
|
15
|
+
@Body('payload') payload: any,
|
|
16
|
+
) {
|
|
17
|
+
return this.googleService.createEvent(googleCred, payload);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Update calendar event
|
|
22
|
+
*/
|
|
23
|
+
@Patch('update/:eventId')
|
|
24
|
+
async updateEvent(
|
|
25
|
+
@Param('eventId') eventId: string,
|
|
26
|
+
@Body('googleCred') googleCred: any,
|
|
27
|
+
@Body('payload') payload: any,
|
|
28
|
+
) {
|
|
29
|
+
return this.googleService.updateEvent(googleCred, eventId, payload);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
GmailOAuthInitDto,
|
|
21
21
|
OutlookOAuthInitDto,
|
|
22
22
|
SendGridVerifiedSendersDto,
|
|
23
|
+
UpdateConfigDto,
|
|
23
24
|
UpdateConfigStatusDto,
|
|
24
25
|
} from '../dto/create-config.dto';
|
|
25
26
|
|
|
@@ -221,4 +222,32 @@ export class CommunicationController {
|
|
|
221
222
|
});
|
|
222
223
|
}
|
|
223
224
|
}
|
|
225
|
+
|
|
226
|
+
@Post('config/update/:hubId')
|
|
227
|
+
@HttpCode(HttpStatus.OK)
|
|
228
|
+
async updateConfig(
|
|
229
|
+
@Param('hubId', ParseIntPipe) hubId: number,
|
|
230
|
+
@Body() updateDto: UpdateConfigDto,
|
|
231
|
+
) {
|
|
232
|
+
try {
|
|
233
|
+
const result = await this.communicationService.updateConfiguration(
|
|
234
|
+
hubId,
|
|
235
|
+
updateDto,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
success: true,
|
|
240
|
+
message: 'Communication configuration updated successfully',
|
|
241
|
+
data: result,
|
|
242
|
+
};
|
|
243
|
+
} catch (error) {
|
|
244
|
+
throw new BadRequestException({
|
|
245
|
+
success: false,
|
|
246
|
+
error: 'UPDATE_ERROR',
|
|
247
|
+
message:
|
|
248
|
+
error.message || 'Failed to update communication configuration',
|
|
249
|
+
code: 'CONFIGURATION_ERROR',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
224
253
|
}
|
|
@@ -115,6 +115,77 @@ export class UpdateConfigStatusDto {
|
|
|
115
115
|
status: number;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
export class UpdateConfigDto {
|
|
119
|
+
@IsOptional()
|
|
120
|
+
@IsObject()
|
|
121
|
+
config?: {
|
|
122
|
+
// OAuth Control
|
|
123
|
+
useOAuth?: boolean;
|
|
124
|
+
|
|
125
|
+
// Gmail API Config
|
|
126
|
+
clientId?: string;
|
|
127
|
+
clientSecret?: string;
|
|
128
|
+
refreshToken?: string;
|
|
129
|
+
accessToken?: string;
|
|
130
|
+
|
|
131
|
+
// Outlook API Config
|
|
132
|
+
tenantId?: string;
|
|
133
|
+
|
|
134
|
+
// WhatsApp Config
|
|
135
|
+
phoneNumberId?: string;
|
|
136
|
+
apiVersion?: string;
|
|
137
|
+
|
|
138
|
+
// Twilio Config
|
|
139
|
+
accountSid?: string;
|
|
140
|
+
authToken?: string;
|
|
141
|
+
fromNumber?: string;
|
|
142
|
+
|
|
143
|
+
// AWS SES Config
|
|
144
|
+
accessKeyId?: string;
|
|
145
|
+
secretAccessKey?: string;
|
|
146
|
+
region?: string;
|
|
147
|
+
fromEmail?: string;
|
|
148
|
+
|
|
149
|
+
// SMTP Config (Gmail, Outlook, Generic)
|
|
150
|
+
email?: string;
|
|
151
|
+
password?: string;
|
|
152
|
+
host?: string;
|
|
153
|
+
port?: number;
|
|
154
|
+
secure?: boolean;
|
|
155
|
+
user?: string;
|
|
156
|
+
from?: string;
|
|
157
|
+
tls?: any;
|
|
158
|
+
|
|
159
|
+
// SendGrid SMTP Config
|
|
160
|
+
apiKey?: string;
|
|
161
|
+
templateId?: string;
|
|
162
|
+
dynamicTemplateData?: any;
|
|
163
|
+
|
|
164
|
+
// Knowlarity Config
|
|
165
|
+
callerNumber?: string;
|
|
166
|
+
apiSecret?: string;
|
|
167
|
+
baseUrl?: string;
|
|
168
|
+
callType?: 'voice' | 'sms';
|
|
169
|
+
voiceMessage?: string;
|
|
170
|
+
language?: string;
|
|
171
|
+
|
|
172
|
+
// Common optional fields
|
|
173
|
+
[key: string]: any;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
@IsOptional()
|
|
177
|
+
@IsNumber()
|
|
178
|
+
priority?: number;
|
|
179
|
+
|
|
180
|
+
@IsOptional()
|
|
181
|
+
@IsBoolean()
|
|
182
|
+
is_default?: boolean;
|
|
183
|
+
|
|
184
|
+
@IsOptional()
|
|
185
|
+
@IsNumber()
|
|
186
|
+
status?: number;
|
|
187
|
+
}
|
|
188
|
+
|
|
118
189
|
export class GenericSendMessageDto {
|
|
119
190
|
@IsNotEmpty()
|
|
120
191
|
@IsNumber()
|
|
@@ -2,10 +2,14 @@ import { Injectable } from '@nestjs/common';
|
|
|
2
2
|
import { BaseFactory } from './base.factory';
|
|
3
3
|
import { CommunicationStrategy } from '../strategies/communication.strategy';
|
|
4
4
|
import { WhatsAppStrategy } from '../strategies/whatsapp.strategy';
|
|
5
|
+
import { WhatsAppCloudStrategy } from '../strategies/whatsapp/whatsapp-cloud.strategy';
|
|
5
6
|
|
|
6
7
|
@Injectable()
|
|
7
8
|
export class WhatsAppFactory implements BaseFactory {
|
|
8
|
-
constructor(
|
|
9
|
+
constructor(
|
|
10
|
+
private whatsappStrategy: WhatsAppStrategy,
|
|
11
|
+
private whatsappCloudStrategy: WhatsAppCloudStrategy,
|
|
12
|
+
) {}
|
|
9
13
|
|
|
10
14
|
createProvider(service: string, provider: string): CommunicationStrategy {
|
|
11
15
|
const key = `${service.toLowerCase()}_${provider.toLowerCase()}`;
|
|
@@ -13,6 +17,9 @@ export class WhatsAppFactory implements BaseFactory {
|
|
|
13
17
|
switch (key) {
|
|
14
18
|
case 'api_whatsapp':
|
|
15
19
|
return this.whatsappStrategy;
|
|
20
|
+
case 'api_whatsapp-cloud':
|
|
21
|
+
case 'api_meta':
|
|
22
|
+
return this.whatsappCloudStrategy;
|
|
16
23
|
|
|
17
24
|
default:
|
|
18
25
|
throw new Error(
|
|
@@ -22,7 +29,11 @@ export class WhatsAppFactory implements BaseFactory {
|
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
getSupportedCombinations(): Array<{ service: string; provider: string }> {
|
|
25
|
-
return [
|
|
32
|
+
return [
|
|
33
|
+
{ service: 'API', provider: 'whatsapp' },
|
|
34
|
+
{ service: 'API', provider: 'whatsapp-cloud' },
|
|
35
|
+
{ service: 'API', provider: 'meta' },
|
|
36
|
+
];
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
validateCombination(service: string, provider: string): boolean {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// src/google/google.service.ts
|
|
2
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import { GmailApiStrategy } from '../strategies/email/gmail-api.strategy';
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class GoogleService {
|
|
8
|
+
private readonly logger = new Logger(GoogleService.name);
|
|
9
|
+
|
|
10
|
+
constructor(private readonly gmailApiStrategy: GmailApiStrategy) {}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create a Google Calendar event
|
|
14
|
+
*/
|
|
15
|
+
async createEvent(googleCred: any, payload: any) {
|
|
16
|
+
if (!googleCred?.refreshToken) {
|
|
17
|
+
throw new Error('Missing refresh token');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const accessToken =
|
|
22
|
+
await this.gmailApiStrategy.refreshAccessToken(googleCred);
|
|
23
|
+
|
|
24
|
+
const event = {
|
|
25
|
+
summary: payload.title,
|
|
26
|
+
description: payload.description,
|
|
27
|
+
location: payload.location,
|
|
28
|
+
start: {
|
|
29
|
+
dateTime: payload.startTime,
|
|
30
|
+
timeZone: payload.timeZone || 'Asia/Kolkata',
|
|
31
|
+
},
|
|
32
|
+
end: {
|
|
33
|
+
dateTime: payload.endTime,
|
|
34
|
+
timeZone: payload.timeZone || 'Asia/Kolkata',
|
|
35
|
+
},
|
|
36
|
+
attendees: payload.attendees?.map((email) => ({ email })) || [],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const response = await axios.post(
|
|
40
|
+
'https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all',
|
|
41
|
+
event,
|
|
42
|
+
{
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${accessToken}`,
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
this.logger.log(`Event created: ${response.data.id}`);
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
eventId: response.data.id,
|
|
54
|
+
htmlLink: response.data.htmlLink,
|
|
55
|
+
accessToken,
|
|
56
|
+
};
|
|
57
|
+
} catch (error: any) {
|
|
58
|
+
this.logger.error('CreateEvent error', error.message);
|
|
59
|
+
return {
|
|
60
|
+
success: false,
|
|
61
|
+
error: error.response?.data?.error?.message || error.message,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Update a Google Calendar event
|
|
68
|
+
*/
|
|
69
|
+
async updateEvent(googleCred: any, eventId: string, payload: any) {
|
|
70
|
+
if (!googleCred?.refreshToken) {
|
|
71
|
+
throw new Error('Missing refresh token');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const accessToken =
|
|
76
|
+
await this.gmailApiStrategy.refreshAccessToken(googleCred);
|
|
77
|
+
|
|
78
|
+
const event = {
|
|
79
|
+
summary: payload.title,
|
|
80
|
+
description: payload.description,
|
|
81
|
+
location: payload.location,
|
|
82
|
+
start: {
|
|
83
|
+
dateTime: payload.startTime,
|
|
84
|
+
timeZone: payload.timeZone || 'Asia/Kolkata',
|
|
85
|
+
},
|
|
86
|
+
end: {
|
|
87
|
+
dateTime: payload.endTime,
|
|
88
|
+
timeZone: payload.timeZone || 'Asia/Kolkata',
|
|
89
|
+
},
|
|
90
|
+
attendees: payload.attendees?.map((email) => ({ email })) || [],
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (payload.meetingType === 'online' && payload.meetingLink) {
|
|
94
|
+
event.description = `${event.description || ''}\nJoin here: ${payload.meetingLink}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const response = await axios.patch(
|
|
98
|
+
`https://www.googleapis.com/calendar/v3/calendars/primary/events/${eventId}?sendUpdates=all`,
|
|
99
|
+
event,
|
|
100
|
+
{
|
|
101
|
+
headers: {
|
|
102
|
+
Authorization: `Bearer ${accessToken}`,
|
|
103
|
+
'Content-Type': 'application/json',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
this.logger.log(`Event updated: ${response.data.id}`);
|
|
109
|
+
return {
|
|
110
|
+
success: true,
|
|
111
|
+
eventId: response.data.id,
|
|
112
|
+
htmlLink: response.data.htmlLink,
|
|
113
|
+
accessToken,
|
|
114
|
+
};
|
|
115
|
+
} catch (error: any) {
|
|
116
|
+
this.logger.error('UpdateEvent error', error.message);
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error: error.response?.data?.error?.message || error.message,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
|
|
2
2
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
3
|
-
import { Repository } from 'typeorm';
|
|
3
|
+
import { Repository, Not } from 'typeorm';
|
|
4
4
|
import { ConfigService } from '@nestjs/config';
|
|
5
5
|
import { google } from 'googleapis';
|
|
6
6
|
import {
|
|
@@ -339,7 +339,7 @@ export class CommunicationService {
|
|
|
339
339
|
): Promise<
|
|
340
340
|
Array<CommunicationHub & { linkedSource?: string; configDetails?: any }>
|
|
341
341
|
> {
|
|
342
|
-
const where: any = { level_id: levelId, level_type: levelType
|
|
342
|
+
const where: any = { level_id: levelId, level_type: levelType };
|
|
343
343
|
|
|
344
344
|
if (filters?.communication_config_type) {
|
|
345
345
|
where.communication_config_type = filters.communication_config_type;
|
|
@@ -669,6 +669,95 @@ export class CommunicationService {
|
|
|
669
669
|
);
|
|
670
670
|
}
|
|
671
671
|
|
|
672
|
+
async updateConfiguration(
|
|
673
|
+
hubId: number,
|
|
674
|
+
updateData: {
|
|
675
|
+
config?: any;
|
|
676
|
+
priority?: number;
|
|
677
|
+
is_default?: boolean;
|
|
678
|
+
status?: number;
|
|
679
|
+
},
|
|
680
|
+
): Promise<CommunicationHub & { config?: any }> {
|
|
681
|
+
// Find the existing hub
|
|
682
|
+
const hub = await this.hubRepository.findOne({
|
|
683
|
+
where: { id: hubId },
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
if (!hub) {
|
|
687
|
+
throw new Error('Communication configuration not found');
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Update configuration JSON if provided
|
|
691
|
+
if (updateData.config) {
|
|
692
|
+
const existingConfig = await this.configRepository.findOne({
|
|
693
|
+
where: { id: hub.config_id },
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
if (!existingConfig) {
|
|
697
|
+
throw new Error('Configuration record not found');
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// Merge the new config with existing config
|
|
701
|
+
const updatedConfigJson = {
|
|
702
|
+
...existingConfig.config_json,
|
|
703
|
+
...updateData.config,
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
await this.configRepository.update(hub.config_id, {
|
|
707
|
+
config_json: updatedConfigJson,
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Handle default configuration logic
|
|
712
|
+
if (updateData.is_default === true) {
|
|
713
|
+
// Remove default from other configurations of same type and level
|
|
714
|
+
await this.hubRepository.update(
|
|
715
|
+
{
|
|
716
|
+
level_id: hub.level_id,
|
|
717
|
+
level_type: hub.level_type,
|
|
718
|
+
communication_config_type: hub.communication_config_type,
|
|
719
|
+
id: Not(hubId), // Exclude current hub
|
|
720
|
+
},
|
|
721
|
+
{ is_default: false },
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Update hub metadata
|
|
726
|
+
const hubUpdateData: any = {};
|
|
727
|
+
if (updateData.priority !== undefined) {
|
|
728
|
+
hubUpdateData.priority = updateData.priority;
|
|
729
|
+
}
|
|
730
|
+
if (updateData.is_default !== undefined) {
|
|
731
|
+
hubUpdateData.is_default = updateData.is_default;
|
|
732
|
+
}
|
|
733
|
+
if (updateData.status !== undefined) {
|
|
734
|
+
hubUpdateData.status = updateData.status;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Apply hub updates if any
|
|
738
|
+
if (Object.keys(hubUpdateData).length > 0) {
|
|
739
|
+
await this.hubRepository.update(hubId, hubUpdateData);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Fetch and return updated hub with config
|
|
743
|
+
const updatedHub = await this.hubRepository.findOne({
|
|
744
|
+
where: { id: hubId },
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
const updatedConfig = await this.configRepository.findOne({
|
|
748
|
+
where: { id: hub.config_id },
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
this.logger.log(
|
|
752
|
+
`Communication configuration updated: Hub ${hubId}, Type ${hub.communication_config_type}`,
|
|
753
|
+
);
|
|
754
|
+
|
|
755
|
+
return {
|
|
756
|
+
...updatedHub!,
|
|
757
|
+
config: updatedConfig?.config_json,
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
672
761
|
async sendGenericMessage(
|
|
673
762
|
messageDto: GenericMessageDto,
|
|
674
763
|
): Promise<CommunicationResult> {
|