Skip to content

Commit

Permalink
Rebase CallMetadataUpdate branch and apply changes
Browse files Browse the repository at this point in the history
  • Loading branch information
SushilMallRC committed Dec 27, 2024
1 parent 9bbb5b3 commit 0e3e941
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 58 deletions.
59 changes: 56 additions & 3 deletions src/adapters/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"serverUrl": "unified-crm-extension.labs.ringcentral.com",
"serverUrl": "https://unified-crm-extension.labs.ringcentral.com",
"redirectUri": "https://ringcentral.github.io/ringcentral-embeddable/redirect.html",
"author": {
"name": "RingCentral Labs",
Expand Down Expand Up @@ -232,7 +232,8 @@
"display": "Contact",
"value": "contact"
}
],"settings": [
],
"settings": [
{
"id": "insightlyCallLogDetails",
"type": "section",
Expand Down Expand Up @@ -604,7 +605,8 @@
]
}
}
},"settings": [
},
"settings": [
{
"id": "redtailCallLogDetails",
"type": "section",
Expand Down Expand Up @@ -1005,6 +1007,57 @@
"customState": "fillerString,platform=netsuite"
}
},
"settings": [
{
"id": "netsuiteCallLogDetails",
"type": "section",
"name": "Call log details",
"items": [
{
"id": "addCallLogNote",
"type": "boolean",
"name": "Add note to call log",
"defaultValue": true
},
{
"id": "addCallLogSubject",
"type": "boolean",
"name": "Add subject to call log",
"defaultValue": false
},
{
"id": "addCallLogContactNumber",
"type": "boolean",
"name": "Add contact phone number to call log",
"defaultValue": false
},
{
"id": "addCallLogDateTime",
"type": "boolean",
"name": "Add date and time to call log",
"defaultValue": false
},
{
"id": "addCallLogDuration",
"type": "boolean",
"name": "Add duration to call log",
"defaultValue": false
},
{
"id": "addCallLogResult",
"type": "boolean",
"name": "Add call result to call log",
"defaultValue": false
},
{
"id": "addCallLogRecording",
"type": "boolean",
"name": "Add recording link to call log",
"defaultValue": true
}
]
}
],
"platform": "netsuite",
"contactPageUrl": "https://{hostname}/app/common/entity/{contactType}.nl?id={contactId}&source=ringcentral",
"logPageUrl": "https://{hostname}/app/crm/calendar/call.nl?id={logId}",
Expand Down
159 changes: 104 additions & 55 deletions src/adapters/netsuite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { parsePhoneNumber } = require('awesome-phonenumber');
const { parse } = require('path');
const { getTimeZone } = require('../../lib/util');
const { get } = require('shortid/lib/alphabet');
const { secondsToHoursMinutesSeconds } = require('../../lib/util');

function getAuthType() {
return 'oauth';
Expand Down Expand Up @@ -253,21 +254,6 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
const oneWorldEnabled = user?.platformAdditionalInfo?.oneWorldEnabled;
let callStartTime = moment(moment(callLog.startTime).toISOString());
let startTimeSLot = moment(callLog.startTime).format('HH:mm');
/**
* Users without a OneWorld license do not have access to subsidiaries.
*/
// if (oneWorldEnabled !== undefined && oneWorldEnabled === true) {
// const subsidiary = await axios.post(
// `https://${user.hostname.split(".")[0]}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql`,
// {
// q: `SELECT * FROM Subsidiary WHERE id = ${user?.platformAdditionalInfo?.subsidiaryId}`
// },
// {
// headers: { 'Authorization': authHeader, 'Content-Type': 'application/json', 'Prefer': 'transient' }
// });
// const timeZone = getTimeZone(subsidiary.data.items[0]?.country, subsidiary.data.items[0]?.state);
// callStartTime = moment(moment(callLog.startTime).toISOString()).tz(timeZone);
// }
try {
const getTimeZoneUrl = `https://${user.hostname.split(".")[0]}.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=customscript_gettimezone&deploy=customdeploy_gettimezone`;
const timeZoneResponse = await axios.get(getTimeZoneUrl, {
Expand All @@ -281,13 +267,19 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
console.log({ message: "Error in getting timezone" });
}
const callEndTime = (callLog.duration === 'pending') ? moment(callStartTime) : moment(callStartTime).add(callLog.duration, 'seconds');
const formatedStartTime = callStartTime.format('YYYY-MM-DD HH:mm:ss');
const formatedEndTime = callEndTime.format('YYYY-MM-DD HH:mm:ss');
let endTimeSlot = callEndTime.format('HH:mm');
if (startTimeSLot === endTimeSlot) {
//If Start Time and End Time are same, then add 1 minute to End Time because endTime can not be less or equal to startTime
endTimeSlot = callEndTime.add(1, 'minutes').format('HH:mm');
}
let comments = '';;
if (user.userSettings?.addCallLogNote?.value ?? true) { comments = upsertCallAgentNote({ body: comments, note }); }
if (user.userSettings?.addCallLogSubject?.value ?? true) { comments = upsertCallSubject({ body: comments, title }); }
if (user.userSettings?.addCallLogContactNumber?.value ?? true) { comments = upsertContactPhoneNumber({ body: comments, phoneNumber: contactInfo.phoneNumber, direction: callLog.direction }); }
if (user.userSettings?.addCallLogResult?.value ?? true) { comments = upsertCallResult({ body: comments, result: callLog.result }); }
if (user.userSettings?.addCallLogDateTime?.value ?? true) { comments = upsertCallDateTime({ body: comments, startTime: callLog.startTime, timezoneOffset: user.timezoneOffset }); }
if (user.userSettings?.addCallLogDuration?.value ?? true) { comments = upsertCallDuration({ body: comments, duration: callLog.duration }); }
if (!!callLog.recording?.link && (user.userSettings?.addCallLogRecording?.value ?? true)) { comments = upsertCallRecording({ body: comments, recordingLink: callLog.recording.link }); }
let postBody = {
title: title,
phone: contactInfo?.phoneNumber || '',
Expand All @@ -297,7 +289,7 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
startTime: startTimeSLot,
endTime: endTimeSlot,
timedEvent: true,
message: `Note: ${note}${callLog.recording ? `\nCall recording link ${callLog.recording.link}` : ''}\n\n--- Created via RingCentral App Connect`,
message: comments,
};
if (contactInfo.type?.toUpperCase() === 'CONTACT') {
const contactInfoRes = await axios.get(`https://${user.hostname.split(".")[0]}.suitetalk.api.netsuite.com/services/rest/record/v1/contact/${contactInfo.id}`, {
Expand Down Expand Up @@ -344,6 +336,7 @@ async function createCallLog({ user, contactInfo, authHeader, callLog, note, add
}
};
} catch (error) {
console.log({ error });
let errorMessage = netSuiteErrorDetails(error, "Error in Creating Call Log");
if (errorMessage.includes("'Subsidiary' was not found.")) {
errorMessage = errorMessage + " OR Permission violation: You need the 'Lists -> Subsidiaries -> View' permission to access this page. "
Expand All @@ -366,9 +359,17 @@ async function getCallLog({ user, callLogId, authHeader }) {
{
headers: { 'Authorization': authHeader }
});
const note = getLogRes.data?.message.includes('Call recording link') ?
getLogRes.data?.message.split('Note: ')[1].split('\nCall recording link')[0] :
getLogRes.data?.message.split('Note: ')[1].split('\n\n--- Created via RingCentral App Connect')[0];
let note = getLogRes.data.message.split('- Note: ')[1];
// const note = getLogRes.data?.message.includes('Call recording link') ?
// getLogRes.data?.message.split('Note: ')[1].split('\nCall recording link')[0] :
// getLogRes.data?.message.split('Note: ')[1].split('\n\n--- Created via RingCentral App Connect')[0];
note = note?.replace(/\n- Summary: .*/, '');
note = note?.replace(/\n- Contact Number: .*/, '');
note = note?.replace(/\n- Result: .*/, '');
note = note?.replace(/\n- Date\/Time: .*/, '');
note = note?.replace(/\n- Duration: .*/, '');
note = note?.replace(/\n- Call recording link: .*/, '');
console.log("Note: ", note);
return {
callLogInfo: {
subject: getLogRes.data.title,
Expand All @@ -395,7 +396,7 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
try {
const existingLogId = existingCallLog.thirdPartyLogId;
const callLogResponse = await axios.get(`https://${user.hostname.split(".")[0]}.suitetalk.api.netsuite.com/services/rest/record/v1/phonecall/${existingLogId}`, { headers: { 'Authorization': authHeader } });
let messageBody = callLogResponse.data.message;
let comments = callLogResponse.data.message;
let patchBody = { title: subject };
if (startTime !== undefined && duration !== undefined) {
let callStartTime = moment(moment(startTime).toISOString());
Expand All @@ -413,8 +414,6 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
console.log({ message: "Error in getting timezone in updateCallLog" });
}
const callEndTime = moment(callStartTime).add(duration, 'seconds');
const formatedStartTime = callStartTime.format('YYYY-MM-DD HH:mm:ss');
const formatedEndTime = callEndTime.format('YYYY-MM-DD HH:mm:ss');
let endTimeSlot = callEndTime.format('HH:mm');
if (startTimeSLot === endTimeSlot) {
//If Start Time and End Time are same, then add 1 minute to End Time because endTime can not be less or equal to startTime
Expand All @@ -423,39 +422,15 @@ async function updateCallLog({ user, existingCallLog, authHeader, recordingLink,
patchBody.startDate = callStartTime;
patchBody.startTime = startTimeSLot;
patchBody.endTime = endTimeSlot;
const contactNumberMatch = messageBody.match(/Contact Number: (\+?\d+)/);
let phoneNumber;
if (contactNumberMatch) {
phoneNumber = contactNumberMatch[1];
}
let callRecordingLink;
const recordingLinkMatch = messageBody.match(/Call recording link: (\S+)/);
if (recordingLinkMatch) {
callRecordingLink = recordingLinkMatch[1];
}
messageBody = `Note: ${note}${callRecordingLink ? `\nCall recording link ${callRecordingLink}` : ''}\n\n--- Created via RingCentral CRM Extension`;
}
if (!!recordingLink) {
const urlDecodedRecordingLink = decodeURIComponent(recordingLink);
if (messageBody.includes('\n\n--- Created via RingCentral App Connect')) {
messageBody = messageBody.replace('\n\n--- Created via RingCentral App Connect', `\nCall recording link${urlDecodedRecordingLink}\n\n--- Created via RingCentral App Connect`);
}
else {
messageBody += `\nCall recording link${urlDecodedRecordingLink}`;
}
}
else {
let originalNote = '';
if (messageBody.includes('\nCall recording link')) {
originalNote = messageBody.split('\nCall recording link')[0].split('Note: ')[1];
}
else {
originalNote = messageBody.split('\n\n--- Created via RingCentral App Connect')[0].split('Note: ')[1];
}
if (!!note && (user.userSettings?.addCallLogNote?.value ?? true)) { comments = upsertCallAgentNote({ body: comments, note }); }
if (!!subject && (user.userSettings?.addCallLogSubject?.value ?? true)) { comments = upsertCallSubject({ body: comments, title: subject }); }
if (!!startTime && (user.userSettings?.addCallLogDateTime?.value ?? true)) { comments = upsertCallDateTime({ body: comments, startTime, timezoneOffset: user.timezoneOffset }); }
if (!!duration && (user.userSettings?.addCallLogDuration?.value ?? true)) { comments = upsertCallDuration({ body: comments, duration }); }
if (!!result && (user.userSettings?.addCallLogResult?.value ?? true)) { comments = upsertCallResult({ body: comments, result }); }
if (!!recordingLink && (user.userSettings?.addCallLogRecording?.value ?? true)) { comments = upsertCallRecording({ body: comments, recordingLink }); }

messageBody = messageBody.replace(`Note: ${originalNote}`, `Note: ${note}`);
}
patchBody.message = messageBody;
patchBody.message = comments;
const patchLogRes = await axios.patch(
`https://${user.hostname.split(".")[0]}.suitetalk.api.netsuite.com/services/rest/record/v1/phoneCall/${existingLogId}`,
patchBody,
Expand Down Expand Up @@ -804,6 +779,80 @@ function netSuiteRestLetError(error, message) {
return errorMessage || message;
}

function upsertCallAgentNote({ body, note }) {
if (!!!note) {
return body;
}
const noteRegex = /^- Note:[^\n]*(?:\n(?!- ).*)*/m;
if (noteRegex.test(body)) {
body = body.replace(noteRegex, `- Note: ${note}\n`);
}
else {
body += `- Note: ${note}\n`;
}
return body;
}

function upsertCallResult({ body, result }) {
const resultRegex = RegExp('- Result: (.+?)\n');
if (resultRegex.test(body)) {
body = body.replace(resultRegex, `- Result: ${result}\n`);
} else {
body += `- Result: ${result}\n`;
}
return body;
}

function upsertCallDuration({ body, duration }) {
const durationRegex = /- Duration: (.+?)(?=\n|$)/g;
if (durationRegex.test(body)) {
body = body.replace(durationRegex, `- Duration: ${secondsToHoursMinutesSeconds(duration)}\n`);
} else {
body += `- Duration: ${secondsToHoursMinutesSeconds(duration)}\n`;
}
return body;
}

function upsertContactPhoneNumber({ body, phoneNumber, direction }) {
const phoneNumberRegex = RegExp('- Contact Number: (.+?)\n');
if (phoneNumberRegex.test(body)) {
body = body.replace(phoneNumberRegex, `- Contact Number: ${phoneNumber}\n`);
} else {
body += `- Contact Number: ${phoneNumber}\n`;
}
return body;
}

function upsertCallRecording({ body, recordingLink }) {
const recordingLinkRegex = RegExp('- Call recording link: (.+?)\n');
if (!!recordingLink && recordingLinkRegex.test(body)) {
body = body.replace(recordingLinkRegex, `- Call recording link: ${recordingLink}\n`);
} else if (!!recordingLink) {
body += `- Call recording link: ${recordingLink}\n`;
}
return body;
}

function upsertCallSubject({ body, title }) {
const subjectRegex = RegExp('- Summary: (.+?)\n');
if (subjectRegex.test(body)) {
body = body.replace(subjectRegex, `- Summary: ${title}\n`);
} else {
body += `- Summary: ${title}\n`;
}
return body;
}

function upsertCallDateTime({ body, startTime, timezoneOffset }) {
const dateTimeRegex = RegExp('- Date/Time: (.+?)\n');
if (dateTimeRegex.test(body)) {
const updatedDateTime = moment(startTime).format('YYYY-MM-DD hh:mm:ss A');
body = body.replace(dateTimeRegex, `- Date/Time: ${updatedDateTime}\n`);
} else {
body += `- Date/Time: ${moment(startTime).format('YYYY-MM-DD hh:mm:ss A')}\n`;
}
return body;
}

exports.getAuthType = getAuthType;
exports.getOauthInfo = getOauthInfo;
Expand Down

0 comments on commit 0e3e941

Please sign in to comment.