Holiday Ansage für DIDs

Ideal wäre, jeder Arzt hätte eine eigene Einwahl, eine eigene Nummer. Diese endet auf irgend einer 3CX Entität (IVR, WS, RG, Nutzer) und diese gehört je einer eigenen Abteilung (dem Arzt) an. Genau dafür ist das 3CX Skript gedacht. Das greift sich dann vorher am Trunk auf Grund der angerufenen Nummer diese Entität, ermittelt die Abteilung und auf Grund deren Einstellung und Zeiten werden eigene Ansagen abgespielt oder eben nicht.
 
Ist das wirklich so gewollt?
Wenn du das willst: ja. Sonst auf die Abteilung leiten und dort bei Feiertagen speziell behandeln lassen. Oder das Skript ändern und den Anruf nach Ansage enden lassen. Deine Entscheidung.
 
Ja nur der IVR ist von extern erreichbar. Die Ärzte selber haben dann ihre Departments/Extensions/DIDs aber diese sind nicht nach aussen kommuniziert.
Wenn beides von dir mit ja beantwortet wird, dann wird es das Sinnvollste sein, das holiday.cs minimal anzupassen und nicht auf eingehende Anrufe auf dem Trunk reagieren zu lassen sondern 'Wenn ein Nutzer einen Wählcode wählt' und das Skript minimal anzupassen. Aktuell fragt das Anrufskript alle eingehenden Regeln eines angerufenen SIP Trunk ab und nur dann läuft es weiter. Das kann man fast komplett entfernen. Der Effekt wird dann sein: der IVR verweist nach der Auswahl des Anrufers auf das modifizierte Anrufskript, das Anrufskript fragt die Abteilung der Rufgruppe ARZT1 nach den Feiertageinstellungen ab und spielt dese evtl. ab - oder eben auch nicht - und leitet dann in jedem Fall auf die Rufgruppe ARZT1 weiter.
 
Hallo fxbastler

Bin mir nicht scher, ob wir uns da nicht missverstehen.
Es gibt ja grundsätzlich 2 Ansätze.
1.) Die Einen möchten das die Kopfnummer die Ansage bekommt, DW sollen davon unberührt bleiben.
2.) Die ganze Anlage befindet sich im Urlaub/Feiertage, also Kopfnummer und Durchwahlen.

Mein Ansatz war bisher, bei V20, so, das die Kopfnummer, die ja i.d. Regel zu einer Warteschleife/IVR geht, hier die Ansage bekommt. Die DW sind da unberührt, kommen also durch.
Der User Entscheidet nun durch seinen Status, bimmelt es, oder hat er z.B. Status Abwesend und leitet daher den Call auch wieder an den IVR oder Warteschleife, bei der dann die Feeiertags/Urlaubsansage abgespielt wird.

Nun ist das aber nicht mehr so, sondern alle DW gehen zu Feiertage und spielen das File ab, anschließend wird dann erst zur Nebenstelle geleitet, das war mit meiner Frage, ist das wirklich so gewollt.
Somit können Kunden die das Prinzip 1 wollen, nicht mehr richtig behandelt werden, denn wenn die Feiertage kommen, legen die meisten ja schon auf.
 
@timmbo
Ich denke schon, dass ich dich richtig verstanden habe. Das originale 3CX holiday.cs deckt Fall 2 ab. Das ist grundsätzlich richtig: wenn Feiertag oder Urlaub dann für alle ;)

Anbei dein Wunsch Anrufskript für Fall 1. Das beruht bis auf 3 Zeilen mit Änderungen und Kommentaren komplett auf dem originalen holiday.cs aus dem 3CX Store, einfach auch weil das so gut ist :D

Mit der Variable holiday_included_extensions zu Anfang werden die Nebenstellennummern festgelegt, für welche die Feiertag- oder Urlaubansage gilt. Anrufe an alle anderen Nummern werden wie sonst auch geroutet.

Wenn es gewünscht ist, nach der Ansage den Anruf zu beenden, dann den Kommentar vor dem // return true; ... fast ganz am Ende entfernen.

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

namespace dummy
{
    //this handler plays holiday prompt as specified for destination
    public class PlaySelectedDestinationHolidayPromptBeforeRouting : ScriptBase<PlaySelectedDestinationHolidayPromptBeforeRouting>
    {
        // holiday prompt extensions
        private readonly string holiday_included_extensions = "200,210,220,800";
  
        //reference implementation of trunk routing.
        DestinationStruct FindDefaultDestination(ExternalLine trunk, string callerID, string DID)
        {
            DestinationStruct retval = new();
            string[] range;
            foreach (var a in trunk.RoutingRules)
            {
                bool match = (a.Conditions.Condition.Type == RuleConditionType.BasedOnDID &&
                (
                    a.Data == DID
                    || (a.Data.StartsWith('*') && DID.EndsWith(a.Data[1..]))
                ))
                ||
                (
                    a.Conditions.Condition.Type == RuleConditionType.BasedOnCallerID &&
                    a.Data.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
                    .Any
                    (x =>
                        x == "*"
                        || x == callerID
                        || x.StartsWith('*') && callerID.EndsWith(x[1..])
                        || x.EndsWith('*') && callerID.StartsWith(x[..^1])
                        || x.StartsWith('*') && x.EndsWith('*') && callerID.Contains(x[1..^1])
                        || ((range = x.Split("-", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)).Length == 2 ?
                        (range[0].Length == callerID.Length && range[1].Length == callerID.Length) && (range[0].CompareTo(callerID) <= 0 && range[1].CompareTo(callerID) >= 0) : false)
                    )
                )
                ||
                (a.Conditions.Condition.Type == RuleConditionType.ForwardAll);

                if (match)
                {
                    retval.CopyFrom(a.ForwardDestinations.OfficeHoursDestination);
                    break;
                }
            }
            return retval;
        }

        public override async Task<bool> StartAsync()
        {
            if(MyCall.Caller.DN is ExternalLine externalLine && MyCall.IsInbound) //only from trunk
            {
                //get the inbound target
                var defaultDestination = FindDefaultDestination(externalLine, MyCall.Caller.CallerID, MyCall.Caller.CalledNumber).Internal;
                //if the destination is Internal
                if (defaultDestination != null && holiday_included_extensions.Contains(defaultDestination.Number))
                {
                    var timeBasedroute = defaultDestination.GetTimeBasedRoutingInfo();

                    //if destination is currently "on holiday" and holiday prompt is defined, we play it
                    if (timeBasedroute.reason == CallControlAPI.DivertReason.Holiday && !string.IsNullOrWhiteSpace(timeBasedroute.holiday?.HolidayPrompt))
                    {
                        await MyCall.AssureMedia()
                            .ContinueWith(x => MyCall.PlayPrompt(null, [timeBasedroute.holiday?.HolidayPrompt], PlayPromptOptions.Blocked))
                            .Unwrap();
                        // return true;  // remove remark to stop further call routing after playing prompt
                    }
                }
            }
            return false;//we always return false to continue default trunk routing procedure.
        }
    }
}

Stichwort: schnipsel
 
  • Like
Reaktionen: manno und mbehrens
Wenn ich Dich richtig verstehe, muss ich au dem

private readonly string holiday_included_extensions = "200,210,220,800"

ein
private readonly string holiday_included_extensions = "0"

machen, wenn ich möchte das alle DW von dem Holiday ausgenommen werden sollen?
Kopfnummer + DW0 soll auch zu der Feiertagansage gehen.



Wäre das so richtig?
 
  • Like
Reaktionen: manno
Der Sinn des Konstruktes, ist die geplanten Holiday Promts beim Transfer vom Default Department in anderes Department abspielen zu können.

Mein Ärzteat nur eine Kopfnummer, und ist quasi immer göffnet, die eingemieteten Ärzte könnten kompett selbstständig ihre Öffnungszeiten definieren und auch ihre Urlaube.zentrum h

Wenn ich deinen Vorschlag richtig deute lasse ich den IVR und schalte für jeden Arzt ein zu modifizierendes Holiday Script vor.
Eine Möglichkeit:
  1. belasse den IVR für die Haupteinwahl
  2. der IVR verweist an Statt auf div. Warteschleifen nun auf div. individuelle Anrufskripte
  3. in jedem Anrufskript ist die Nummer auf welche anschl. weitergeleitet werden soll statisch hinterlegt, Erklärung s.u.
  4. das Skript ermittelt für das statisch hinterlegte Ziel die Abteilung und prüft ob diese im Feiertag-/Urlaubsmodus ist,
    wenn ja, dann wird die hinterlegte Ansage abgespielt
  5. das Anrufskript transferiert abschließend in jedem Fall den Anruf auf das statisch hinterlegte Ziel
Es gibt leider keine schöne Lösung für dein Anliegen. Es läuft darauf hinaus, für jeden Arzt ein minimal anderes Anrufskript zu bauen. Das liegt einfach daran, dass das Anrufskript nicht ermitteln kann, welche Nummer (WS oder RG des Arztes) hätte angerufen werden sollen. Das Skript bekommt immer nur den Anruf vom IVR (noch nicht einmal die getroffene Auswahl im IVR) und daher muss im Skript die anzurufende Nummer des Arztes (WS oder RG) statisch hinterlegt werden. Ist leider so. In der WS oder RG kann dann für den Fall eines Feiertages eine Weiterleitung auf z.B. einen AB eingerichtet werden.

Anbei das eine Vorlage des Anrufskriptes für dich. Jedes dieser verwendeten Anrufskripte sollte einen eigenen Namen bekommen und wird ausgeführt wenn ein Nutzer einen Wählcode wählt. Das Skript kann Systemweit gelten, das ist egal. Wichtig ist noch ein individueller Name der Klasse. Das sollte zwei mal gleich in der Zeile
public class PlayDestinationHolidayPrompt : ScriptBase<PlayDestinationHolidayPrompt> pro Skript individuell hinterlegt werden. Für jedes individuelle Ziel (WS des Arztes) die Zeile
var defaultDestination = (MyCall.PS as PhoneSystem).GetDNByNumber("815"); mit der gewünschten Nummer individualisieren.

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

namespace dummy
{
    //this handler plays holiday prompt as specified for destination
    public class PlayDestinationHolidayPrompt : ScriptBase<PlayDestinationHolidayPrompt>
    {
        public override async Task<bool> StartAsync()
        {
            //get the destination target
            var defaultDestination = (MyCall.PS as PhoneSystem).GetDNByNumber("815");
 
            if (defaultDestination != null)
            {
                var timeBasedroute = defaultDestination.GetTimeBasedRoutingInfo();

                //if destination is currently "on holiday" and holiday prompt is defined, we play it
                if (timeBasedroute.reason == CallControlAPI.DivertReason.Holiday && !string.IsNullOrWhiteSpace(timeBasedroute.holiday?.HolidayPrompt))
                {
                    await MyCall.AssureMedia()
                        .ContinueWith(x => MyCall.PlayPrompt(null, [timeBasedroute.holiday?.HolidayPrompt], PlayPromptOptions.Blocked))
                        .Unwrap();
                }
                await MyCall.RouteTo(defaultDestination.Number, MyCall.Caller.CallerID, 300); 
            }
            return true;
        }
    }
}

Noch ein abschließender Hinweis für den der das Skript verwendet: Wenn das Skript angesprochen wird und es gilt für das Ziel gerade kein Feiertag oder Urlaub und das Ziel ist keine WS sondern eine RG, dann wird der Anrufer normal an die RG weitergeleitet aber hört kein Audio. Das ist bei einer RG so. Da müsste sinnvollerweise eine WS benutzt werden. Wenn doch eine RG verwendet werden soll, dann muss separat MOH abgespielt werden. Das ist in diesem Skript noch nicht eingearbeitet.

Stichwort: schnipsel
 
Zuletzt bearbeitet:
  • Like
Reaktionen: manno
Wenn ich Dich richtig verstehe, muss ich au dem

private readonly string holiday_included_extensions = "200,210,220,800"

ein
private readonly string holiday_included_extensions = "0"

machen, wenn ich möchte das alle DW von dem Holiday ausgenommen werden sollen?
NEIN -->> Kopfnummer + DW0 soll auch zu der Feiertagansage gehen. << --- NEIN



Wäre das so richtig?
grundsätzlich ja
Du kannst auch
private readonly string holiday_included_extensions = ""; für so einen Fall definieren ;)

oder
private readonly string holiday_included_extensions = "alle Anwahlen werden angenommen";
oder
private readonly string holiday_included_extensions = "keine Ahnung was hier rein kommt";

So werden Feiertagregelungen komplett ignoriert. Dazu brauchst du kein Skript.

Aber:
NEIN -->> Kopfnummer + DW0 soll auch zu der Feiertagansage gehen. << --- NEIN
Wenn die Kopfnummer+DW0 zu einer Feiertagansage führen soll, dann musst du das Ziel dieser Kopfnummer+DW0 Zuweisung in der 3CX im String hinterlegen.
 
Zuletzt bearbeitet:
  • Like
Reaktionen: manno
Habs soweit verstanden.
In OE gibt es die Kopfnummer, die gibt es in DE nicht bzw. ist die in DE nicht anrufbar, da es in DE Blöcke gibt in OE nicht, da gibts nur eine Rufnummer, eben die Kopfnummer und alles was dahinter kommt gehört dazu, solange es die erlaubte Rufnummernlänge nicht überschreitet.
Da viele internationale Kunden hier auch die DW 0 als Zentrale angeben, muss die ja mit zur Ansage.
 
  • Like
Reaktionen: manno
In OE gibt es die Kopfnummer, die gibt es in DE nicht bzw. ist die in DE nicht anrufbar
Die gibts bei uns auch. Die ist auch anrufbar. Kommt entweder auf die Gestaltung der DID an bzw. die Kopfnummer ist oft die Trunk-Hauptnummer in den SIP Trunk Einstellungen und die kann man auch zuweisen.

in OE nicht, da gibts nur eine Rufnummer
Nein, ihr habt da auch Rufnummernblöcke, mit Kopfnummer, so wie in D auch - wenn gewünscht und bestellt.

eben die Kopfnummer und alles was dahinter kommt gehört dazu, solange es die erlaubte Rufnummernlänge nicht überschreitet.
Haben wir hier auch. Funktioniert nur nicht überall. Das ist Providerabhängig. Manche Provider sperren dieses Feature bei einzelnen Nummern. Da werden zusätzlich hinten angestellte Nummern abgeschnitten.
Wo kommen wir denn hin, wenn jede Nummer durchwahlfähig wäre ... ;)
 
  • Like
Reaktionen: manno
Achso, die Nebenstellennummer muß da rein, nicht die Durchwahl, verstehe.
Also für IVR/WS die 800, so richtig?
Also wie ich noch in DE war, hat man Blöcke bekommen z.B. 12345 0-29
Demnach war die 12345-0 Die Vermittlung, die 12345 war nicht anrufbar, ist das jetzt in DE anders?
 
Achso, die Nebenstellennummer mu0 da rein, nicht die Durchwahl, verstehe.
ja

Als für IVR/WS die 800, so richtig?
Wenn die NSt. 800 die DID Kopfnummer+DW0 zugewiesen bekommen hat: ja.

Also wie ich noch in DE war, hat man Blöcke bekommen z.B. 12345 0-29
Wenn man dafür bezahlt. Das ist ein Rufnummernblock. Das sind dann Business Kunden von Providern mit einem Business Kunden Modell und vmtl. auch mit einer Business Kunden Internetanbindung. Das lassen die sich gut bezahlen. Danke T-Com u.a. :mad:

Demnach war die 12345-0 Die Vermittlung
Bei einem Rufnummernblock: richtig
die 12345 war nicht anrufbar, ist das jetzt in DE anders?
Bei einem Rufnummernblock: diese Nummer gibt es i.d.R. gar nicht im zentralen Telefonverzeichnis in D. Gab es früher und auch heute nicht.

Aber wenn es nur eine einzelne Nummer und kein Rufnummernblock ist (z.B. eben 12345) und der Provider nicht der falsche ist, dann ist diese einzelne Nummer (12345) anwählbar und alles andere dahinter auch - sofern das 15 Stellen insgesamt (inkl. einer 49 davor und der Ortsvorwahl) nicht überschreitet, der Provider das komplett durchreicht und nicht abschneidet oder der Provider das von vornherein nicht unterbindet. Eine mögliche Bezeichnung dafür ist durchwahlfähig.

Ich persönlich habe mehrere solcher einzelnen aber durchwahlfähigen Nummern hier in D, aber eben von Providern die das mitmachen.
 
Zuletzt bearbeitet:
Ah, ok, ja klar.
Ich sprach natürlich von Businesskunden und nicht von Privaten.
Bei uns in OE bekommen Businesskunden die 12345 und alles dahinter ist auch anrufbar, genauso wie die 12345(Kopfnummer).
Bei Privatkunden ist das nicht so, die bekommen die 12345 und alles was dahinter ist, ist nicht anrufbar.
 
Bei uns in OE bekommen Businesskunden die 12345 und alles dahinter ist auch anrufbar, genauso wie die 12345(Kopfnummer).
Wie geschrieben, das haben wir hier auch. Grundsätzlich egal ob Firmenkunde oder nicht. Das ist aber eher unüblich und eben abhängig vom Provider.

Das alles ist historisch bedingt und wurde von so einigen großen Anbietern in das VOIP Zeitalter rübergerettet weil man damit Firmenkunden andere Verträge aufhalsen kann. Technisch notwendig ist das nicht.

Aber mal ehrlich: sonst lassen sich doch keine Rufnummernblöcke mehr verkaufen weil die keiner mehr braucht wenn alle normalen Endkundenanschlüsse durchwahlfähig wären, evtl. gar noch mit mehr als nur 2 parallelen Rufen ;)
 
Naja, muß mich damit noch beschäftigen bzw. mich updaten, was da in DE so los ist.
Habe eine Münchner Rufnummer, die ist aber eine Einzelne, also nicht DW-fähig.
Weil das eine Private Nummer ist.

Danke aber für die Infos.
 
  • Like
Reaktionen: fxbastler
Muß das noch testen, aber ich denke schon.
Habe mir es nun kopiert.

Danke
 
Eine Möglichkeit:
  1. belasse den IVR für die Haupteinwahl
  2. der IVR verweist an Statt auf div. Warteschleifen nun auf div. individuelle Anrufskripte
  3. in jedem Anrufskript ist die Nummer auf welche anschl. weitergeleitet werden soll statisch hinterlegt, Erklärung s.u.
  4. das Skript ermittelt für das statisch hinterlegte Ziel die Abteilung und prüft ob diese im Feiertag-/Urlaubsmodus ist,
    wenn ja, dann wird die hinterlegte Ansage abgespielt
  5. das Anrufskript transferiert abschließend in jedem Fall den Anruf auf das statisch hinterlegte Ziel
Es gibt leider keine schöne Lösung für dein Anliegen. Es läuft darauf hinaus, für jeden Arzt ein minimal anderes Anrufskript zu bauen. Das liegt einfach daran, dass das Anrufskript nicht ermitteln kann, welche Nummer (WS oder RG des Arztes) hätte angerufen werden sollen. Das Skript bekommt immer nur den Anruf vom IVR (noch nicht einmal die getroffene Auswahl im IVR) und daher muss im Skript die anzurufende Nummer des Arztes (WS oder RG) statisch hinterlegt werden. Ist leider so. In der WS oder RG kann dann für den Fall eines Feiertages eine Weiterleitung auf z.B. einen AB eingerichtet werden.

Anbei das eine Vorlage des Anrufskriptes für dich. Jedes dieser verwendeten Anrufskripte sollte einen eigenen Namen bekommen und wird ausgeführt wenn ein Nutzer einen Wählcode wählt. Das Skript kann Systemweit gelten, das ist egal. Wichtig ist noch ein individueller Name der Klasse. Das sollte zwei mal gleich in der Zeile
public class PlayDestinationHolidayPrompt : ScriptBase<PlayDestinationHolidayPrompt> pro Skript individuell hinterlegt werden. Für jedes individuelle Ziel (WS des Arztes) die Zeile
var defaultDestination = (MyCall.PS as PhoneSystem).GetDNByNumber("815"); mit der gewünschten Nummer individualisieren.

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

namespace dummy
{
    //this handler plays holiday prompt as specified for destination
    public class PlayDestinationHolidayPrompt : ScriptBase<PlayDestinationHolidayPrompt>
    {
        public override async Task<bool> StartAsync()
        {
            //get the destination target
            var defaultDestination = (MyCall.PS as PhoneSystem).GetDNByNumber("815");
 
            if (defaultDestination != null)
            {
                var timeBasedroute = defaultDestination.GetTimeBasedRoutingInfo();

                //if destination is currently "on holiday" and holiday prompt is defined, we play it
                if (timeBasedroute.reason == CallControlAPI.DivertReason.Holiday && !string.IsNullOrWhiteSpace(timeBasedroute.holiday?.HolidayPrompt))
                {
                    await MyCall.AssureMedia()
                        .ContinueWith(x => MyCall.PlayPrompt(null, [timeBasedroute.holiday?.HolidayPrompt], PlayPromptOptions.Blocked))
                        .Unwrap();
                }
                await MyCall.RouteTo(defaultDestination.Number, MyCall.Caller.CallerID, 300);
            }
            return true;
        }
    }
}

Noch ein abschließender Hinweis für den der das Skript verwendet: Wenn das Skript angesprochen wird und es gilt für das Ziel gerade kein Feiertag oder Urlaub und das Ziel ist keine WS sondern eine RG, dann wird der Anrufer normal an die RG weitergeleitet aber hört kein Audio. Das ist bei einer RG so. Da müsste sinnvollerweise eine WS benutzt werden. Wenn doch eine RG verwendet werden soll, dann muss separat MOH abgespielt werden. Das ist in diesem Skript noch nicht eingearbeitet.

Stichwort: schnipsel
Nochmal Herzlichen Dank, funktioniert perfekt. RGs verwenden eigentlich nie. ( Außer bei Türsprechsachen ;D )
 
@timmbo
Ich denke schon, dass ich dich richtig verstanden habe. Das originale 3CX holiday.cs deckt Fall 2 ab. Das ist grundsätzlich richtig: wenn Feiertag oder Urlaub dann für alle ;)

Anbei dein Wunsch Anrufskript für Fall 1. Das beruht bis auf 3 Zeilen mit Änderungen und Kommentaren komplett auf dem originalen holiday.cs aus dem 3CX Store, einfach auch weil das so gut ist :D

Mit der Variable holiday_included_extensions zu Anfang werden die Nebenstellennummern festgelegt, für welche die Feiertag- oder Urlaubansage gilt. Anrufe an alle anderen Nummern werden wie sonst auch geroutet.

Wenn es gewünscht ist, nach der Ansage den Anruf zu beenden, dann den Kommentar vor dem // return true; ... fast ganz am Ende entfernen.

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

namespace dummy
{
    //this handler plays holiday prompt as specified for destination
    public class PlaySelectedDestinationHolidayPromptBeforeRouting : ScriptBase<PlaySelectedDestinationHolidayPromptBeforeRouting>
    {
        // holiday prompt extensions
        private readonly string holiday_included_extensions = "200,210,220,800";
 
        //reference implementation of trunk routing.
        DestinationStruct FindDefaultDestination(ExternalLine trunk, string callerID, string DID)
        {
            DestinationStruct retval = new();
            string[] range;
            foreach (var a in trunk.RoutingRules)
            {
                bool match = (a.Conditions.Condition.Type == RuleConditionType.BasedOnDID &&
                (
                    a.Data == DID
                    || (a.Data.StartsWith('*') && DID.EndsWith(a.Data[1..]))
                ))
                ||
                (
                    a.Conditions.Condition.Type == RuleConditionType.BasedOnCallerID &&
                    a.Data.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
                    .Any
                    (x =>
                        x == "*"
                        || x == callerID
                        || x.StartsWith('*') && callerID.EndsWith(x[1..])
                        || x.EndsWith('*') && callerID.StartsWith(x[..^1])
                        || x.StartsWith('*') && x.EndsWith('*') && callerID.Contains(x[1..^1])
                        || ((range = x.Split("-", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)).Length == 2 ?
                        (range[0].Length == callerID.Length && range[1].Length == callerID.Length) && (range[0].CompareTo(callerID) <= 0 && range[1].CompareTo(callerID) >= 0) : false)
                    )
                )
                ||
                (a.Conditions.Condition.Type == RuleConditionType.ForwardAll);

                if (match)
                {
                    retval.CopyFrom(a.ForwardDestinations.OfficeHoursDestination);
                    break;
                }
            }
            return retval;
        }

        public override async Task<bool> StartAsync()
        {
            if(MyCall.Caller.DN is ExternalLine externalLine && MyCall.IsInbound) //only from trunk
            {
                //get the inbound target
                var defaultDestination = FindDefaultDestination(externalLine, MyCall.Caller.CallerID, MyCall.Caller.CalledNumber).Internal;
                //if the destination is Internal
                if (defaultDestination != null && holiday_included_extensions.Contains(defaultDestination.Number))
                {
                    var timeBasedroute = defaultDestination.GetTimeBasedRoutingInfo();

                    //if destination is currently "on holiday" and holiday prompt is defined, we play it
                    if (timeBasedroute.reason == CallControlAPI.DivertReason.Holiday && !string.IsNullOrWhiteSpace(timeBasedroute.holiday?.HolidayPrompt))
                    {
                        await MyCall.AssureMedia()
                            .ContinueWith(x => MyCall.PlayPrompt(null, [timeBasedroute.holiday?.HolidayPrompt], PlayPromptOptions.Blocked))
                            .Unwrap();
                        // return true;  // remove remark to stop further call routing after playing prompt
                    }
                }
            }
            return false;//we always return false to continue default trunk routing procedure.
        }
    }
}

Stichwort: schnipsel
Auch nochmals vielen Dank dafür von mir! Man könnte die Awesomeness noch weiter ausbauen, indem man einen zweiten String beziehungsweise eine zweite Liste abfragt. Diese Liste würde festlegen, welche User-Extensions vom SIP-Trunk (also extern) außerhalb der Öffnungszeiten der Gruppe dieser Extension – jedoch nur dann, wenn kein Feiertag ist, no , na – nicht erreichbar sein sollen. Anschließend könnten solche Anrufe automatisch an eine im Skript konfigurierbare, statische Extension weitergeleitet werden, in unserem Fall üblicherweise ein IVR mit "Nachtansage" und anschließendem Auflegen.

Damit wäre in einem einzigen Skript all das geregelt, was mit V20 nicht mehr ganz so einfach zu handeln ist.
 
Zuletzt bearbeitet:
Du meinst so etwas wie das hier:
C#:
// holiday prompt extensions
private readonly string holiday_included_extensions = "200,210,220,800";

// mapping table of did destination extension, group with defined business hours, target extension and vmb used
// table is used when no holiday routing has been processed
// every entry has 4 parameter:
//  1) string: incoming DID destination which should match for processing, * matches all (no further definitions / entries in table needed)
//  2) string: group name used for office hours definitions, if empty then main department from extension in parameter 1 will be used
//  3) string: destination extension for out of office / break hours, if empty then dnd or away destination for extension in parameter 1 will be used
//  4) bool: if true and if parameter 3 with extension is given, destination for out of office and break hours is the voice mailbox for this extension
...
private readonly bool use_incoming_rules_map = true; // rules map table will only processed if true
ganz oben?

Ja, das habe ich schon irgendwo gesehen.
 
Zuletzt bearbeitet:

Statistik des Forums

Themen
44.463
Beiträge
232.871
Mitglieder
78.355
Neuestes Mitglied
enkiTech