在转移呼叫时,Asterisk 中的 cdr 事件会存储多个呼叫日志

问题描述 投票:0回答:1

转接呼叫时,呼叫的生命周期会抛出 5 个不同的 cdr 事件。队列中的一个充当入站呼叫。

 this.ami.on('cdr', async (evt) => {
      if (evt.source == '//somerandomtestphonenumber//') {
        console.log(evt);
      }
      var destination: string = evt.destination.toString();

      var destinationcontext: string = evt.destinationcontext.toString();
      var disposition: string = evt.disposition.toString();
      var channel: string = evt.channel.toString();
      var destinationchannel: string = evt.destinationchannel.toString();
      var source: string = evt.source.toString();
      const landline: string = '+97715970084';
      var receiver: string = evt.destination.toString();
      var startTime: Date = new Date(evt.starttime);
      var answerTime: Date =
        evt.answertime == '' ? null : new Date(evt.answertime);
      var endTime: Date = new Date(evt.endtime);
      var totalTime: number = parseFloat(evt.duration);
      var callTime: number = parseFloat(evt.billableseconds);
      var holdTime: number = totalTime - callTime;
      var lastapplication = evt.lastapplication.toString();
      var duration: string = evt.duration.toString();
      var billableseconds: string = evt.billableseconds.toString();
      var uniqueId: string = evt.uniqueid.toString();

      // Voicemail
      if (destination == 's' && evt.lastapplication == 'VoiceMail') {
        const contextFirstPart = destinationcontext.substring(
          destinationcontext.indexOf('-') + 1,
          destinationcontext.length,
        );
        const queue = contextFirstPart.substring(
          contextFirstPart.indexOf('-') + 1,
          contextFirstPart.length,
        );
        // Note : Event is handled in voicemail service

        this.eventEmitter.emit(
          'voicemail-received',
          new VoicemailLogDto(
            queue,
            source,
            startTime,
            answerTime,
            endTime,
            duration,
            disposition,
            uniqueId,
            channel,
          ),
        );
      }

      if (
        !destinationcontext.includes('ivr') &&
        !disposition.includes('CONGESTION') &&
        !disposition.includes('FAILED')
      ) {
        var caller: string =
          source == landline
            ? evt.channel.split('/')[1].split('-')[0]
            : evt.source.toString();

        const callLogEntry = new CreateCalllogDto(
          caller,
          receiver,
          startTime,
          answerTime,
          endTime,
          evt.endtime,
          holdTime,
          totalTime,
          callTime,
          disposition,
          'unknown',
          uniqueId,
        );

        // For Outbound
        if (source == landline && destinationcontext == 'from-internal') {
          callLogEntry.type = 'outbound';
          if (process.env.NODE_ENV !== 'development') {
            await this.callLogService.create(callLogEntry);
          }

          if (
            callLogEntry.disposition == 'NO ANSWER' ||
            callLogEntry.disposition == 'BUSY'
          ) {
            this.realtimeGateway.emitData(
              'outbound-missed',
              'outbound-missed',
              [Role.ADMIN, Role.SUPERVISOR, Role.AGENT],
            );
          }
          if (callLogEntry.disposition == 'ANSWERED') {
            this.realtimeGateway.emitData(
              'outbound-success',
              'outbound-success',
              [Role.ADMIN, Role.SUPERVISOR, Role.AGENT],
            );
          }
        }

        // For inbound
        if (source != landline && destinationcontext == 'from-internal') {
          callLogEntry.type = 'inbound';
          var result = await this.callLogService.create(callLogEntry);
        }

        // For internal
        if (destinationchannel.includes('from-internal-xfer')) {
          callLogEntry.type = 'internal';
          await this.callLogService.create(callLogEntry);
        }

        // For queue
        if (source != landline && destinationcontext == 'ext-queues') {
          const queueLogEntry = new CreateQueueReceiveLogDto(
            caller,
            destinationchannel.substring(
              destinationchannel.indexOf('/') + 1,
              destinationchannel.indexOf('@'),
            ),
            receiver,
            'ANSWERED',
            uniqueId,
            evt.endtime,
          );
          if (process.env.NODE_ENV !== 'development') {
            await this.queueLogService.createQueueReceiveLog(queueLogEntry);
          }
        }
      }
    });
  }

这里,如果有正常呼叫(无分机),则该呼叫将充当入站呼叫,并且仅创建一次呼叫日志报告(抛出 2 个 cdr 事件,1 个用于队列,1 个用于入站) 但是,如果当前正在进行的呼叫中分机之间存在任何呼叫转移,则会有 5 个不同的 cdr 事件,其中 1 个用于队列,4 个事件用于入站,并且会为单个呼叫创建 4 个不同的日志报告。 如果呼叫生命周期中发生任何转接,是否有可能仅创建 1 个呼叫日志报告?

带有传输的 cdr 事件的 console.log(evt) 记录为:

{
  event: 'Cdr',
  privilege: 'cdr,all',
  accountcode: '',
  source: '/somerandomphonenumber/',
  destination: '4043',
  destinationcontext: 'from-internal',
  callerid: '"/somerandomphonenumber/" </somerandomphonenumber/>',
  channel: 'Local/4043@from-internal-0000032a;2',
  destinationchannel: 'SIP/4043-00000835',
  lastapplication: 'Dial',
  lastdata: 'SIP/4043,,trM(auto-blkvm)I',
  starttime: '2023-10-03 11:52:49',
  answertime: '2023-10-03 11:52:52',
  endtime: '2023-10-03 11:52:57',
  duration: '7',
  billableseconds: '4',
  disposition: 'ANSWERED',
  amaflags: 'DOCUMENTATION',
  uniqueid: '1696313269.25353',
  userfield: ''
}
{
  event: 'Cdr',
  privilege: 'cdr,all',
  accountcode: '',
  source: '/somerandomphonenumber/',
  destination: '4042',
  destinationcontext: 'from-internal',
  callerid: '"/somerandomphonenumber/" </somerandomphonenumber/>',
  channel: 'Local/4042@from-queue-00000327;2',
  destinationchannel: 'SIP/4042-0000082f',
  lastapplication: 'Dial',
  lastdata: 'SIP/4042,,trM(auto-blkvm)',
  starttime: '2023-10-03 11:52:30',
  answertime: '2023-10-03 11:52:36',
  endtime: '2023-10-03 11:52:49',
  duration: '18',
  billableseconds: '12',
  disposition: 'ANSWERED',
  amaflags: 'DOCUMENTATION',
  uniqueid: '1696313250.25287',
  userfield: ''
}
{
  event: 'Cdr',
  privilege: 'cdr,all',
  accountcode: '',
  source: '/somerandomphonenumber/',
  destination: '4042',
  destinationcontext: 'from-internal',
  callerid: '"/somerandomphonenumber/" </somerandomphonenumber/>',
  channel: 'Local/4042@from-queue-00000327;2',
  destinationchannel: 'Local/4043@from-internal-0000032a;1',
  lastapplication: 'Dial',
  lastdata: 'SIP/4042,,trM(auto-blkvm)',
  starttime: '2023-10-03 11:52:49',
  answertime: '2023-10-03 11:52:49',
  endtime: '2023-10-03 11:52:57',
  duration: '7',
  billableseconds: '7',
  disposition: 'ANSWERED',
  amaflags: 'DOCUMENTATION',
  uniqueid: '1696313250.25287',
  userfield: ''
}
{
  event: 'Cdr',
  privilege: 'cdr,all',
  accountcode: '',
  source: '/somerandomphonenumber/',
  destination: '4042',
  destinationcontext: 'from-internal',
  callerid: '"/somerandomphonenumber/" </somerandomphonenumber/>',
  channel: 'Local/4042@from-queue-00000327;2',
  destinationchannel: 'SIP/4043-00000835',
  lastapplication: 'Dial',
  lastdata: 'SIP/4042,,trM(auto-blkvm)',
  starttime: '2023-10-03 11:52:57',
  answertime: '2023-10-03 11:52:57',
  endtime: '2023-10-03 11:53:02',
  duration: '4',
  billableseconds: '4',
  disposition: 'ANSWERED',
  amaflags: 'DOCUMENTATION',
  uniqueid: '1696313250.25287',
  userfield: ''
}
{
  event: 'Cdr',
  privilege: 'cdr,all',
  accountcode: '',
  source: '/somerandomphonenumber/',
  destination: '602',
  destinationcontext: 'ext-queues',
  callerid: '"/somerandomphonenumber/" </somerandomphonenumber/>',
  channel: 'SIP/ntc_sip-0000082d',
  destinationchannel: 'Local/4042@from-queue-00000327;1',
  lastapplication: 'Queue',
  lastdata: '602,t,,,10,,,,,',
  starttime: '2023-10-03 11:52:27',
  answertime: '2023-10-03 11:52:27',
  endtime: '2023-10-03 11:53:02',
  duration: '34',
  billableseconds: '34',
  disposition: 'ANSWERED',
  amaflags: 'DOCUMENTATION',
  uniqueid: '1696313247.25273',
  userfield: ''
}
nestjs asterisk
1个回答
0
投票

了解您已经了解 PBX 上的拨号计划是如何组织的。

Asterisk 存储的 CDR 记录不是针对每个呼叫,而是针对每个使用的频道。除了它消除了该方案中的传出通道。

因此,如果您使用本地/频道,则您有两个始发频道和两个 CDR。

当您参加转接时,您的手机可能会先创建另一个(第三个)通道到目的地,然后与它通话,然后桥接旧通道。

您可以通过在其上发出NoCDR命令来消除某些通道,但它很复杂,并且对于某些有人值守的转接/硬件电话来说不会。

队列呼叫有一个呼入通道,以及与呼叫相关的无限(可以轻松100+)呼出通道。这就是它的工作原理。

在大多数情况下,您可以通过 linkedid/linkeduniq 字段连接所有这些 CDR。

© www.soinside.com 2019 - 2024. All rights reserved.