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
2 changes: 1 addition & 1 deletion migrations/sqls/20260610000000-calling-routing-down.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ declare
v_purchasing_strategy sms.number_purchasing_strategy;
begin
-- Create the phone number record
insert into sms.all_phone_numbers (
insert into sms.phone_numbers (
sending_location_id,
phone_number
)
Expand Down
26 changes: 13 additions & 13 deletions src/apis/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import config from '../config';
import { pgPool } from '../db';
import { auth, ClientAuthenticatedRequest } from '../lib/auth';
import {
countAvailableCallingNumbers,
getCallingNumberForSendingLocation,
getCallingNumberWithCount,
requestCallingNumber,
} from '../lib/process-call';
import { getFromNumberMapping } from '../lib/process-message';
Expand Down Expand Up @@ -45,9 +44,13 @@ app.get('/get-number-for-contact', auth.client, async (req, res) => {
[profile_id]
);

if (!profile) {
return res.status(404).json({ error: 'Profile not found' });
}

const { daily_calling_limit } = profile;

if (!profile || daily_calling_limit === null) {
if (daily_calling_limit === null) {
return res.status(400).json({
error:
'Profile does not have calling configured (daily_calling_limit not set)',
Expand All @@ -61,16 +64,19 @@ app.get('/get-number-for-contact', auth.client, async (req, res) => {
});

if (prevMapping !== undefined) {
const { sending_location_id, from_number } = prevMapping;

const {
rows: [{ count }],
} = await client.query<{ count: string }>(
`select count(*) from sms.outbound_calls
where from_number = $1
where sending_location_id = $1
and from_number = $2
and created_at > date_trunc('day', now() at time zone 'America/Los_Angeles') at time zone 'UTC'`,
[prevMapping.from_number]
[sending_location_id, from_number]
);
const todayCallCount = parseInt(count, 10);

const todayCallCount = parseInt(count, 10);
if (todayCallCount < daily_calling_limit) {
await client.query(
`update sms.from_number_mappings
Expand Down Expand Up @@ -110,7 +116,7 @@ app.get('/get-number-for-contact', auth.client, async (req, res) => {
.json({ error: 'No sending location found for contact' });
}

const fromNumber = await getCallingNumberForSendingLocation(
const { fromNumber, availableCount } = await getCallingNumberWithCount(
client,
sendingLocationId,
daily_calling_limit
Expand All @@ -131,12 +137,6 @@ app.get('/get-number-for-contact', auth.client, async (req, res) => {
[fromNumber, sendingLocationId]
);

const availableCount = await countAvailableCallingNumbers(
client,
sendingLocationId,
daily_calling_limit
);

if (availableCount <= sendingLocationMinCallingNumbers) {
await requestCallingNumber(client, sendingLocationId);
}
Expand Down
41 changes: 19 additions & 22 deletions src/lib/process-call.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,32 @@
import { PoolOrPoolClient } from '../db';
import { chooseAreaCodeForSendingLocation } from './process-message';

export const getCallingNumberForSendingLocation = async (
export const getCallingNumberWithCount = async (
client: PoolOrPoolClient,
sendingLocationId: string,
dailyCallingLimit: number
): Promise<string | null> => {
): Promise<{ fromNumber: string | null; availableCount: number }> => {
const {
rows: [row],
} = await client.query<{ phone_number: string | null }>(
`select phone_number
from sms.get_available_calling_numbers($1, $2)
order by priority asc, call_count asc
limit 1`,
[sendingLocationId, dailyCallingLimit]
);
return row?.phone_number ?? null;
};

export const countAvailableCallingNumbers = async (
client: PoolOrPoolClient,
sendingLocationId: string,
dailyCallingLimit: number
): Promise<number> => {
const {
rows: [{ count }],
} = await client.query<{ count: string }>(
'select count(*) from sms.get_available_calling_numbers($1, $2)',
} = await client.query<{ phone_number: string | null; count: string }>(
`with available as (
select phone_number, priority, call_count
from sms.get_available_calling_numbers($1, $2)
),
ranked as (
select
first_value(phone_number) over (order by priority, call_count) as phone_number,
count(*) over () as count
from available
limit 1
)
select phone_number, count from ranked`,
[sendingLocationId, dailyCallingLimit]
);
return parseInt(count, 10);
return {
fromNumber: row?.phone_number ?? null,
availableCount: row?.count ? parseInt(row.count, 10) : 0,
};
};

export const requestCallingNumber = async (
Expand Down
Loading