После завершении исходящего звонках, инициированного с Terrasoft XRM, и заполнения карточки, XRM выдает сообщение: "Телефонный номер еще не был набран. Вы хотите совершить звонок?" -- хотя вызов уже состоялся.

Замечено что, при инициировании звонка с телефона после ответа клиента, в открывшейся карточке клиента внизу проставляется "Время до соединения" и включается таймер "Время в разговоре", чего не происходит если исходящий звонок делается из XRM.

Подскажите, пожалуйста, что необходимо подправить в настройках. Используем Terrasoft XRM Distribution version 3.3.2.280 с модулем "Звонки"

Нравится

19 комментариев

Дорбрый день.
Начинать анализ в данном случае нужно с интеграции, точнее с того, с чем интегрированы.
Terrasoft - реагирует на события, герерируемые COM-объектом или драйвером TAPI.
Если время разгора не было запущена - это говорит о том, что не пришло соответсвующее событие.
В сервисе wnd_CallEditScript это событие отрабатывается функцией ProcessLineStateChangedNotify().

Уточните, с чем Вы интегрируетесь, пожалуйста. Подскажу куда дальше смотреть.

Интегрируемся в Asterisk 1.8.13 Используя Activa TSP 1.8.8

Судя по тому, что написано здесь: activa.sourceforge.net Activa TSP поддерживает TAPI драйвер.

Проверить все передаваемые оповещения в Terrasoft из Asterisk можно воспользовавшись одной из приложенных утилит (в tapi-test.rar).
Я пользуюсь Conference.

По Вашему совету воспользовались Conference. Во время тестирования получили следующие результаты: При инициации звонка из Conference карточка клиента в XRM открывается и после ответа клиента запускается таймер разговора, чего не происходит при звонках с самого XRM.

При анализе лога Сonference обнаружилось, что звонок, инициированный этим приложением - исходящий (первое сигнальное TAPI событие LINE_REPLY), а звонок, инициированный из ХRM - входящий (первое сигнальное TAPI событие LINE_APPNEWCALL после чего следует событие LINE_CALLSTATE). По следующим событиям и их содержанием звонки - идентичны.

conference.txt
xrm.txt

Добрый день.
Поговорил с разработчиками. У астериска часто расходжения со спецификацие TAPI 2.0 на которую они ориентировались : TAPI 2.0 (Windows)

По логу из XRM первым отрабатывает событие: LINE_APPNEWCALL
В конфигурации это событие обрабатывается в (Common\Library\scr_TAPIClientUtils) метод: this.OnTapiMessage

case (LINE_APPNEWCALL):
	this.InsertCall(DeviceID, MessageID, Param1, Param2, Param3);
	this.UpdateUserCurrentStateMenuItem();
	break;

Необходимо отладиться в этом case - проверить попадаете ли Вы в this.InsertCall.
Если да, выполняется ли условие:

if (!IsEmptyGUID(CallID)) {
			CallInfo.IsStartTimeCalc = true;
			Attributes('RecordID') = CallID;
			Attributes('IsInitializedByEvent') = true;
			var EmptyDefaultValues = GetNewDictionary();
			var CallEditWindow = 
				ShowEditWindowEx('wnd_CallEdit', Attributes, EmptyDefaultValues);
				CallEditWindow.Notify(CallEditWindow, 'RingStarted', CallInfo);
			return;
		}

В нем происходит запус таймера.

В указанном Вами блоке добавили строку для логирования:

			case (LINE_APPNEWCALL):   
				Log.Write(1, 'LINE_APPNEWCALL; DeviceID = '+DeviceID +', MessageID = '+MessageID+', Param1 = '+Param1+ ', Param2 = '+Param2+', Param3 = '+Param3);
				this.InsertCall(DeviceID, MessageID, Param1, Param2, Param3);
				this.UpdateUserCurrentStateMenuItem();
				break;

При звонке из Conferense в Журнале сообщений Terrasoft появляется запись: "LINE_APPNEWCALL; DeviceID = 66303, MessageID = 23, Param1 = 0, Param2 = 65928, Param3 = 2". При звонках из XRM в Журнале сообщений - тишина.

Добрый день, Катерина.
А Вы звонок инициируете прямо из террасофт? А если попробовать выполнить все действия из SoftPhone (или физический аппарат) Cisco? Подозреваю, что Cisco ATC просто не генерирует оповещение APPNEWCALL если линия находится состоянии IDLE (положена трубка) на аппарате (или SoftPhone).

Добрый день, Павел!

Звонок инициируем прямо с Террасофт. В первом посте я указывала, что при звонках с телефонного аппарата, таймеры в карточке клиента запускаются

Катерина, добрый день.

Проверьте содержимое функции ProcessChainEnterNotify(Data) в wnd_CallEditScript
Включение данного таймера происходит в ней, выражением tmrBeforeConnectionTime.IsEnabled = true;
В ранних версиях конфигурации здесь была оибка.

function ProcessChainEnterNotify(Data) { 
//debugger;
	Connector.Attributes('CallClientObject').ChainEnterNotify(Self, Data);
	UpdateWindowCaption();
	UpdateCallToolbar();
	if (Connector.Attributes('CallClientObject').ClientType == 'cctTAPI') {
		var Dataset = dlData.Dataset;
		if (Dataset('DirectionID') == cdOutgoing && !CallEdit.IsStartHoldAction) {
			tmrBeforeConnectionTime.IsEnabled = true;
		}
		var PhoneNumberDataField = Dataset.DataFields('PhoneNumber');
		if (Assigned(Data) && Data.OpponentNumber) {
			Dataset.Attributes('DisableStandartPhoneChangeEvent') = true;
			try {
				PhoneNumberDataField.Value = Data.OpponentNumber;
				FillSubjectInfoByOutgoingPhone(Dataset, Data.OpponentNumber);
			} finally {
				Dataset.Attributes('DisableStandartPhoneChangeEvent') = false;
			}
		} 
	}
}

Если код указанной функции не отличается у Вас - проверьте в отладчике вызов CallInformationsByHandle(DeviceID) в scr_TAPIClientUtils, происходит по событиям:

Обрабботчик "this.UpdateCall"

  • LINECALLSTATE_CONNECTED - оповещение в карточку звонка "CommutationStarted"
  • LINECALLSTATE_RINGBACK - оповещение в карточку звонка "ChainEnter"

Обрабботчик "this.OnTapiMessage"

  • LINE_CALLINFO - оповещение в карточку звонка "LineCallInfo"

В данном случае нас инересуют события ChainEnter в первую очередь и LineCallInfo.

Добрый день, Павел!

Код функции ProcessChainEnterNotify(Data) в wnd_CallEditScript в точности соответствует Вашему примеру.

В обработчик "this.UpdateCall" дописали строки для логирования:

this.UpdateCall = function (DeviceID, MessageID, Param1, Param2, Param3) {
		WriteInLogMessageName(Param1);
		var CallID = GetUniqueCallID(DeviceID);
		var CallEditWindow = FindEditWindow('wnd_CallEdit', 'IntegrationID', CallID);
		var NotifyMessage = null;
		var Data = null;
		switch (Param1) {
		...
		case LINECALLSTATE_RINGBACK:
			    Log.Write(1, 'LINECALLSTATE_RINGBACK');
				NotifyMessage = 'ChainEnter';
				Log.Write(1, 'NotifyMessage = ChainEnter');
				var CallInfo = this.TAPILine.CallInformationsByHandle(DeviceID)
				Data = {};
				switch (CallInfo.Direction) {
					case cdIncoming:
						Data.OpponentNumber = CallInfo.CallerID;
						break;                              
					case cdOutgoing:
						Data.OpponentNumber = CallInfo.CalledID;
						break;
				}
				break;
		...
		case LINECALLSTATE_CONNECTED:
			    Log.Write(1, 'LINECALLSTATE_CONNECTED')
				NotifyMessage = 'CommutationStarted';
				Log.Write(1, 'NotifyMessage = CommutationStarted');
				var CallInfo = this.TAPILine.CallInformationsByHandle(DeviceID)
				Data = {};
				switch (CallInfo.Direction) {
					case cdIncoming:
						Data.OpponentNumber = CallInfo.CallerID;
						break;
					case cdOutgoing:
						Data.OpponentNumber = CallInfo.CalledID;
						break;
				}

Обрабботчик "this.OnTapiMessage" также добавили строки для логирования:

This.OnTapiMessage = function (TAPILine, DeviceID, MessageID, Param1, Param2, Param3) {
		Log.Write(1, 'OnTapiMessage. DeviceID = ' + DeviceID + ' MessageID = ' + MessageID + ' ' + WriteInLogLineMessageName(MessageID)+', Param1 = '+Param1+ ' ' + WriteInLogMessageName(Param1)+ ', Param2 = '+Param2+', Param3 = '+Param3)
		switch (MessageID) {
			case (LINE_APPNEWCALL):   
				Log.Write(1, 'LINE_APPNEWCALL; DeviceID = '+DeviceID +', MessageID = '+MessageID+', Param1 = '+Param1+ ', Param2 = '+Param2+', Param3 = '+Param3);
				Log.Write(1, 'LINE_APPNEWCALL');
				this.InsertCall(DeviceID, MessageID, Param1, Param2, Param3);
				this.UpdateUserCurrentStateMenuItem();
				break;
			case LINE_CALLINFO:
			    Log.Write(1, 'LINE_CALLINFO; DeviceID = '+DeviceID +', MessageID = '+MessageID+', Param1 = '+Param1+ ', Param2 = '+Param2+', Param3 = '+Param3);
				Log.Write(1, 'LINE_CALLINFO')
				//this.UpdateCall(DeviceID, MessageID, LINECALLSTATE_CONNECTED, Param2, Param3);
				if (((Param1 & LINECALLINFOSTATE_CALLEDID) == LINECALLINFOSTATE_CALLEDID) 
					&& ((Param1 & LINECALLINFOSTATE_CALLERID) == LINECALLINFOSTATE_CALLERID) 
					&& ((Param1 & LINECALLINFOSTATE_CONNECTEDID) == LINECALLINFOSTATE_CONNECTEDID)) {
 
					var CallEditWindow = FindEditWindow('wnd_CallEdit', 
						'IntegrationID', GetUniqueCallID(DeviceID));
					var NotifyMessage = 'LineCallInfo';
					Log.Write(1, 'NotifyMessage = LineCallInfo')
					var CallInfo = this.TAPILine.CallInformationsByHandle(DeviceID);
					var Data = {};
					switch (CallInfo.Direction) {
						case cdIncoming:
							Data.OpponentNumber = CallInfo.CallerID;
							break;
						case cdOutgoing:
							Data.OpponentNumber = CallInfo.CalledID;
							break;
					}
					if (CallEditWindow && NotifyMessage) {
						CallEditWindow.Notify(CallEditWindow, NotifyMessage, Data);
					}
					this.UpdateUserCurrentStateMenuItem();
				}
				break;

При звонках из XRM в Журнале сообщений появляются сообщения:

(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 32 LINECALLSTATE_RINGBACK, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_RINGBACK
(W)	NotifyMessage = ChainEnter
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 256 LINECALLSTATE_CONNECTED, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_CONNECTED
(W)	NotifyMessage = CommutationStarted
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 16384 LINECALLSTATE_DISCONNECTED, Param2 = 1, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 1 LINECALLSTATE_IDLE, Param2 = 1, Param3 = 0

При звонках с Conference в Журнале сообщений получаем следующее:

(W)	OnTapiMessage. DeviceID = 66508 MessageID = 8 LINE_LINEDEVSTATE, Param1 = 512 LINECALLSTATE_PROCEEDING, Param2 = 0, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66508 MessageID = 23 LINE_APPNEWCALL, Param1 = 0 undefined, Param2 = 66355, Param3 = 2
(W)	LINE_APPNEWCALL; DeviceID = 66508, MessageID = 23, Param1 = 0, Param2 = 66355, Param3 = 2
(W)	LINE_APPNEWCALL
(W)	OnTapiMessage. DeviceID = 66355 MessageID = 2 LINE_CALLSTATE, Param1 = 32768 LINECALLSTATE_UNKNOWN, Param2 = 0, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66355 MessageID = 2 LINE_CALLSTATE, Param1 = 32 LINECALLSTATE_RINGBACK, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_RINGBACK
(W)	NotifyMessage = ChainEnter
(W)	OnTapiMessage. DeviceID = 66355 MessageID = 2 LINE_CALLSTATE, Param1 = 256 LINECALLSTATE_CONNECTED, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_CONNECTED
(W)	NotifyMessage = CommutationStarted
(W)	OnTapiMessage. DeviceID = 66355 MessageID = 2 LINE_CALLSTATE, Param1 = 16384 LINECALLSTATE_DISCONNECTED, Param2 = 1, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66355 MessageID = 2 LINE_CALLSTATE, Param1 = 1 LINECALLSTATE_IDLE, Param2 = 1, Param3 = 0

Т.е. в обоих случаях (как при звонках с Conference так и при звонках с XRM) нет LINE_CALLINFO, но при звонках с XRM есть LINE_APPNEWCALL

Катерина, есть несоответсвия между логами conference, xrm и последней предоставленной информации от Вас.
В логе "xrm" первым событие LINE_APPNEWCALL, в последних логах это событие наблюдается "При звонках с Conference": (W) LINE_APPNEWCALL; DeviceID = 66508, MessageID = 23, Param1 = 0, Param2 = 66355, Param3 = 2.

Разбираться становится тяжелее.

Направьте нам, пожалуйста Ваши сервисы, для анализа:
- Call\General\Main Grid\wnd_CallEditScript
- Common\Library\scr_CallClientUtils
- Common\Library\scr_TAPIClientUtils
- TAPI\Common\scr_TAPIUtils

Добрый день, Павел!

Сервисы в аттаче.

Катерина, добрый день, в сервисе wnd_CallEditScript сделайте исправления:
1) function ProcessLineCallInfoNotify() исправьте на function ProcessLineCallInfoNotify(Data)
2) В function ProcessLineStateChangedNotify(NotifyData) блок условия

		if ((State == dstInsert)||(State == dstEdit)) {
			Dataset('PhoneNumber') = NotifyData.OpponentNumber;
		}

заменить на

		if ((State == dstInsert)||(State == dstEdit)) {
			Dataset('PhoneNumber') = NotifyData.OpponentNumber;
			<strong>FillSubjectInfoByOutgoingPhone(Dataset, NotifyData.OpponentNumber);</strong>
		}

3) В обработчике закоментировать условие if (IsEmptyDateTime(Dataset('ConnectionDate')))

		function tmrBeforeConnectionTimeOnTimer(Timer) {
			var Dataset = dlData.Dataset;
			//if (IsEmptyDateTime(Dataset('ConnectionDate'))) {
				SetCurrentDateToDataField(Dataset, 'ConnectionDate');
			//}	
		}

На всякий случай можно еще повторить выгрузку scr_TAPIUtils, вместо него в файле у Вас прикреплен scr_TaskUtils.

Проверьте работу сразу после испарвления.
Пункты 1 и 3 существенны.

Добрый день, Павел!

Сделали пункты 1 и 3. К сожалению таймеры так и не запускаются.

При звонке из XRM в Журнеле:

(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 32 LINECALLSTATE_RINGBACK, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_RINGBACK
(W)	NotifyMessage = ChainEnter
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 256 LINECALLSTATE_CONNECTED, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_CONNECTED
(W)	NotifyMessage = CommutationStarted
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 16384 LINECALLSTATE_DISCONNECTED, Param2 = 1, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 2 LINE_CALLSTATE, Param1 = 1 LINECALLSTATE_IDLE, Param2 = 1, Param3 = 0

При звонке из Conference:

(W)	OnTapiMessage. DeviceID = 66508 MessageID = 8 LINE_LINEDEVSTATE, Param1 = 512 LINECALLSTATE_PROCEEDING, Param2 = 0, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66440 MessageID = 1 LINE_CALLINFO, Param1 = 8192 LINECALLSTATE_ONHOLDPENDTRANSFER, Param2 = 0, Param3 = 0
(W)	LINE_CALLINFO; DeviceID = 66440, MessageID = 1, Param1 = 8192, Param2 = 0, Param3 = 0
(W)	LINE_CALLINFO
(W)	OnTapiMessage. DeviceID = 66508 MessageID = 23 LINE_APPNEWCALL, Param1 = 0 undefined, Param2 = 66303, Param3 = 2
(W)	LINE_APPNEWCALL; DeviceID = 66508, MessageID = 23, Param1 = 0, Param2 = 66303, Param3 = 2
(W)	LINE_APPNEWCALL
(W)	OnTapiMessage. DeviceID = 66303 MessageID = 2 LINE_CALLSTATE, Param1 = 32768 LINECALLSTATE_UNKNOWN, Param2 = 0, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66303 MessageID = 2 LINE_CALLSTATE, Param1 = 32 LINECALLSTATE_RINGBACK, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_RINGBACK
(W)	NotifyMessage = ChainEnter
(W)	OnTapiMessage. DeviceID = 66303 MessageID = 2 LINE_CALLSTATE, Param1 = 256 LINECALLSTATE_CONNECTED, Param2 = 0, Param3 = 0
(W)	LINECALLSTATE_CONNECTED
(W)	NotifyMessage = CommutationStarted
(W)	OnTapiMessage. DeviceID = 66303 MessageID = 2 LINE_CALLSTATE, Param1 = 16384 LINECALLSTATE_DISCONNECTED, Param2 = 1, Param3 = 0
(W)	OnTapiMessage. DeviceID = 66303 MessageID = 2 LINE_CALLSTATE, Param1 = 1 LINECALLSTATE_IDLE, Param2 = 1, Param3 = 0

После выполнения пункта 2 во время компиляции происходит ошибка, скриншот во вложении.

Как Вы и просили выгрузили scr_TAPIUtils

Катерина, добрый день.
По п.2: при вставке в код здесь на форуме не очистились HTML теги:
в конфигурацию вместо

<strong>FillSubjectInfoByOutgoingPhone(Dataset, NotifyData.OpponentNumber);</strong>

должно быть:

FillSubjectInfoByOutgoingPhone(Dataset, NotifyData.OpponentNumber);

TAPIUtils проверю.

Катерина, Ваш scr_TAPIUtils от базового не отличается.
Нужно будет удаленно подклютиться и подстраивать Terrasoft под Asterisk где-то в обработчике this.OnTapiMessage

Добрый день!
Павел, подскажите, пожалуйста, как Вам или Вашим инженерам будет удобней подключиться к нашему XRM?

Добрый день, Катерина.
Подключиться можно посредством Ammyy Admin или Teamviewer. Для подтверждения готовности, обратитесь к нам по телефону +7 (495) 710-86-95 или Е-майл: support@terrasoft.ru, сославшись на номер обращения: 0137562.

Подключение желательно планировать хотя бы за несколько часов, чтобы мы могли запланировать и распределить задачи.

Здравствуйте.
Известно ли какое решение нашли данному вопросу?
Похожая ситуация, только с телефонией Cisco через TAPI драйвер.

Показать все комментарии