Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions lambdas/account-scoped/src/scheduled-jobs/create-schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ import { ScheduledJobType } from '@tech-matters/scheduled-jobs/dist/scheduled-jo
import { AccountScopedHandler, HttpError } from '../httpTypes';
import { newErr, newOk, Result } from '@tech-matters/result-type';
import { createScheduledJob, isValidVoicemailTask } from '@tech-matters/scheduled-jobs';
import { addHours } from 'date-fns/addHours';
import { addMinutes } from 'date-fns/addMinutes';
import { retrieveServiceConfigurationAttributes } from '../configuration/aseloConfiguration';
import { getTwilioClient } from '@tech-matters/twilio-configuration';

const supportedJobType: ScheduledJobType['jobType'][] = ['create-voicemail-schedule'];

const DEFAULT_MINUTES_VOICEMAIL_SCHEDULE = 1440; // 24 hours

export const handleCreateScheduleJob: AccountScopedHandler = async (
request,
accountSid,
Expand All @@ -39,7 +43,7 @@ export const handleCreateScheduleJob: AccountScopedHandler = async (
}

if (jobType === 'create-voicemail-schedule') {
const { voicemailTask } = request.body;
const voicemailTask = { ...(request.body.voicemailTask ?? {}), accountSid };

if (!isValidVoicemailTask(voicemailTask)) {
return newErr({
Expand All @@ -48,6 +52,10 @@ export const handleCreateScheduleJob: AccountScopedHandler = async (
});
}

// eslint-disable-next-line @typescript-eslint/naming-convention
const { voicemail_schedule_retry_later_minutes } =
await retrieveServiceConfigurationAttributes(await getTwilioClient(accountSid));

const scheduleName = `${jobType}-${voicemailTask.attributes.callSid}`;
const {
workflowSid,
Expand All @@ -56,7 +64,7 @@ export const handleCreateScheduleJob: AccountScopedHandler = async (
from,
name,
routingAttributes,
callbackAttemptsMade,
callbackAttempts,
maxCallbackAttempts,
},
} = voicemailTask;
Expand All @@ -65,7 +73,7 @@ export const handleCreateScheduleJob: AccountScopedHandler = async (
voicemailTask: {
accountSid,
attributes: {
callbackAttemptsMade,
callbackAttempts,
from,
callSid,
routingAttributes,
Expand All @@ -75,7 +83,12 @@ export const handleCreateScheduleJob: AccountScopedHandler = async (
workflowSid,
},
};
const scheduleExpression = `at(${addHours(Date.now(), 24).toISOString().slice(0, 19)})`; // 24 hours later
const scheduleExpression = `at(${addMinutes(
Date.now(),
voicemail_schedule_retry_later_minutes ?? DEFAULT_MINUTES_VOICEMAIL_SCHEDULE,
)
.toISOString()
.slice(0, 19)})`;

await createScheduledJob({
scheduledJob,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const recordingCompleteCallback: AccountScopedHandler = async (
accountSid,
routingAttributes: body.routingAttributes ? JSON.parse(body.routingAttributes) : {},
receivedTime: receivedTime.toISOString(),
callbackAttemptsMade: 0,
callbackAttempts: [],
maxCallbackAttempts: maxCallbackAttempts,
callSid,
from,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ describe('recordingCompleteCallback', () => {
callSid: TEST_CALL_SID,
channelType: channelTypes.VOICEMAIL,
customChannelType: channelTypes.VOICEMAIL,
callbackAttemptsMade: 0,
callbackAttempts: [],
maxCallbackAttempts: 3,
receivedTime: RECORDING_START_TIME.toISOString(),
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,56 @@
[
{
"name": "child",
"label": "Child calling about self",
"type": "button",
"category": "data"
},
{
"name": "caller",
"label": "Someone calling about a child",
"type": "button",
"category": "data"
},
{
"name": "silent",
"label": "Silent",
"type": "button",
"category": "non-data"
},
{
"name": "hangup",
"label": "Hang up",
"type": "button",
"category": "non-data"
},
{
"name": "abusive",
"label": "Abusive",
"type": "button",
"category": "non-data"
},
{
"name": "thanks",
"label": "Thank you",
"type": "button",
"category": "non-data"
},
{
"name": "questions",
"label": "Questions",
"type": "button",
"category": "non-data"
},
{
"name": "emergency",
"label": "Emergency",
"type": "button",
"category": "non-data"
}
{
"name": "child",
"label": "Child calling about self",
"type": "button",
"category": "data"
},
{
"name": "caller",
"label": "Someone calling about a child",
"type": "button",
"category": "data"
},
{
"name": "silent",
"label": "Silent",
"type": "button",
"category": "non-data"
},
{
"name": "hangup",
"label": "Hang up",
"type": "button",
"category": "non-data"
},
{
"name": "abusive",
"label": "Abusive",
"type": "button",
"category": "non-data"
},
{
"name": "thanks",
"label": "Thank you",
"type": "button",
"category": "non-data"
},
{
"name": "questions",
"label": "Questions",
"type": "button",
"category": "non-data"
},
{
"name": "emergency",
"label": "Emergency",
"type": "button",
"category": "non-data"
},
{
"name": "voicemail",
"label": "Complete Voicemail",
"type": "button",
"category": "non-data"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
"BottomBar-CancelNewCaseAndClose": "Sí, Cancelar el Nueva ECUPHS y Cierre",
"BottomBar-AddThisContactToExistingCase": "Agregar esta Conversación a ECUPHS existente",
"ResumeContactButtonText": "Reanudar la Conversación Fuera de Línea",
"CallType-CloseContact": "Cerrar Conversación",
"CallType-SaveDialog-CloseContact": "Cerrar Conversación",
"ConnectDialog-Caller": "¿Copiar información del llamante de este registro a un nueva conversación?",
"ContactDetails-GeneralDetails-ContactSummary": "Resumen de Conversación",
"ContactDetails-UnsavedContact": "Conversación no guardada",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
"CallType-blank": "Blank",
"CallType-caller": "Someone contacting about a person of concern ",
"CallType-child": "Person contacting about self",
"CallType-CloseContact": "Close Contact",
"CallType-SaveDialog-CloseContact": "Close Contact",
"CallType-hangup": "Hang up",
"CallType-joke": "Joke",
"CallType-silent": "Silent",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"SearchResultsIndex-ViewContacts": "View Interactions",
"SearchResultsIndex-NonDataContacts": "Non-Data Interactions",
"SearchForm-Counselor": "Tinkle Friend",
"CallType-CloseContact": "Close Interaction",
"CallType-SaveDialog-CloseContact": "Close Interaction",
"CallTypeButtons-Categorize": "categorize this interaction",
"CallTypeButtons-Or": "Or was this interaction…",
"ConnectDialog-Child": "Copy client information from this record to new interaction?",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"CallType-hangup": "Hang up",
"CallType-wrongnumber": "Wrong Number",
"CallType-abusive": "Abusive",
"CallType-CloseContact": "Close Event",
"CallType-SaveDialog-CloseContact": "Close Event",
"CallTypeButtons-Categorize": "categorize this event",
"CallTypeButtons-Or": "Or was this event…",
"ConnectDialog-Child": "Copy person information from this record to new event?",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"CallType-hangup": "Hang up",
"CallType-wrongnumber": "Wrong Number",
"CallType-abusive": "Abusive",
"CallType-CloseContact": "Close Contact",
"CallType-SaveDialog-CloseContact": "Close Contact",
"CallTypeButtons-Categorize": "categorize this contact",
"CallTypeButtons-Or": "Or was this contact…",
"ConnectDialog-Child": "Copy support seeker information from this record to new contact?",
Expand Down Expand Up @@ -500,7 +500,6 @@
"BottomBar-SaveOnClose": "Save Changes?",
"BottomBar-DontSave": "No, Don't Save",
"BottomBar-Save": "Yes, Save",
"Toolkit-ConfirmTextOne": "You will be redirected to an external knowledge management system.",
"Toolkit-ConfirmTextTwo": "Are you sure you want to continue?",
"MaskIdentifiers": "XXXXXX",
"UnmaskPhoneNumber": "Phone Number Revealed",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"CallSummary-Counselor": "Specialist: ",
"CallType-child": "Help Seeker calling about self",
"CallType-caller": "Someone calling about a help seeker",
"CallType-CloseContact": "Close Connection",
"CallType-SaveDialog-CloseContact": "Close Connection",
"CallTypeButtons-Categorize": "categorize this connection",
"CallTypeButtons-Or": "Or was this connection…",
"ConnectDialog-Child": "Copy help seeker information from this record to new connection?",
Expand Down
56 changes: 41 additions & 15 deletions lambdas/packages/scheduled-jobs/src/scheduled-job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,66 @@ export type CreateVoicemailSchedule = {
callSid: string;
from: string;
name: string;
callbackAttemptsMade: number;
callbackAttempts: [string, string][];
maxCallbackAttempts?: number;
routingAttributes?: Record<string, any>;
};
workflowSid: string;
};
};

export const isValidVoicemailTask = (
task: any,
): task is CreateVoicemailSchedule['voicemailTask'] => {
if (!task || typeof task !== 'object') return false;
if (!task.accountSid || typeof task.accountSid !== 'string') return false;
if (!task.workflowSid || typeof task.workflowSid !== 'string') return false;
if (!task.attributes || typeof task.attributes !== 'object') return false;
if (!task.attributes || typeof task.attributes !== 'object') return false;
if (!task.attributes.callSid || typeof task.attributes.callSid !== 'string')
if (!task || typeof task !== 'object') {
console.debug('isValidVoicemailTask: invalid task');
return false;
}
if (!task.accountSid || typeof task.accountSid !== 'string') {
console.debug('isValidVoicemailTask: invalid task.accountSid');
return false;
}
if (!task.workflowSid || typeof task.workflowSid !== 'string') {
console.debug('isValidVoicemailTask: invalid task.workflowSid');
return false;
}
if (!task.attributes || typeof task.attributes !== 'object') {
console.debug('isValidVoicemailTask: invalid task.attributes');
return false;
}
if (!task.attributes.callSid || typeof task.attributes.callSid !== 'string') {
console.debug('isValidVoicemailTask: invalid task.attributes.callSid');
return false;
}
if (!task.attributes.from || typeof task.attributes.from !== 'string') {
console.debug('isValidVoicemailTask: invalid task.attributes.from');
return false;
}
if (!task.attributes.name || typeof task.attributes.name !== 'string') {
console.debug('isValidVoicemailTask: invalid task.attributes.name');
return false;
if (!task.attributes.from || typeof task.attributes.from !== 'string') return false;
if (!task.attributes.name || typeof task.attributes.name !== 'string') return false;
}
if (
!task.attributes.callbackAttemptsMade ||
typeof task.attributes.callbackAttemptsMade !== 'number'
)
!task.attributes.callbackAttempts ||
!Array.isArray(task.attributes.callbackAttempts)
) {
console.debug('isValidVoicemailTask: invalid task.attributes.callbackAttempts');
return false;
}
if (
task.attributes.maxCallbackAttempts &&
typeof task.attributes.maxCallbackAttempts !== 'number'
)
) {
console.debug('isValidVoicemailTask: invalid task.attributes.maxCallbackAttempts');
return false;
}
if (
task.attributes.routingAttributes ||
task.attributes.routingAttributes &&
typeof task.attributes.routingAttributes !== 'object'
)
) {
console.debug('isValidVoicemailTask: invalid task.attributes.routingAttributes');
return false;
}

return true;
};
Expand Down
6 changes: 3 additions & 3 deletions lambdas/packages/voicemail/src/createVoicemailTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const DEFAULT_MAX_CALLBACK_ATTEMPTS = 3;
export const createVoicemailTask = async ({
accountSid,
workflowSid,
callbackAttemptsMade,
callbackAttempts,
receivedTime,
from,
name,
Expand All @@ -33,7 +33,7 @@ export const createVoicemailTask = async ({
}: {
accountSid: AccountSID;
receivedTime: string;
callbackAttemptsMade: number;
callbackAttempts: [string, string][];
maxCallbackAttempts?: number;
callSid: string;
from: string;
Expand All @@ -52,7 +52,7 @@ export const createVoicemailTask = async ({
isVoicemail: true,
routingAttributes: routingAttributes ?? {},
receivedTime,
callbackAttemptsMade,
callbackAttempts,
maxCallbackAttempts: maxCallbackAttempts ?? DEFAULT_MAX_CALLBACK_ATTEMPTS,
callSid,
from,
Expand Down
2 changes: 1 addition & 1 deletion lambdas/scheduled-jobs-processor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const handleCreateVoicemailJob = async ({
callSid: attributes.callSid,
from: attributes.from,
receivedTime: new Date().toISOString(),
callbackAttemptsMade: attributes.callbackAttemptsMade,
callbackAttempts: attributes.callbackAttempts,
workflowSid,
});

Expand Down
1 change: 1 addition & 0 deletions plugin-hrm-form/src/HrmFormPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ const setUpComponents = (featureFlags: FeatureFlags, setupObject: ReturnType<typ
Channels.setupTelegramChatChannel();
Channels.setupInstagramChatChannel();
Channels.setupLineChatChannel();
Channels.setupVoicemailChannel();

setUpViewMaskedVoiceNumber();

Expand Down
Loading
Loading