Начало Блог

Телефонна централа с CRM за клиника с няколко обекта

Казус От Валентин Кирилов 8 мин четене

Клиника с няколко обекта има един проблем, който изглежда малък, докато не се сблъскате с него: пациентът не знае и не го интересува в кой обект звъни. Той звъни на клиниката. Всичко след това е ваша работа.

Това е историята на телефонната платформа, която изградихме за дентална практика с три локации в София – от заданието до решенията, които се оказаха важни. Показаните екрани са макети с примерни данни; архитектурата и числата за самата система са истински.

Телефонната платформа за клиники: указател с вътрешни номера за три обекта

Заданието

Три рецепции, три публикувани мобилни номера, никаква обща история. Пациент, който е звънял в един обект и после в друг, втория път беше непознат. Пропуснатите обаждания бяха пропуснати; никой не знаеше колко са.

Клиниката искаше един номер, който се държи като една клиника: история на обажданията по пациент, а не по апарат; заявки за обратно обаждане като списък, за който някой отговаря; и жив изглед какво се случва по линиите. Две ограничения оформиха всичко останало. Първо, системата трябваше да е собствена: запис, в който пациент обяснява защо се обажда, е здравна информация и клиниката не искаше той да стои при нает външен доставчик. Второ, никакви нови стационарни телефони. Рецепциите вдигат на служебните мобилни, които вече носят, и на компютър, ако са пред него.

Какво се случва с едно обаждане

Схема на потока: един публикуван номер, проверка на работното време по локация, всички рецепции звънят едновременно, после прието или на опашка
Пътят на входящо обаждане, както е конфигурирана системата днес.

Централата първо проверява дали клиниката е отворена. Всяка локация има собствено работно време и празници, и те се различават повече, отколкото бихте предположили: един обект не работи в понеделник, друг няма съботни часове. Публикуваната линия следва най-широкия график. Извън работно време обаждащият се чува записано съобщение и може да остави гласова поща; записът се изпраща по имейл на клиниката като аудио файл, така че сутринта започва със списък, а не с догадки.

В работно време всички рецепции звънят едновременно. Всяка звъни по два канала паралелно: софтфонът в браузъра на компютъра на рецепцията и служебният мобилен, през линията на телекома. Първият вдигнал поема разговора, а останалите спират. Ако всички линии са заети, обаждащият се чака с музика, системата опитва отново всеки десет секунди и само след три минути без свободен човек преминава към гласова поща. Никой не чува сигнал „заето“.

Менюто, което изградихме и изключихме

Първият проект имаше гласово меню: натиснете 2 за спешен случай, 3 за ортодонтия, иначе изчакайте рецепция. Менюто съществува, тествано е и е изключено по подразбиране.

Причината е начинът, по който клиниката реално работи. Рецепциите вдигат на мобилни, които вече са в джобовете им; най-бързият път от позвъняване до човек надви всяко меню, което можехме да проектираме. Спешният път се сля със същото поведение: всяко обаждане и без това звъни на всички едновременно, а точно за това служи спешният път, и никой пациент с болка не трябва първо да намери правилната цифра. Менюто остава в кода за деня, в който обемите го оправдаят. Изграждането му не беше загуба; пускането му щеше да бъде.

Какво вижда операторът

Макет на екрана на оператора: входящо обаждане с разпознат пациент, състояние на трите рецепции, заявки за обратно обаждане и последни записи
Какво вижда операторът, когато телефонът звънне. Примерни данни.

При входящо обаждане екранен прозорец показва номера, към коя рецепция е насочено, колко пъти този номер е звънял преди и кога, а след свързване с програмата за пациенти на клиниката – и името на пациента с връзка директно към картона му. Броят на предишните обаждания се изчислява по последните девет цифри на номера, така че пациент, който звъни от същия телефон с различен префикс, си остава същият пациент.

Живото табло показва състоянието на всяка линия в момента, в който се промени: звъни, в разговор, свободна, и колко от каналите на телекома са заети. Това върви през WebSockets, а не през таймер за презареждане. Оператор, който вижда, че колега в друг обект е свободен, прехвърля разговора; оператор, който не вижда, оставя пациента да чака. Реалното време не е показност, а въпрос кои решения изобщо са възможни.

Заявките за обратно обаждане са списък със статус, а не бележка на хартия. Всяко обаждане се записва, след като бъде прието, и записът се слуша в браузъра от историята на обажданията. Същата история захранва малък набор числа: пропуснати обаждания по локация, средно време до вдигане, най-натоварените часове.

Собствена централа – в облака

„Собствена“ обикновено извиква образа на сървър в шкаф. Тази е виртуален сървър, който клиниката контролира, в център за данни, с малък шлюз в клиниката и криптиран тунел между двете.

Схема: шлюзът на клиниката и линията на телекома от една страна, тунел към сървър с централата, бекенда, базата и таблото, с нощни резервни копия и мониторинг
Как са разположени частите. Линията на телекома никога не влиза в мрежата на клиниката.

Телекомът доставя телефонната линия като мрежов кабел. Този кабел влиза в шлюза, а не в суича на клиниката: адресите на доставчика биха се сблъскали с компютрите на рецепцията и биха съборили мрежата. От шлюза WireGuard тунел пренася телефонния трафик до сървъра, както ако беше локален. На сървъра Docker пуска четири неща: самата централа (Asterisk), Node.js бекенд, който държи правилата за насочване, работното време и интеграциите, PostgreSQL за историята и конфигурацията и React таблото зад Nginx с TLS.

Няколко решения в тази кутия заслужават да се назоват. Всички телефони и линията на телекома са ограничени до един аудио кодек, така че централата предава звука, без да го транскодира; това държи малкия сървър спокоен и качеството на гласа високо. Входът изисква еднократен код от приложение за автентикация, което за система с история на пациентски обаждания не е лукс. Всяка нощ скрипт прави копие на базата и архивира папката със записите в един файл и пази седем дни назад. На всеки пет минути друг скрипт проверява дали централата работи, дали базата отговаря и дали има място на диска, и изпраща съобщение в Telegram, ако нещо от това не е така.

Интеграция със система, която още никой не беше назовал

Когато започнахме, за програмата за пациенти на клиниката се знаеше, че съществува, но не и как се казва. Затова интеграционният слой беше изграден неутрално спрямо доставчика: при всяко позвъняване бекендът пита конфигурируем адрес чий е номерът, чака най-много три секунди и поглъща всяка грешка. Бавна или липсваща система никога не забавя звънящо обаждане. Когато програмата за пациенти предостави справка, един адрес влиза в конфигурацията и екранният прозорец започва да показва имена; без промяна в кода.

В обратната посока всяко събитие по обаждане (звъни, прието, приключено) се изпраща към всеки адрес, който клиниката конфигурира, подписано така, че приемащата система да провери, че идва от централата. Така програма за пациенти, табло или инструмент за автоматизация може да реагира на обажданията, без някой да пише конектор по поръчка.

Тестване на телефонна система без телефон

Телефонните системи са трудни за тестване, защото интересното поведение е времево: кой звъни кога, какво става на петнадесетата секунда, какво става, когато петата линия бъде заета. Бекендът носи 26 автоматични теста, а таблото – 16, и те покриват точно поведението, което клиниката поиска: три рецепции звънят едновременно, номерът на обаждащия се се запазва при прехвърляне към мобилен, обаждащ се чака на опашка вместо да попадне в гласова поща при заети линии, опашката изтича след максималното изчакване и последователният резервен вариант работи за групите, конфигурирани така. Нула употреби на any в TypeScript кода – правило, а не хвалба: телефонна система е лошо място да откриеш грешка в типовете.

Статус

Изградена и тествана от край до край – и още не е на живо пред пациенти. Пускането чака две решения и една зависимост, които стоят извън кода: кой от трите съществуващи номера става единният публикуван номер, договорът с телекома за линията (колко едновременни канала, което определя колко обаждащи се могат да звънят на мобилни едновременно) и програмата за пациенти да предостави своята справка. Казваме го ясно, защото разстоянието между „изградено“ и „в употреба“ е точно това, което обикновено се замазва.

Какво отнасяме нататък

Три неща. Насочването на обажданията трябва да отразява как организацията реално вдига, а не как схемата казва, че трябва; решението за едновременно звънене дойде от наблюдение на рецепциите, а не от документ с изисквания. Реалното време не е украса. И интеграционен слой, който не предполага нищо за другата система, е този, който се пуска – защото другата система никога не е готова, когато вие сте.

Имате няколко обекта с телефония, разпъната неудобно между тях? Разкажете ни как е организирана днес.

← Всички публикации