Rufgruppe weiterleitung bei Abwesend auf Mailbox bzw. mobil

TobiasS

Bronze Partner
Basic Certified
Mitglied seit
30. Oktober 2020
Beiträge
15
Hallo zusammen, stehe irgendwie auf dem Schlauch:
Habe eine Rufgruppe Empfang mit zwei Nutzern: Empfang1 und Empfang2. Wenn Empfang2 nicht da, stellt man dort auf DND.

Bei Empfang1 habe ich bei Abwesend kondiguriert, dass er die Anrufe aus der Rufgruppe annehmen, aber direkt auf die Mailbox leiten soll. Funktioniert aber nicht, Telefon klingelt trotzdem.

Das gleiche bei DND, dort habe ich konfiguriert, Anruf aus Rufgruppe soll angenommen werden, aber direkt an die Mobilgruppe ( 3 Mobilteile) weitergeleitet.

Es will nicht funktionieren? Wenn ich die Rufgruppe raus lassen und den Anruf direkt an Empfang1 leite, geht es? Hab ich nen Denkfehler?

Ich brauche die Rufgruppe aber wegen dem Empfang2 und wenn besetzt zur weiterleitung in die Warteschleife.

Danke für eure Ideenanstöße VG Tobias
 
Wenn ein Anruf über eine Rufgruppe kommt wird den Weiterleitungen der Teilnehmer nicht gefolgt.

Also auch keine Weiterleitung auf die Mailbox.

Das kann man sonst halt über Anrufziel bei nicht Annahme in der Rufgruppe realisieren.
 
Ich brauche die Rufgruppe aber wegen dem Empfang2 und wenn besetzt zur weiterleitung in die Warteschleife.
Wenn ein Anruf über eine Rufgruppe kommt wird den Weiterleitungen der Teilnehmer nicht gefolgt.
...
Das kann man sonst halt über Anrufziel bei nicht Annahme in der Rufgruppe realisieren.
Die einzige praktische Möglichkeit, den Überlauf der RG nutzen.

Sonst 'etwas vor der RG machen' (Dummy NSt., Abteilung) und an Stelle DND / Abwesend / Geschäftszeiten deren Staus mit Skript auf einer BLF umschalten lassen.

Weit ausgeholt: die grds. einzig dauerhafte und praktische Alternative dazu ist ein Anrufskript das auf dem SIP Trunk triggert. Das Skript fragt die Teilnehmer der RG ab und leitet entweder auf die RG oder (aufgrund irgendwelcher Präferenzen) sonstwohin weiter. Warum ein Anrufskript auf dem Trunk: das nimmt den Anruf initial nicht an (wg. Rufgruppe usw.).
 
  • Like
Reaktionen: Claas Beyersdorf
@TobiasS
Um das Thema noch einmal für eine Lösung aufzugreifen.

Es gab noch die Möglichkeit Anrufe parallel an der eigenen Mobilnummer signalisieren zu lassen und dafür die Nummer (mind. 4stellig) oder SIP ID einer anderen NSt. zu nutzen. Das funktioniert leider nicht mehr. Damit hätte man dir ein Szenario bauen können.

Daher also ein Anrufskript, das wäre eine Lösung. Um den von dir gewünschen Plan einmal zu verstehen:
aktuell gibt es eine RG mit zwei Mitgliedern (Empfang1 und ...2) und einem Überlauf auf eine WS.
Das gewünschte Telefonieverhalten bei externen Anrufen auf die DID der RG in vereinfachter Form sollte wohl sein:
Code:
Empfang1    Empfang2    Verhalten
bereit      bereit      es ruft an der RG an beiden NSt.
bereit      belegt      es ruft an der RG an NSt. Empfang1
belegt      bereit      es ruft an der RG an NSt. Empfang2
belegt      belegt      direkt überlauf zur WS
bereit      DND         es ruft an der RG
belegt      DND         direkt überlauf zur WS
DND         bereit      es ruft an der RG
DND         belegt      direkt überlauf zur WS
DND         DND         direkt überlauf zur WS
Abwesend    DND         direkte Weiterleitung an die MB von Empfang1, das ist der Sonderfall

Kurze vereinfachte Erklärung Zustand der NSt.:
  • Bereit bedeutet: ein Endgerät ist an der 3CX an dieser NSt. angemeldet, die NSt. ist in einem Status der den Anruf von RG Anrufen erlaubt und die NSt. ist nicht im Gespräch.
  • Belegt bedeutet: ein Endgerät ist an der 3CX an dieser NSt. angemeldet, die NSt. ist in einem Status der den Anruf von RG Anrufen erlaubt, die NSt. ist in einem Gespräch und kann keine weiteren Anrufe entgegennehmen.
  • Abwesend bedeutet: die NSt. ist im Status Abwesend. Dabei ist es egal ob: die NSt. ein Gespräch führt, Anrufe von RG in diesem Status annehmen kann (sollte nicht aktiviert sein) oder ob überhaupt ein Endgerät an dieser NSt. angemeldet ist.
Ist das grob der Plan? Sonst korrigiere das bitte entsprechend.
 
  • Like
Reaktionen: TobiasS
@fxbastler ja genau so sollte es sein! Danke VG
 
Das geht wohl nur mit einem C# Anrufskript zu lösen. Das funktioniert auch nur bei externen Anrufen, die direkt per DID oder per Definition der Standardroute oder per CID Regel an diese RG geleitet werden.

Das Anrufskript triggert bei jedem eingehenden Anruf auf dem SIP Trunk und fragt das direkte Ziel des Anrufes ab, s.o.. Wenn das Ziel die RG ist dann werden die NSt. der RG abgefragt. Wenn sich alle NSt. außer der NSt. Empfang1 auf DND befinden und die NSt. Empfang1 sich im Status Abwesend befindet, dann wird auf die MB der NSt. Empfang1 weitergeleitet.
Anders geht es wohl nicht.

Wäre das überhaupt denkbar bei dir?

Ich habe seit einigen Tagen ein ganz anderes Problem dessen Ursache die Unmöglichkeit der bisher mögl. Nutzung der SIP ID ist, s.o. und siehe hier. Das wäre auch bei dir eine sehr einfache - fast geradlinige - Lösung gewesen. Aber das geht nicht mehr :(

Nachtrag
Wichtige Nachfrage falls die o.g. Frage zutrifft:
Wird schon ein Anrufskript das auf SIP Trunk triggert eingesetzt und wenn ja welches (z.B. das 3CX holiday.cs)?
 
Zuletzt bearbeitet:
Brauchst du eingehend zwingend ein Freizeichen oder geht auch Wartemusik?
Wenn Wartemusik passt, kann man es mit dem CFD umsetzen und das sogar halbwegs simpel.
 
Bestehen die Rufgruppen jeweils nur aus einen Teilnehmer?

Grundsätzlich kenne ich das schon immer so das verketten von Rufumleitungen nicht funktionieren. Bei Alcatel konnte man auch die Gruppe umleiten.
 
@TobiasS

Anrufskript special_rg_call.cs als Skript, das bei jedem eingehenden Anruf auf dem SIP Trunk auslöst (Abteilung ist egal):
C#:
#nullable disable

using CallFlow;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
using TCX.Configuration;
using TCX.PBXAPI;

namespace dummy
{
    //this handler plays holiday prompt as specified for destination
    public class special_rg_call : ScriptBase<special_rg_call>
    {
        public string rgnumber  = "800";    // ring group number as destination
        public string extnumber = "220";    // extension number as ring group member which status decides about different routing
        public string extstatus = "Away";   // extension status which decides about different routing, maybe Out Of Office, Custom 1 oder Custom 2

        // nearly the reference implementation of trunk routing by 3CX, difference: match sequence of cid, did and standard route match
        DestinationStruct FindRealDefaultDestination(ExternalLine trunk, string callerID, string DID)
        {
            DestinationStruct retval = new();
            string[] range;
            foreach (var a in trunk.RoutingRules)
            {
                bool match =
                (a.Conditions.Condition.Type == RuleConditionType.BasedOnCallerID &&    // CID check
                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.BasedOnDID &&         // DID check
                (
                    a.Data == DID
                    || (a.Data.StartsWith('*') && DID.EndsWith(a.Data[1..]))
                ))
                ||
                (a.Conditions.Condition.Type == RuleConditionType.ForwardAll);          // standard route check

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

        public string CheckRG(DN dest)
        {
            string retval = null;
            RingGroup rgdn = (MyCall.PS as PhoneSystem).GetDNByNumber(rgnumber) as RingGroup;
            // check destination (number, if ringgroup) and status of all member
            if (dest.Number.Equals(rgnumber) &&
                rgdn != null &&
                rgdn.GetType().ToString().Equals("TCX.Configuration.Interop.Wringgroup") &&
                rgdn.Members.Where(m => m.Number != extnumber).All(m => (m as Extension).CurrentProfile.Name == "Out of office") &&
                rgdn.Members.Any(m => m.Number == extnumber && (m as Extension).CurrentProfile.Name == extstatus))
            {
                // check business and non-business hours and destinations
                var tbr = rgdn.GetTimeBasedRoutingInfo();
                if (tbr.reason == CallControlAPI.DivertReason.OfficeHours ||
                   (tbr.reason == CallControlAPI.DivertReason.OutOfOfficeHours && rgdn.OutOfOfficeHoursRoute.To == DestinationType.ProceedWithNoExceptions) ||
                   (tbr.reason == CallControlAPI.DivertReason.BreakTime && rgdn.BreakTimeRoute.To == DestinationType.ProceedWithNoExceptions) ||
                   (tbr.reason == CallControlAPI.DivertReason.Holiday && rgdn.HolidaysRoute.To == DestinationType.ProceedWithNoExceptions) )
                {
                    retval = extnumber; // yes, all conditions right, route to other number ...
                }
            }
            return retval;
        }
   
        public override async Task<bool> StartAsync()
        {
            if (MyCall.Caller.DN is ExternalLine externalLine && MyCall.IsInbound) // calls only from trunk
            {
                // get the real inbound target
                var defaultDestination = FindRealDefaultDestination(externalLine, MyCall.Caller.CallerID, MyCall.Caller.CalledNumber).Internal;
                if (defaultDestination != null)
                {
                    string destnr = CheckRG(defaultDestination);
                    if( destnr != null )
                    {
                        try
                        {
                            // route call to vmb: usually prepend "*4" to the number, get it from the global 3CX dial code parameter
                            destnr = (MyCall.PS as PhoneSystem).GetParameterByName("VMAIL").Value + destnr;
                            await MyCall.RouteTo(destnr, MyCall.Caller.CallerID, 3600);
                            return true; // a new route for incoming call, exit the script and further processing if transfer is done
                        }
                        catch (Exception ex)
                        {
                            MyCall.Error($"special_rg_call.cs script execution failed: {ex}");
                        }                  
                    }
                }
            }
            return false; // return true means: call ends here, return false means: call will further processed by 3CX
        }
    }
}

Passe dir oben noch die zwei Variablen rgnumber (kenne ich bei dir nicht) und extnumber (die Nummer von Empfang1, kenne ich auch nicht) an. Den Status von Empfang1 (extstatus) wolltest du ja als Away = Abwesend haben, das passt.

Der Anruf kommt auf dem SIP Trunk an und das Skript startet. Wenn das Ziel der angerufenen DID die Rufgruppe mit Nummer rgnumber ist, alle Nutzer dieser Rufgruppe auf DND stehen außer extnumber (bei dir Empfang1) die auf Abwesend steht, dann wird der Anruf auf die Mailbox von extnumber weitergeleitet. Einfach probieren und berichten.

Das hier ist eine Spezialversion nur für dich.

Wie schon geschrieben: wir hatten das mal (haben wir gar noch?) anderswo so ähnlich für eine Warteschleife mit einer priorisierten Nebenstelle deren Status die gesamte WS ausschließt. Das hier ist sehr ähnlich.

Man stelle sich vor: eine RG (oder WS) hat einige Teilnehmer, alle haben nur phys. Endgeräte und nicht alle wollen manuell auf DND stellen damit die RG / WS überläuft. Also stellt z.B. eine einzige spezielle Nebenstelle auf Custom 1, ist damit selber intern noch erreichbar aber die RG / WS wird auf eine anderes Ziel gelenkt. Das war bei uns mal die Aufgabe.
 
Zuletzt bearbeitet:
  • Like
Reaktionen: patrickb und bitn2
Nachtrag zu o.b. Code:
//this handler plays holiday prompt as specified for destination
Wenn schon copy&paste aus einem anderen Projekt, dann sollte man (ich) auch die unpassenden Kommentare entfernen. Diese Zeile gehört nicht zu diesem C# Anrufskript, bitte ignorieren oder entfernen. Ich kann das in dem Beitrag leider nicht mehr.
 
alles klar vielen Dank, werde es Ende der Woche testen und mich rückmelden! VG
 
  • Like
Reaktionen: fxbastler

Statistik des Forums

Themen
44.411
Beiträge
232.703
Mitglieder
78.327
Neuestes Mitglied
jlx