Call flow innerhalb / außerhalb der Geschäftszeiten

DKA-Service

Customer
Mitglied seit
14. April 2025
Beiträge
8
Hallo
Ich habe folgende Konstellation:
SIP Trunk mit DID Nummern 2 stellig
20-29 Standort A
30-39 Standort B
Rufgruppe für Standort A ist die 72, für Standort B die 73
Die Rufnummern des Standortes sind den entsprechenden Rufgruppen zugeordnet
Abhängig ob innerhalb oder Außerhalb der Geschäftszeiten werden unterschiedliche Ansagen abgespielt.

Innerhalb der Geschäftszeiten sollen die Teilnehmer direkt von extern erreichbar sein. Außerhalb der Geschäftszeiten sollen alle Anrufe zur entsprechenden Rufgruppe gehen.
Von intern sollen grundsätzlich alle Teilnehmer immer erreichbar sein.

Problem:
aktiviere ich bei den Teilnehmern die Geschäftszeiten, werden die externen Anrufe entsprechend verteilt. Allerdings sind die Mitarbeiter außerhalb der Geschäftzeiten nicht von intern erreichbar.
deaktiviere ich die Zeiten, sind die Mitarbeiter generell von intern und extern erreichbar.

Ich versuche das Problem über ein Anrufscript zu lösen. Mittels "Date & Time Condition" und der Funktion "Transfer" habe ich das für "außerhalb der Geschäftszeiten" hin bekommen.
Dabei fehlt mir die Info, wie ich innerhalb der Geschäftszeiten der "Transfer" Funktion sage, dass der Ruf zur gewählten Rufnummer durchgestellt werden soll.
Oder muss ich für jede DID ein eigenes Anrufscript bauen?

Viele Grüße
 
Ich würde die Logik anders herum aufbauen.
Normalbetrieb über die Anlage einrichten und außerhalb der GZ über eine Interception auf die Gruppen routen.

Schau dir mal die unteren 3 Beispiele aus dem Store an.
Aus der Erinnerung müsste timebasecallscript.cs in die richtige Richtung gehen. Da müsstest du „nur noch“ abhängig vom Standort / der DID das Ziel definieren. Bonus wäre dann das Lesen der Zeiten aus den Geschäftszeiten der Anlage.

Gruß
 
  • Like
Reaktionen: fxbastler
@DKA-Service

Da gibt es - wie so oft - mehrere Möglichkeiten.

1.
Grundsätzlich braucht man gar kein Anrufskript.
Man baut sich eine Ausnahme: bei einer 3CX mit 2stell. NSt. Nummern alle Anrufe von 100-999999999999999 außerhalb der GZ an die entspr. RG weiterleiten. Evtl. das Gleiche noch einmal für Anrufe die mit + beginnen. Das darf man eben für alle NSt. die es betrifft einrichten. Das kann man auch mit der 3CX Configuration API - xapi - automatisiert ausrollen.

2.
Eine andere Möglichkeiten ist: alle diese Anrufe auf ein Abteilung leiten, außerhalb der GZ auf die entspr. RG, innerhalb der GZ auf ein Anrufskript und das verteilt entspr. der angerufenen DID usw.. So ein Skript und weitere ähnliche gibt es schon im Forum, einfach mal suchen.
Bedingung dabei ist evtl., dass die DID den int. Durchwahlen entsprechen müssen bzw. man dafür noch eine Umsetzungstabelle braucht.

3.
Falls das zu viele NSt. sind, man das nicht überall manuell einstellen will und mit der xapi nicht klar kommt, dann kann man dafür ein Anrufskript nutzen, was bei allen eingehenden Anrufen auf dem SIP Trunk startet. Wenn schon so etwas wie das holiday.cs verwendet wird muss man das eben da mit einbauen.
Der eingehende Anruf wird verfolgt auf welche NSt. der geht, es wird überprüft ob die NSt. / deren Hauptabteilung innerhalb oder außerhalb der GZ ist und davon abhängig wird entweder der normale Anrufablauf verfolgt oder an eine vordefinierte RG weitergeleitet.
So ein Anrufskript gibt es schon, nur nicht im öffentlichen Forum. Wenn da wirklich Bedarf besteht würde ich das mal fallenlassen. Das nennt sich incoming_calls.cs, damit werden die ehem. eing. Regeln nachgebaut und einiges mehr und das beinhaltet auch die Behandlung solcher Fälle wie deinen.

4.
Alle weiteren Verfahren braucht man schon nicht mehr, 1 bis 3 sollte aktuell reichen.
 
Zuletzt bearbeitet:
Vielen Dank für die Hinweise.

Ich werde die Variante 1 von fxbastler testen.
Mit einer Ausnahme hatte ich das versucht, aber anders herum. Außerhalb der Geschäftszeiten die Anrufe von internen Rufnummern zulassen. Das hatte jedoch nicht den Erfolg gebracht.
Daher wollte ich es über ein Script realisieren.

Danke erst einmal.
 
Die Idee mit dem timebasecallscript.cs ist in dem Fall glaube ich die einfachere. Den Script passt du dir so an, das er jeweils nur ausserhalb der Geschäftszeiten greift. Dazu dann eine Erkennung der DID einbauen und sagen: Wenn DID ist zwischen 20 und 29 dann an Ziel A, wenn did zwischen 30 und 39 dann an Ziel B. Alles andere Standard.
 
@patrickb
Ich bin gerade erst dabei, mich in die Scripts einzuarbeiten.
Wie mache ich die Erkennung der DID konkret?
 
Ungetestet, aber das Prinzip ist hoffentlich ersichtlich.
Z28 & 29 Die Ziele der Weiterleitungen
Z73 & 74 Die DIDs auf die weitergeleitet wird.

Der Block ab Z79 wurde einfach noch einmal kopiert für die Bearbeitung des zweiten Blockes

C#:
/*
 * Time Base Call Routing - Use code with caution!
 * Calls will be intercepted and redirected to the specified DestinationDN during the following times:
 * Monday to Sunday: 5:30 PM to 7:00 AM
 * The current destination DN is set to "801" modify destination to any system extension or extension you want.
 *
 * INSTRUCTIONS
 * - Configure Date & Time (Line 31)
 * - Change the destination DN, and modify the value of the constant DestinationDN to any destination you want to route call (Line 26).
 */

#nullable disable
using CallFlow;
using System;
using System.Threading;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.Linq;
using CallFlow.CFD;

namespace interceptcall
{
    public class InterceptInboundCall : ScriptBase<InterceptInboundCall>
    {
        // The destination DN to which the call will be redirected
        const string DestinationDN1 = "72";
        const string DestinationDN2 = "73";
      
        // Define a schedule for when calls should be intercepted
        static readonly Schedule schedule = new Schedule(RuleHoursType.SpecificHours)
        {
            { DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }
        };

        public override async void Start()
        {
            // Handle calls as a detached task, catching all exceptions.
            try
            {
                await Task.Run(async () =>
                {
                    try
                    {
                        MyCall.Debug($"Script start delay: {DateTime.UtcNow - MyCall.LastChangeStatus}");
                        MyCall.Debug($"Incoming connection {MyCall} from {MyCall.Caller}");
                        bool intercepted = false;
                        var ps = MyCall.PS as PhoneSystem;

                        if (MyCall.Caller.DN is ExternalLine externalLine)
                        {
                            var DIDNumber = MyCall.Caller["inbound_did"];
                            var CallerID = MyCall.Caller.CallerID;
                            var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);

                            // Intercept calls during the specified schedule
                            if (schedule.IsActiveTime(currentTime))
                            {
                                string[] DIDs1 = { "+49571444420","+49571444421","+49571444422"  }; // Allow DID -20,-21,-22
                                string[] DIDs2 = { "+49571444430","+49571444431","+49571444432" }; // Allow DID  -30,-31,-32
                                string[] Callers = { "*" }; // Allow all Callers
                                

                                // Check if the call's DID and CallerID match the interception criteria
                                if ((DIDs1.Contains(DIDNumber) || DIDs1.Contains("*")) &&
                                    (Callers.Contains(CallerID) || Callers.Contains("*")))
                                {
                                    try
                                    {
                                        var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN1));
                                        var result = await MyCall.RouteToAsync(destination_struct);
                                        MyCall.Info($"{CallerID} -> {DIDNumber} has been redirected to {DestinationDN1} ({result})");
                                        intercepted = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        MyCall.Info($"{CallerID} -> {DIDNumber}: interception failed. '{DestinationDN1}' is not reachable: {ex}");
                                    }
                                }
                                else if ((DIDs2.Contains(DIDNumber) || DIDs2.Contains("*")) &&
                                    (Callers.Contains(CallerID) || Callers.Contains("*")))
                                {
                                    try
                                    {
                                        var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN2));
                                        var result = await MyCall.RouteToAsync(destination_struct);
                                        MyCall.Info($"{CallerID} -> {DIDNumber} has been redirected to {DestinationDN2} ({result})");
                                        intercepted = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        MyCall.Info($"{CallerID} -> {DIDNumber}: interception failed. '{DestinationDN2}' is not reachable: {ex}");
                                    }
                                }
                                else
                                {
                                    MyCall.Info($"{CallerID} -> {DIDNumber}@{currentTime}: Default CallerID/DID based routing will be applied");
                                }
                            }
                        }

                        MyCall.Return(intercepted);
                    }
                    catch (Exception ex)
                    {
                        MyCall.Error($"Script execution failed: {ex}");
                        MyCall.Return(false);
                    }
                });
            }
            catch (Exception ex)
            {
                MyCall.Error($"Task execution failed: {ex}");
                MyCall.Return(false);
            }
        }
    }
}
 
Ungetestet, aber das Prinzip ist hoffentlich ersichtlich.
Z28 & 29 Die Ziele der Weiterleitungen
Z73 & 74 Die DIDs auf die weitergeleitet wird.

Der Block ab Z79 wurde einfach noch einmal kopiert für die Bearbeitung des zweiten Blockes

C#:
/*
 * Time Base Call Routing - Use code with caution!
 * Calls will be intercepted and redirected to the specified DestinationDN during the following times:
 * Monday to Sunday: 5:30 PM to 7:00 AM
 * The current destination DN is set to "801" modify destination to any system extension or extension you want.
 *
 * INSTRUCTIONS
 * - Configure Date & Time (Line 31)
 * - Change the destination DN, and modify the value of the constant DestinationDN to any destination you want to route call (Line 26).
 */

#nullable disable
using CallFlow;
using System;
using System.Threading;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.Linq;
using CallFlow.CFD;

namespace interceptcall
{
    public class InterceptInboundCall : ScriptBase<InterceptInboundCall>
    {
        // The destination DN to which the call will be redirected
        const string DestinationDN1 = "72";
        const string DestinationDN2 = "73";
     
        // Define a schedule for when calls should be intercepted
        static readonly Schedule schedule = new Schedule(RuleHoursType.SpecificHours)
        {
            { DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
            { DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
            { DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }
        };

        public override async void Start()
        {
            // Handle calls as a detached task, catching all exceptions.
            try
            {
                await Task.Run(async () =>
                {
                    try
                    {
                        MyCall.Debug($"Script start delay: {DateTime.UtcNow - MyCall.LastChangeStatus}");
                        MyCall.Debug($"Incoming connection {MyCall} from {MyCall.Caller}");
                        bool intercepted = false;
                        var ps = MyCall.PS as PhoneSystem;

                        if (MyCall.Caller.DN is ExternalLine externalLine)
                        {
                            var DIDNumber = MyCall.Caller["inbound_did"];
                            var CallerID = MyCall.Caller.CallerID;
                            var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);

                            // Intercept calls during the specified schedule
                            if (schedule.IsActiveTime(currentTime))
                            {
                                string[] DIDs1 = { "+49571444420","+49571444421","+49571444422"  }; // Allow DID -20,-21,-22
                                string[] DIDs2 = { "+49571444430","+49571444431","+49571444432" }; // Allow DID  -30,-31,-32
                                string[] Callers = { "*" }; // Allow all Callers
                               

                                // Check if the call's DID and CallerID match the interception criteria
                                if ((DIDs1.Contains(DIDNumber) || DIDs1.Contains("*")) &&
                                    (Callers.Contains(CallerID) || Callers.Contains("*")))
                                {
                                    try
                                    {
                                        var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN1));
                                        var result = await MyCall.RouteToAsync(destination_struct);
                                        MyCall.Info($"{CallerID} -> {DIDNumber} has been redirected to {DestinationDN1} ({result})");
                                        intercepted = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        MyCall.Info($"{CallerID} -> {DIDNumber}: interception failed. '{DestinationDN1}' is not reachable: {ex}");
                                    }
                                }
                                else if ((DIDs2.Contains(DIDNumber) || DIDs2.Contains("*")) &&
                                    (Callers.Contains(CallerID) || Callers.Contains("*")))
                                {
                                    try
                                    {
                                        var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN2));
                                        var result = await MyCall.RouteToAsync(destination_struct);
                                        MyCall.Info($"{CallerID} -> {DIDNumber} has been redirected to {DestinationDN2} ({result})");
                                        intercepted = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        MyCall.Info($"{CallerID} -> {DIDNumber}: interception failed. '{DestinationDN2}' is not reachable: {ex}");
                                    }
                                }
                                else
                                {
                                    MyCall.Info($"{CallerID} -> {DIDNumber}@{currentTime}: Default CallerID/DID based routing will be applied");
                                }
                            }
                        }

                        MyCall.Return(intercepted);
                    }
                    catch (Exception ex)
                    {
                        MyCall.Error($"Script execution failed: {ex}");
                        MyCall.Return(false);
                    }
                });
            }
            catch (Exception ex)
            {
                MyCall.Error($"Task execution failed: {ex}");
                MyCall.Return(false);
            }
        }
    }
}
Das sieht doch gut aus :) Genau so wars "erdacht". Ist zwar ein bisschen manuelle Arbeit das zu pflegen aber das ist der einfachste Weg.
 
@patrickb
Hallo
Bin jetzt erst dazu gekommen das weiter zu testen.
Wenn ich das Script aktiviere, funktioniert die Rufzustellung "Außerhalb der Geschäftszeiten". Allerdings werden innerhalb der Geschäftszeiten keine Rufe mehr zugestellt. Der Anruf wird angenommen und sofort beendet, ohne dass ein Telefon klingelt.
Wie wird eigentlich definiert, was außerhalb der definierten Zeiten geschieht?

Zur Fehlereingrenzung habe ich das Script erst mal auf ein Telefon reduziert, für die DiD 28.
Mit den Geschäftszeiten habe ich "gespielt", um es auch während der regulären Geschäftszeiten testen zu können.

Da sieht es so aus:

/*
* Time Base Call Routing - Use code with caution!
* Calls will be intercepted and redirected to the specified DestinationDN during the following times:
* Monday to Sunday: 5:30 PM to 7:00 AM
* The current destination DN is set to "801" modify destination to any system extension or extension you want.
*
* INSTRUCTIONS
* - Configure Date & Time (Line 31)
* - Change the destination DN, and modify the value of the constant DestinationDN to any destination you want to route call (Line 26).
*/

#nullable disable
using CallFlow;
using System;
using System.Threading;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.Linq;
using CallFlow.CFD;

namespace interceptcall
{
public class InterceptInboundCall : ScriptBase<InterceptInboundCall>
{
// The destination DN to which the call will be redirected
const string DestinationDN = "72";

// Define a schedule for when calls should be intercepted
static readonly Schedule schedule = new Schedule(RuleHoursType.SpecificHours)
{
{ DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Monday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(11)) },
{ DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Tuesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(11)) },
{ DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Friday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },
{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },
{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }
};

public override async void Start()
{
// Handle calls as a detached task, catching all exceptions.
try
{
await Task.Run(async () =>
{
try
{
MyCall.Debug($"Script start delay: {DateTime.UtcNow - MyCall.LastChangeStatus}");
MyCall.Debug($"Incoming connection {MyCall} from {MyCall.Caller}");
bool intercepted = false;
var ps = MyCall.PS as PhoneSystem;

if (MyCall.Caller.DN is ExternalLine externalLine)
{
var DIDNumber = MyCall.Caller["inbound_did"];
var CallerID = MyCall.Caller.CallerID;
var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);

// Intercept calls during the specified schedule
if (schedule.IsActiveTime(currentTime))
{
string[] DIDs = { "*" }; // Allow all DIDs
string[] Callers = { "*" }; // Allow all Callers
var destination_struct = new DestinationStruct(ps.GetDNByNumber(DestinationDN));

// Check if the call's DID and CallerID match the interception criteria
if ((DIDs.Contains(DIDNumber) || DIDs.Contains("*")) &&
(Callers.Contains(CallerID) || Callers.Contains("*")))
{
try
{
var result = await MyCall.RouteToAsync(destination_struct);
MyCall.Info($"{CallerID} -> {DIDNumber} has been redirected to {DestinationDN} ({result})");
intercepted = true;
}
catch (Exception ex)
{
MyCall.Info($"{CallerID} -> {DIDNumber}: interception failed. '{DestinationDN}' is not reachable: {ex}");
}
}
else
{
MyCall.Info($"{CallerID} -> {DIDNumber}@{currentTime}: Default CallerID/DID based routing will be applied");
}
}
}

MyCall.Return(intercepted);
}
catch (Exception ex)
{
MyCall.Error($"Script execution failed: {ex}");
MyCall.Return(false);
}
});
}
catch (Exception ex)
{
MyCall.Error($"Task execution failed: {ex}");
MyCall.Return(false);
}
}
}
}
 
@DKA-Service

Vllt. nicht an jeder Stelle der schlankste Code (und es fehlen die Feiertage) aber läuft grundsätzlich mal und ist für deine Zwecke flexibel, weil du jeweils die DIDs bzw. die Endungen der DIDs einzeln setzen könntest und nicht zwingend auf die Bereiche festgelegt bist:

C#:
#nullable disable
using CallFlow;
using System;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Linq;

namespace interceptcall
{
    public class InterceptInboundCall : ScriptBase<InterceptInboundCall>
    {
        public override async void Start()
        {
            try
            {
                await Task.Run(async () =>
                {
                    try
                    {
                        var ps = MyCall.PS as PhoneSystem;
                        var callerID = MyCall.Caller.CallerID;
                        var didNumber = MyCall.Caller["inbound_did"];

                        bool intercepted = false;

                        // Geschäftszeiten: Mo–Fr 08:00–17:30 (bei Bedarf anpassen)
                        var now = DateTime.Now;
                        bool isBusinessTime =
                            now.DayOfWeek >= DayOfWeek.Monday &&
                            now.DayOfWeek <= DayOfWeek.Friday &&
                            now.TimeOfDay >= new TimeSpan(8, 0, 0) &&
                            now.TimeOfDay < new TimeSpan(17, 30, 0);

                        // Prüfen, ob Anruf über externe DID hereinkommt
                        if (!string.IsNullOrEmpty(didNumber))
                        {
                            if (isBusinessTime)
                            {
                                // Während der Geschäftszeiten: direkt zum Ziel der DID routen
                                try
                                {
                                    var target = ps.GetDNByNumber(didNumber);
                                    if (target != null)
                                    {
                                        var result = await MyCall.RouteToAsync(new DestinationStruct(target));
                                        MyCall.Info($"{callerID} (extern) -> {didNumber} direkt zugestellt ({result})");
                                        intercepted = true;
                                    }
                                    else
                                    {
                                        MyCall.Warn($"Kein Ziel für DID {didNumber} gefunden");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    MyCall.Error($"Fehler beim Durchstellen an {didNumber}: {ex}");
                                }
                            }
                            else
                            {
                                // Außerhalb Geschäftszeiten → Weiterleitung an Standort-Rufgruppen
                                string groupDN = null;
                              
                                // Zuordnung bestimmter DID-Endungen zu Standort A
                                if (didNumber.EndsWith("20") || didNumber.EndsWith("21") ||
                                    didNumber.EndsWith("22") || didNumber.EndsWith("23") ||
                                    didNumber.EndsWith("24") || didNumber.EndsWith("25") ||
                                    didNumber.EndsWith("26") || didNumber.EndsWith("27") ||
                                    didNumber.EndsWith("28") || didNumber.EndsWith("29"))
                                {
                                    groupDN = "72"; // Durchwahl für Standort A (Rufgruppe)
                                }
                                // Zuordnung bestimmter DID-Endungen zu Standort B
                                else if (didNumber.EndsWith("30") || didNumber.EndsWith("31") ||
                                         didNumber.EndsWith("32") || didNumber.EndsWith("33") ||
                                         didNumber.EndsWith("34") || didNumber.EndsWith("35") ||
                                         didNumber.EndsWith("36") || didNumber.EndsWith("37") ||
                                         didNumber.EndsWith("38") || didNumber.EndsWith("39"))
                                {
                                    groupDN = "73"; // Durchwahl für Standort B (Rufgruppe)
                                }

                                if (groupDN != null)
                                {
                                    try
                                    {
                                        var result = await MyCall.RouteToAsync(new DestinationStruct(ps.GetDNByNumber(groupDN)));
                                        MyCall.Info($"{callerID} (extern) -> {didNumber} an Rufgruppe {groupDN} weitergeleitet ({result})");
                                        intercepted = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        MyCall.Error($"Fehler beim Weiterleiten an Rufgruppe {groupDN}: {ex}");
                                    }
                                }
                                else
                                {
                                    MyCall.Warn($"Keine Zuordnung für DID {didNumber}, Standardrouting");
                                }
                            }
                        }

                        MyCall.Return(intercepted);
                    }
                    catch (Exception ex)
                    {
                        MyCall.Error($"Script execution failed: {ex}");
                        MyCall.Return(false);
                    }
                });
            }
            catch (Exception ex)
            {
                MyCall.Error($"Task execution failed: {ex}");
                MyCall.Return(false);
            }
        }
    }
}
 
Zuletzt bearbeitet:

Statistik des Forums

Themen
44.751
Beiträge
233.645
Mitglieder
78.494
Neuestes Mitglied
Hans20262026